Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+1203 -1
+1 -1
drivers/gpu/drm/radeon/Makefile
··· 77 77 evergreen_hdmi.o radeon_trace_points.o ni.o cayman_blit_shaders.o \ 78 78 atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ 79 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 82 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o 83 83 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
+12
drivers/gpu/drm/radeon/radeon_asic.c
··· 1242 1242 .set_clock_gating = NULL, 1243 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 1257 .pflip = { 1246 1258 .pre_page_flip = &rs600_pre_page_flip, 1247 1259 .page_flip = &rs600_page_flip,
+12
drivers/gpu/drm/radeon/radeon_asic.h
··· 402 402 u32 r600_get_xclk(struct radeon_device *rdev); 403 403 uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev); 404 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 418 /* uvd */ 407 419 int r600_uvd_init(struct radeon_device *rdev);
+7
drivers/gpu/drm/radeon/radeon_pm.c
··· 1030 1030 { 1031 1031 /* enable dpm on rv6xx+ */ 1032 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 1040 default: 1034 1041 /* default to profile method */ 1035 1042 rdev->pm.pm_method = PM_METHOD_PROFILE;
+894
drivers/gpu/drm/radeon/rs780_dpm.c
··· 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, &dividers); 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, &current_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 + }
+109
drivers/gpu/drm/radeon/rs780_dpm.h
··· 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
+168
drivers/gpu/drm/radeon/rs780d.h
··· 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