diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-04-12 13:59:22 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-06-27 10:49:25 -0400 |
commit | 9d67006e6ebc6c5bc553d04b8c2dabea168e5e5b (patch) | |
tree | abbbd0efe290bc984cd5a35d9fc784817dc69dfd | |
parent | 2e9d4c05a17e3f3056c823c76f2c908d4eda17aa (diff) |
drm/radeon/kms: add dpm support for rs780/rs880
This adds dpm support for rs780/rs880 asics. This includes:
- clockgating
- dynamic engine clock scaling
- dynamic voltage scaling
set radeon.dpm=1 to enable it.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/radeon/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rs780_dpm.c | 894 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rs780_dpm.h | 109 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rs780d.h | 168 |
7 files changed, 1203 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index a131a13fc810..e44b046d8752 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
@@ -77,7 +77,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ | |||
77 | evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ | 77 | evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ |
78 | atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ | 78 | atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ |
79 | si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \ | 79 | si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \ |
80 | r600_dpm.o | 80 | r600_dpm.o rs780_dpm.o |
81 | 81 | ||
82 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o | 82 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o |
83 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o | 83 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 8559ff3aa8ee..1448270e5b06 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
@@ -1242,6 +1242,18 @@ static struct radeon_asic rs780_asic = { | |||
1242 | .set_clock_gating = NULL, | 1242 | .set_clock_gating = NULL, |
1243 | .get_temperature = &rv6xx_get_temp, | 1243 | .get_temperature = &rv6xx_get_temp, |
1244 | }, | 1244 | }, |
1245 | .dpm = { | ||
1246 | .init = &rs780_dpm_init, | ||
1247 | .setup_asic = &rs780_dpm_setup_asic, | ||
1248 | .enable = &rs780_dpm_enable, | ||
1249 | .disable = &rs780_dpm_disable, | ||
1250 | .set_power_state = &rs780_dpm_set_power_state, | ||
1251 | .display_configuration_changed = &rs780_dpm_display_configuration_changed, | ||
1252 | .fini = &rs780_dpm_fini, | ||
1253 | .get_sclk = &rs780_dpm_get_sclk, | ||
1254 | .get_mclk = &rs780_dpm_get_mclk, | ||
1255 | .print_power_state = &rs780_dpm_print_power_state, | ||
1256 | }, | ||
1245 | .pflip = { | 1257 | .pflip = { |
1246 | .pre_page_flip = &rs600_pre_page_flip, | 1258 | .pre_page_flip = &rs600_pre_page_flip, |
1247 | .page_flip = &rs600_page_flip, | 1259 | .page_flip = &rs600_page_flip, |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 0879f3be8cbc..a2faabd81c01 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -402,6 +402,18 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev); | |||
402 | u32 r600_get_xclk(struct radeon_device *rdev); | 402 | u32 r600_get_xclk(struct radeon_device *rdev); |
403 | uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev); | 403 | uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev); |
404 | int rv6xx_get_temp(struct radeon_device *rdev); | 404 | int rv6xx_get_temp(struct radeon_device *rdev); |
405 | /* rs780 dpm */ | ||
406 | int rs780_dpm_init(struct radeon_device *rdev); | ||
407 | int rs780_dpm_enable(struct radeon_device *rdev); | ||
408 | void rs780_dpm_disable(struct radeon_device *rdev); | ||
409 | int rs780_dpm_set_power_state(struct radeon_device *rdev); | ||
410 | void rs780_dpm_setup_asic(struct radeon_device *rdev); | ||
411 | void rs780_dpm_display_configuration_changed(struct radeon_device *rdev); | ||
412 | void rs780_dpm_fini(struct radeon_device *rdev); | ||
413 | u32 rs780_dpm_get_sclk(struct radeon_device *rdev, bool low); | ||
414 | u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low); | ||
415 | void rs780_dpm_print_power_state(struct radeon_device *rdev, | ||
416 | struct radeon_ps *ps); | ||
405 | 417 | ||
406 | /* uvd */ | 418 | /* uvd */ |
407 | int r600_uvd_init(struct radeon_device *rdev); | 419 | int r600_uvd_init(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 4f5422e6ccbb..853a8a2e141b 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -1030,6 +1030,13 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
1030 | { | 1030 | { |
1031 | /* enable dpm on rv6xx+ */ | 1031 | /* enable dpm on rv6xx+ */ |
1032 | switch (rdev->family) { | 1032 | switch (rdev->family) { |
1033 | case CHIP_RS780: | ||
1034 | case CHIP_RS880: | ||
1035 | if (radeon_dpm == 1) | ||
1036 | rdev->pm.pm_method = PM_METHOD_DPM; | ||
1037 | else | ||
1038 | rdev->pm.pm_method = PM_METHOD_PROFILE; | ||
1039 | break; | ||
1033 | default: | 1040 | default: |
1034 | /* default to profile method */ | 1041 | /* default to profile method */ |
1035 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 1042 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c new file mode 100644 index 000000000000..f594900160a0 --- /dev/null +++ b/drivers/gpu/drm/radeon/rs780_dpm.c | |||
@@ -0,0 +1,894 @@ | |||
1 | /* | ||
2 | * Copyright 2011 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: Alex Deucher | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | #include "radeon.h" | ||
27 | #include "rs780d.h" | ||
28 | #include "r600_dpm.h" | ||
29 | #include "rs780_dpm.h" | ||
30 | #include "atom.h" | ||
31 | |||
32 | static struct igp_ps *rs780_get_ps(struct radeon_ps *rps) | ||
33 | { | ||
34 | struct igp_ps *ps = rps->ps_priv; | ||
35 | |||
36 | return ps; | ||
37 | } | ||
38 | |||
39 | static struct igp_power_info *rs780_get_pi(struct radeon_device *rdev) | ||
40 | { | ||
41 | struct igp_power_info *pi = rdev->pm.dpm.priv; | ||
42 | |||
43 | return pi; | ||
44 | } | ||
45 | |||
46 | static void rs780_get_pm_mode_parameters(struct radeon_device *rdev) | ||
47 | { | ||
48 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
49 | struct radeon_mode_info *minfo = &rdev->mode_info; | ||
50 | struct drm_crtc *crtc; | ||
51 | struct radeon_crtc *radeon_crtc; | ||
52 | int i; | ||
53 | |||
54 | /* defaults */ | ||
55 | pi->crtc_id = 0; | ||
56 | pi->refresh_rate = 60; | ||
57 | |||
58 | for (i = 0; i < rdev->num_crtc; i++) { | ||
59 | crtc = (struct drm_crtc *)minfo->crtcs[i]; | ||
60 | if (crtc && crtc->enabled) { | ||
61 | radeon_crtc = to_radeon_crtc(crtc); | ||
62 | pi->crtc_id = radeon_crtc->crtc_id; | ||
63 | if (crtc->mode.htotal && crtc->mode.vtotal) | ||
64 | pi->refresh_rate = | ||
65 | (crtc->mode.clock * 1000) / | ||
66 | (crtc->mode.htotal * crtc->mode.vtotal); | ||
67 | break; | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static void rs780_voltage_scaling_enable(struct radeon_device *rdev, bool enable); | ||
73 | |||
74 | static int rs780_initialize_dpm_power_state(struct radeon_device *rdev) | ||
75 | { | ||
76 | struct atom_clock_dividers dividers; | ||
77 | struct igp_ps *default_state = rs780_get_ps(rdev->pm.dpm.boot_ps); | ||
78 | int i, ret; | ||
79 | |||
80 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, | ||
81 | default_state->sclk_low, false, ÷rs); | ||
82 | if (ret) | ||
83 | return ret; | ||
84 | |||
85 | r600_engine_clock_entry_set_reference_divider(rdev, 0, dividers.ref_div); | ||
86 | r600_engine_clock_entry_set_feedback_divider(rdev, 0, dividers.fb_div); | ||
87 | r600_engine_clock_entry_set_post_divider(rdev, 0, dividers.post_div); | ||
88 | |||
89 | if (dividers.enable_post_div) | ||
90 | r600_engine_clock_entry_enable_post_divider(rdev, 0, true); | ||
91 | else | ||
92 | r600_engine_clock_entry_enable_post_divider(rdev, 0, false); | ||
93 | |||
94 | r600_engine_clock_entry_set_step_time(rdev, 0, R600_SST_DFLT); | ||
95 | r600_engine_clock_entry_enable_pulse_skipping(rdev, 0, false); | ||
96 | |||
97 | r600_engine_clock_entry_enable(rdev, 0, true); | ||
98 | for (i = 1; i < R600_PM_NUMBER_OF_SCLKS; i++) | ||
99 | r600_engine_clock_entry_enable(rdev, i, false); | ||
100 | |||
101 | r600_enable_mclk_control(rdev, false); | ||
102 | r600_voltage_control_enable_pins(rdev, 0); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int rs780_initialize_dpm_parameters(struct radeon_device *rdev) | ||
108 | { | ||
109 | int ret = 0; | ||
110 | int i; | ||
111 | |||
112 | r600_set_bsp(rdev, R600_BSU_DFLT, R600_BSP_DFLT); | ||
113 | |||
114 | r600_set_at(rdev, 0, 0, 0, 0); | ||
115 | |||
116 | r600_set_git(rdev, R600_GICST_DFLT); | ||
117 | |||
118 | for (i = 0; i < R600_PM_NUMBER_OF_TC; i++) | ||
119 | r600_set_tc(rdev, i, 0, 0); | ||
120 | |||
121 | r600_select_td(rdev, R600_TD_DFLT); | ||
122 | r600_set_vrc(rdev, 0); | ||
123 | |||
124 | r600_set_tpu(rdev, R600_TPU_DFLT); | ||
125 | r600_set_tpc(rdev, R600_TPC_DFLT); | ||
126 | |||
127 | r600_set_sstu(rdev, R600_SSTU_DFLT); | ||
128 | r600_set_sst(rdev, R600_SST_DFLT); | ||
129 | |||
130 | r600_set_fctu(rdev, R600_FCTU_DFLT); | ||
131 | r600_set_fct(rdev, R600_FCT_DFLT); | ||
132 | |||
133 | r600_set_vddc3d_oorsu(rdev, R600_VDDC3DOORSU_DFLT); | ||
134 | r600_set_vddc3d_oorphc(rdev, R600_VDDC3DOORPHC_DFLT); | ||
135 | r600_set_vddc3d_oorsdc(rdev, R600_VDDC3DOORSDC_DFLT); | ||
136 | r600_set_ctxcgtt3d_rphc(rdev, R600_CTXCGTT3DRPHC_DFLT); | ||
137 | r600_set_ctxcgtt3d_rsdc(rdev, R600_CTXCGTT3DRSDC_DFLT); | ||
138 | |||
139 | r600_vid_rt_set_vru(rdev, R600_VRU_DFLT); | ||
140 | r600_vid_rt_set_vrt(rdev, R600_VOLTAGERESPONSETIME_DFLT); | ||
141 | r600_vid_rt_set_ssu(rdev, R600_SPLLSTEPUNIT_DFLT); | ||
142 | |||
143 | ret = rs780_initialize_dpm_power_state(rdev); | ||
144 | |||
145 | r600_power_level_set_voltage_index(rdev, R600_POWER_LEVEL_LOW, 0); | ||
146 | r600_power_level_set_voltage_index(rdev, R600_POWER_LEVEL_MEDIUM, 0); | ||
147 | r600_power_level_set_voltage_index(rdev, R600_POWER_LEVEL_HIGH, 0); | ||
148 | |||
149 | r600_power_level_set_mem_clock_index(rdev, R600_POWER_LEVEL_LOW, 0); | ||
150 | r600_power_level_set_mem_clock_index(rdev, R600_POWER_LEVEL_MEDIUM, 0); | ||
151 | r600_power_level_set_mem_clock_index(rdev, R600_POWER_LEVEL_HIGH, 0); | ||
152 | |||
153 | r600_power_level_set_eng_clock_index(rdev, R600_POWER_LEVEL_LOW, 0); | ||
154 | r600_power_level_set_eng_clock_index(rdev, R600_POWER_LEVEL_MEDIUM, 0); | ||
155 | r600_power_level_set_eng_clock_index(rdev, R600_POWER_LEVEL_HIGH, 0); | ||
156 | |||
157 | r600_power_level_set_watermark_id(rdev, R600_POWER_LEVEL_LOW, R600_DISPLAY_WATERMARK_HIGH); | ||
158 | r600_power_level_set_watermark_id(rdev, R600_POWER_LEVEL_MEDIUM, R600_DISPLAY_WATERMARK_HIGH); | ||
159 | r600_power_level_set_watermark_id(rdev, R600_POWER_LEVEL_HIGH, R600_DISPLAY_WATERMARK_HIGH); | ||
160 | |||
161 | r600_power_level_enable(rdev, R600_POWER_LEVEL_CTXSW, false); | ||
162 | r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, false); | ||
163 | r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, false); | ||
164 | r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, true); | ||
165 | |||
166 | r600_power_level_set_enter_index(rdev, R600_POWER_LEVEL_LOW); | ||
167 | |||
168 | r600_set_vrc(rdev, RS780_CGFTV_DFLT); | ||
169 | |||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | static void rs780_start_dpm(struct radeon_device *rdev) | ||
174 | { | ||
175 | r600_enable_sclk_control(rdev, false); | ||
176 | r600_enable_mclk_control(rdev, false); | ||
177 | |||
178 | r600_dynamicpm_enable(rdev, true); | ||
179 | |||
180 | radeon_wait_for_vblank(rdev, 0); | ||
181 | radeon_wait_for_vblank(rdev, 1); | ||
182 | |||
183 | r600_enable_spll_bypass(rdev, true); | ||
184 | r600_wait_for_spll_change(rdev); | ||
185 | r600_enable_spll_bypass(rdev, false); | ||
186 | r600_wait_for_spll_change(rdev); | ||
187 | |||
188 | r600_enable_spll_bypass(rdev, true); | ||
189 | r600_wait_for_spll_change(rdev); | ||
190 | r600_enable_spll_bypass(rdev, false); | ||
191 | r600_wait_for_spll_change(rdev); | ||
192 | |||
193 | r600_enable_sclk_control(rdev, true); | ||
194 | } | ||
195 | |||
196 | |||
197 | static void rs780_preset_ranges_slow_clk_fbdiv_en(struct radeon_device *rdev) | ||
198 | { | ||
199 | WREG32_P(FVTHROT_SLOW_CLK_FEEDBACK_DIV_REG1, RANGE_SLOW_CLK_FEEDBACK_DIV_EN, | ||
200 | ~RANGE_SLOW_CLK_FEEDBACK_DIV_EN); | ||
201 | |||
202 | WREG32_P(FVTHROT_SLOW_CLK_FEEDBACK_DIV_REG1, | ||
203 | RANGE0_SLOW_CLK_FEEDBACK_DIV(RS780_SLOWCLKFEEDBACKDIV_DFLT), | ||
204 | ~RANGE0_SLOW_CLK_FEEDBACK_DIV_MASK); | ||
205 | } | ||
206 | |||
207 | static void rs780_preset_starting_fbdiv(struct radeon_device *rdev) | ||
208 | { | ||
209 | u32 fbdiv = (RREG32(CG_SPLL_FUNC_CNTL) & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT; | ||
210 | |||
211 | WREG32_P(FVTHROT_FBDIV_REG1, STARTING_FEEDBACK_DIV(fbdiv), | ||
212 | ~STARTING_FEEDBACK_DIV_MASK); | ||
213 | |||
214 | WREG32_P(FVTHROT_FBDIV_REG2, FORCED_FEEDBACK_DIV(fbdiv), | ||
215 | ~FORCED_FEEDBACK_DIV_MASK); | ||
216 | |||
217 | WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, ~FORCE_FEEDBACK_DIV); | ||
218 | } | ||
219 | |||
220 | static void rs780_voltage_scaling_init(struct radeon_device *rdev) | ||
221 | { | ||
222 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
223 | struct drm_device *dev = rdev->ddev; | ||
224 | u32 fv_throt_pwm_fb_div_range[3]; | ||
225 | u32 fv_throt_pwm_range[4]; | ||
226 | |||
227 | if (dev->pdev->device == 0x9614) { | ||
228 | fv_throt_pwm_fb_div_range[0] = RS780D_FVTHROTPWMFBDIVRANGEREG0_DFLT; | ||
229 | fv_throt_pwm_fb_div_range[1] = RS780D_FVTHROTPWMFBDIVRANGEREG1_DFLT; | ||
230 | fv_throt_pwm_fb_div_range[2] = RS780D_FVTHROTPWMFBDIVRANGEREG2_DFLT; | ||
231 | } else if ((dev->pdev->device == 0x9714) || | ||
232 | (dev->pdev->device == 0x9715)) { | ||
233 | fv_throt_pwm_fb_div_range[0] = RS880D_FVTHROTPWMFBDIVRANGEREG0_DFLT; | ||
234 | fv_throt_pwm_fb_div_range[1] = RS880D_FVTHROTPWMFBDIVRANGEREG1_DFLT; | ||
235 | fv_throt_pwm_fb_div_range[2] = RS880D_FVTHROTPWMFBDIVRANGEREG2_DFLT; | ||
236 | } else { | ||
237 | fv_throt_pwm_fb_div_range[0] = RS780_FVTHROTPWMFBDIVRANGEREG0_DFLT; | ||
238 | fv_throt_pwm_fb_div_range[1] = RS780_FVTHROTPWMFBDIVRANGEREG1_DFLT; | ||
239 | fv_throt_pwm_fb_div_range[2] = RS780_FVTHROTPWMFBDIVRANGEREG2_DFLT; | ||
240 | } | ||
241 | |||
242 | if (pi->pwm_voltage_control) { | ||
243 | fv_throt_pwm_range[0] = pi->min_voltage; | ||
244 | fv_throt_pwm_range[1] = pi->min_voltage; | ||
245 | fv_throt_pwm_range[2] = pi->max_voltage; | ||
246 | fv_throt_pwm_range[3] = pi->max_voltage; | ||
247 | } else { | ||
248 | fv_throt_pwm_range[0] = pi->invert_pwm_required ? | ||
249 | RS780_FVTHROTPWMRANGE3_GPIO_DFLT : RS780_FVTHROTPWMRANGE0_GPIO_DFLT; | ||
250 | fv_throt_pwm_range[1] = pi->invert_pwm_required ? | ||
251 | RS780_FVTHROTPWMRANGE2_GPIO_DFLT : RS780_FVTHROTPWMRANGE1_GPIO_DFLT; | ||
252 | fv_throt_pwm_range[2] = pi->invert_pwm_required ? | ||
253 | RS780_FVTHROTPWMRANGE1_GPIO_DFLT : RS780_FVTHROTPWMRANGE2_GPIO_DFLT; | ||
254 | fv_throt_pwm_range[3] = pi->invert_pwm_required ? | ||
255 | RS780_FVTHROTPWMRANGE0_GPIO_DFLT : RS780_FVTHROTPWMRANGE3_GPIO_DFLT; | ||
256 | } | ||
257 | |||
258 | WREG32_P(FVTHROT_PWM_CTRL_REG0, | ||
259 | STARTING_PWM_HIGHTIME(pi->max_voltage), | ||
260 | ~STARTING_PWM_HIGHTIME_MASK); | ||
261 | |||
262 | WREG32_P(FVTHROT_PWM_CTRL_REG0, | ||
263 | NUMBER_OF_CYCLES_IN_PERIOD(pi->num_of_cycles_in_period), | ||
264 | ~NUMBER_OF_CYCLES_IN_PERIOD_MASK); | ||
265 | |||
266 | WREG32_P(FVTHROT_PWM_CTRL_REG0, FORCE_STARTING_PWM_HIGHTIME, | ||
267 | ~FORCE_STARTING_PWM_HIGHTIME); | ||
268 | |||
269 | if (pi->invert_pwm_required) | ||
270 | WREG32_P(FVTHROT_PWM_CTRL_REG0, INVERT_PWM_WAVEFORM, ~INVERT_PWM_WAVEFORM); | ||
271 | else | ||
272 | WREG32_P(FVTHROT_PWM_CTRL_REG0, 0, ~INVERT_PWM_WAVEFORM); | ||
273 | |||
274 | rs780_voltage_scaling_enable(rdev, true); | ||
275 | |||
276 | WREG32(FVTHROT_PWM_CTRL_REG1, | ||
277 | (MIN_PWM_HIGHTIME(pi->min_voltage) | | ||
278 | MAX_PWM_HIGHTIME(pi->max_voltage))); | ||
279 | |||
280 | WREG32(FVTHROT_PWM_US_REG0, RS780_FVTHROTPWMUSREG0_DFLT); | ||
281 | WREG32(FVTHROT_PWM_US_REG1, RS780_FVTHROTPWMUSREG1_DFLT); | ||
282 | WREG32(FVTHROT_PWM_DS_REG0, RS780_FVTHROTPWMDSREG0_DFLT); | ||
283 | WREG32(FVTHROT_PWM_DS_REG1, RS780_FVTHROTPWMDSREG1_DFLT); | ||
284 | |||
285 | WREG32_P(FVTHROT_PWM_FEEDBACK_DIV_REG1, | ||
286 | RANGE0_PWM_FEEDBACK_DIV(fv_throt_pwm_fb_div_range[0]), | ||
287 | ~RANGE0_PWM_FEEDBACK_DIV_MASK); | ||
288 | |||
289 | WREG32(FVTHROT_PWM_FEEDBACK_DIV_REG2, | ||
290 | (RANGE1_PWM_FEEDBACK_DIV(fv_throt_pwm_fb_div_range[1]) | | ||
291 | RANGE2_PWM_FEEDBACK_DIV(fv_throt_pwm_fb_div_range[2]))); | ||
292 | |||
293 | WREG32(FVTHROT_PWM_FEEDBACK_DIV_REG3, | ||
294 | (RANGE0_PWM(fv_throt_pwm_range[1]) | | ||
295 | RANGE1_PWM(fv_throt_pwm_range[2]))); | ||
296 | WREG32(FVTHROT_PWM_FEEDBACK_DIV_REG4, | ||
297 | (RANGE2_PWM(fv_throt_pwm_range[1]) | | ||
298 | RANGE3_PWM(fv_throt_pwm_range[2]))); | ||
299 | } | ||
300 | |||
301 | static void rs780_clk_scaling_enable(struct radeon_device *rdev, bool enable) | ||
302 | { | ||
303 | if (enable) | ||
304 | WREG32_P(FVTHROT_CNTRL_REG, ENABLE_FV_THROT | ENABLE_FV_UPDATE, | ||
305 | ~(ENABLE_FV_THROT | ENABLE_FV_UPDATE)); | ||
306 | else | ||
307 | WREG32_P(FVTHROT_CNTRL_REG, 0, | ||
308 | ~(ENABLE_FV_THROT | ENABLE_FV_UPDATE)); | ||
309 | } | ||
310 | |||
311 | static void rs780_voltage_scaling_enable(struct radeon_device *rdev, bool enable) | ||
312 | { | ||
313 | if (enable) | ||
314 | WREG32_P(FVTHROT_CNTRL_REG, ENABLE_FV_THROT_IO, ~ENABLE_FV_THROT_IO); | ||
315 | else | ||
316 | WREG32_P(FVTHROT_CNTRL_REG, 0, ~ENABLE_FV_THROT_IO); | ||
317 | } | ||
318 | |||
319 | static void rs780_set_engine_clock_wfc(struct radeon_device *rdev) | ||
320 | { | ||
321 | WREG32(FVTHROT_UTC0, RS780_FVTHROTUTC0_DFLT); | ||
322 | WREG32(FVTHROT_UTC1, RS780_FVTHROTUTC1_DFLT); | ||
323 | WREG32(FVTHROT_UTC2, RS780_FVTHROTUTC2_DFLT); | ||
324 | WREG32(FVTHROT_UTC3, RS780_FVTHROTUTC3_DFLT); | ||
325 | WREG32(FVTHROT_UTC4, RS780_FVTHROTUTC4_DFLT); | ||
326 | |||
327 | WREG32(FVTHROT_DTC0, RS780_FVTHROTDTC0_DFLT); | ||
328 | WREG32(FVTHROT_DTC1, RS780_FVTHROTDTC1_DFLT); | ||
329 | WREG32(FVTHROT_DTC2, RS780_FVTHROTDTC2_DFLT); | ||
330 | WREG32(FVTHROT_DTC3, RS780_FVTHROTDTC3_DFLT); | ||
331 | WREG32(FVTHROT_DTC4, RS780_FVTHROTDTC4_DFLT); | ||
332 | } | ||
333 | |||
334 | static void rs780_set_engine_clock_sc(struct radeon_device *rdev) | ||
335 | { | ||
336 | WREG32_P(FVTHROT_FBDIV_REG2, | ||
337 | FB_DIV_TIMER_VAL(RS780_FBDIVTIMERVAL_DFLT), | ||
338 | ~FB_DIV_TIMER_VAL_MASK); | ||
339 | |||
340 | WREG32_P(FVTHROT_CNTRL_REG, | ||
341 | REFRESH_RATE_DIVISOR(0) | MINIMUM_CIP(0xf), | ||
342 | ~(REFRESH_RATE_DIVISOR_MASK | MINIMUM_CIP_MASK)); | ||
343 | } | ||
344 | |||
345 | static void rs780_set_engine_clock_tdc(struct radeon_device *rdev) | ||
346 | { | ||
347 | WREG32_P(FVTHROT_CNTRL_REG, 0, ~(FORCE_TREND_SEL | TREND_SEL_MODE)); | ||
348 | } | ||
349 | |||
350 | static void rs780_set_engine_clock_ssc(struct radeon_device *rdev) | ||
351 | { | ||
352 | WREG32(FVTHROT_FB_US_REG0, RS780_FVTHROTFBUSREG0_DFLT); | ||
353 | WREG32(FVTHROT_FB_US_REG1, RS780_FVTHROTFBUSREG1_DFLT); | ||
354 | WREG32(FVTHROT_FB_DS_REG0, RS780_FVTHROTFBDSREG0_DFLT); | ||
355 | WREG32(FVTHROT_FB_DS_REG1, RS780_FVTHROTFBDSREG1_DFLT); | ||
356 | |||
357 | WREG32_P(FVTHROT_FBDIV_REG1, MAX_FEEDBACK_STEP(1), ~MAX_FEEDBACK_STEP_MASK); | ||
358 | } | ||
359 | |||
360 | static void rs780_program_at(struct radeon_device *rdev) | ||
361 | { | ||
362 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
363 | |||
364 | WREG32(FVTHROT_TARGET_REG, 30000000 / pi->refresh_rate); | ||
365 | WREG32(FVTHROT_CB1, 1000000 * 5 / pi->refresh_rate); | ||
366 | WREG32(FVTHROT_CB2, 1000000 * 10 / pi->refresh_rate); | ||
367 | WREG32(FVTHROT_CB3, 1000000 * 30 / pi->refresh_rate); | ||
368 | WREG32(FVTHROT_CB4, 1000000 * 50 / pi->refresh_rate); | ||
369 | } | ||
370 | |||
371 | static void rs780_disable_vbios_powersaving(struct radeon_device *rdev) | ||
372 | { | ||
373 | WREG32_P(CG_INTGFX_MISC, 0, ~0xFFF00000); | ||
374 | } | ||
375 | |||
376 | static void rs780_force_voltage_to_high(struct radeon_device *rdev) | ||
377 | { | ||
378 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
379 | struct igp_ps *current_state = rs780_get_ps(rdev->pm.dpm.current_ps); | ||
380 | |||
381 | if ((current_state->max_voltage == RS780_VDDC_LEVEL_HIGH) && | ||
382 | (current_state->min_voltage == RS780_VDDC_LEVEL_HIGH)) | ||
383 | return; | ||
384 | |||
385 | WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL); | ||
386 | |||
387 | udelay(1); | ||
388 | |||
389 | WREG32_P(FVTHROT_PWM_CTRL_REG0, | ||
390 | STARTING_PWM_HIGHTIME(pi->max_voltage), | ||
391 | ~STARTING_PWM_HIGHTIME_MASK); | ||
392 | |||
393 | WREG32_P(FVTHROT_PWM_CTRL_REG0, | ||
394 | FORCE_STARTING_PWM_HIGHTIME, ~FORCE_STARTING_PWM_HIGHTIME); | ||
395 | |||
396 | WREG32_P(FVTHROT_PWM_FEEDBACK_DIV_REG1, 0, | ||
397 | ~RANGE_PWM_FEEDBACK_DIV_EN); | ||
398 | |||
399 | udelay(1); | ||
400 | |||
401 | WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL); | ||
402 | } | ||
403 | |||
404 | static int rs780_set_engine_clock_scaling(struct radeon_device *rdev) | ||
405 | { | ||
406 | struct atom_clock_dividers min_dividers, max_dividers, current_max_dividers; | ||
407 | struct igp_ps *new_state = rs780_get_ps(rdev->pm.dpm.requested_ps); | ||
408 | struct igp_ps *old_state = rs780_get_ps(rdev->pm.dpm.current_ps); | ||
409 | int ret; | ||
410 | |||
411 | if ((new_state->sclk_high == old_state->sclk_high) && | ||
412 | (new_state->sclk_low == old_state->sclk_low)) | ||
413 | return 0; | ||
414 | |||
415 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, | ||
416 | new_state->sclk_low, false, &min_dividers); | ||
417 | if (ret) | ||
418 | return ret; | ||
419 | |||
420 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, | ||
421 | new_state->sclk_high, false, &max_dividers); | ||
422 | if (ret) | ||
423 | return ret; | ||
424 | |||
425 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, | ||
426 | old_state->sclk_high, false, ¤t_max_dividers); | ||
427 | if (ret) | ||
428 | return ret; | ||
429 | |||
430 | WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL); | ||
431 | |||
432 | WREG32_P(FVTHROT_FBDIV_REG2, FORCED_FEEDBACK_DIV(max_dividers.fb_div), | ||
433 | ~FORCED_FEEDBACK_DIV_MASK); | ||
434 | WREG32_P(FVTHROT_FBDIV_REG1, STARTING_FEEDBACK_DIV(max_dividers.fb_div), | ||
435 | ~STARTING_FEEDBACK_DIV_MASK); | ||
436 | WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, ~FORCE_FEEDBACK_DIV); | ||
437 | |||
438 | udelay(100); | ||
439 | |||
440 | WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL); | ||
441 | |||
442 | if (max_dividers.fb_div > min_dividers.fb_div) { | ||
443 | WREG32_P(FVTHROT_FBDIV_REG0, | ||
444 | MIN_FEEDBACK_DIV(min_dividers.fb_div) | | ||
445 | MAX_FEEDBACK_DIV(max_dividers.fb_div), | ||
446 | ~(MIN_FEEDBACK_DIV_MASK | MAX_FEEDBACK_DIV_MASK)); | ||
447 | |||
448 | WREG32_P(FVTHROT_FBDIV_REG1, 0, ~FORCE_FEEDBACK_DIV); | ||
449 | } | ||
450 | |||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static void rs780_set_engine_clock_spc(struct radeon_device *rdev) | ||
455 | { | ||
456 | struct igp_ps *new_state = rs780_get_ps(rdev->pm.dpm.requested_ps); | ||
457 | struct igp_ps *old_state = rs780_get_ps(rdev->pm.dpm.current_ps); | ||
458 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
459 | |||
460 | if ((new_state->sclk_high == old_state->sclk_high) && | ||
461 | (new_state->sclk_low == old_state->sclk_low)) | ||
462 | return; | ||
463 | |||
464 | if (pi->crtc_id == 0) | ||
465 | WREG32_P(CG_INTGFX_MISC, 0, ~FVTHROT_VBLANK_SEL); | ||
466 | else | ||
467 | WREG32_P(CG_INTGFX_MISC, FVTHROT_VBLANK_SEL, ~FVTHROT_VBLANK_SEL); | ||
468 | |||
469 | } | ||
470 | |||
471 | static void rs780_activate_engine_clk_scaling(struct radeon_device *rdev) | ||
472 | { | ||
473 | struct igp_ps *new_state = rs780_get_ps(rdev->pm.dpm.requested_ps); | ||
474 | struct igp_ps *old_state = rs780_get_ps(rdev->pm.dpm.current_ps); | ||
475 | |||
476 | if ((new_state->sclk_high == old_state->sclk_high) && | ||
477 | (new_state->sclk_low == old_state->sclk_low)) | ||
478 | return; | ||
479 | |||
480 | rs780_clk_scaling_enable(rdev, true); | ||
481 | } | ||
482 | |||
483 | static u32 rs780_get_voltage_for_vddc_level(struct radeon_device *rdev, | ||
484 | enum rs780_vddc_level vddc) | ||
485 | { | ||
486 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
487 | |||
488 | if (vddc == RS780_VDDC_LEVEL_HIGH) | ||
489 | return pi->max_voltage; | ||
490 | else if (vddc == RS780_VDDC_LEVEL_LOW) | ||
491 | return pi->min_voltage; | ||
492 | else | ||
493 | return pi->max_voltage; | ||
494 | } | ||
495 | |||
496 | static void rs780_enable_voltage_scaling(struct radeon_device *rdev) | ||
497 | { | ||
498 | struct igp_ps *new_state = rs780_get_ps(rdev->pm.dpm.requested_ps); | ||
499 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
500 | enum rs780_vddc_level vddc_high, vddc_low; | ||
501 | |||
502 | udelay(100); | ||
503 | |||
504 | if ((new_state->max_voltage == RS780_VDDC_LEVEL_HIGH) && | ||
505 | (new_state->min_voltage == RS780_VDDC_LEVEL_HIGH)) | ||
506 | return; | ||
507 | |||
508 | vddc_high = rs780_get_voltage_for_vddc_level(rdev, | ||
509 | new_state->max_voltage); | ||
510 | vddc_low = rs780_get_voltage_for_vddc_level(rdev, | ||
511 | new_state->min_voltage); | ||
512 | |||
513 | WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL); | ||
514 | |||
515 | udelay(1); | ||
516 | if (vddc_high > vddc_low) { | ||
517 | WREG32_P(FVTHROT_PWM_FEEDBACK_DIV_REG1, | ||
518 | RANGE_PWM_FEEDBACK_DIV_EN, ~RANGE_PWM_FEEDBACK_DIV_EN); | ||
519 | |||
520 | WREG32_P(FVTHROT_PWM_CTRL_REG0, 0, ~FORCE_STARTING_PWM_HIGHTIME); | ||
521 | } else if (vddc_high == vddc_low) { | ||
522 | if (pi->max_voltage != vddc_high) { | ||
523 | WREG32_P(FVTHROT_PWM_CTRL_REG0, | ||
524 | STARTING_PWM_HIGHTIME(vddc_high), | ||
525 | ~STARTING_PWM_HIGHTIME_MASK); | ||
526 | |||
527 | WREG32_P(FVTHROT_PWM_CTRL_REG0, | ||
528 | FORCE_STARTING_PWM_HIGHTIME, | ||
529 | ~FORCE_STARTING_PWM_HIGHTIME); | ||
530 | } | ||
531 | } | ||
532 | |||
533 | WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL); | ||
534 | } | ||
535 | |||
536 | int rs780_dpm_enable(struct radeon_device *rdev) | ||
537 | { | ||
538 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
539 | |||
540 | rs780_get_pm_mode_parameters(rdev); | ||
541 | rs780_disable_vbios_powersaving(rdev); | ||
542 | |||
543 | if (r600_dynamicpm_enabled(rdev)) | ||
544 | return -EINVAL; | ||
545 | if (rs780_initialize_dpm_parameters(rdev)) | ||
546 | return -EINVAL; | ||
547 | rs780_start_dpm(rdev); | ||
548 | |||
549 | rs780_preset_ranges_slow_clk_fbdiv_en(rdev); | ||
550 | rs780_preset_starting_fbdiv(rdev); | ||
551 | if (pi->voltage_control) | ||
552 | rs780_voltage_scaling_init(rdev); | ||
553 | rs780_clk_scaling_enable(rdev, true); | ||
554 | rs780_set_engine_clock_sc(rdev); | ||
555 | rs780_set_engine_clock_wfc(rdev); | ||
556 | rs780_program_at(rdev); | ||
557 | rs780_set_engine_clock_tdc(rdev); | ||
558 | rs780_set_engine_clock_ssc(rdev); | ||
559 | |||
560 | if (pi->gfx_clock_gating) | ||
561 | r600_gfx_clockgating_enable(rdev, true); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | void rs780_dpm_disable(struct radeon_device *rdev) | ||
567 | { | ||
568 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
569 | |||
570 | r600_dynamicpm_enable(rdev, false); | ||
571 | |||
572 | rs780_clk_scaling_enable(rdev, false); | ||
573 | rs780_voltage_scaling_enable(rdev, false); | ||
574 | |||
575 | if (pi->gfx_clock_gating) | ||
576 | r600_gfx_clockgating_enable(rdev, false); | ||
577 | } | ||
578 | |||
579 | int rs780_dpm_set_power_state(struct radeon_device *rdev) | ||
580 | { | ||
581 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
582 | |||
583 | rs780_get_pm_mode_parameters(rdev); | ||
584 | |||
585 | if (pi->voltage_control) { | ||
586 | rs780_force_voltage_to_high(rdev); | ||
587 | mdelay(5); | ||
588 | } | ||
589 | |||
590 | rs780_set_engine_clock_scaling(rdev); | ||
591 | rs780_set_engine_clock_spc(rdev); | ||
592 | |||
593 | rs780_activate_engine_clk_scaling(rdev); | ||
594 | |||
595 | if (pi->voltage_control) | ||
596 | rs780_enable_voltage_scaling(rdev); | ||
597 | |||
598 | return 0; | ||
599 | } | ||
600 | |||
601 | void rs780_dpm_setup_asic(struct radeon_device *rdev) | ||
602 | { | ||
603 | |||
604 | } | ||
605 | |||
606 | void rs780_dpm_display_configuration_changed(struct radeon_device *rdev) | ||
607 | { | ||
608 | rs780_get_pm_mode_parameters(rdev); | ||
609 | rs780_program_at(rdev); | ||
610 | } | ||
611 | |||
612 | union igp_info { | ||
613 | struct _ATOM_INTEGRATED_SYSTEM_INFO info; | ||
614 | struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; | ||
615 | }; | ||
616 | |||
617 | union power_info { | ||
618 | struct _ATOM_POWERPLAY_INFO info; | ||
619 | struct _ATOM_POWERPLAY_INFO_V2 info_2; | ||
620 | struct _ATOM_POWERPLAY_INFO_V3 info_3; | ||
621 | struct _ATOM_PPLIB_POWERPLAYTABLE pplib; | ||
622 | struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; | ||
623 | struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; | ||
624 | }; | ||
625 | |||
626 | union pplib_clock_info { | ||
627 | struct _ATOM_PPLIB_R600_CLOCK_INFO r600; | ||
628 | struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; | ||
629 | struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; | ||
630 | struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; | ||
631 | }; | ||
632 | |||
633 | union pplib_power_state { | ||
634 | struct _ATOM_PPLIB_STATE v1; | ||
635 | struct _ATOM_PPLIB_STATE_V2 v2; | ||
636 | }; | ||
637 | |||
638 | static void rs780_parse_pplib_non_clock_info(struct radeon_device *rdev, | ||
639 | struct radeon_ps *rps, | ||
640 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, | ||
641 | u8 table_rev) | ||
642 | { | ||
643 | rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); | ||
644 | rps->class = le16_to_cpu(non_clock_info->usClassification); | ||
645 | rps->class2 = le16_to_cpu(non_clock_info->usClassification2); | ||
646 | |||
647 | if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { | ||
648 | rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); | ||
649 | rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); | ||
650 | } else if (r600_is_uvd_state(rps->class, rps->class2)) { | ||
651 | rps->vclk = RS780_DEFAULT_VCLK_FREQ; | ||
652 | rps->dclk = RS780_DEFAULT_DCLK_FREQ; | ||
653 | } else { | ||
654 | rps->vclk = 0; | ||
655 | rps->dclk = 0; | ||
656 | } | ||
657 | |||
658 | if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) | ||
659 | rdev->pm.dpm.boot_ps = rps; | ||
660 | if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) | ||
661 | rdev->pm.dpm.uvd_ps = rps; | ||
662 | } | ||
663 | |||
664 | static void rs780_parse_pplib_clock_info(struct radeon_device *rdev, | ||
665 | struct radeon_ps *rps, | ||
666 | union pplib_clock_info *clock_info) | ||
667 | { | ||
668 | struct igp_ps *ps = rs780_get_ps(rps); | ||
669 | u32 sclk; | ||
670 | |||
671 | sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow); | ||
672 | sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; | ||
673 | ps->sclk_low = sclk; | ||
674 | sclk = le16_to_cpu(clock_info->rs780.usHighEngineClockLow); | ||
675 | sclk |= clock_info->rs780.ucHighEngineClockHigh << 16; | ||
676 | ps->sclk_high = sclk; | ||
677 | switch (le16_to_cpu(clock_info->rs780.usVDDC)) { | ||
678 | case ATOM_PPLIB_RS780_VOLTAGE_NONE: | ||
679 | default: | ||
680 | ps->min_voltage = RS780_VDDC_LEVEL_UNKNOWN; | ||
681 | ps->max_voltage = RS780_VDDC_LEVEL_UNKNOWN; | ||
682 | break; | ||
683 | case ATOM_PPLIB_RS780_VOLTAGE_LOW: | ||
684 | ps->min_voltage = RS780_VDDC_LEVEL_LOW; | ||
685 | ps->max_voltage = RS780_VDDC_LEVEL_LOW; | ||
686 | break; | ||
687 | case ATOM_PPLIB_RS780_VOLTAGE_HIGH: | ||
688 | ps->min_voltage = RS780_VDDC_LEVEL_HIGH; | ||
689 | ps->max_voltage = RS780_VDDC_LEVEL_HIGH; | ||
690 | break; | ||
691 | case ATOM_PPLIB_RS780_VOLTAGE_VARIABLE: | ||
692 | ps->min_voltage = RS780_VDDC_LEVEL_LOW; | ||
693 | ps->max_voltage = RS780_VDDC_LEVEL_HIGH; | ||
694 | break; | ||
695 | } | ||
696 | ps->flags = le32_to_cpu(clock_info->rs780.ulFlags); | ||
697 | |||
698 | if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { | ||
699 | ps->sclk_low = rdev->clock.default_sclk; | ||
700 | ps->sclk_high = rdev->clock.default_sclk; | ||
701 | ps->min_voltage = RS780_VDDC_LEVEL_HIGH; | ||
702 | ps->max_voltage = RS780_VDDC_LEVEL_HIGH; | ||
703 | } | ||
704 | } | ||
705 | |||
706 | static int rs780_parse_power_table(struct radeon_device *rdev) | ||
707 | { | ||
708 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
709 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; | ||
710 | union pplib_power_state *power_state; | ||
711 | int i; | ||
712 | union pplib_clock_info *clock_info; | ||
713 | union power_info *power_info; | ||
714 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); | ||
715 | u16 data_offset; | ||
716 | u8 frev, crev; | ||
717 | struct igp_ps *ps; | ||
718 | |||
719 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, | ||
720 | &frev, &crev, &data_offset)) | ||
721 | return -EINVAL; | ||
722 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); | ||
723 | |||
724 | rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * | ||
725 | power_info->pplib.ucNumStates, GFP_KERNEL); | ||
726 | if (!rdev->pm.dpm.ps) | ||
727 | return -ENOMEM; | ||
728 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
729 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
730 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
731 | |||
732 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { | ||
733 | power_state = (union pplib_power_state *) | ||
734 | (mode_info->atom_context->bios + data_offset + | ||
735 | le16_to_cpu(power_info->pplib.usStateArrayOffset) + | ||
736 | i * power_info->pplib.ucStateEntrySize); | ||
737 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) | ||
738 | (mode_info->atom_context->bios + data_offset + | ||
739 | le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + | ||
740 | (power_state->v1.ucNonClockStateIndex * | ||
741 | power_info->pplib.ucNonClockSize)); | ||
742 | if (power_info->pplib.ucStateEntrySize - 1) { | ||
743 | clock_info = (union pplib_clock_info *) | ||
744 | (mode_info->atom_context->bios + data_offset + | ||
745 | le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + | ||
746 | (power_state->v1.ucClockStateIndices[0] * | ||
747 | power_info->pplib.ucClockInfoSize)); | ||
748 | ps = kzalloc(sizeof(struct igp_ps), GFP_KERNEL); | ||
749 | if (ps == NULL) { | ||
750 | kfree(rdev->pm.dpm.ps); | ||
751 | return -ENOMEM; | ||
752 | } | ||
753 | rdev->pm.dpm.ps[i].ps_priv = ps; | ||
754 | rs780_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], | ||
755 | non_clock_info, | ||
756 | power_info->pplib.ucNonClockSize); | ||
757 | rs780_parse_pplib_clock_info(rdev, | ||
758 | &rdev->pm.dpm.ps[i], | ||
759 | clock_info); | ||
760 | } | ||
761 | } | ||
762 | rdev->pm.dpm.num_ps = power_info->pplib.ucNumStates; | ||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | int rs780_dpm_init(struct radeon_device *rdev) | ||
767 | { | ||
768 | struct igp_power_info *pi; | ||
769 | int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); | ||
770 | union igp_info *info; | ||
771 | u16 data_offset; | ||
772 | u8 frev, crev; | ||
773 | int ret; | ||
774 | |||
775 | pi = kzalloc(sizeof(struct igp_power_info), GFP_KERNEL); | ||
776 | if (pi == NULL) | ||
777 | return -ENOMEM; | ||
778 | rdev->pm.dpm.priv = pi; | ||
779 | |||
780 | ret = rs780_parse_power_table(rdev); | ||
781 | if (ret) | ||
782 | return ret; | ||
783 | |||
784 | pi->voltage_control = false; | ||
785 | pi->gfx_clock_gating = true; | ||
786 | |||
787 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, | ||
788 | &frev, &crev, &data_offset)) { | ||
789 | info = (union igp_info *)(rdev->mode_info.atom_context->bios + data_offset); | ||
790 | |||
791 | /* Get various system informations from bios */ | ||
792 | switch (crev) { | ||
793 | case 1: | ||
794 | pi->num_of_cycles_in_period = | ||
795 | info->info.ucNumberOfCyclesInPeriod; | ||
796 | pi->num_of_cycles_in_period |= | ||
797 | info->info.ucNumberOfCyclesInPeriodHi << 8; | ||
798 | pi->invert_pwm_required = | ||
799 | (pi->num_of_cycles_in_period & 0x8000) ? true : false; | ||
800 | pi->boot_voltage = info->info.ucStartingPWM_HighTime; | ||
801 | pi->max_voltage = info->info.ucMaxNBVoltage; | ||
802 | pi->max_voltage |= info->info.ucMaxNBVoltageHigh << 8; | ||
803 | pi->min_voltage = info->info.ucMinNBVoltage; | ||
804 | pi->min_voltage |= info->info.ucMinNBVoltageHigh << 8; | ||
805 | pi->inter_voltage_low = | ||
806 | le16_to_cpu(info->info.usInterNBVoltageLow); | ||
807 | pi->inter_voltage_high = | ||
808 | le16_to_cpu(info->info.usInterNBVoltageHigh); | ||
809 | pi->voltage_control = true; | ||
810 | pi->bootup_uma_clk = info->info.usK8MemoryClock * 100; | ||
811 | break; | ||
812 | case 2: | ||
813 | pi->num_of_cycles_in_period = | ||
814 | le16_to_cpu(info->info_2.usNumberOfCyclesInPeriod); | ||
815 | pi->invert_pwm_required = | ||
816 | (pi->num_of_cycles_in_period & 0x8000) ? true : false; | ||
817 | pi->boot_voltage = | ||
818 | le16_to_cpu(info->info_2.usBootUpNBVoltage); | ||
819 | pi->max_voltage = | ||
820 | le16_to_cpu(info->info_2.usMaxNBVoltage); | ||
821 | pi->min_voltage = | ||
822 | le16_to_cpu(info->info_2.usMinNBVoltage); | ||
823 | pi->system_config = | ||
824 | le32_to_cpu(info->info_2.ulSystemConfig); | ||
825 | pi->pwm_voltage_control = | ||
826 | (pi->system_config & 0x4) ? true : false; | ||
827 | pi->voltage_control = true; | ||
828 | pi->bootup_uma_clk = le32_to_cpu(info->info_2.ulBootUpUMAClock); | ||
829 | break; | ||
830 | default: | ||
831 | DRM_ERROR("No integrated system info for your GPU\n"); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | if (pi->min_voltage > pi->max_voltage) | ||
835 | pi->voltage_control = false; | ||
836 | if (pi->pwm_voltage_control) { | ||
837 | if ((pi->num_of_cycles_in_period == 0) || | ||
838 | (pi->max_voltage == 0) || | ||
839 | (pi->min_voltage == 0)) | ||
840 | pi->voltage_control = false; | ||
841 | } else { | ||
842 | if ((pi->num_of_cycles_in_period == 0) || | ||
843 | (pi->max_voltage == 0)) | ||
844 | pi->voltage_control = false; | ||
845 | } | ||
846 | |||
847 | return 0; | ||
848 | } | ||
849 | radeon_dpm_fini(rdev); | ||
850 | return -EINVAL; | ||
851 | } | ||
852 | |||
853 | void rs780_dpm_print_power_state(struct radeon_device *rdev, | ||
854 | struct radeon_ps *rps) | ||
855 | { | ||
856 | struct igp_ps *ps = rs780_get_ps(rps); | ||
857 | |||
858 | r600_dpm_print_class_info(rps->class, rps->class2); | ||
859 | r600_dpm_print_cap_info(rps->caps); | ||
860 | printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); | ||
861 | printk("\t\tpower level 0 sclk: %u vddc_index: %d\n", | ||
862 | ps->sclk_low, ps->min_voltage); | ||
863 | printk("\t\tpower level 1 sclk: %u vddc_index: %d\n", | ||
864 | ps->sclk_high, ps->max_voltage); | ||
865 | r600_dpm_print_ps_status(rdev, rps); | ||
866 | } | ||
867 | |||
868 | void rs780_dpm_fini(struct radeon_device *rdev) | ||
869 | { | ||
870 | int i; | ||
871 | |||
872 | for (i = 0; i < rdev->pm.dpm.num_ps; i++) { | ||
873 | kfree(rdev->pm.dpm.ps[i].ps_priv); | ||
874 | } | ||
875 | kfree(rdev->pm.dpm.ps); | ||
876 | kfree(rdev->pm.dpm.priv); | ||
877 | } | ||
878 | |||
879 | u32 rs780_dpm_get_sclk(struct radeon_device *rdev, bool low) | ||
880 | { | ||
881 | struct igp_ps *requested_state = rs780_get_ps(rdev->pm.dpm.requested_ps); | ||
882 | |||
883 | if (low) | ||
884 | return requested_state->sclk_low; | ||
885 | else | ||
886 | return requested_state->sclk_high; | ||
887 | } | ||
888 | |||
889 | u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low) | ||
890 | { | ||
891 | struct igp_power_info *pi = rs780_get_pi(rdev); | ||
892 | |||
893 | return pi->bootup_uma_clk; | ||
894 | } | ||
diff --git a/drivers/gpu/drm/radeon/rs780_dpm.h b/drivers/gpu/drm/radeon/rs780_dpm.h new file mode 100644 index 000000000000..47a40b14fa43 --- /dev/null +++ b/drivers/gpu/drm/radeon/rs780_dpm.h | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * Copyright 2011 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 | */ | ||
23 | #ifndef __RS780_DPM_H__ | ||
24 | #define __RS780_DPM_H__ | ||
25 | |||
26 | enum rs780_vddc_level { | ||
27 | RS780_VDDC_LEVEL_UNKNOWN = 0, | ||
28 | RS780_VDDC_LEVEL_LOW = 1, | ||
29 | RS780_VDDC_LEVEL_HIGH = 2, | ||
30 | }; | ||
31 | |||
32 | struct igp_power_info { | ||
33 | /* flags */ | ||
34 | bool invert_pwm_required; | ||
35 | bool pwm_voltage_control; | ||
36 | bool voltage_control; | ||
37 | bool gfx_clock_gating; | ||
38 | /* stored values */ | ||
39 | u32 system_config; | ||
40 | u32 bootup_uma_clk; | ||
41 | u16 max_voltage; | ||
42 | u16 min_voltage; | ||
43 | u16 boot_voltage; | ||
44 | u16 inter_voltage_low; | ||
45 | u16 inter_voltage_high; | ||
46 | u16 num_of_cycles_in_period; | ||
47 | /* variable */ | ||
48 | int crtc_id; | ||
49 | int refresh_rate; | ||
50 | }; | ||
51 | |||
52 | struct igp_ps { | ||
53 | enum rs780_vddc_level min_voltage; | ||
54 | enum rs780_vddc_level max_voltage; | ||
55 | u32 sclk_low; | ||
56 | u32 sclk_high; | ||
57 | u32 flags; | ||
58 | }; | ||
59 | |||
60 | #define RS780_CGFTV_DFLT 0x0303000f | ||
61 | #define RS780_FBDIVTIMERVAL_DFLT 0x2710 | ||
62 | |||
63 | #define RS780_FVTHROTUTC0_DFLT 0x04010040 | ||
64 | #define RS780_FVTHROTUTC1_DFLT 0x04010040 | ||
65 | #define RS780_FVTHROTUTC2_DFLT 0x04010040 | ||
66 | #define RS780_FVTHROTUTC3_DFLT 0x04010040 | ||
67 | #define RS780_FVTHROTUTC4_DFLT 0x04010040 | ||
68 | |||
69 | #define RS780_FVTHROTDTC0_DFLT 0x04010040 | ||
70 | #define RS780_FVTHROTDTC1_DFLT 0x04010040 | ||
71 | #define RS780_FVTHROTDTC2_DFLT 0x04010040 | ||
72 | #define RS780_FVTHROTDTC3_DFLT 0x04010040 | ||
73 | #define RS780_FVTHROTDTC4_DFLT 0x04010040 | ||
74 | |||
75 | #define RS780_FVTHROTFBUSREG0_DFLT 0x00001001 | ||
76 | #define RS780_FVTHROTFBUSREG1_DFLT 0x00002002 | ||
77 | #define RS780_FVTHROTFBDSREG0_DFLT 0x00004001 | ||
78 | #define RS780_FVTHROTFBDSREG1_DFLT 0x00020010 | ||
79 | |||
80 | #define RS780_FVTHROTPWMUSREG0_DFLT 0x00002001 | ||
81 | #define RS780_FVTHROTPWMUSREG1_DFLT 0x00004003 | ||
82 | #define RS780_FVTHROTPWMDSREG0_DFLT 0x00002001 | ||
83 | #define RS780_FVTHROTPWMDSREG1_DFLT 0x00004003 | ||
84 | |||
85 | #define RS780_FVTHROTPWMFBDIVRANGEREG0_DFLT 0x37 | ||
86 | #define RS780_FVTHROTPWMFBDIVRANGEREG1_DFLT 0x4b | ||
87 | #define RS780_FVTHROTPWMFBDIVRANGEREG2_DFLT 0x8b | ||
88 | |||
89 | #define RS780D_FVTHROTPWMFBDIVRANGEREG0_DFLT 0x8b | ||
90 | #define RS780D_FVTHROTPWMFBDIVRANGEREG1_DFLT 0x8c | ||
91 | #define RS780D_FVTHROTPWMFBDIVRANGEREG2_DFLT 0xb5 | ||
92 | |||
93 | #define RS880D_FVTHROTPWMFBDIVRANGEREG0_DFLT 0x8d | ||
94 | #define RS880D_FVTHROTPWMFBDIVRANGEREG1_DFLT 0x8e | ||
95 | #define RS880D_FVTHROTPWMFBDIVRANGEREG2_DFLT 0xBa | ||
96 | |||
97 | #define RS780_FVTHROTPWMRANGE0_GPIO_DFLT 0x1a | ||
98 | #define RS780_FVTHROTPWMRANGE1_GPIO_DFLT 0x1a | ||
99 | #define RS780_FVTHROTPWMRANGE2_GPIO_DFLT 0x0 | ||
100 | #define RS780_FVTHROTPWMRANGE3_GPIO_DFLT 0x0 | ||
101 | |||
102 | #define RS780_SLOWCLKFEEDBACKDIV_DFLT 110 | ||
103 | |||
104 | #define RS780_CGCLKGATING_DFLT 0x0000E204 | ||
105 | |||
106 | #define RS780_DEFAULT_VCLK_FREQ 53300 /* 10 khz */ | ||
107 | #define RS780_DEFAULT_DCLK_FREQ 40000 /* 10 khz */ | ||
108 | |||
109 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/rs780d.h b/drivers/gpu/drm/radeon/rs780d.h new file mode 100644 index 000000000000..b1142ed1c628 --- /dev/null +++ b/drivers/gpu/drm/radeon/rs780d.h | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * Copyright 2011 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 | */ | ||
23 | #ifndef __RS780D_H__ | ||
24 | #define __RS780D_H__ | ||
25 | |||
26 | #define CG_SPLL_FUNC_CNTL 0x600 | ||
27 | # define SPLL_RESET (1 << 0) | ||
28 | # define SPLL_SLEEP (1 << 1) | ||
29 | # define SPLL_REF_DIV(x) ((x) << 2) | ||
30 | # define SPLL_REF_DIV_MASK (7 << 2) | ||
31 | # define SPLL_FB_DIV(x) ((x) << 5) | ||
32 | # define SPLL_FB_DIV_MASK (0xff << 2) | ||
33 | # define SPLL_FB_DIV_SHIFT 2 | ||
34 | # define SPLL_PULSEEN (1 << 13) | ||
35 | # define SPLL_PULSENUM(x) ((x) << 14) | ||
36 | # define SPLL_PULSENUM_MASK (3 << 14) | ||
37 | # define SPLL_SW_HILEN(x) ((x) << 16) | ||
38 | # define SPLL_SW_HILEN_MASK (0xf << 16) | ||
39 | # define SPLL_SW_LOLEN(x) ((x) << 20) | ||
40 | # define SPLL_SW_LOLEN_MASK (0xf << 20) | ||
41 | # define SPLL_DIVEN (1 << 24) | ||
42 | # define SPLL_BYPASS_EN (1 << 25) | ||
43 | # define SPLL_CHG_STATUS (1 << 29) | ||
44 | # define SPLL_CTLREQ (1 << 30) | ||
45 | # define SPLL_CTLACK (1 << 31) | ||
46 | |||
47 | /* RS780/RS880 PM */ | ||
48 | #define FVTHROT_CNTRL_REG 0x3000 | ||
49 | #define DONT_WAIT_FOR_FBDIV_WRAP (1 << 0) | ||
50 | #define MINIMUM_CIP(x) ((x) << 1) | ||
51 | #define MINIMUM_CIP_SHIFT 1 | ||
52 | #define MINIMUM_CIP_MASK 0x1fffffe | ||
53 | #define REFRESH_RATE_DIVISOR(x) ((x) << 25) | ||
54 | #define REFRESH_RATE_DIVISOR_SHIFT 25 | ||
55 | #define REFRESH_RATE_DIVISOR_MASK (0x3 << 25) | ||
56 | #define ENABLE_FV_THROT (1 << 27) | ||
57 | #define ENABLE_FV_UPDATE (1 << 28) | ||
58 | #define TREND_SEL_MODE (1 << 29) | ||
59 | #define FORCE_TREND_SEL (1 << 30) | ||
60 | #define ENABLE_FV_THROT_IO (1 << 31) | ||
61 | #define FVTHROT_TARGET_REG 0x3004 | ||
62 | #define TARGET_IDLE_COUNT(x) ((x) << 0) | ||
63 | #define TARGET_IDLE_COUNT_MASK 0xffffff | ||
64 | #define TARGET_IDLE_COUNT_SHIFT 0 | ||
65 | #define FVTHROT_CB1 0x3008 | ||
66 | #define FVTHROT_CB2 0x300c | ||
67 | #define FVTHROT_CB3 0x3010 | ||
68 | #define FVTHROT_CB4 0x3014 | ||
69 | #define FVTHROT_UTC0 0x3018 | ||
70 | #define FVTHROT_UTC1 0x301c | ||
71 | #define FVTHROT_UTC2 0x3020 | ||
72 | #define FVTHROT_UTC3 0x3024 | ||
73 | #define FVTHROT_UTC4 0x3028 | ||
74 | #define FVTHROT_DTC0 0x302c | ||
75 | #define FVTHROT_DTC1 0x3030 | ||
76 | #define FVTHROT_DTC2 0x3034 | ||
77 | #define FVTHROT_DTC3 0x3038 | ||
78 | #define FVTHROT_DTC4 0x303c | ||
79 | #define FVTHROT_FBDIV_REG0 0x3040 | ||
80 | #define MIN_FEEDBACK_DIV(x) ((x) << 0) | ||
81 | #define MIN_FEEDBACK_DIV_MASK 0xfff | ||
82 | #define MIN_FEEDBACK_DIV_SHIFT 0 | ||
83 | #define MAX_FEEDBACK_DIV(x) ((x) << 12) | ||
84 | #define MAX_FEEDBACK_DIV_MASK (0xfff << 12) | ||
85 | #define MAX_FEEDBACK_DIV_SHIFT 12 | ||
86 | #define FVTHROT_FBDIV_REG1 0x3044 | ||
87 | #define MAX_FEEDBACK_STEP(x) ((x) << 0) | ||
88 | #define MAX_FEEDBACK_STEP_MASK 0xfff | ||
89 | #define MAX_FEEDBACK_STEP_SHIFT 0 | ||
90 | #define STARTING_FEEDBACK_DIV(x) ((x) << 12) | ||
91 | #define STARTING_FEEDBACK_DIV_MASK (0xfff << 12) | ||
92 | #define STARTING_FEEDBACK_DIV_SHIFT 12 | ||
93 | #define FORCE_FEEDBACK_DIV (1 << 24) | ||
94 | #define FVTHROT_FBDIV_REG2 0x3048 | ||
95 | #define FORCED_FEEDBACK_DIV(x) ((x) << 0) | ||
96 | #define FORCED_FEEDBACK_DIV_MASK 0xfff | ||
97 | #define FORCED_FEEDBACK_DIV_SHIFT 0 | ||
98 | #define FB_DIV_TIMER_VAL(x) ((x) << 12) | ||
99 | #define FB_DIV_TIMER_VAL_MASK (0xffff << 12) | ||
100 | #define FB_DIV_TIMER_VAL_SHIFT 12 | ||
101 | #define FVTHROT_FB_US_REG0 0x304c | ||
102 | #define FVTHROT_FB_US_REG1 0x3050 | ||
103 | #define FVTHROT_FB_DS_REG0 0x3054 | ||
104 | #define FVTHROT_FB_DS_REG1 0x3058 | ||
105 | #define FVTHROT_PWM_CTRL_REG0 0x305c | ||
106 | #define STARTING_PWM_HIGHTIME(x) ((x) << 0) | ||
107 | #define STARTING_PWM_HIGHTIME_MASK 0xfff | ||
108 | #define STARTING_PWM_HIGHTIME_SHIFT 0 | ||
109 | #define NUMBER_OF_CYCLES_IN_PERIOD(x) ((x) << 12) | ||
110 | #define NUMBER_OF_CYCLES_IN_PERIOD_MASK (0xfff << 12) | ||
111 | #define NUMBER_OF_CYCLES_IN_PERIOD_SHIFT 12 | ||
112 | #define FORCE_STARTING_PWM_HIGHTIME (1 << 24) | ||
113 | #define INVERT_PWM_WAVEFORM (1 << 25) | ||
114 | #define FVTHROT_PWM_CTRL_REG1 0x3060 | ||
115 | #define MIN_PWM_HIGHTIME(x) ((x) << 0) | ||
116 | #define MIN_PWM_HIGHTIME_MASK 0xfff | ||
117 | #define MIN_PWM_HIGHTIME_SHIFT 0 | ||
118 | #define MAX_PWM_HIGHTIME(x) ((x) << 12) | ||
119 | #define MAX_PWM_HIGHTIME_MASK (0xfff << 12) | ||
120 | #define MAX_PWM_HIGHTIME_SHIFT 12 | ||
121 | #define FVTHROT_PWM_US_REG0 0x3064 | ||
122 | #define FVTHROT_PWM_US_REG1 0x3068 | ||
123 | #define FVTHROT_PWM_DS_REG0 0x306c | ||
124 | #define FVTHROT_PWM_DS_REG1 0x3070 | ||
125 | #define FVTHROT_STATUS_REG0 0x3074 | ||
126 | #define CURRENT_FEEDBACK_DIV_MASK 0xfff | ||
127 | #define CURRENT_FEEDBACK_DIV_SHIFT 0 | ||
128 | #define FVTHROT_STATUS_REG1 0x3078 | ||
129 | #define FVTHROT_STATUS_REG2 0x307c | ||
130 | #define CG_INTGFX_MISC 0x3080 | ||
131 | #define FVTHROT_VBLANK_SEL (1 << 9) | ||
132 | #define FVTHROT_PWM_FEEDBACK_DIV_REG1 0x308c | ||
133 | #define RANGE0_PWM_FEEDBACK_DIV(x) ((x) << 0) | ||
134 | #define RANGE0_PWM_FEEDBACK_DIV_MASK 0xfff | ||
135 | #define RANGE0_PWM_FEEDBACK_DIV_SHIFT 0 | ||
136 | #define RANGE_PWM_FEEDBACK_DIV_EN (1 << 12) | ||
137 | #define FVTHROT_PWM_FEEDBACK_DIV_REG2 0x3090 | ||
138 | #define RANGE1_PWM_FEEDBACK_DIV(x) ((x) << 0) | ||
139 | #define RANGE1_PWM_FEEDBACK_DIV_MASK 0xfff | ||
140 | #define RANGE1_PWM_FEEDBACK_DIV_SHIFT 0 | ||
141 | #define RANGE2_PWM_FEEDBACK_DIV(x) ((x) << 12) | ||
142 | #define RANGE2_PWM_FEEDBACK_DIV_MASK (0xfff << 12) | ||
143 | #define RANGE2_PWM_FEEDBACK_DIV_SHIFT 12 | ||
144 | #define FVTHROT_PWM_FEEDBACK_DIV_REG3 0x3094 | ||
145 | #define RANGE0_PWM(x) ((x) << 0) | ||
146 | #define RANGE0_PWM_MASK 0xfff | ||
147 | #define RANGE0_PWM_SHIFT 0 | ||
148 | #define RANGE1_PWM(x) ((x) << 12) | ||
149 | #define RANGE1_PWM_MASK (0xfff << 12) | ||
150 | #define RANGE1_PWM_SHIFT 12 | ||
151 | #define FVTHROT_PWM_FEEDBACK_DIV_REG4 0x3098 | ||
152 | #define RANGE2_PWM(x) ((x) << 0) | ||
153 | #define RANGE2_PWM_MASK 0xfff | ||
154 | #define RANGE2_PWM_SHIFT 0 | ||
155 | #define RANGE3_PWM(x) ((x) << 12) | ||
156 | #define RANGE3_PWM_MASK (0xfff << 12) | ||
157 | #define RANGE3_PWM_SHIFT 12 | ||
158 | #define FVTHROT_SLOW_CLK_FEEDBACK_DIV_REG1 0x30ac | ||
159 | #define RANGE0_SLOW_CLK_FEEDBACK_DIV(x) ((x) << 0) | ||
160 | #define RANGE0_SLOW_CLK_FEEDBACK_DIV_MASK 0xfff | ||
161 | #define RANGE0_SLOW_CLK_FEEDBACK_DIV_SHIFT 0 | ||
162 | #define RANGE_SLOW_CLK_FEEDBACK_DIV_EN (1 << 12) | ||
163 | |||
164 | #define GFX_MACRO_BYPASS_CNTL 0x30c0 | ||
165 | #define SPLL_BYPASS_CNTL (1 << 0) | ||
166 | #define UPLL_BYPASS_CNTL (1 << 1) | ||
167 | |||
168 | #endif | ||