diff options
-rw-r--r-- | drivers/gpu/drm/radeon/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/ppsmc.h | 78 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600d.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 1 | ||||
-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 | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ucode.h | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv730_dpm.c | 508 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv730d.h | 165 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv740_dpm.c | 417 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv740d.h | 117 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770_dpm.c | 2337 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770_dpm.h | 273 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770_smc.c | 404 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770_smc.h | 208 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv770d.h | 279 |
18 files changed, 4876 insertions, 13 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 3aa20dc686fc..c97753d3d970 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
@@ -77,7 +77,8 @@ 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 rs780_dpm.o rv6xx_dpm.o | 80 | r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \ |
81 | rv770_smc.o | ||
81 | 82 | ||
82 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o | 83 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o |
83 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o | 84 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o |
diff --git a/drivers/gpu/drm/radeon/ppsmc.h b/drivers/gpu/drm/radeon/ppsmc.h new file mode 100644 index 000000000000..c85b96eac75f --- /dev/null +++ b/drivers/gpu/drm/radeon/ppsmc.h | |||
@@ -0,0 +1,78 @@ | |||
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 PP_SMC_H | ||
24 | #define PP_SMC_H | ||
25 | |||
26 | #pragma pack(push, 1) | ||
27 | |||
28 | #define PPSMC_SWSTATE_FLAG_DC 0x01 | ||
29 | |||
30 | #define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 | ||
31 | #define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 | ||
32 | #define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff | ||
33 | |||
34 | #define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 | ||
35 | #define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 | ||
36 | #define PPSMC_SYSTEMFLAG_GDDR5 0x04 | ||
37 | #define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 | ||
38 | #define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 | ||
39 | |||
40 | #define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 | ||
41 | #define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 | ||
42 | #define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 | ||
43 | #define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 | ||
44 | |||
45 | #define PPSMC_DISPLAY_WATERMARK_LOW 0 | ||
46 | #define PPSMC_DISPLAY_WATERMARK_HIGH 1 | ||
47 | |||
48 | #define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 | ||
49 | |||
50 | #define PPSMC_Result_OK ((uint8_t)0x01) | ||
51 | #define PPSMC_Result_Failed ((uint8_t)0xFF) | ||
52 | |||
53 | typedef uint8_t PPSMC_Result; | ||
54 | |||
55 | #define PPSMC_MSG_Halt ((uint8_t)0x10) | ||
56 | #define PPSMC_MSG_Resume ((uint8_t)0x11) | ||
57 | #define PPSMC_MSG_ZeroLevelsDisabled ((uint8_t)0x13) | ||
58 | #define PPSMC_MSG_OneLevelsDisabled ((uint8_t)0x14) | ||
59 | #define PPSMC_MSG_TwoLevelsDisabled ((uint8_t)0x15) | ||
60 | #define PPSMC_MSG_EnableThermalInterrupt ((uint8_t)0x16) | ||
61 | #define PPSMC_MSG_SwitchToSwState ((uint8_t)0x20) | ||
62 | #define PPSMC_MSG_SwitchToInitialState ((uint8_t)0x40) | ||
63 | #define PPSMC_MSG_NoForcedLevel ((uint8_t)0x41) | ||
64 | #define PPSMC_MSG_SwitchToMinimumPower ((uint8_t)0x51) | ||
65 | #define PPSMC_MSG_ResumeFromMinimumPower ((uint8_t)0x52) | ||
66 | #define PPSMC_MSG_NoDisplay ((uint8_t)0x5D) | ||
67 | #define PPSMC_MSG_HasDisplay ((uint8_t)0x5E) | ||
68 | #define PPSMC_MSG_EnableULV ((uint8_t)0x62) | ||
69 | #define PPSMC_MSG_DisableULV ((uint8_t)0x63) | ||
70 | #define PPSMC_MSG_EnterULV ((uint8_t)0x64) | ||
71 | #define PPSMC_MSG_ExitULV ((uint8_t)0x65) | ||
72 | #define PPSMC_MSG_ResetToDefaults ((uint8_t)0x84) | ||
73 | |||
74 | typedef uint8_t PPSMC_Msg; | ||
75 | |||
76 | #pragma pack(pop) | ||
77 | |||
78 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index ce5aa1febb80..a27d746386ae 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -57,10 +57,14 @@ MODULE_FIRMWARE("radeon/RS780_pfp.bin"); | |||
57 | MODULE_FIRMWARE("radeon/RS780_me.bin"); | 57 | MODULE_FIRMWARE("radeon/RS780_me.bin"); |
58 | MODULE_FIRMWARE("radeon/RV770_pfp.bin"); | 58 | MODULE_FIRMWARE("radeon/RV770_pfp.bin"); |
59 | MODULE_FIRMWARE("radeon/RV770_me.bin"); | 59 | MODULE_FIRMWARE("radeon/RV770_me.bin"); |
60 | MODULE_FIRMWARE("radeon/RV770_smc.bin"); | ||
60 | MODULE_FIRMWARE("radeon/RV730_pfp.bin"); | 61 | MODULE_FIRMWARE("radeon/RV730_pfp.bin"); |
61 | MODULE_FIRMWARE("radeon/RV730_me.bin"); | 62 | MODULE_FIRMWARE("radeon/RV730_me.bin"); |
63 | MODULE_FIRMWARE("radeon/RV730_smc.bin"); | ||
64 | MODULE_FIRMWARE("radeon/RV740_smc.bin"); | ||
62 | MODULE_FIRMWARE("radeon/RV710_pfp.bin"); | 65 | MODULE_FIRMWARE("radeon/RV710_pfp.bin"); |
63 | MODULE_FIRMWARE("radeon/RV710_me.bin"); | 66 | MODULE_FIRMWARE("radeon/RV710_me.bin"); |
67 | MODULE_FIRMWARE("radeon/RV710_smc.bin"); | ||
64 | MODULE_FIRMWARE("radeon/R600_rlc.bin"); | 68 | MODULE_FIRMWARE("radeon/R600_rlc.bin"); |
65 | MODULE_FIRMWARE("radeon/R700_rlc.bin"); | 69 | MODULE_FIRMWARE("radeon/R700_rlc.bin"); |
66 | MODULE_FIRMWARE("radeon/CEDAR_pfp.bin"); | 70 | MODULE_FIRMWARE("radeon/CEDAR_pfp.bin"); |
@@ -2139,7 +2143,8 @@ int r600_init_microcode(struct radeon_device *rdev) | |||
2139 | struct platform_device *pdev; | 2143 | struct platform_device *pdev; |
2140 | const char *chip_name; | 2144 | const char *chip_name; |
2141 | const char *rlc_chip_name; | 2145 | const char *rlc_chip_name; |
2142 | size_t pfp_req_size, me_req_size, rlc_req_size; | 2146 | const char *smc_chip_name = "RV770"; |
2147 | size_t pfp_req_size, me_req_size, rlc_req_size, smc_req_size = 0; | ||
2143 | char fw_name[30]; | 2148 | char fw_name[30]; |
2144 | int err; | 2149 | int err; |
2145 | 2150 | ||
@@ -2185,15 +2190,26 @@ int r600_init_microcode(struct radeon_device *rdev) | |||
2185 | case CHIP_RV770: | 2190 | case CHIP_RV770: |
2186 | chip_name = "RV770"; | 2191 | chip_name = "RV770"; |
2187 | rlc_chip_name = "R700"; | 2192 | rlc_chip_name = "R700"; |
2193 | smc_chip_name = "RV770"; | ||
2194 | smc_req_size = ALIGN(RV770_SMC_UCODE_SIZE, 4); | ||
2188 | break; | 2195 | break; |
2189 | case CHIP_RV730: | 2196 | case CHIP_RV730: |
2190 | case CHIP_RV740: | ||
2191 | chip_name = "RV730"; | 2197 | chip_name = "RV730"; |
2192 | rlc_chip_name = "R700"; | 2198 | rlc_chip_name = "R700"; |
2199 | smc_chip_name = "RV730"; | ||
2200 | smc_req_size = ALIGN(RV730_SMC_UCODE_SIZE, 4); | ||
2193 | break; | 2201 | break; |
2194 | case CHIP_RV710: | 2202 | case CHIP_RV710: |
2195 | chip_name = "RV710"; | 2203 | chip_name = "RV710"; |
2196 | rlc_chip_name = "R700"; | 2204 | rlc_chip_name = "R700"; |
2205 | smc_chip_name = "RV710"; | ||
2206 | smc_req_size = ALIGN(RV710_SMC_UCODE_SIZE, 4); | ||
2207 | break; | ||
2208 | case CHIP_RV740: | ||
2209 | chip_name = "RV730"; | ||
2210 | rlc_chip_name = "R700"; | ||
2211 | smc_chip_name = "RV740"; | ||
2212 | smc_req_size = ALIGN(RV740_SMC_UCODE_SIZE, 4); | ||
2197 | break; | 2213 | break; |
2198 | case CHIP_CEDAR: | 2214 | case CHIP_CEDAR: |
2199 | chip_name = "CEDAR"; | 2215 | chip_name = "CEDAR"; |
@@ -2277,6 +2293,19 @@ int r600_init_microcode(struct radeon_device *rdev) | |||
2277 | err = -EINVAL; | 2293 | err = -EINVAL; |
2278 | } | 2294 | } |
2279 | 2295 | ||
2296 | if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) { | ||
2297 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", smc_chip_name); | ||
2298 | err = request_firmware(&rdev->smc_fw, fw_name, &pdev->dev); | ||
2299 | if (err) | ||
2300 | goto out; | ||
2301 | if (rdev->smc_fw->size != smc_req_size) { | ||
2302 | printk(KERN_ERR | ||
2303 | "smc: Bogus length %zu in firmware \"%s\"\n", | ||
2304 | rdev->smc_fw->size, fw_name); | ||
2305 | err = -EINVAL; | ||
2306 | } | ||
2307 | } | ||
2308 | |||
2280 | out: | 2309 | out: |
2281 | platform_device_unregister(pdev); | 2310 | platform_device_unregister(pdev); |
2282 | 2311 | ||
@@ -2291,6 +2320,8 @@ out: | |||
2291 | rdev->me_fw = NULL; | 2320 | rdev->me_fw = NULL; |
2292 | release_firmware(rdev->rlc_fw); | 2321 | release_firmware(rdev->rlc_fw); |
2293 | rdev->rlc_fw = NULL; | 2322 | rdev->rlc_fw = NULL; |
2323 | release_firmware(rdev->smc_fw); | ||
2324 | rdev->smc_fw = NULL; | ||
2294 | } | 2325 | } |
2295 | return err; | 2326 | return err; |
2296 | } | 2327 | } |
@@ -4039,10 +4070,13 @@ int r600_irq_set(struct radeon_device *rdev) | |||
4039 | if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) { | 4070 | if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) { |
4040 | thermal_int = RREG32(CG_THERMAL_INT) & | 4071 | thermal_int = RREG32(CG_THERMAL_INT) & |
4041 | ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); | 4072 | ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); |
4042 | if (rdev->irq.dpm_thermal) { | 4073 | } else if (rdev->family >= CHIP_RV770) { |
4043 | DRM_DEBUG("dpm thermal\n"); | 4074 | thermal_int = RREG32(RV770_CG_THERMAL_INT) & |
4044 | thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; | 4075 | ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); |
4045 | } | 4076 | } |
4077 | if (rdev->irq.dpm_thermal) { | ||
4078 | DRM_DEBUG("dpm thermal\n"); | ||
4079 | thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; | ||
4046 | } | 4080 | } |
4047 | 4081 | ||
4048 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { | 4082 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
@@ -4128,6 +4162,8 @@ int r600_irq_set(struct radeon_device *rdev) | |||
4128 | } | 4162 | } |
4129 | if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) { | 4163 | if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) { |
4130 | WREG32(CG_THERMAL_INT, thermal_int); | 4164 | WREG32(CG_THERMAL_INT, thermal_int); |
4165 | } else if (rdev->family >= CHIP_RV770) { | ||
4166 | WREG32(RV770_CG_THERMAL_INT, thermal_int); | ||
4131 | } | 4167 | } |
4132 | 4168 | ||
4133 | return 0; | 4169 | return 0; |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3bca4db4c46f..f1b3084d8f51 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
@@ -320,6 +320,8 @@ | |||
320 | #define THERM_INT_MASK_HIGH (1 << 24) | 320 | #define THERM_INT_MASK_HIGH (1 << 24) |
321 | #define THERM_INT_MASK_LOW (1 << 25) | 321 | #define THERM_INT_MASK_LOW (1 << 25) |
322 | 322 | ||
323 | #define RV770_CG_THERMAL_INT 0x734 | ||
324 | |||
323 | #define HDP_HOST_PATH_CNTL 0x2C00 | 325 | #define HDP_HOST_PATH_CNTL 0x2C00 |
324 | #define HDP_NONSURFACE_BASE 0x2C04 | 326 | #define HDP_NONSURFACE_BASE 0x2C04 |
325 | #define HDP_NONSURFACE_INFO 0x2C08 | 327 | #define HDP_NONSURFACE_INFO 0x2C08 |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f9069055b069..7221ff43fdc8 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -1913,6 +1913,7 @@ struct radeon_device { | |||
1913 | const struct firmware *uvd_fw; /* UVD firmware */ | 1913 | const struct firmware *uvd_fw; /* UVD firmware */ |
1914 | const struct firmware *mec_fw; /* CIK MEC firmware */ | 1914 | const struct firmware *mec_fw; /* CIK MEC firmware */ |
1915 | const struct firmware *sdma_fw; /* CIK SDMA firmware */ | 1915 | const struct firmware *sdma_fw; /* CIK SDMA firmware */ |
1916 | const struct firmware *smc_fw; /* SMC firmware */ | ||
1916 | struct r600_blit r600_blit; | 1917 | struct r600_blit r600_blit; |
1917 | struct r600_vram_scratch vram_scratch; | 1918 | struct r600_vram_scratch vram_scratch; |
1918 | int msi_enabled; /* msi enabled */ | 1919 | int msi_enabled; /* msi enabled */ |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 45fb196c2cb9..2c18a796d351 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
@@ -1374,6 +1374,18 @@ static struct radeon_asic rv770_asic = { | |||
1374 | .set_uvd_clocks = &rv770_set_uvd_clocks, | 1374 | .set_uvd_clocks = &rv770_set_uvd_clocks, |
1375 | .get_temperature = &rv770_get_temp, | 1375 | .get_temperature = &rv770_get_temp, |
1376 | }, | 1376 | }, |
1377 | .dpm = { | ||
1378 | .init = &rv770_dpm_init, | ||
1379 | .setup_asic = &rv770_dpm_setup_asic, | ||
1380 | .enable = &rv770_dpm_enable, | ||
1381 | .disable = &rv770_dpm_disable, | ||
1382 | .set_power_state = &rv770_dpm_set_power_state, | ||
1383 | .display_configuration_changed = &rv770_dpm_display_configuration_changed, | ||
1384 | .fini = &rv770_dpm_fini, | ||
1385 | .get_sclk = &rv770_dpm_get_sclk, | ||
1386 | .get_mclk = &rv770_dpm_get_mclk, | ||
1387 | .print_power_state = &rv770_dpm_print_power_state, | ||
1388 | }, | ||
1377 | .pflip = { | 1389 | .pflip = { |
1378 | .pre_page_flip = &rs600_pre_page_flip, | 1390 | .pre_page_flip = &rs600_pre_page_flip, |
1379 | .page_flip = &rv770_page_flip, | 1391 | .page_flip = &rv770_page_flip, |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 36f66faa1d15..ad668a533848 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -460,6 +460,18 @@ u32 rv770_get_xclk(struct radeon_device *rdev); | |||
460 | int rv770_uvd_resume(struct radeon_device *rdev); | 460 | int rv770_uvd_resume(struct radeon_device *rdev); |
461 | int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); | 461 | int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); |
462 | int rv770_get_temp(struct radeon_device *rdev); | 462 | int rv770_get_temp(struct radeon_device *rdev); |
463 | /* rv7xx pm */ | ||
464 | int rv770_dpm_init(struct radeon_device *rdev); | ||
465 | int rv770_dpm_enable(struct radeon_device *rdev); | ||
466 | void rv770_dpm_disable(struct radeon_device *rdev); | ||
467 | int rv770_dpm_set_power_state(struct radeon_device *rdev); | ||
468 | void rv770_dpm_setup_asic(struct radeon_device *rdev); | ||
469 | void rv770_dpm_display_configuration_changed(struct radeon_device *rdev); | ||
470 | void rv770_dpm_fini(struct radeon_device *rdev); | ||
471 | u32 rv770_dpm_get_sclk(struct radeon_device *rdev, bool low); | ||
472 | u32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low); | ||
473 | void rv770_dpm_print_power_state(struct radeon_device *rdev, | ||
474 | struct radeon_ps *ps); | ||
463 | 475 | ||
464 | /* | 476 | /* |
465 | * evergreen | 477 | * evergreen |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 17f28974745e..09eef285f27b 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -1037,6 +1037,10 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
1037 | case CHIP_RV670: | 1037 | case CHIP_RV670: |
1038 | case CHIP_RS780: | 1038 | case CHIP_RS780: |
1039 | case CHIP_RS880: | 1039 | case CHIP_RS880: |
1040 | case CHIP_RV770: | ||
1041 | case CHIP_RV730: | ||
1042 | case CHIP_RV710: | ||
1043 | case CHIP_RV740: | ||
1040 | if (radeon_dpm == 1) | 1044 | if (radeon_dpm == 1) |
1041 | rdev->pm.pm_method = PM_METHOD_DPM; | 1045 | rdev->pm.pm_method = PM_METHOD_DPM; |
1042 | else | 1046 | else |
diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h index d2642b01578a..19105455330d 100644 --- a/drivers/gpu/drm/radeon/radeon_ucode.h +++ b/drivers/gpu/drm/radeon/radeon_ucode.h | |||
@@ -44,4 +44,25 @@ | |||
44 | #define BTC_MC_UCODE_SIZE 6024 | 44 | #define BTC_MC_UCODE_SIZE 6024 |
45 | #define CAYMAN_MC_UCODE_SIZE 6037 | 45 | #define CAYMAN_MC_UCODE_SIZE 6037 |
46 | 46 | ||
47 | /* SMC */ | ||
48 | #define RV770_SMC_UCODE_START 0x0100 | ||
49 | #define RV770_SMC_UCODE_SIZE 0x410d | ||
50 | #define RV770_SMC_INT_VECTOR_START 0xffc0 | ||
51 | #define RV770_SMC_INT_VECTOR_SIZE 0x0040 | ||
52 | |||
53 | #define RV730_SMC_UCODE_START 0x0100 | ||
54 | #define RV730_SMC_UCODE_SIZE 0x412c | ||
55 | #define RV730_SMC_INT_VECTOR_START 0xffc0 | ||
56 | #define RV730_SMC_INT_VECTOR_SIZE 0x0040 | ||
57 | |||
58 | #define RV710_SMC_UCODE_START 0x0100 | ||
59 | #define RV710_SMC_UCODE_SIZE 0x3f1f | ||
60 | #define RV710_SMC_INT_VECTOR_START 0xffc0 | ||
61 | #define RV710_SMC_INT_VECTOR_SIZE 0x0040 | ||
62 | |||
63 | #define RV740_SMC_UCODE_START 0x0100 | ||
64 | #define RV740_SMC_UCODE_SIZE 0x41c5 | ||
65 | #define RV740_SMC_INT_VECTOR_START 0xffc0 | ||
66 | #define RV740_SMC_INT_VECTOR_SIZE 0x0040 | ||
67 | |||
47 | #endif | 68 | #endif |
diff --git a/drivers/gpu/drm/radeon/rv730_dpm.c b/drivers/gpu/drm/radeon/rv730_dpm.c new file mode 100644 index 000000000000..3f5e1cf138ba --- /dev/null +++ b/drivers/gpu/drm/radeon/rv730_dpm.c | |||
@@ -0,0 +1,508 @@ | |||
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 "rv730d.h" | ||
28 | #include "r600_dpm.h" | ||
29 | #include "rv770_dpm.h" | ||
30 | #include "atom.h" | ||
31 | |||
32 | #define MC_CG_ARB_FREQ_F0 0x0a | ||
33 | #define MC_CG_ARB_FREQ_F1 0x0b | ||
34 | #define MC_CG_ARB_FREQ_F2 0x0c | ||
35 | #define MC_CG_ARB_FREQ_F3 0x0d | ||
36 | |||
37 | struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps); | ||
38 | struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev); | ||
39 | |||
40 | int rv730_populate_sclk_value(struct radeon_device *rdev, | ||
41 | u32 engine_clock, | ||
42 | RV770_SMC_SCLK_VALUE *sclk) | ||
43 | { | ||
44 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
45 | struct atom_clock_dividers dividers; | ||
46 | u32 spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl; | ||
47 | u32 spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2; | ||
48 | u32 spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3; | ||
49 | u32 cg_spll_spread_spectrum = pi->clk_regs.rv730.cg_spll_spread_spectrum; | ||
50 | u32 cg_spll_spread_spectrum_2 = pi->clk_regs.rv730.cg_spll_spread_spectrum_2; | ||
51 | u64 tmp; | ||
52 | u32 reference_clock = rdev->clock.spll.reference_freq; | ||
53 | u32 reference_divider, post_divider; | ||
54 | u32 fbdiv; | ||
55 | int ret; | ||
56 | |||
57 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, | ||
58 | engine_clock, false, ÷rs); | ||
59 | if (ret) | ||
60 | return ret; | ||
61 | |||
62 | reference_divider = 1 + dividers.ref_div; | ||
63 | |||
64 | if (dividers.enable_post_div) | ||
65 | post_divider = ((dividers.post_div >> 4) & 0xf) + | ||
66 | (dividers.post_div & 0xf) + 2; | ||
67 | else | ||
68 | post_divider = 1; | ||
69 | |||
70 | tmp = (u64) engine_clock * reference_divider * post_divider * 16384; | ||
71 | do_div(tmp, reference_clock); | ||
72 | fbdiv = (u32) tmp; | ||
73 | |||
74 | /* set up registers */ | ||
75 | if (dividers.enable_post_div) | ||
76 | spll_func_cntl |= SPLL_DIVEN; | ||
77 | else | ||
78 | spll_func_cntl &= ~SPLL_DIVEN; | ||
79 | spll_func_cntl &= ~(SPLL_HILEN_MASK | SPLL_LOLEN_MASK | SPLL_REF_DIV_MASK); | ||
80 | spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div); | ||
81 | spll_func_cntl |= SPLL_HILEN((dividers.post_div >> 4) & 0xf); | ||
82 | spll_func_cntl |= SPLL_LOLEN(dividers.post_div & 0xf); | ||
83 | |||
84 | spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; | ||
85 | spll_func_cntl_2 |= SCLK_MUX_SEL(2); | ||
86 | |||
87 | spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; | ||
88 | spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); | ||
89 | spll_func_cntl_3 |= SPLL_DITHEN; | ||
90 | |||
91 | if (pi->sclk_ss) { | ||
92 | struct radeon_atom_ss ss; | ||
93 | u32 vco_freq = engine_clock * post_divider; | ||
94 | |||
95 | if (radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
96 | ASIC_INTERNAL_ENGINE_SS, vco_freq)) { | ||
97 | u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); | ||
98 | u32 clk_v = ss.percentage * fbdiv / (clk_s * 10000); | ||
99 | |||
100 | cg_spll_spread_spectrum &= ~CLK_S_MASK; | ||
101 | cg_spll_spread_spectrum |= CLK_S(clk_s); | ||
102 | cg_spll_spread_spectrum |= SSEN; | ||
103 | |||
104 | cg_spll_spread_spectrum_2 &= ~CLK_V_MASK; | ||
105 | cg_spll_spread_spectrum_2 |= CLK_V(clk_v); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | sclk->sclk_value = cpu_to_be32(engine_clock); | ||
110 | sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); | ||
111 | sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); | ||
112 | sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); | ||
113 | sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum); | ||
114 | sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2); | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | int rv730_populate_mclk_value(struct radeon_device *rdev, | ||
120 | u32 engine_clock, u32 memory_clock, | ||
121 | LPRV7XX_SMC_MCLK_VALUE mclk) | ||
122 | { | ||
123 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
124 | u32 mclk_pwrmgt_cntl = pi->clk_regs.rv730.mclk_pwrmgt_cntl; | ||
125 | u32 dll_cntl = pi->clk_regs.rv730.dll_cntl; | ||
126 | u32 mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl; | ||
127 | u32 mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2; | ||
128 | u32 mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3; | ||
129 | u32 mpll_ss = pi->clk_regs.rv730.mpll_ss; | ||
130 | u32 mpll_ss2 = pi->clk_regs.rv730.mpll_ss2; | ||
131 | struct atom_clock_dividers dividers; | ||
132 | u32 post_divider, reference_divider; | ||
133 | int ret; | ||
134 | |||
135 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM, | ||
136 | memory_clock, false, ÷rs); | ||
137 | if (ret) | ||
138 | return ret; | ||
139 | |||
140 | reference_divider = dividers.ref_div + 1; | ||
141 | |||
142 | if (dividers.enable_post_div) | ||
143 | post_divider = ((dividers.post_div >> 4) & 0xf) + | ||
144 | (dividers.post_div & 0xf) + 2; | ||
145 | else | ||
146 | post_divider = 1; | ||
147 | |||
148 | /* setup the registers */ | ||
149 | if (dividers.enable_post_div) | ||
150 | mpll_func_cntl |= MPLL_DIVEN; | ||
151 | else | ||
152 | mpll_func_cntl &= ~MPLL_DIVEN; | ||
153 | |||
154 | mpll_func_cntl &= ~(MPLL_REF_DIV_MASK | MPLL_HILEN_MASK | MPLL_LOLEN_MASK); | ||
155 | mpll_func_cntl |= MPLL_REF_DIV(dividers.ref_div); | ||
156 | mpll_func_cntl |= MPLL_HILEN((dividers.post_div >> 4) & 0xf); | ||
157 | mpll_func_cntl |= MPLL_LOLEN(dividers.post_div & 0xf); | ||
158 | |||
159 | mpll_func_cntl_3 &= ~MPLL_FB_DIV_MASK; | ||
160 | mpll_func_cntl_3 |= MPLL_FB_DIV(dividers.fb_div); | ||
161 | if (dividers.enable_dithen) | ||
162 | mpll_func_cntl_3 |= MPLL_DITHEN; | ||
163 | else | ||
164 | mpll_func_cntl_3 &= ~MPLL_DITHEN; | ||
165 | |||
166 | if (pi->mclk_ss) { | ||
167 | struct radeon_atom_ss ss; | ||
168 | u32 vco_freq = memory_clock * post_divider; | ||
169 | |||
170 | if (radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
171 | ASIC_INTERNAL_MEMORY_SS, vco_freq)) { | ||
172 | u32 reference_clock = rdev->clock.mpll.reference_freq; | ||
173 | u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); | ||
174 | u32 clk_v = ss.percentage * dividers.fb_div / (clk_s * 10000); | ||
175 | |||
176 | mpll_ss &= ~CLK_S_MASK; | ||
177 | mpll_ss |= CLK_S(clk_s); | ||
178 | mpll_ss |= SSEN; | ||
179 | |||
180 | mpll_ss2 &= ~CLK_V_MASK; | ||
181 | mpll_ss |= CLK_V(clk_v); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | |||
186 | mclk->mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); | ||
187 | mclk->mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl); | ||
188 | mclk->mclk730.mclk_value = cpu_to_be32(memory_clock); | ||
189 | mclk->mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl); | ||
190 | mclk->mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2); | ||
191 | mclk->mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3); | ||
192 | mclk->mclk730.vMPLL_SS = cpu_to_be32(mpll_ss); | ||
193 | mclk->mclk730.vMPLL_SS2 = cpu_to_be32(mpll_ss2); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | void rv730_read_clock_registers(struct radeon_device *rdev) | ||
199 | { | ||
200 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
201 | |||
202 | pi->clk_regs.rv730.cg_spll_func_cntl = | ||
203 | RREG32(CG_SPLL_FUNC_CNTL); | ||
204 | pi->clk_regs.rv730.cg_spll_func_cntl_2 = | ||
205 | RREG32(CG_SPLL_FUNC_CNTL_2); | ||
206 | pi->clk_regs.rv730.cg_spll_func_cntl_3 = | ||
207 | RREG32(CG_SPLL_FUNC_CNTL_3); | ||
208 | pi->clk_regs.rv730.cg_spll_spread_spectrum = | ||
209 | RREG32(CG_SPLL_SPREAD_SPECTRUM); | ||
210 | pi->clk_regs.rv730.cg_spll_spread_spectrum_2 = | ||
211 | RREG32(CG_SPLL_SPREAD_SPECTRUM_2); | ||
212 | |||
213 | pi->clk_regs.rv730.mclk_pwrmgt_cntl = | ||
214 | RREG32(TCI_MCLK_PWRMGT_CNTL); | ||
215 | pi->clk_regs.rv730.dll_cntl = | ||
216 | RREG32(TCI_DLL_CNTL); | ||
217 | pi->clk_regs.rv730.mpll_func_cntl = | ||
218 | RREG32(CG_MPLL_FUNC_CNTL); | ||
219 | pi->clk_regs.rv730.mpll_func_cntl2 = | ||
220 | RREG32(CG_MPLL_FUNC_CNTL_2); | ||
221 | pi->clk_regs.rv730.mpll_func_cntl3 = | ||
222 | RREG32(CG_MPLL_FUNC_CNTL_3); | ||
223 | pi->clk_regs.rv730.mpll_ss = | ||
224 | RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM); | ||
225 | pi->clk_regs.rv730.mpll_ss2 = | ||
226 | RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM_2); | ||
227 | } | ||
228 | |||
229 | int rv730_populate_smc_acpi_state(struct radeon_device *rdev, | ||
230 | RV770_SMC_STATETABLE *table) | ||
231 | { | ||
232 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
233 | u32 mpll_func_cntl = 0; | ||
234 | u32 mpll_func_cntl_2 = 0 ; | ||
235 | u32 mpll_func_cntl_3 = 0; | ||
236 | u32 mclk_pwrmgt_cntl; | ||
237 | u32 dll_cntl; | ||
238 | u32 spll_func_cntl; | ||
239 | u32 spll_func_cntl_2; | ||
240 | u32 spll_func_cntl_3; | ||
241 | |||
242 | table->ACPIState = table->initialState; | ||
243 | table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC; | ||
244 | |||
245 | if (pi->acpi_vddc) { | ||
246 | rv770_populate_vddc_value(rdev, pi->acpi_vddc, | ||
247 | &table->ACPIState.levels[0].vddc); | ||
248 | table->ACPIState.levels[0].gen2PCIE = pi->pcie_gen2 ? | ||
249 | pi->acpi_pcie_gen2 : 0; | ||
250 | table->ACPIState.levels[0].gen2XSP = | ||
251 | pi->acpi_pcie_gen2; | ||
252 | } else { | ||
253 | rv770_populate_vddc_value(rdev, pi->min_vddc_in_table, | ||
254 | &table->ACPIState.levels[0].vddc); | ||
255 | table->ACPIState.levels[0].gen2PCIE = 0; | ||
256 | } | ||
257 | |||
258 | mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl; | ||
259 | mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2; | ||
260 | mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3; | ||
261 | |||
262 | mpll_func_cntl |= MPLL_RESET | MPLL_BYPASS_EN; | ||
263 | mpll_func_cntl &= ~MPLL_SLEEP; | ||
264 | |||
265 | mpll_func_cntl_2 &= ~MCLK_MUX_SEL_MASK; | ||
266 | mpll_func_cntl_2 |= MCLK_MUX_SEL(1); | ||
267 | |||
268 | mclk_pwrmgt_cntl = (MRDCKA_RESET | | ||
269 | MRDCKB_RESET | | ||
270 | MRDCKC_RESET | | ||
271 | MRDCKD_RESET | | ||
272 | MRDCKE_RESET | | ||
273 | MRDCKF_RESET | | ||
274 | MRDCKG_RESET | | ||
275 | MRDCKH_RESET | | ||
276 | MRDCKA_SLEEP | | ||
277 | MRDCKB_SLEEP | | ||
278 | MRDCKC_SLEEP | | ||
279 | MRDCKD_SLEEP | | ||
280 | MRDCKE_SLEEP | | ||
281 | MRDCKF_SLEEP | | ||
282 | MRDCKG_SLEEP | | ||
283 | MRDCKH_SLEEP); | ||
284 | |||
285 | dll_cntl = 0xff000000; | ||
286 | |||
287 | spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl; | ||
288 | spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2; | ||
289 | spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3; | ||
290 | |||
291 | spll_func_cntl |= SPLL_RESET | SPLL_BYPASS_EN; | ||
292 | spll_func_cntl &= ~SPLL_SLEEP; | ||
293 | |||
294 | spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; | ||
295 | spll_func_cntl_2 |= SCLK_MUX_SEL(4); | ||
296 | |||
297 | table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl); | ||
298 | table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2); | ||
299 | table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3); | ||
300 | table->ACPIState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); | ||
301 | table->ACPIState.levels[0].mclk.mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl); | ||
302 | |||
303 | table->ACPIState.levels[0].mclk.mclk730.mclk_value = 0; | ||
304 | |||
305 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); | ||
306 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); | ||
307 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); | ||
308 | |||
309 | table->ACPIState.levels[0].sclk.sclk_value = 0; | ||
310 | |||
311 | rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd); | ||
312 | |||
313 | table->ACPIState.levels[1] = table->ACPIState.levels[0]; | ||
314 | table->ACPIState.levels[2] = table->ACPIState.levels[0]; | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | int rv730_populate_smc_initial_state(struct radeon_device *rdev, | ||
320 | struct radeon_ps *radeon_state, | ||
321 | RV770_SMC_STATETABLE *table) | ||
322 | { | ||
323 | struct rv7xx_ps *initial_state = rv770_get_ps(radeon_state); | ||
324 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
325 | u32 a_t; | ||
326 | |||
327 | table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL = | ||
328 | cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl); | ||
329 | table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 = | ||
330 | cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl2); | ||
331 | table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 = | ||
332 | cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl3); | ||
333 | table->initialState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL = | ||
334 | cpu_to_be32(pi->clk_regs.rv730.mclk_pwrmgt_cntl); | ||
335 | table->initialState.levels[0].mclk.mclk730.vDLL_CNTL = | ||
336 | cpu_to_be32(pi->clk_regs.rv730.dll_cntl); | ||
337 | table->initialState.levels[0].mclk.mclk730.vMPLL_SS = | ||
338 | cpu_to_be32(pi->clk_regs.rv730.mpll_ss); | ||
339 | table->initialState.levels[0].mclk.mclk730.vMPLL_SS2 = | ||
340 | cpu_to_be32(pi->clk_regs.rv730.mpll_ss2); | ||
341 | |||
342 | table->initialState.levels[0].mclk.mclk730.mclk_value = | ||
343 | cpu_to_be32(initial_state->low.mclk); | ||
344 | |||
345 | table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = | ||
346 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl); | ||
347 | table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = | ||
348 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_2); | ||
349 | table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = | ||
350 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_3); | ||
351 | table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM = | ||
352 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum); | ||
353 | table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 = | ||
354 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum_2); | ||
355 | |||
356 | table->initialState.levels[0].sclk.sclk_value = | ||
357 | cpu_to_be32(initial_state->low.sclk); | ||
358 | |||
359 | table->initialState.levels[0].arbValue = MC_CG_ARB_FREQ_F0; | ||
360 | |||
361 | table->initialState.levels[0].seqValue = | ||
362 | rv770_get_seq_value(rdev, &initial_state->low); | ||
363 | |||
364 | rv770_populate_vddc_value(rdev, | ||
365 | initial_state->low.vddc, | ||
366 | &table->initialState.levels[0].vddc); | ||
367 | rv770_populate_initial_mvdd_value(rdev, | ||
368 | &table->initialState.levels[0].mvdd); | ||
369 | |||
370 | a_t = CG_R(0xffff) | CG_L(0); | ||
371 | |||
372 | table->initialState.levels[0].aT = cpu_to_be32(a_t); | ||
373 | |||
374 | table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp); | ||
375 | |||
376 | if (pi->boot_in_gen2) | ||
377 | table->initialState.levels[0].gen2PCIE = 1; | ||
378 | else | ||
379 | table->initialState.levels[0].gen2PCIE = 0; | ||
380 | if (initial_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) | ||
381 | table->initialState.levels[0].gen2XSP = 1; | ||
382 | else | ||
383 | table->initialState.levels[0].gen2XSP = 0; | ||
384 | |||
385 | table->initialState.levels[1] = table->initialState.levels[0]; | ||
386 | table->initialState.levels[2] = table->initialState.levels[0]; | ||
387 | |||
388 | table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC; | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | void rv730_program_memory_timing_parameters(struct radeon_device *rdev, | ||
394 | struct radeon_ps *radeon_state) | ||
395 | { | ||
396 | struct rv7xx_ps *state = rv770_get_ps(radeon_state); | ||
397 | u32 arb_refresh_rate = 0; | ||
398 | u32 dram_timing = 0; | ||
399 | u32 dram_timing2 = 0; | ||
400 | u32 old_dram_timing = 0; | ||
401 | u32 old_dram_timing2 = 0; | ||
402 | |||
403 | arb_refresh_rate = RREG32(MC_ARB_RFSH_RATE) & | ||
404 | ~(POWERMODE1_MASK | POWERMODE2_MASK | POWERMODE3_MASK); | ||
405 | arb_refresh_rate |= | ||
406 | (POWERMODE1(rv770_calculate_memory_refresh_rate(rdev, state->low.sclk)) | | ||
407 | POWERMODE2(rv770_calculate_memory_refresh_rate(rdev, state->medium.sclk)) | | ||
408 | POWERMODE3(rv770_calculate_memory_refresh_rate(rdev, state->high.sclk))); | ||
409 | WREG32(MC_ARB_RFSH_RATE, arb_refresh_rate); | ||
410 | |||
411 | /* save the boot dram timings */ | ||
412 | old_dram_timing = RREG32(MC_ARB_DRAM_TIMING); | ||
413 | old_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); | ||
414 | |||
415 | radeon_atom_set_engine_dram_timings(rdev, | ||
416 | state->high.sclk, | ||
417 | state->high.mclk); | ||
418 | |||
419 | dram_timing = RREG32(MC_ARB_DRAM_TIMING); | ||
420 | dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); | ||
421 | |||
422 | WREG32(MC_ARB_DRAM_TIMING_3, dram_timing); | ||
423 | WREG32(MC_ARB_DRAM_TIMING2_3, dram_timing2); | ||
424 | |||
425 | radeon_atom_set_engine_dram_timings(rdev, | ||
426 | state->medium.sclk, | ||
427 | state->medium.mclk); | ||
428 | |||
429 | dram_timing = RREG32(MC_ARB_DRAM_TIMING); | ||
430 | dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); | ||
431 | |||
432 | WREG32(MC_ARB_DRAM_TIMING_2, dram_timing); | ||
433 | WREG32(MC_ARB_DRAM_TIMING2_2, dram_timing2); | ||
434 | |||
435 | radeon_atom_set_engine_dram_timings(rdev, | ||
436 | state->low.sclk, | ||
437 | state->low.mclk); | ||
438 | |||
439 | dram_timing = RREG32(MC_ARB_DRAM_TIMING); | ||
440 | dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); | ||
441 | |||
442 | WREG32(MC_ARB_DRAM_TIMING_1, dram_timing); | ||
443 | WREG32(MC_ARB_DRAM_TIMING2_1, dram_timing2); | ||
444 | |||
445 | /* restore the boot dram timings */ | ||
446 | WREG32(MC_ARB_DRAM_TIMING, old_dram_timing); | ||
447 | WREG32(MC_ARB_DRAM_TIMING2, old_dram_timing2); | ||
448 | |||
449 | } | ||
450 | |||
451 | void rv730_start_dpm(struct radeon_device *rdev) | ||
452 | { | ||
453 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF); | ||
454 | |||
455 | WREG32_P(TCI_MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF); | ||
456 | |||
457 | WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); | ||
458 | } | ||
459 | |||
460 | void rv730_stop_dpm(struct radeon_device *rdev) | ||
461 | { | ||
462 | PPSMC_Result result; | ||
463 | |||
464 | result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled); | ||
465 | |||
466 | if (result != PPSMC_Result_OK) | ||
467 | DRM_ERROR("Could not force DPM to low\n"); | ||
468 | |||
469 | WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); | ||
470 | |||
471 | WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); | ||
472 | |||
473 | WREG32_P(TCI_MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF); | ||
474 | } | ||
475 | |||
476 | void rv730_program_dcodt(struct radeon_device *rdev, bool use_dcodt) | ||
477 | { | ||
478 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
479 | u32 i = use_dcodt ? 0 : 1; | ||
480 | u32 mc4_io_pad_cntl; | ||
481 | |||
482 | mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0); | ||
483 | mc4_io_pad_cntl &= 0xFFFFFF00; | ||
484 | mc4_io_pad_cntl |= pi->odt_value_0[i]; | ||
485 | WREG32(MC4_IO_DQ_PAD_CNTL_D0_I0, mc4_io_pad_cntl); | ||
486 | WREG32(MC4_IO_DQ_PAD_CNTL_D0_I1, mc4_io_pad_cntl); | ||
487 | |||
488 | mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0); | ||
489 | mc4_io_pad_cntl &= 0xFFFFFF00; | ||
490 | mc4_io_pad_cntl |= pi->odt_value_1[i]; | ||
491 | WREG32(MC4_IO_QS_PAD_CNTL_D0_I0, mc4_io_pad_cntl); | ||
492 | WREG32(MC4_IO_QS_PAD_CNTL_D0_I1, mc4_io_pad_cntl); | ||
493 | } | ||
494 | |||
495 | void rv730_get_odt_values(struct radeon_device *rdev) | ||
496 | { | ||
497 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
498 | u32 mc4_io_pad_cntl; | ||
499 | |||
500 | pi->odt_value_0[0] = (u8)0; | ||
501 | pi->odt_value_1[0] = (u8)0x80; | ||
502 | |||
503 | mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0); | ||
504 | pi->odt_value_0[1] = (u8)(mc4_io_pad_cntl & 0xff); | ||
505 | |||
506 | mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0); | ||
507 | pi->odt_value_1[1] = (u8)(mc4_io_pad_cntl & 0xff); | ||
508 | } | ||
diff --git a/drivers/gpu/drm/radeon/rv730d.h b/drivers/gpu/drm/radeon/rv730d.h new file mode 100644 index 000000000000..f0a7954fb1cb --- /dev/null +++ b/drivers/gpu/drm/radeon/rv730d.h | |||
@@ -0,0 +1,165 @@ | |||
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 RV730_H | ||
24 | #define RV730_H | ||
25 | |||
26 | #define CG_SPLL_FUNC_CNTL 0x600 | ||
27 | #define SPLL_RESET (1 << 0) | ||
28 | #define SPLL_SLEEP (1 << 1) | ||
29 | #define SPLL_DIVEN (1 << 2) | ||
30 | #define SPLL_BYPASS_EN (1 << 3) | ||
31 | #define SPLL_REF_DIV(x) ((x) << 4) | ||
32 | #define SPLL_REF_DIV_MASK (0x3f << 4) | ||
33 | #define SPLL_HILEN(x) ((x) << 12) | ||
34 | #define SPLL_HILEN_MASK (0xf << 12) | ||
35 | #define SPLL_LOLEN(x) ((x) << 16) | ||
36 | #define SPLL_LOLEN_MASK (0xf << 16) | ||
37 | #define CG_SPLL_FUNC_CNTL_2 0x604 | ||
38 | #define SCLK_MUX_SEL(x) ((x) << 0) | ||
39 | #define SCLK_MUX_SEL_MASK (0x1ff << 0) | ||
40 | #define CG_SPLL_FUNC_CNTL_3 0x608 | ||
41 | #define SPLL_FB_DIV(x) ((x) << 0) | ||
42 | #define SPLL_FB_DIV_MASK (0x3ffffff << 0) | ||
43 | #define SPLL_DITHEN (1 << 28) | ||
44 | |||
45 | #define CG_MPLL_FUNC_CNTL 0x624 | ||
46 | #define MPLL_RESET (1 << 0) | ||
47 | #define MPLL_SLEEP (1 << 1) | ||
48 | #define MPLL_DIVEN (1 << 2) | ||
49 | #define MPLL_BYPASS_EN (1 << 3) | ||
50 | #define MPLL_REF_DIV(x) ((x) << 4) | ||
51 | #define MPLL_REF_DIV_MASK (0x3f << 4) | ||
52 | #define MPLL_HILEN(x) ((x) << 12) | ||
53 | #define MPLL_HILEN_MASK (0xf << 12) | ||
54 | #define MPLL_LOLEN(x) ((x) << 16) | ||
55 | #define MPLL_LOLEN_MASK (0xf << 16) | ||
56 | #define CG_MPLL_FUNC_CNTL_2 0x628 | ||
57 | #define MCLK_MUX_SEL(x) ((x) << 0) | ||
58 | #define MCLK_MUX_SEL_MASK (0x1ff << 0) | ||
59 | #define CG_MPLL_FUNC_CNTL_3 0x62c | ||
60 | #define MPLL_FB_DIV(x) ((x) << 0) | ||
61 | #define MPLL_FB_DIV_MASK (0x3ffffff << 0) | ||
62 | #define MPLL_DITHEN (1 << 28) | ||
63 | |||
64 | #define CG_TCI_MPLL_SPREAD_SPECTRUM 0x634 | ||
65 | #define CG_TCI_MPLL_SPREAD_SPECTRUM_2 0x638 | ||
66 | #define GENERAL_PWRMGT 0x63c | ||
67 | # define GLOBAL_PWRMGT_EN (1 << 0) | ||
68 | # define STATIC_PM_EN (1 << 1) | ||
69 | # define THERMAL_PROTECTION_DIS (1 << 2) | ||
70 | # define THERMAL_PROTECTION_TYPE (1 << 3) | ||
71 | # define ENABLE_GEN2PCIE (1 << 4) | ||
72 | # define ENABLE_GEN2XSP (1 << 5) | ||
73 | # define SW_SMIO_INDEX(x) ((x) << 6) | ||
74 | # define SW_SMIO_INDEX_MASK (3 << 6) | ||
75 | # define LOW_VOLT_D2_ACPI (1 << 8) | ||
76 | # define LOW_VOLT_D3_ACPI (1 << 9) | ||
77 | # define VOLT_PWRMGT_EN (1 << 10) | ||
78 | # define BACKBIAS_PAD_EN (1 << 18) | ||
79 | # define BACKBIAS_VALUE (1 << 19) | ||
80 | # define DYN_SPREAD_SPECTRUM_EN (1 << 23) | ||
81 | # define AC_DC_SW (1 << 24) | ||
82 | |||
83 | #define SCLK_PWRMGT_CNTL 0x644 | ||
84 | # define SCLK_PWRMGT_OFF (1 << 0) | ||
85 | # define SCLK_LOW_D1 (1 << 1) | ||
86 | # define FIR_RESET (1 << 4) | ||
87 | # define FIR_FORCE_TREND_SEL (1 << 5) | ||
88 | # define FIR_TREND_MODE (1 << 6) | ||
89 | # define DYN_GFX_CLK_OFF_EN (1 << 7) | ||
90 | # define GFX_CLK_FORCE_ON (1 << 8) | ||
91 | # define GFX_CLK_REQUEST_OFF (1 << 9) | ||
92 | # define GFX_CLK_FORCE_OFF (1 << 10) | ||
93 | # define GFX_CLK_OFF_ACPI_D1 (1 << 11) | ||
94 | # define GFX_CLK_OFF_ACPI_D2 (1 << 12) | ||
95 | # define GFX_CLK_OFF_ACPI_D3 (1 << 13) | ||
96 | |||
97 | #define TCI_MCLK_PWRMGT_CNTL 0x648 | ||
98 | # define MPLL_PWRMGT_OFF (1 << 5) | ||
99 | # define DLL_READY (1 << 6) | ||
100 | # define MC_INT_CNTL (1 << 7) | ||
101 | # define MRDCKA_SLEEP (1 << 8) | ||
102 | # define MRDCKB_SLEEP (1 << 9) | ||
103 | # define MRDCKC_SLEEP (1 << 10) | ||
104 | # define MRDCKD_SLEEP (1 << 11) | ||
105 | # define MRDCKE_SLEEP (1 << 12) | ||
106 | # define MRDCKF_SLEEP (1 << 13) | ||
107 | # define MRDCKG_SLEEP (1 << 14) | ||
108 | # define MRDCKH_SLEEP (1 << 15) | ||
109 | # define MRDCKA_RESET (1 << 16) | ||
110 | # define MRDCKB_RESET (1 << 17) | ||
111 | # define MRDCKC_RESET (1 << 18) | ||
112 | # define MRDCKD_RESET (1 << 19) | ||
113 | # define MRDCKE_RESET (1 << 20) | ||
114 | # define MRDCKF_RESET (1 << 21) | ||
115 | # define MRDCKG_RESET (1 << 22) | ||
116 | # define MRDCKH_RESET (1 << 23) | ||
117 | # define DLL_READY_READ (1 << 24) | ||
118 | # define USE_DISPLAY_GAP (1 << 25) | ||
119 | # define USE_DISPLAY_URGENT_NORMAL (1 << 26) | ||
120 | # define MPLL_TURNOFF_D2 (1 << 28) | ||
121 | #define TCI_DLL_CNTL 0x64c | ||
122 | |||
123 | #define CG_PG_CNTL 0x858 | ||
124 | # define PWRGATE_ENABLE (1 << 0) | ||
125 | |||
126 | #define CG_AT 0x6d4 | ||
127 | #define CG_R(x) ((x) << 0) | ||
128 | #define CG_R_MASK (0xffff << 0) | ||
129 | #define CG_L(x) ((x) << 16) | ||
130 | #define CG_L_MASK (0xffff << 16) | ||
131 | |||
132 | #define CG_SPLL_SPREAD_SPECTRUM 0x790 | ||
133 | #define SSEN (1 << 0) | ||
134 | #define CLK_S(x) ((x) << 4) | ||
135 | #define CLK_S_MASK (0xfff << 4) | ||
136 | #define CG_SPLL_SPREAD_SPECTRUM_2 0x794 | ||
137 | #define CLK_V(x) ((x) << 0) | ||
138 | #define CLK_V_MASK (0x3ffffff << 0) | ||
139 | |||
140 | #define MC_ARB_DRAM_TIMING 0x2774 | ||
141 | #define MC_ARB_DRAM_TIMING2 0x2778 | ||
142 | |||
143 | #define MC_ARB_RFSH_RATE 0x27b0 | ||
144 | #define POWERMODE0(x) ((x) << 0) | ||
145 | #define POWERMODE0_MASK (0xff << 0) | ||
146 | #define POWERMODE1(x) ((x) << 8) | ||
147 | #define POWERMODE1_MASK (0xff << 8) | ||
148 | #define POWERMODE2(x) ((x) << 16) | ||
149 | #define POWERMODE2_MASK (0xff << 16) | ||
150 | #define POWERMODE3(x) ((x) << 24) | ||
151 | #define POWERMODE3_MASK (0xff << 24) | ||
152 | |||
153 | #define MC_ARB_DRAM_TIMING_1 0x27f0 | ||
154 | #define MC_ARB_DRAM_TIMING_2 0x27f4 | ||
155 | #define MC_ARB_DRAM_TIMING_3 0x27f8 | ||
156 | #define MC_ARB_DRAM_TIMING2_1 0x27fc | ||
157 | #define MC_ARB_DRAM_TIMING2_2 0x2800 | ||
158 | #define MC_ARB_DRAM_TIMING2_3 0x2804 | ||
159 | |||
160 | #define MC4_IO_DQ_PAD_CNTL_D0_I0 0x2978 | ||
161 | #define MC4_IO_DQ_PAD_CNTL_D0_I1 0x297c | ||
162 | #define MC4_IO_QS_PAD_CNTL_D0_I0 0x2980 | ||
163 | #define MC4_IO_QS_PAD_CNTL_D0_I1 0x2984 | ||
164 | |||
165 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/rv740_dpm.c b/drivers/gpu/drm/radeon/rv740_dpm.c new file mode 100644 index 000000000000..f6d79a1f62c1 --- /dev/null +++ b/drivers/gpu/drm/radeon/rv740_dpm.c | |||
@@ -0,0 +1,417 @@ | |||
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 "rv740d.h" | ||
28 | #include "r600_dpm.h" | ||
29 | #include "rv770_dpm.h" | ||
30 | #include "atom.h" | ||
31 | |||
32 | struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps); | ||
33 | struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev); | ||
34 | |||
35 | u32 rv740_get_decoded_reference_divider(u32 encoded_ref) | ||
36 | { | ||
37 | u32 ref = 0; | ||
38 | |||
39 | switch (encoded_ref) { | ||
40 | case 0: | ||
41 | ref = 1; | ||
42 | break; | ||
43 | case 16: | ||
44 | ref = 2; | ||
45 | break; | ||
46 | case 17: | ||
47 | ref = 3; | ||
48 | break; | ||
49 | case 18: | ||
50 | ref = 2; | ||
51 | break; | ||
52 | case 19: | ||
53 | ref = 3; | ||
54 | break; | ||
55 | case 20: | ||
56 | ref = 4; | ||
57 | break; | ||
58 | case 21: | ||
59 | ref = 5; | ||
60 | break; | ||
61 | default: | ||
62 | DRM_ERROR("Invalid encoded Reference Divider\n"); | ||
63 | ref = 0; | ||
64 | break; | ||
65 | } | ||
66 | |||
67 | return ref; | ||
68 | } | ||
69 | |||
70 | struct dll_speed_setting { | ||
71 | u16 min; | ||
72 | u16 max; | ||
73 | u32 dll_speed; | ||
74 | }; | ||
75 | |||
76 | static struct dll_speed_setting dll_speed_table[16] = | ||
77 | { | ||
78 | { 270, 320, 0x0f }, | ||
79 | { 240, 270, 0x0e }, | ||
80 | { 200, 240, 0x0d }, | ||
81 | { 180, 200, 0x0c }, | ||
82 | { 160, 180, 0x0b }, | ||
83 | { 140, 160, 0x0a }, | ||
84 | { 120, 140, 0x09 }, | ||
85 | { 110, 120, 0x08 }, | ||
86 | { 95, 110, 0x07 }, | ||
87 | { 85, 95, 0x06 }, | ||
88 | { 78, 85, 0x05 }, | ||
89 | { 70, 78, 0x04 }, | ||
90 | { 65, 70, 0x03 }, | ||
91 | { 60, 65, 0x02 }, | ||
92 | { 42, 60, 0x01 }, | ||
93 | { 00, 42, 0x00 } | ||
94 | }; | ||
95 | |||
96 | u32 rv740_get_dll_speed(bool is_gddr5, u32 memory_clock) | ||
97 | { | ||
98 | int i; | ||
99 | u32 factor; | ||
100 | u16 data_rate; | ||
101 | |||
102 | if (is_gddr5) | ||
103 | factor = 4; | ||
104 | else | ||
105 | factor = 2; | ||
106 | |||
107 | data_rate = (u16)(memory_clock * factor / 1000); | ||
108 | |||
109 | if (data_rate < dll_speed_table[0].max) { | ||
110 | for (i = 0; i < 16; i++) { | ||
111 | if (data_rate > dll_speed_table[i].min && | ||
112 | data_rate <= dll_speed_table[i].max) | ||
113 | return dll_speed_table[i].dll_speed; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | DRM_DEBUG_KMS("Target MCLK greater than largest MCLK in DLL speed table\n"); | ||
118 | |||
119 | return 0x0f; | ||
120 | } | ||
121 | |||
122 | int rv740_populate_sclk_value(struct radeon_device *rdev, u32 engine_clock, | ||
123 | RV770_SMC_SCLK_VALUE *sclk) | ||
124 | { | ||
125 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
126 | struct atom_clock_dividers dividers; | ||
127 | u32 spll_func_cntl = pi->clk_regs.rv770.cg_spll_func_cntl; | ||
128 | u32 spll_func_cntl_2 = pi->clk_regs.rv770.cg_spll_func_cntl_2; | ||
129 | u32 spll_func_cntl_3 = pi->clk_regs.rv770.cg_spll_func_cntl_3; | ||
130 | u32 cg_spll_spread_spectrum = pi->clk_regs.rv770.cg_spll_spread_spectrum; | ||
131 | u32 cg_spll_spread_spectrum_2 = pi->clk_regs.rv770.cg_spll_spread_spectrum_2; | ||
132 | u64 tmp; | ||
133 | u32 reference_clock = rdev->clock.spll.reference_freq; | ||
134 | u32 reference_divider; | ||
135 | u32 fbdiv; | ||
136 | int ret; | ||
137 | |||
138 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, | ||
139 | engine_clock, false, ÷rs); | ||
140 | if (ret) | ||
141 | return ret; | ||
142 | |||
143 | reference_divider = 1 + dividers.ref_div; | ||
144 | |||
145 | tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16384; | ||
146 | do_div(tmp, reference_clock); | ||
147 | fbdiv = (u32) tmp; | ||
148 | |||
149 | spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK); | ||
150 | spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div); | ||
151 | spll_func_cntl |= SPLL_PDIV_A(dividers.post_div); | ||
152 | |||
153 | spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; | ||
154 | spll_func_cntl_2 |= SCLK_MUX_SEL(2); | ||
155 | |||
156 | spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; | ||
157 | spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); | ||
158 | spll_func_cntl_3 |= SPLL_DITHEN; | ||
159 | |||
160 | if (pi->sclk_ss) { | ||
161 | struct radeon_atom_ss ss; | ||
162 | u32 vco_freq = engine_clock * dividers.post_div; | ||
163 | |||
164 | if (radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
165 | ASIC_INTERNAL_ENGINE_SS, vco_freq)) { | ||
166 | u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); | ||
167 | u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000); | ||
168 | |||
169 | cg_spll_spread_spectrum &= ~CLK_S_MASK; | ||
170 | cg_spll_spread_spectrum |= CLK_S(clk_s); | ||
171 | cg_spll_spread_spectrum |= SSEN; | ||
172 | |||
173 | cg_spll_spread_spectrum_2 &= ~CLK_V_MASK; | ||
174 | cg_spll_spread_spectrum_2 |= CLK_V(clk_v); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | sclk->sclk_value = cpu_to_be32(engine_clock); | ||
179 | sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); | ||
180 | sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); | ||
181 | sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); | ||
182 | sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum); | ||
183 | sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | int rv740_populate_mclk_value(struct radeon_device *rdev, | ||
189 | u32 engine_clock, u32 memory_clock, | ||
190 | RV7XX_SMC_MCLK_VALUE *mclk) | ||
191 | { | ||
192 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
193 | u32 mpll_ad_func_cntl = pi->clk_regs.rv770.mpll_ad_func_cntl; | ||
194 | u32 mpll_ad_func_cntl_2 = pi->clk_regs.rv770.mpll_ad_func_cntl_2; | ||
195 | u32 mpll_dq_func_cntl = pi->clk_regs.rv770.mpll_dq_func_cntl; | ||
196 | u32 mpll_dq_func_cntl_2 = pi->clk_regs.rv770.mpll_dq_func_cntl_2; | ||
197 | u32 mclk_pwrmgt_cntl = pi->clk_regs.rv770.mclk_pwrmgt_cntl; | ||
198 | u32 dll_cntl = pi->clk_regs.rv770.dll_cntl; | ||
199 | u32 mpll_ss1 = pi->clk_regs.rv770.mpll_ss1; | ||
200 | u32 mpll_ss2 = pi->clk_regs.rv770.mpll_ss2; | ||
201 | struct atom_clock_dividers dividers; | ||
202 | u32 ibias; | ||
203 | u32 dll_speed; | ||
204 | int ret; | ||
205 | |||
206 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM, | ||
207 | memory_clock, false, ÷rs); | ||
208 | if (ret) | ||
209 | return ret; | ||
210 | |||
211 | ibias = rv770_map_clkf_to_ibias(rdev, dividers.whole_fb_div); | ||
212 | |||
213 | mpll_ad_func_cntl &= ~(CLKR_MASK | | ||
214 | YCLK_POST_DIV_MASK | | ||
215 | CLKF_MASK | | ||
216 | CLKFRAC_MASK | | ||
217 | IBIAS_MASK); | ||
218 | mpll_ad_func_cntl |= CLKR(dividers.ref_div); | ||
219 | mpll_ad_func_cntl |= YCLK_POST_DIV(dividers.post_div); | ||
220 | mpll_ad_func_cntl |= CLKF(dividers.whole_fb_div); | ||
221 | mpll_ad_func_cntl |= CLKFRAC(dividers.frac_fb_div); | ||
222 | mpll_ad_func_cntl |= IBIAS(ibias); | ||
223 | |||
224 | if (dividers.vco_mode) | ||
225 | mpll_ad_func_cntl_2 |= VCO_MODE; | ||
226 | else | ||
227 | mpll_ad_func_cntl_2 &= ~VCO_MODE; | ||
228 | |||
229 | if (pi->mem_gddr5) { | ||
230 | mpll_dq_func_cntl &= ~(CLKR_MASK | | ||
231 | YCLK_POST_DIV_MASK | | ||
232 | CLKF_MASK | | ||
233 | CLKFRAC_MASK | | ||
234 | IBIAS_MASK); | ||
235 | mpll_dq_func_cntl |= CLKR(dividers.ref_div); | ||
236 | mpll_dq_func_cntl |= YCLK_POST_DIV(dividers.post_div); | ||
237 | mpll_dq_func_cntl |= CLKF(dividers.whole_fb_div); | ||
238 | mpll_dq_func_cntl |= CLKFRAC(dividers.frac_fb_div); | ||
239 | mpll_dq_func_cntl |= IBIAS(ibias); | ||
240 | |||
241 | if (dividers.vco_mode) | ||
242 | mpll_dq_func_cntl_2 |= VCO_MODE; | ||
243 | else | ||
244 | mpll_dq_func_cntl_2 &= ~VCO_MODE; | ||
245 | } | ||
246 | |||
247 | if (pi->mclk_ss) { | ||
248 | struct radeon_atom_ss ss; | ||
249 | u32 vco_freq = memory_clock * dividers.post_div; | ||
250 | |||
251 | if (radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
252 | ASIC_INTERNAL_MEMORY_SS, vco_freq)) { | ||
253 | u32 reference_clock = rdev->clock.mpll.reference_freq; | ||
254 | u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div); | ||
255 | u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate); | ||
256 | u32 clk_v = 0x40000 * ss.percentage * | ||
257 | (dividers.whole_fb_div + (dividers.frac_fb_div / 8)) / (clk_s * 10000); | ||
258 | |||
259 | mpll_ss1 &= ~CLKV_MASK; | ||
260 | mpll_ss1 |= CLKV(clk_v); | ||
261 | |||
262 | mpll_ss2 &= ~CLKS_MASK; | ||
263 | mpll_ss2 |= CLKS(clk_s); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | dll_speed = rv740_get_dll_speed(pi->mem_gddr5, | ||
268 | memory_clock); | ||
269 | |||
270 | mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK; | ||
271 | mclk_pwrmgt_cntl |= DLL_SPEED(dll_speed); | ||
272 | |||
273 | mclk->mclk770.mclk_value = cpu_to_be32(memory_clock); | ||
274 | mclk->mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl); | ||
275 | mclk->mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2); | ||
276 | mclk->mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl); | ||
277 | mclk->mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2); | ||
278 | mclk->mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); | ||
279 | mclk->mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl); | ||
280 | mclk->mclk770.vMPLL_SS = cpu_to_be32(mpll_ss1); | ||
281 | mclk->mclk770.vMPLL_SS2 = cpu_to_be32(mpll_ss2); | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | void rv740_read_clock_registers(struct radeon_device *rdev) | ||
287 | { | ||
288 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
289 | |||
290 | pi->clk_regs.rv770.cg_spll_func_cntl = | ||
291 | RREG32(CG_SPLL_FUNC_CNTL); | ||
292 | pi->clk_regs.rv770.cg_spll_func_cntl_2 = | ||
293 | RREG32(CG_SPLL_FUNC_CNTL_2); | ||
294 | pi->clk_regs.rv770.cg_spll_func_cntl_3 = | ||
295 | RREG32(CG_SPLL_FUNC_CNTL_3); | ||
296 | pi->clk_regs.rv770.cg_spll_spread_spectrum = | ||
297 | RREG32(CG_SPLL_SPREAD_SPECTRUM); | ||
298 | pi->clk_regs.rv770.cg_spll_spread_spectrum_2 = | ||
299 | RREG32(CG_SPLL_SPREAD_SPECTRUM_2); | ||
300 | |||
301 | pi->clk_regs.rv770.mpll_ad_func_cntl = | ||
302 | RREG32(MPLL_AD_FUNC_CNTL); | ||
303 | pi->clk_regs.rv770.mpll_ad_func_cntl_2 = | ||
304 | RREG32(MPLL_AD_FUNC_CNTL_2); | ||
305 | pi->clk_regs.rv770.mpll_dq_func_cntl = | ||
306 | RREG32(MPLL_DQ_FUNC_CNTL); | ||
307 | pi->clk_regs.rv770.mpll_dq_func_cntl_2 = | ||
308 | RREG32(MPLL_DQ_FUNC_CNTL_2); | ||
309 | pi->clk_regs.rv770.mclk_pwrmgt_cntl = | ||
310 | RREG32(MCLK_PWRMGT_CNTL); | ||
311 | pi->clk_regs.rv770.dll_cntl = RREG32(DLL_CNTL); | ||
312 | pi->clk_regs.rv770.mpll_ss1 = RREG32(MPLL_SS1); | ||
313 | pi->clk_regs.rv770.mpll_ss2 = RREG32(MPLL_SS2); | ||
314 | } | ||
315 | |||
316 | int rv740_populate_smc_acpi_state(struct radeon_device *rdev, | ||
317 | RV770_SMC_STATETABLE *table) | ||
318 | { | ||
319 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
320 | u32 mpll_ad_func_cntl = pi->clk_regs.rv770.mpll_ad_func_cntl; | ||
321 | u32 mpll_ad_func_cntl_2 = pi->clk_regs.rv770.mpll_ad_func_cntl_2; | ||
322 | u32 mpll_dq_func_cntl = pi->clk_regs.rv770.mpll_dq_func_cntl; | ||
323 | u32 mpll_dq_func_cntl_2 = pi->clk_regs.rv770.mpll_dq_func_cntl_2; | ||
324 | u32 spll_func_cntl = pi->clk_regs.rv770.cg_spll_func_cntl; | ||
325 | u32 spll_func_cntl_2 = pi->clk_regs.rv770.cg_spll_func_cntl_2; | ||
326 | u32 spll_func_cntl_3 = pi->clk_regs.rv770.cg_spll_func_cntl_3; | ||
327 | u32 mclk_pwrmgt_cntl = pi->clk_regs.rv770.mclk_pwrmgt_cntl; | ||
328 | u32 dll_cntl = pi->clk_regs.rv770.dll_cntl; | ||
329 | |||
330 | table->ACPIState = table->initialState; | ||
331 | |||
332 | table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC; | ||
333 | |||
334 | if (pi->acpi_vddc) { | ||
335 | rv770_populate_vddc_value(rdev, pi->acpi_vddc, | ||
336 | &table->ACPIState.levels[0].vddc); | ||
337 | table->ACPIState.levels[0].gen2PCIE = | ||
338 | pi->pcie_gen2 ? | ||
339 | pi->acpi_pcie_gen2 : 0; | ||
340 | table->ACPIState.levels[0].gen2XSP = | ||
341 | pi->acpi_pcie_gen2; | ||
342 | } else { | ||
343 | rv770_populate_vddc_value(rdev, pi->min_vddc_in_table, | ||
344 | &table->ACPIState.levels[0].vddc); | ||
345 | table->ACPIState.levels[0].gen2PCIE = 0; | ||
346 | } | ||
347 | |||
348 | mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN; | ||
349 | |||
350 | mpll_dq_func_cntl_2 |= BYPASS | BIAS_GEN_PDNB | RESET_EN; | ||
351 | |||
352 | mclk_pwrmgt_cntl |= (MRDCKA0_RESET | | ||
353 | MRDCKA1_RESET | | ||
354 | MRDCKB0_RESET | | ||
355 | MRDCKB1_RESET | | ||
356 | MRDCKC0_RESET | | ||
357 | MRDCKC1_RESET | | ||
358 | MRDCKD0_RESET | | ||
359 | MRDCKD1_RESET); | ||
360 | |||
361 | dll_cntl |= (MRDCKA0_BYPASS | | ||
362 | MRDCKA1_BYPASS | | ||
363 | MRDCKB0_BYPASS | | ||
364 | MRDCKB1_BYPASS | | ||
365 | MRDCKC0_BYPASS | | ||
366 | MRDCKC1_BYPASS | | ||
367 | MRDCKD0_BYPASS | | ||
368 | MRDCKD1_BYPASS); | ||
369 | |||
370 | spll_func_cntl |= SPLL_RESET | SPLL_SLEEP | SPLL_BYPASS_EN; | ||
371 | |||
372 | spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; | ||
373 | spll_func_cntl_2 |= SCLK_MUX_SEL(4); | ||
374 | |||
375 | table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl); | ||
376 | table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2); | ||
377 | table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl); | ||
378 | table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2); | ||
379 | table->ACPIState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); | ||
380 | table->ACPIState.levels[0].mclk.mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl); | ||
381 | |||
382 | table->ACPIState.levels[0].mclk.mclk770.mclk_value = 0; | ||
383 | |||
384 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); | ||
385 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); | ||
386 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); | ||
387 | |||
388 | table->ACPIState.levels[0].sclk.sclk_value = 0; | ||
389 | |||
390 | table->ACPIState.levels[1] = table->ACPIState.levels[0]; | ||
391 | table->ACPIState.levels[2] = table->ACPIState.levels[0]; | ||
392 | |||
393 | rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd); | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | void rv740_enable_mclk_spread_spectrum(struct radeon_device *rdev, | ||
399 | bool enable) | ||
400 | { | ||
401 | if (enable) | ||
402 | WREG32_P(MPLL_CNTL_MODE, SS_SSEN, ~SS_SSEN); | ||
403 | else | ||
404 | WREG32_P(MPLL_CNTL_MODE, 0, ~SS_SSEN); | ||
405 | } | ||
406 | |||
407 | u8 rv740_get_mclk_frequency_ratio(u32 memory_clock) | ||
408 | { | ||
409 | u8 mc_para_index; | ||
410 | |||
411 | if ((memory_clock < 10000) || (memory_clock > 47500)) | ||
412 | mc_para_index = 0x00; | ||
413 | else | ||
414 | mc_para_index = (u8)((memory_clock - 10000) / 2500); | ||
415 | |||
416 | return mc_para_index; | ||
417 | } | ||
diff --git a/drivers/gpu/drm/radeon/rv740d.h b/drivers/gpu/drm/radeon/rv740d.h new file mode 100644 index 000000000000..fe5ab075dc17 --- /dev/null +++ b/drivers/gpu/drm/radeon/rv740d.h | |||
@@ -0,0 +1,117 @@ | |||
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 RV740_H | ||
24 | #define RV740_H | ||
25 | |||
26 | #define CG_SPLL_FUNC_CNTL 0x600 | ||
27 | #define SPLL_RESET (1 << 0) | ||
28 | #define SPLL_SLEEP (1 << 1) | ||
29 | #define SPLL_BYPASS_EN (1 << 3) | ||
30 | #define SPLL_REF_DIV(x) ((x) << 4) | ||
31 | #define SPLL_REF_DIV_MASK (0x3f << 4) | ||
32 | #define SPLL_PDIV_A(x) ((x) << 20) | ||
33 | #define SPLL_PDIV_A_MASK (0x7f << 20) | ||
34 | #define CG_SPLL_FUNC_CNTL_2 0x604 | ||
35 | #define SCLK_MUX_SEL(x) ((x) << 0) | ||
36 | #define SCLK_MUX_SEL_MASK (0x1ff << 0) | ||
37 | #define CG_SPLL_FUNC_CNTL_3 0x608 | ||
38 | #define SPLL_FB_DIV(x) ((x) << 0) | ||
39 | #define SPLL_FB_DIV_MASK (0x3ffffff << 0) | ||
40 | #define SPLL_DITHEN (1 << 28) | ||
41 | |||
42 | #define MPLL_CNTL_MODE 0x61c | ||
43 | #define SS_SSEN (1 << 24) | ||
44 | |||
45 | #define MPLL_AD_FUNC_CNTL 0x624 | ||
46 | #define CLKF(x) ((x) << 0) | ||
47 | #define CLKF_MASK (0x7f << 0) | ||
48 | #define CLKR(x) ((x) << 7) | ||
49 | #define CLKR_MASK (0x1f << 7) | ||
50 | #define CLKFRAC(x) ((x) << 12) | ||
51 | #define CLKFRAC_MASK (0x1f << 12) | ||
52 | #define YCLK_POST_DIV(x) ((x) << 17) | ||
53 | #define YCLK_POST_DIV_MASK (3 << 17) | ||
54 | #define IBIAS(x) ((x) << 20) | ||
55 | #define IBIAS_MASK (0x3ff << 20) | ||
56 | #define RESET (1 << 30) | ||
57 | #define PDNB (1 << 31) | ||
58 | #define MPLL_AD_FUNC_CNTL_2 0x628 | ||
59 | #define BYPASS (1 << 19) | ||
60 | #define BIAS_GEN_PDNB (1 << 24) | ||
61 | #define RESET_EN (1 << 25) | ||
62 | #define VCO_MODE (1 << 29) | ||
63 | #define MPLL_DQ_FUNC_CNTL 0x62c | ||
64 | #define MPLL_DQ_FUNC_CNTL_2 0x630 | ||
65 | |||
66 | #define MCLK_PWRMGT_CNTL 0x648 | ||
67 | #define DLL_SPEED(x) ((x) << 0) | ||
68 | #define DLL_SPEED_MASK (0x1f << 0) | ||
69 | # define MPLL_PWRMGT_OFF (1 << 5) | ||
70 | # define DLL_READY (1 << 6) | ||
71 | # define MC_INT_CNTL (1 << 7) | ||
72 | # define MRDCKA0_SLEEP (1 << 8) | ||
73 | # define MRDCKA1_SLEEP (1 << 9) | ||
74 | # define MRDCKB0_SLEEP (1 << 10) | ||
75 | # define MRDCKB1_SLEEP (1 << 11) | ||
76 | # define MRDCKC0_SLEEP (1 << 12) | ||
77 | # define MRDCKC1_SLEEP (1 << 13) | ||
78 | # define MRDCKD0_SLEEP (1 << 14) | ||
79 | # define MRDCKD1_SLEEP (1 << 15) | ||
80 | # define MRDCKA0_RESET (1 << 16) | ||
81 | # define MRDCKA1_RESET (1 << 17) | ||
82 | # define MRDCKB0_RESET (1 << 18) | ||
83 | # define MRDCKB1_RESET (1 << 19) | ||
84 | # define MRDCKC0_RESET (1 << 20) | ||
85 | # define MRDCKC1_RESET (1 << 21) | ||
86 | # define MRDCKD0_RESET (1 << 22) | ||
87 | # define MRDCKD1_RESET (1 << 23) | ||
88 | # define DLL_READY_READ (1 << 24) | ||
89 | # define USE_DISPLAY_GAP (1 << 25) | ||
90 | # define USE_DISPLAY_URGENT_NORMAL (1 << 26) | ||
91 | # define MPLL_TURNOFF_D2 (1 << 28) | ||
92 | #define DLL_CNTL 0x64c | ||
93 | # define MRDCKA0_BYPASS (1 << 24) | ||
94 | # define MRDCKA1_BYPASS (1 << 25) | ||
95 | # define MRDCKB0_BYPASS (1 << 26) | ||
96 | # define MRDCKB1_BYPASS (1 << 27) | ||
97 | # define MRDCKC0_BYPASS (1 << 28) | ||
98 | # define MRDCKC1_BYPASS (1 << 29) | ||
99 | # define MRDCKD0_BYPASS (1 << 30) | ||
100 | # define MRDCKD1_BYPASS (1 << 31) | ||
101 | |||
102 | #define CG_SPLL_SPREAD_SPECTRUM 0x790 | ||
103 | #define SSEN (1 << 0) | ||
104 | #define CLK_S(x) ((x) << 4) | ||
105 | #define CLK_S_MASK (0xfff << 4) | ||
106 | #define CG_SPLL_SPREAD_SPECTRUM_2 0x794 | ||
107 | #define CLK_V(x) ((x) << 0) | ||
108 | #define CLK_V_MASK (0x3ffffff << 0) | ||
109 | |||
110 | #define MPLL_SS1 0x85c | ||
111 | #define CLKV(x) ((x) << 0) | ||
112 | #define CLKV_MASK (0x3ffffff << 0) | ||
113 | #define MPLL_SS2 0x860 | ||
114 | #define CLKS(x) ((x) << 0) | ||
115 | #define CLKS_MASK (0xfff << 0) | ||
116 | |||
117 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c new file mode 100644 index 000000000000..232b2fdf57eb --- /dev/null +++ b/drivers/gpu/drm/radeon/rv770_dpm.c | |||
@@ -0,0 +1,2337 @@ | |||
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 "rv770d.h" | ||
28 | #include "r600_dpm.h" | ||
29 | #include "rv770_dpm.h" | ||
30 | #include "atom.h" | ||
31 | |||
32 | #define MC_CG_ARB_FREQ_F0 0x0a | ||
33 | #define MC_CG_ARB_FREQ_F1 0x0b | ||
34 | #define MC_CG_ARB_FREQ_F2 0x0c | ||
35 | #define MC_CG_ARB_FREQ_F3 0x0d | ||
36 | |||
37 | #define MC_CG_SEQ_DRAMCONF_S0 0x05 | ||
38 | #define MC_CG_SEQ_DRAMCONF_S1 0x06 | ||
39 | |||
40 | #define PCIE_BUS_CLK 10000 | ||
41 | #define TCLK (PCIE_BUS_CLK / 10) | ||
42 | |||
43 | #define SMC_RAM_END 0xC000 | ||
44 | |||
45 | struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps) | ||
46 | { | ||
47 | struct rv7xx_ps *ps = rps->ps_priv; | ||
48 | |||
49 | return ps; | ||
50 | } | ||
51 | |||
52 | struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev) | ||
53 | { | ||
54 | struct rv7xx_power_info *pi = rdev->pm.dpm.priv; | ||
55 | |||
56 | return pi; | ||
57 | } | ||
58 | |||
59 | static void rv770_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev, | ||
60 | bool enable) | ||
61 | { | ||
62 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
63 | u32 tmp; | ||
64 | |||
65 | tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); | ||
66 | if (enable) { | ||
67 | tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK; | ||
68 | tmp |= LC_HW_VOLTAGE_IF_CONTROL(1); | ||
69 | tmp |= LC_GEN2_EN_STRAP; | ||
70 | } else { | ||
71 | if (!pi->boot_in_gen2) { | ||
72 | tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK; | ||
73 | tmp &= ~LC_GEN2_EN_STRAP; | ||
74 | } | ||
75 | } | ||
76 | if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) || | ||
77 | (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2)) | ||
78 | WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp); | ||
79 | |||
80 | } | ||
81 | |||
82 | static void rv770_enable_l0s(struct radeon_device *rdev) | ||
83 | { | ||
84 | u32 tmp; | ||
85 | |||
86 | tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL) & ~LC_L0S_INACTIVITY_MASK; | ||
87 | tmp |= LC_L0S_INACTIVITY(3); | ||
88 | WREG32_PCIE_PORT(PCIE_LC_CNTL, tmp); | ||
89 | } | ||
90 | |||
91 | static void rv770_enable_l1(struct radeon_device *rdev) | ||
92 | { | ||
93 | u32 tmp; | ||
94 | |||
95 | tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL); | ||
96 | tmp &= ~LC_L1_INACTIVITY_MASK; | ||
97 | tmp |= LC_L1_INACTIVITY(4); | ||
98 | tmp &= ~LC_PMI_TO_L1_DIS; | ||
99 | tmp &= ~LC_ASPM_TO_L1_DIS; | ||
100 | WREG32_PCIE_PORT(PCIE_LC_CNTL, tmp); | ||
101 | } | ||
102 | |||
103 | static void rv770_enable_pll_sleep_in_l1(struct radeon_device *rdev) | ||
104 | { | ||
105 | u32 tmp; | ||
106 | |||
107 | tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL) & ~LC_L1_INACTIVITY_MASK; | ||
108 | tmp |= LC_L1_INACTIVITY(8); | ||
109 | WREG32_PCIE_PORT(PCIE_LC_CNTL, tmp); | ||
110 | |||
111 | /* NOTE, this is a PCIE indirect reg, not PCIE PORT */ | ||
112 | tmp = RREG32_PCIE(PCIE_P_CNTL); | ||
113 | tmp |= P_PLL_PWRDN_IN_L1L23; | ||
114 | tmp &= ~P_PLL_BUF_PDNB; | ||
115 | tmp &= ~P_PLL_PDNB; | ||
116 | tmp |= P_ALLOW_PRX_FRONTEND_SHUTOFF; | ||
117 | WREG32_PCIE(PCIE_P_CNTL, tmp); | ||
118 | } | ||
119 | |||
120 | static void rv770_gfx_clock_gating_enable(struct radeon_device *rdev, | ||
121 | bool enable) | ||
122 | { | ||
123 | if (enable) | ||
124 | WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN); | ||
125 | else { | ||
126 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN); | ||
127 | WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON); | ||
128 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON); | ||
129 | RREG32(GB_TILING_CONFIG); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | static void rv770_mg_clock_gating_enable(struct radeon_device *rdev, | ||
134 | bool enable) | ||
135 | { | ||
136 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
137 | |||
138 | if (enable) { | ||
139 | u32 mgcg_cgtt_local0; | ||
140 | |||
141 | if (rdev->family == CHIP_RV770) | ||
142 | mgcg_cgtt_local0 = RV770_MGCGTTLOCAL0_DFLT; | ||
143 | else | ||
144 | mgcg_cgtt_local0 = RV7XX_MGCGTTLOCAL0_DFLT; | ||
145 | |||
146 | WREG32(CG_CGTT_LOCAL_0, mgcg_cgtt_local0); | ||
147 | WREG32(CG_CGTT_LOCAL_1, (RV770_MGCGTTLOCAL1_DFLT & 0xFFFFCFFF)); | ||
148 | |||
149 | if (pi->mgcgtssm) | ||
150 | WREG32(CGTS_SM_CTRL_REG, RV770_MGCGCGTSSMCTRL_DFLT); | ||
151 | } else { | ||
152 | WREG32(CG_CGTT_LOCAL_0, 0xFFFFFFFF); | ||
153 | WREG32(CG_CGTT_LOCAL_1, 0xFFFFCFFF); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | void rv770_restore_cgcg(struct radeon_device *rdev) | ||
158 | { | ||
159 | bool dpm_en = false, cg_en = false; | ||
160 | |||
161 | if (RREG32(GENERAL_PWRMGT) & GLOBAL_PWRMGT_EN) | ||
162 | dpm_en = true; | ||
163 | if (RREG32(SCLK_PWRMGT_CNTL) & DYN_GFX_CLK_OFF_EN) | ||
164 | cg_en = true; | ||
165 | |||
166 | if (dpm_en && !cg_en) | ||
167 | WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN); | ||
168 | } | ||
169 | |||
170 | static void rv770_start_dpm(struct radeon_device *rdev) | ||
171 | { | ||
172 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF); | ||
173 | |||
174 | WREG32_P(MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF); | ||
175 | |||
176 | WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); | ||
177 | } | ||
178 | |||
179 | void rv770_stop_dpm(struct radeon_device *rdev) | ||
180 | { | ||
181 | PPSMC_Result result; | ||
182 | |||
183 | result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled); | ||
184 | |||
185 | if (result != PPSMC_Result_OK) | ||
186 | DRM_ERROR("Could not force DPM to low.\n"); | ||
187 | |||
188 | WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); | ||
189 | |||
190 | WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); | ||
191 | |||
192 | WREG32_P(MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF); | ||
193 | } | ||
194 | |||
195 | bool rv770_dpm_enabled(struct radeon_device *rdev) | ||
196 | { | ||
197 | if (RREG32(GENERAL_PWRMGT) & GLOBAL_PWRMGT_EN) | ||
198 | return true; | ||
199 | else | ||
200 | return false; | ||
201 | } | ||
202 | |||
203 | void rv770_enable_thermal_protection(struct radeon_device *rdev, | ||
204 | bool enable) | ||
205 | { | ||
206 | if (enable) | ||
207 | WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); | ||
208 | else | ||
209 | WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); | ||
210 | } | ||
211 | |||
212 | void rv770_enable_acpi_pm(struct radeon_device *rdev) | ||
213 | { | ||
214 | WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN); | ||
215 | } | ||
216 | |||
217 | u8 rv770_get_seq_value(struct radeon_device *rdev, | ||
218 | struct rv7xx_pl *pl) | ||
219 | { | ||
220 | return (pl->flags & ATOM_PPLIB_R600_FLAGS_LOWPOWER) ? | ||
221 | MC_CG_SEQ_DRAMCONF_S0 : MC_CG_SEQ_DRAMCONF_S1; | ||
222 | } | ||
223 | |||
224 | int rv770_read_smc_soft_register(struct radeon_device *rdev, | ||
225 | u16 reg_offset, u32 *value) | ||
226 | { | ||
227 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
228 | |||
229 | return rv770_read_smc_sram_dword(rdev, | ||
230 | pi->soft_regs_start + reg_offset, | ||
231 | value, pi->sram_end); | ||
232 | } | ||
233 | |||
234 | int rv770_write_smc_soft_register(struct radeon_device *rdev, | ||
235 | u16 reg_offset, u32 value) | ||
236 | { | ||
237 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
238 | |||
239 | return rv770_write_smc_sram_dword(rdev, | ||
240 | pi->soft_regs_start + reg_offset, | ||
241 | value, pi->sram_end); | ||
242 | } | ||
243 | |||
244 | int rv770_populate_smc_t(struct radeon_device *rdev, | ||
245 | struct radeon_ps *radeon_state, | ||
246 | RV770_SMC_SWSTATE *smc_state) | ||
247 | { | ||
248 | struct rv7xx_ps *state = rv770_get_ps(radeon_state); | ||
249 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
250 | int i; | ||
251 | int a_n; | ||
252 | int a_d; | ||
253 | u8 l[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE]; | ||
254 | u8 r[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE]; | ||
255 | u32 a_t; | ||
256 | |||
257 | l[0] = 0; | ||
258 | r[2] = 100; | ||
259 | |||
260 | a_n = (int)state->medium.sclk * RV770_LMP_DFLT + | ||
261 | (int)state->low.sclk * (R600_AH_DFLT - RV770_RLP_DFLT); | ||
262 | a_d = (int)state->low.sclk * (100 - (int)RV770_RLP_DFLT) + | ||
263 | (int)state->medium.sclk * RV770_LMP_DFLT; | ||
264 | |||
265 | l[1] = (u8)(RV770_LMP_DFLT - (int)RV770_LMP_DFLT * a_n / a_d); | ||
266 | r[0] = (u8)(RV770_RLP_DFLT + (100 - (int)RV770_RLP_DFLT) * a_n / a_d); | ||
267 | |||
268 | a_n = (int)state->high.sclk * RV770_LHP_DFLT + | ||
269 | (int)state->medium.sclk * | ||
270 | (R600_AH_DFLT - RV770_RMP_DFLT); | ||
271 | a_d = (int)state->medium.sclk * (100 - (int)RV770_RMP_DFLT) + | ||
272 | (int)state->high.sclk * RV770_LHP_DFLT; | ||
273 | |||
274 | l[2] = (u8)(RV770_LHP_DFLT - (int)RV770_LHP_DFLT * a_n / a_d); | ||
275 | r[1] = (u8)(RV770_RMP_DFLT + (100 - (int)RV770_RMP_DFLT) * a_n / a_d); | ||
276 | |||
277 | for (i = 0; i < (RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1); i++) { | ||
278 | a_t = CG_R(r[i] * pi->bsp / 200) | CG_L(l[i] * pi->bsp / 200); | ||
279 | smc_state->levels[i].aT = cpu_to_be32(a_t); | ||
280 | } | ||
281 | |||
282 | a_t = CG_R(r[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1] * pi->pbsp / 200) | | ||
283 | CG_L(l[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1] * pi->pbsp / 200); | ||
284 | |||
285 | smc_state->levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1].aT = | ||
286 | cpu_to_be32(a_t); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | int rv770_populate_smc_sp(struct radeon_device *rdev, | ||
292 | struct radeon_ps *radeon_state, | ||
293 | RV770_SMC_SWSTATE *smc_state) | ||
294 | { | ||
295 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
296 | int i; | ||
297 | |||
298 | for (i = 0; i < (RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1); i++) | ||
299 | smc_state->levels[i].bSP = cpu_to_be32(pi->dsp); | ||
300 | |||
301 | smc_state->levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1].bSP = | ||
302 | cpu_to_be32(pi->psp); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static void rv770_calculate_fractional_mpll_feedback_divider(u32 memory_clock, | ||
308 | u32 reference_clock, | ||
309 | bool gddr5, | ||
310 | struct atom_clock_dividers *dividers, | ||
311 | u32 *clkf, | ||
312 | u32 *clkfrac) | ||
313 | { | ||
314 | u32 post_divider, reference_divider, feedback_divider8; | ||
315 | u32 fyclk; | ||
316 | |||
317 | if (gddr5) | ||
318 | fyclk = (memory_clock * 8) / 2; | ||
319 | else | ||
320 | fyclk = (memory_clock * 4) / 2; | ||
321 | |||
322 | post_divider = dividers->post_div; | ||
323 | reference_divider = dividers->ref_div; | ||
324 | |||
325 | feedback_divider8 = | ||
326 | (8 * fyclk * reference_divider * post_divider) / reference_clock; | ||
327 | |||
328 | *clkf = feedback_divider8 / 8; | ||
329 | *clkfrac = feedback_divider8 % 8; | ||
330 | } | ||
331 | |||
332 | static int rv770_encode_yclk_post_div(u32 postdiv, u32 *encoded_postdiv) | ||
333 | { | ||
334 | int ret = 0; | ||
335 | |||
336 | switch (postdiv) { | ||
337 | case 1: | ||
338 | *encoded_postdiv = 0; | ||
339 | break; | ||
340 | case 2: | ||
341 | *encoded_postdiv = 1; | ||
342 | break; | ||
343 | case 4: | ||
344 | *encoded_postdiv = 2; | ||
345 | break; | ||
346 | case 8: | ||
347 | *encoded_postdiv = 3; | ||
348 | break; | ||
349 | case 16: | ||
350 | *encoded_postdiv = 4; | ||
351 | break; | ||
352 | default: | ||
353 | ret = -EINVAL; | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | u32 rv770_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf) | ||
361 | { | ||
362 | if (clkf <= 0x10) | ||
363 | return 0x4B; | ||
364 | if (clkf <= 0x19) | ||
365 | return 0x5B; | ||
366 | if (clkf <= 0x21) | ||
367 | return 0x2B; | ||
368 | if (clkf <= 0x27) | ||
369 | return 0x6C; | ||
370 | if (clkf <= 0x31) | ||
371 | return 0x9D; | ||
372 | return 0xC6; | ||
373 | } | ||
374 | |||
375 | static int rv770_populate_mclk_value(struct radeon_device *rdev, | ||
376 | u32 engine_clock, u32 memory_clock, | ||
377 | RV7XX_SMC_MCLK_VALUE *mclk) | ||
378 | { | ||
379 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
380 | u8 encoded_reference_dividers[] = { 0, 16, 17, 20, 21 }; | ||
381 | u32 mpll_ad_func_cntl = | ||
382 | pi->clk_regs.rv770.mpll_ad_func_cntl; | ||
383 | u32 mpll_ad_func_cntl_2 = | ||
384 | pi->clk_regs.rv770.mpll_ad_func_cntl_2; | ||
385 | u32 mpll_dq_func_cntl = | ||
386 | pi->clk_regs.rv770.mpll_dq_func_cntl; | ||
387 | u32 mpll_dq_func_cntl_2 = | ||
388 | pi->clk_regs.rv770.mpll_dq_func_cntl_2; | ||
389 | u32 mclk_pwrmgt_cntl = | ||
390 | pi->clk_regs.rv770.mclk_pwrmgt_cntl; | ||
391 | u32 dll_cntl = pi->clk_regs.rv770.dll_cntl; | ||
392 | struct atom_clock_dividers dividers; | ||
393 | u32 reference_clock = rdev->clock.mpll.reference_freq; | ||
394 | u32 clkf, clkfrac; | ||
395 | u32 postdiv_yclk; | ||
396 | u32 ibias; | ||
397 | int ret; | ||
398 | |||
399 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM, | ||
400 | memory_clock, false, ÷rs); | ||
401 | if (ret) | ||
402 | return ret; | ||
403 | |||
404 | if ((dividers.ref_div < 1) || (dividers.ref_div > 5)) | ||
405 | return -EINVAL; | ||
406 | |||
407 | rv770_calculate_fractional_mpll_feedback_divider(memory_clock, reference_clock, | ||
408 | pi->mem_gddr5, | ||
409 | ÷rs, &clkf, &clkfrac); | ||
410 | |||
411 | ret = rv770_encode_yclk_post_div(dividers.post_div, &postdiv_yclk); | ||
412 | if (ret) | ||
413 | return ret; | ||
414 | |||
415 | ibias = rv770_map_clkf_to_ibias(rdev, clkf); | ||
416 | |||
417 | mpll_ad_func_cntl &= ~(CLKR_MASK | | ||
418 | YCLK_POST_DIV_MASK | | ||
419 | CLKF_MASK | | ||
420 | CLKFRAC_MASK | | ||
421 | IBIAS_MASK); | ||
422 | mpll_ad_func_cntl |= CLKR(encoded_reference_dividers[dividers.ref_div - 1]); | ||
423 | mpll_ad_func_cntl |= YCLK_POST_DIV(postdiv_yclk); | ||
424 | mpll_ad_func_cntl |= CLKF(clkf); | ||
425 | mpll_ad_func_cntl |= CLKFRAC(clkfrac); | ||
426 | mpll_ad_func_cntl |= IBIAS(ibias); | ||
427 | |||
428 | if (dividers.vco_mode) | ||
429 | mpll_ad_func_cntl_2 |= VCO_MODE; | ||
430 | else | ||
431 | mpll_ad_func_cntl_2 &= ~VCO_MODE; | ||
432 | |||
433 | if (pi->mem_gddr5) { | ||
434 | rv770_calculate_fractional_mpll_feedback_divider(memory_clock, | ||
435 | reference_clock, | ||
436 | pi->mem_gddr5, | ||
437 | ÷rs, &clkf, &clkfrac); | ||
438 | |||
439 | ibias = rv770_map_clkf_to_ibias(rdev, clkf); | ||
440 | |||
441 | ret = rv770_encode_yclk_post_div(dividers.post_div, &postdiv_yclk); | ||
442 | if (ret) | ||
443 | return ret; | ||
444 | |||
445 | mpll_dq_func_cntl &= ~(CLKR_MASK | | ||
446 | YCLK_POST_DIV_MASK | | ||
447 | CLKF_MASK | | ||
448 | CLKFRAC_MASK | | ||
449 | IBIAS_MASK); | ||
450 | mpll_dq_func_cntl |= CLKR(encoded_reference_dividers[dividers.ref_div - 1]); | ||
451 | mpll_dq_func_cntl |= YCLK_POST_DIV(postdiv_yclk); | ||
452 | mpll_dq_func_cntl |= CLKF(clkf); | ||
453 | mpll_dq_func_cntl |= CLKFRAC(clkfrac); | ||
454 | mpll_dq_func_cntl |= IBIAS(ibias); | ||
455 | |||
456 | if (dividers.vco_mode) | ||
457 | mpll_dq_func_cntl_2 |= VCO_MODE; | ||
458 | else | ||
459 | mpll_dq_func_cntl_2 &= ~VCO_MODE; | ||
460 | } | ||
461 | |||
462 | mclk->mclk770.mclk_value = cpu_to_be32(memory_clock); | ||
463 | mclk->mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl); | ||
464 | mclk->mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2); | ||
465 | mclk->mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl); | ||
466 | mclk->mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2); | ||
467 | mclk->mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); | ||
468 | mclk->mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static int rv770_populate_sclk_value(struct radeon_device *rdev, | ||
474 | u32 engine_clock, | ||
475 | RV770_SMC_SCLK_VALUE *sclk) | ||
476 | { | ||
477 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
478 | struct atom_clock_dividers dividers; | ||
479 | u32 spll_func_cntl = | ||
480 | pi->clk_regs.rv770.cg_spll_func_cntl; | ||
481 | u32 spll_func_cntl_2 = | ||
482 | pi->clk_regs.rv770.cg_spll_func_cntl_2; | ||
483 | u32 spll_func_cntl_3 = | ||
484 | pi->clk_regs.rv770.cg_spll_func_cntl_3; | ||
485 | u32 cg_spll_spread_spectrum = | ||
486 | pi->clk_regs.rv770.cg_spll_spread_spectrum; | ||
487 | u32 cg_spll_spread_spectrum_2 = | ||
488 | pi->clk_regs.rv770.cg_spll_spread_spectrum_2; | ||
489 | u64 tmp; | ||
490 | u32 reference_clock = rdev->clock.spll.reference_freq; | ||
491 | u32 reference_divider, post_divider; | ||
492 | u32 fbdiv; | ||
493 | int ret; | ||
494 | |||
495 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, | ||
496 | engine_clock, false, ÷rs); | ||
497 | if (ret) | ||
498 | return ret; | ||
499 | |||
500 | reference_divider = 1 + dividers.ref_div; | ||
501 | |||
502 | if (dividers.enable_post_div) | ||
503 | post_divider = (0x0f & (dividers.post_div >> 4)) + (0x0f & dividers.post_div) + 2; | ||
504 | else | ||
505 | post_divider = 1; | ||
506 | |||
507 | tmp = (u64) engine_clock * reference_divider * post_divider * 16384; | ||
508 | do_div(tmp, reference_clock); | ||
509 | fbdiv = (u32) tmp; | ||
510 | |||
511 | if (dividers.enable_post_div) | ||
512 | spll_func_cntl |= SPLL_DIVEN; | ||
513 | else | ||
514 | spll_func_cntl &= ~SPLL_DIVEN; | ||
515 | spll_func_cntl &= ~(SPLL_HILEN_MASK | SPLL_LOLEN_MASK | SPLL_REF_DIV_MASK); | ||
516 | spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div); | ||
517 | spll_func_cntl |= SPLL_HILEN((dividers.post_div >> 4) & 0xf); | ||
518 | spll_func_cntl |= SPLL_LOLEN(dividers.post_div & 0xf); | ||
519 | |||
520 | spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; | ||
521 | spll_func_cntl_2 |= SCLK_MUX_SEL(2); | ||
522 | |||
523 | spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; | ||
524 | spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); | ||
525 | spll_func_cntl_3 |= SPLL_DITHEN; | ||
526 | |||
527 | if (pi->sclk_ss) { | ||
528 | struct radeon_atom_ss ss; | ||
529 | u32 vco_freq = engine_clock * post_divider; | ||
530 | |||
531 | if (radeon_atombios_get_asic_ss_info(rdev, &ss, | ||
532 | ASIC_INTERNAL_ENGINE_SS, vco_freq)) { | ||
533 | u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); | ||
534 | u32 clk_v = ss.percentage * fbdiv / (clk_s * 10000); | ||
535 | |||
536 | cg_spll_spread_spectrum &= ~CLKS_MASK; | ||
537 | cg_spll_spread_spectrum |= CLKS(clk_s); | ||
538 | cg_spll_spread_spectrum |= SSEN; | ||
539 | |||
540 | cg_spll_spread_spectrum_2 &= ~CLKV_MASK; | ||
541 | cg_spll_spread_spectrum_2 |= CLKV(clk_v); | ||
542 | } | ||
543 | } | ||
544 | |||
545 | sclk->sclk_value = cpu_to_be32(engine_clock); | ||
546 | sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); | ||
547 | sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); | ||
548 | sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); | ||
549 | sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum); | ||
550 | sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2); | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | int rv770_populate_vddc_value(struct radeon_device *rdev, u16 vddc, | ||
556 | RV770_SMC_VOLTAGE_VALUE *voltage) | ||
557 | { | ||
558 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
559 | int i; | ||
560 | |||
561 | if (!pi->voltage_control) { | ||
562 | voltage->index = 0; | ||
563 | voltage->value = 0; | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | for (i = 0; i < pi->valid_vddc_entries; i++) { | ||
568 | if (vddc <= pi->vddc_table[i].vddc) { | ||
569 | voltage->index = pi->vddc_table[i].vddc_index; | ||
570 | voltage->value = cpu_to_be16(vddc); | ||
571 | break; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | if (i == pi->valid_vddc_entries) | ||
576 | return -EINVAL; | ||
577 | |||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | int rv770_populate_mvdd_value(struct radeon_device *rdev, u32 mclk, | ||
582 | RV770_SMC_VOLTAGE_VALUE *voltage) | ||
583 | { | ||
584 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
585 | |||
586 | if (!pi->mvdd_control) { | ||
587 | voltage->index = MVDD_HIGH_INDEX; | ||
588 | voltage->value = cpu_to_be16(MVDD_HIGH_VALUE); | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | if (mclk <= pi->mvdd_split_frequency) { | ||
593 | voltage->index = MVDD_LOW_INDEX; | ||
594 | voltage->value = cpu_to_be16(MVDD_LOW_VALUE); | ||
595 | } else { | ||
596 | voltage->index = MVDD_HIGH_INDEX; | ||
597 | voltage->value = cpu_to_be16(MVDD_HIGH_VALUE); | ||
598 | } | ||
599 | |||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int rv770_convert_power_level_to_smc(struct radeon_device *rdev, | ||
604 | struct rv7xx_pl *pl, | ||
605 | RV770_SMC_HW_PERFORMANCE_LEVEL *level, | ||
606 | u8 watermark_level) | ||
607 | { | ||
608 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
609 | int ret; | ||
610 | |||
611 | level->gen2PCIE = pi->pcie_gen2 ? | ||
612 | ((pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0) : 0; | ||
613 | level->gen2XSP = (pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0; | ||
614 | level->backbias = (pl->flags & ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE) ? 1 : 0; | ||
615 | level->displayWatermark = watermark_level; | ||
616 | |||
617 | if (rdev->family == CHIP_RV740) | ||
618 | ret = rv740_populate_sclk_value(rdev, pl->sclk, | ||
619 | &level->sclk); | ||
620 | else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
621 | ret = rv730_populate_sclk_value(rdev, pl->sclk, | ||
622 | &level->sclk); | ||
623 | else | ||
624 | ret = rv770_populate_sclk_value(rdev, pl->sclk, | ||
625 | &level->sclk); | ||
626 | if (ret) | ||
627 | return ret; | ||
628 | |||
629 | if (rdev->family == CHIP_RV740) { | ||
630 | if (pi->mem_gddr5) { | ||
631 | if (pl->mclk <= pi->mclk_strobe_mode_threshold) | ||
632 | level->strobeMode = | ||
633 | rv740_get_mclk_frequency_ratio(pl->mclk) | 0x10; | ||
634 | else | ||
635 | level->strobeMode = 0; | ||
636 | |||
637 | if (pl->mclk > pi->mclk_edc_enable_threshold) | ||
638 | level->mcFlags = SMC_MC_EDC_RD_FLAG | SMC_MC_EDC_WR_FLAG; | ||
639 | else | ||
640 | level->mcFlags = 0; | ||
641 | } | ||
642 | ret = rv740_populate_mclk_value(rdev, pl->sclk, | ||
643 | pl->mclk, &level->mclk); | ||
644 | } else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
645 | ret = rv730_populate_mclk_value(rdev, pl->sclk, | ||
646 | pl->mclk, &level->mclk); | ||
647 | else | ||
648 | ret = rv770_populate_mclk_value(rdev, pl->sclk, | ||
649 | pl->mclk, &level->mclk); | ||
650 | if (ret) | ||
651 | return ret; | ||
652 | |||
653 | ret = rv770_populate_vddc_value(rdev, pl->vddc, | ||
654 | &level->vddc); | ||
655 | if (ret) | ||
656 | return ret; | ||
657 | |||
658 | ret = rv770_populate_mvdd_value(rdev, pl->mclk, &level->mvdd); | ||
659 | |||
660 | return ret; | ||
661 | } | ||
662 | |||
663 | static int rv770_convert_power_state_to_smc(struct radeon_device *rdev, | ||
664 | struct radeon_ps *radeon_state, | ||
665 | RV770_SMC_SWSTATE *smc_state) | ||
666 | { | ||
667 | struct rv7xx_ps *state = rv770_get_ps(radeon_state); | ||
668 | int ret; | ||
669 | |||
670 | if (!(radeon_state->caps & ATOM_PPLIB_DISALLOW_ON_DC)) | ||
671 | smc_state->flags |= PPSMC_SWSTATE_FLAG_DC; | ||
672 | |||
673 | ret = rv770_convert_power_level_to_smc(rdev, | ||
674 | &state->low, | ||
675 | &smc_state->levels[0], | ||
676 | PPSMC_DISPLAY_WATERMARK_LOW); | ||
677 | if (ret) | ||
678 | return ret; | ||
679 | |||
680 | ret = rv770_convert_power_level_to_smc(rdev, | ||
681 | &state->medium, | ||
682 | &smc_state->levels[1], | ||
683 | PPSMC_DISPLAY_WATERMARK_LOW); | ||
684 | if (ret) | ||
685 | return ret; | ||
686 | |||
687 | ret = rv770_convert_power_level_to_smc(rdev, | ||
688 | &state->high, | ||
689 | &smc_state->levels[2], | ||
690 | PPSMC_DISPLAY_WATERMARK_HIGH); | ||
691 | if (ret) | ||
692 | return ret; | ||
693 | |||
694 | smc_state->levels[0].arbValue = MC_CG_ARB_FREQ_F1; | ||
695 | smc_state->levels[1].arbValue = MC_CG_ARB_FREQ_F2; | ||
696 | smc_state->levels[2].arbValue = MC_CG_ARB_FREQ_F3; | ||
697 | |||
698 | smc_state->levels[0].seqValue = rv770_get_seq_value(rdev, | ||
699 | &state->low); | ||
700 | smc_state->levels[1].seqValue = rv770_get_seq_value(rdev, | ||
701 | &state->medium); | ||
702 | smc_state->levels[2].seqValue = rv770_get_seq_value(rdev, | ||
703 | &state->high); | ||
704 | |||
705 | rv770_populate_smc_sp(rdev, radeon_state, smc_state); | ||
706 | |||
707 | return rv770_populate_smc_t(rdev, radeon_state, smc_state); | ||
708 | |||
709 | } | ||
710 | |||
711 | u32 rv770_calculate_memory_refresh_rate(struct radeon_device *rdev, | ||
712 | u32 engine_clock) | ||
713 | { | ||
714 | u32 dram_rows; | ||
715 | u32 dram_refresh_rate; | ||
716 | u32 mc_arb_rfsh_rate; | ||
717 | u32 tmp; | ||
718 | |||
719 | tmp = (RREG32(MC_ARB_RAMCFG) & NOOFROWS_MASK) >> NOOFROWS_SHIFT; | ||
720 | dram_rows = 1 << (tmp + 10); | ||
721 | tmp = RREG32(MC_SEQ_MISC0) & 3; | ||
722 | dram_refresh_rate = 1 << (tmp + 3); | ||
723 | mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64; | ||
724 | |||
725 | return mc_arb_rfsh_rate; | ||
726 | } | ||
727 | |||
728 | static void rv770_program_memory_timing_parameters(struct radeon_device *rdev, | ||
729 | struct radeon_ps *radeon_state) | ||
730 | { | ||
731 | struct rv7xx_ps *state = rv770_get_ps(radeon_state); | ||
732 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
733 | u32 sqm_ratio; | ||
734 | u32 arb_refresh_rate; | ||
735 | u32 high_clock; | ||
736 | |||
737 | if (state->high.sclk < (state->low.sclk * 0xFF / 0x40)) | ||
738 | high_clock = state->high.sclk; | ||
739 | else | ||
740 | high_clock = (state->low.sclk * 0xFF / 0x40); | ||
741 | |||
742 | radeon_atom_set_engine_dram_timings(rdev, high_clock, | ||
743 | state->high.mclk); | ||
744 | |||
745 | sqm_ratio = | ||
746 | STATE0(64 * high_clock / pi->boot_sclk) | | ||
747 | STATE1(64 * high_clock / state->low.sclk) | | ||
748 | STATE2(64 * high_clock / state->medium.sclk) | | ||
749 | STATE3(64 * high_clock / state->high.sclk); | ||
750 | WREG32(MC_ARB_SQM_RATIO, sqm_ratio); | ||
751 | |||
752 | arb_refresh_rate = | ||
753 | POWERMODE0(rv770_calculate_memory_refresh_rate(rdev, pi->boot_sclk)) | | ||
754 | POWERMODE1(rv770_calculate_memory_refresh_rate(rdev, state->low.sclk)) | | ||
755 | POWERMODE2(rv770_calculate_memory_refresh_rate(rdev, state->medium.sclk)) | | ||
756 | POWERMODE3(rv770_calculate_memory_refresh_rate(rdev, state->high.sclk)); | ||
757 | WREG32(MC_ARB_RFSH_RATE, arb_refresh_rate); | ||
758 | } | ||
759 | |||
760 | void rv770_enable_backbias(struct radeon_device *rdev, | ||
761 | bool enable) | ||
762 | { | ||
763 | if (enable) | ||
764 | WREG32_P(GENERAL_PWRMGT, BACKBIAS_PAD_EN, ~BACKBIAS_PAD_EN); | ||
765 | else | ||
766 | WREG32_P(GENERAL_PWRMGT, 0, ~(BACKBIAS_VALUE | BACKBIAS_PAD_EN)); | ||
767 | } | ||
768 | |||
769 | static void rv770_enable_spread_spectrum(struct radeon_device *rdev, | ||
770 | bool enable) | ||
771 | { | ||
772 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
773 | |||
774 | if (enable) { | ||
775 | if (pi->sclk_ss) | ||
776 | WREG32_P(GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, ~DYN_SPREAD_SPECTRUM_EN); | ||
777 | |||
778 | if (pi->mclk_ss) { | ||
779 | if (rdev->family == CHIP_RV740) | ||
780 | rv740_enable_mclk_spread_spectrum(rdev, true); | ||
781 | } | ||
782 | } else { | ||
783 | WREG32_P(CG_SPLL_SPREAD_SPECTRUM, 0, ~SSEN); | ||
784 | |||
785 | WREG32_P(GENERAL_PWRMGT, 0, ~DYN_SPREAD_SPECTRUM_EN); | ||
786 | |||
787 | WREG32_P(CG_MPLL_SPREAD_SPECTRUM, 0, ~SSEN); | ||
788 | |||
789 | if (rdev->family == CHIP_RV740) | ||
790 | rv740_enable_mclk_spread_spectrum(rdev, false); | ||
791 | } | ||
792 | } | ||
793 | |||
794 | static void rv770_program_mpll_timing_parameters(struct radeon_device *rdev) | ||
795 | { | ||
796 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
797 | |||
798 | if ((rdev->family == CHIP_RV770) && !pi->mem_gddr5) { | ||
799 | WREG32(MPLL_TIME, | ||
800 | (MPLL_LOCK_TIME(R600_MPLLLOCKTIME_DFLT * pi->ref_div) | | ||
801 | MPLL_RESET_TIME(R600_MPLLRESETTIME_DFLT))); | ||
802 | } | ||
803 | } | ||
804 | |||
805 | void rv770_setup_bsp(struct radeon_device *rdev) | ||
806 | { | ||
807 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
808 | u32 xclk = radeon_get_xclk(rdev); | ||
809 | |||
810 | r600_calculate_u_and_p(pi->asi, | ||
811 | xclk, | ||
812 | 16, | ||
813 | &pi->bsp, | ||
814 | &pi->bsu); | ||
815 | |||
816 | r600_calculate_u_and_p(pi->pasi, | ||
817 | xclk, | ||
818 | 16, | ||
819 | &pi->pbsp, | ||
820 | &pi->pbsu); | ||
821 | |||
822 | pi->dsp = BSP(pi->bsp) | BSU(pi->bsu); | ||
823 | pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu); | ||
824 | |||
825 | WREG32(CG_BSP, pi->dsp); | ||
826 | |||
827 | } | ||
828 | |||
829 | void rv770_program_git(struct radeon_device *rdev) | ||
830 | { | ||
831 | WREG32_P(CG_GIT, CG_GICST(R600_GICST_DFLT), ~CG_GICST_MASK); | ||
832 | } | ||
833 | |||
834 | void rv770_program_tp(struct radeon_device *rdev) | ||
835 | { | ||
836 | int i; | ||
837 | enum r600_td td = R600_TD_DFLT; | ||
838 | |||
839 | for (i = 0; i < R600_PM_NUMBER_OF_TC; i++) | ||
840 | WREG32(CG_FFCT_0 + (i * 4), (UTC_0(r600_utc[i]) | DTC_0(r600_dtc[i]))); | ||
841 | |||
842 | if (td == R600_TD_AUTO) | ||
843 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL); | ||
844 | else | ||
845 | WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL); | ||
846 | if (td == R600_TD_UP) | ||
847 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE); | ||
848 | if (td == R600_TD_DOWN) | ||
849 | WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE); | ||
850 | } | ||
851 | |||
852 | void rv770_program_tpp(struct radeon_device *rdev) | ||
853 | { | ||
854 | WREG32(CG_TPC, R600_TPC_DFLT); | ||
855 | } | ||
856 | |||
857 | void rv770_program_sstp(struct radeon_device *rdev) | ||
858 | { | ||
859 | WREG32(CG_SSP, (SSTU(R600_SSTU_DFLT) | SST(R600_SST_DFLT))); | ||
860 | } | ||
861 | |||
862 | void rv770_program_engine_speed_parameters(struct radeon_device *rdev) | ||
863 | { | ||
864 | WREG32_P(SPLL_CNTL_MODE, SPLL_DIV_SYNC, ~SPLL_DIV_SYNC); | ||
865 | } | ||
866 | |||
867 | static void rv770_enable_display_gap(struct radeon_device *rdev) | ||
868 | { | ||
869 | u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL); | ||
870 | |||
871 | tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK); | ||
872 | tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE) | | ||
873 | DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE)); | ||
874 | WREG32(CG_DISPLAY_GAP_CNTL, tmp); | ||
875 | } | ||
876 | |||
877 | void rv770_program_vc(struct radeon_device *rdev) | ||
878 | { | ||
879 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
880 | |||
881 | WREG32(CG_FTV, pi->vrc); | ||
882 | } | ||
883 | |||
884 | void rv770_clear_vc(struct radeon_device *rdev) | ||
885 | { | ||
886 | WREG32(CG_FTV, 0); | ||
887 | } | ||
888 | |||
889 | int rv770_upload_firmware(struct radeon_device *rdev) | ||
890 | { | ||
891 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
892 | int ret; | ||
893 | |||
894 | rv770_reset_smc(rdev); | ||
895 | rv770_stop_smc_clock(rdev); | ||
896 | |||
897 | ret = rv770_load_smc_ucode(rdev, pi->sram_end); | ||
898 | if (ret) | ||
899 | return ret; | ||
900 | |||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | static int rv770_populate_smc_acpi_state(struct radeon_device *rdev, | ||
905 | RV770_SMC_STATETABLE *table) | ||
906 | { | ||
907 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
908 | |||
909 | u32 mpll_ad_func_cntl = | ||
910 | pi->clk_regs.rv770.mpll_ad_func_cntl; | ||
911 | u32 mpll_ad_func_cntl_2 = | ||
912 | pi->clk_regs.rv770.mpll_ad_func_cntl_2; | ||
913 | u32 mpll_dq_func_cntl = | ||
914 | pi->clk_regs.rv770.mpll_dq_func_cntl; | ||
915 | u32 mpll_dq_func_cntl_2 = | ||
916 | pi->clk_regs.rv770.mpll_dq_func_cntl_2; | ||
917 | u32 spll_func_cntl = | ||
918 | pi->clk_regs.rv770.cg_spll_func_cntl; | ||
919 | u32 spll_func_cntl_2 = | ||
920 | pi->clk_regs.rv770.cg_spll_func_cntl_2; | ||
921 | u32 spll_func_cntl_3 = | ||
922 | pi->clk_regs.rv770.cg_spll_func_cntl_3; | ||
923 | u32 mclk_pwrmgt_cntl; | ||
924 | u32 dll_cntl; | ||
925 | |||
926 | table->ACPIState = table->initialState; | ||
927 | |||
928 | table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC; | ||
929 | |||
930 | if (pi->acpi_vddc) { | ||
931 | rv770_populate_vddc_value(rdev, pi->acpi_vddc, | ||
932 | &table->ACPIState.levels[0].vddc); | ||
933 | if (pi->pcie_gen2) { | ||
934 | if (pi->acpi_pcie_gen2) | ||
935 | table->ACPIState.levels[0].gen2PCIE = 1; | ||
936 | else | ||
937 | table->ACPIState.levels[0].gen2PCIE = 0; | ||
938 | } else | ||
939 | table->ACPIState.levels[0].gen2PCIE = 0; | ||
940 | if (pi->acpi_pcie_gen2) | ||
941 | table->ACPIState.levels[0].gen2XSP = 1; | ||
942 | else | ||
943 | table->ACPIState.levels[0].gen2XSP = 0; | ||
944 | } else { | ||
945 | rv770_populate_vddc_value(rdev, pi->min_vddc_in_table, | ||
946 | &table->ACPIState.levels[0].vddc); | ||
947 | table->ACPIState.levels[0].gen2PCIE = 0; | ||
948 | } | ||
949 | |||
950 | |||
951 | mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN; | ||
952 | |||
953 | mpll_dq_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN; | ||
954 | |||
955 | mclk_pwrmgt_cntl = (MRDCKA0_RESET | | ||
956 | MRDCKA1_RESET | | ||
957 | MRDCKB0_RESET | | ||
958 | MRDCKB1_RESET | | ||
959 | MRDCKC0_RESET | | ||
960 | MRDCKC1_RESET | | ||
961 | MRDCKD0_RESET | | ||
962 | MRDCKD1_RESET); | ||
963 | |||
964 | dll_cntl = 0xff000000; | ||
965 | |||
966 | spll_func_cntl |= SPLL_RESET | SPLL_SLEEP | SPLL_BYPASS_EN; | ||
967 | |||
968 | spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; | ||
969 | spll_func_cntl_2 |= SCLK_MUX_SEL(4); | ||
970 | |||
971 | table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl); | ||
972 | table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2); | ||
973 | table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl); | ||
974 | table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2); | ||
975 | |||
976 | table->ACPIState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); | ||
977 | table->ACPIState.levels[0].mclk.mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl); | ||
978 | |||
979 | table->ACPIState.levels[0].mclk.mclk770.mclk_value = 0; | ||
980 | |||
981 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); | ||
982 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); | ||
983 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); | ||
984 | |||
985 | table->ACPIState.levels[0].sclk.sclk_value = 0; | ||
986 | |||
987 | rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd); | ||
988 | |||
989 | table->ACPIState.levels[1] = table->ACPIState.levels[0]; | ||
990 | table->ACPIState.levels[2] = table->ACPIState.levels[0]; | ||
991 | |||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | int rv770_populate_initial_mvdd_value(struct radeon_device *rdev, | ||
996 | RV770_SMC_VOLTAGE_VALUE *voltage) | ||
997 | { | ||
998 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
999 | |||
1000 | if ((pi->s0_vid_lower_smio_cntl & pi->mvdd_mask_low) == | ||
1001 | (pi->mvdd_low_smio[MVDD_LOW_INDEX] & pi->mvdd_mask_low) ) { | ||
1002 | voltage->index = MVDD_LOW_INDEX; | ||
1003 | voltage->value = cpu_to_be16(MVDD_LOW_VALUE); | ||
1004 | } else { | ||
1005 | voltage->index = MVDD_HIGH_INDEX; | ||
1006 | voltage->value = cpu_to_be16(MVDD_HIGH_VALUE); | ||
1007 | } | ||
1008 | |||
1009 | return 0; | ||
1010 | } | ||
1011 | |||
1012 | static int rv770_populate_smc_initial_state(struct radeon_device *rdev, | ||
1013 | struct radeon_ps *radeon_state, | ||
1014 | RV770_SMC_STATETABLE *table) | ||
1015 | { | ||
1016 | struct rv7xx_ps *initial_state = rv770_get_ps(radeon_state); | ||
1017 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1018 | u32 a_t; | ||
1019 | |||
1020 | table->initialState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL = | ||
1021 | cpu_to_be32(pi->clk_regs.rv770.mpll_ad_func_cntl); | ||
1022 | table->initialState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 = | ||
1023 | cpu_to_be32(pi->clk_regs.rv770.mpll_ad_func_cntl_2); | ||
1024 | table->initialState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL = | ||
1025 | cpu_to_be32(pi->clk_regs.rv770.mpll_dq_func_cntl); | ||
1026 | table->initialState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 = | ||
1027 | cpu_to_be32(pi->clk_regs.rv770.mpll_dq_func_cntl_2); | ||
1028 | table->initialState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL = | ||
1029 | cpu_to_be32(pi->clk_regs.rv770.mclk_pwrmgt_cntl); | ||
1030 | table->initialState.levels[0].mclk.mclk770.vDLL_CNTL = | ||
1031 | cpu_to_be32(pi->clk_regs.rv770.dll_cntl); | ||
1032 | |||
1033 | table->initialState.levels[0].mclk.mclk770.vMPLL_SS = | ||
1034 | cpu_to_be32(pi->clk_regs.rv770.mpll_ss1); | ||
1035 | table->initialState.levels[0].mclk.mclk770.vMPLL_SS2 = | ||
1036 | cpu_to_be32(pi->clk_regs.rv770.mpll_ss2); | ||
1037 | |||
1038 | table->initialState.levels[0].mclk.mclk770.mclk_value = | ||
1039 | cpu_to_be32(initial_state->low.mclk); | ||
1040 | |||
1041 | table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = | ||
1042 | cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl); | ||
1043 | table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = | ||
1044 | cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl_2); | ||
1045 | table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = | ||
1046 | cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl_3); | ||
1047 | table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM = | ||
1048 | cpu_to_be32(pi->clk_regs.rv770.cg_spll_spread_spectrum); | ||
1049 | table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 = | ||
1050 | cpu_to_be32(pi->clk_regs.rv770.cg_spll_spread_spectrum_2); | ||
1051 | |||
1052 | table->initialState.levels[0].sclk.sclk_value = | ||
1053 | cpu_to_be32(initial_state->low.sclk); | ||
1054 | |||
1055 | table->initialState.levels[0].arbValue = MC_CG_ARB_FREQ_F0; | ||
1056 | |||
1057 | table->initialState.levels[0].seqValue = | ||
1058 | rv770_get_seq_value(rdev, &initial_state->low); | ||
1059 | |||
1060 | rv770_populate_vddc_value(rdev, | ||
1061 | initial_state->low.vddc, | ||
1062 | &table->initialState.levels[0].vddc); | ||
1063 | rv770_populate_initial_mvdd_value(rdev, | ||
1064 | &table->initialState.levels[0].mvdd); | ||
1065 | |||
1066 | a_t = CG_R(0xffff) | CG_L(0); | ||
1067 | table->initialState.levels[0].aT = cpu_to_be32(a_t); | ||
1068 | |||
1069 | table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp); | ||
1070 | |||
1071 | if (pi->boot_in_gen2) | ||
1072 | table->initialState.levels[0].gen2PCIE = 1; | ||
1073 | else | ||
1074 | table->initialState.levels[0].gen2PCIE = 0; | ||
1075 | if (initial_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) | ||
1076 | table->initialState.levels[0].gen2XSP = 1; | ||
1077 | else | ||
1078 | table->initialState.levels[0].gen2XSP = 0; | ||
1079 | |||
1080 | if (rdev->family == CHIP_RV740) { | ||
1081 | if (pi->mem_gddr5) { | ||
1082 | if (initial_state->low.mclk <= pi->mclk_strobe_mode_threshold) | ||
1083 | table->initialState.levels[0].strobeMode = | ||
1084 | rv740_get_mclk_frequency_ratio(initial_state->low.mclk) | 0x10; | ||
1085 | else | ||
1086 | table->initialState.levels[0].strobeMode = 0; | ||
1087 | |||
1088 | if (initial_state->low.mclk >= pi->mclk_edc_enable_threshold) | ||
1089 | table->initialState.levels[0].mcFlags = SMC_MC_EDC_RD_FLAG | SMC_MC_EDC_WR_FLAG; | ||
1090 | else | ||
1091 | table->initialState.levels[0].mcFlags = 0; | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | table->initialState.levels[1] = table->initialState.levels[0]; | ||
1096 | table->initialState.levels[2] = table->initialState.levels[0]; | ||
1097 | |||
1098 | table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC; | ||
1099 | |||
1100 | return 0; | ||
1101 | } | ||
1102 | |||
1103 | static int rv770_populate_smc_vddc_table(struct radeon_device *rdev, | ||
1104 | RV770_SMC_STATETABLE *table) | ||
1105 | { | ||
1106 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1107 | int i; | ||
1108 | |||
1109 | for (i = 0; i < pi->valid_vddc_entries; i++) { | ||
1110 | table->highSMIO[pi->vddc_table[i].vddc_index] = | ||
1111 | pi->vddc_table[i].high_smio; | ||
1112 | table->lowSMIO[pi->vddc_table[i].vddc_index] = | ||
1113 | cpu_to_be32(pi->vddc_table[i].low_smio); | ||
1114 | } | ||
1115 | |||
1116 | table->voltageMaskTable.highMask[RV770_SMC_VOLTAGEMASK_VDDC] = 0; | ||
1117 | table->voltageMaskTable.lowMask[RV770_SMC_VOLTAGEMASK_VDDC] = | ||
1118 | cpu_to_be32(pi->vddc_mask_low); | ||
1119 | |||
1120 | for (i = 0; | ||
1121 | ((i < pi->valid_vddc_entries) && | ||
1122 | (pi->max_vddc_in_table > | ||
1123 | pi->vddc_table[i].vddc)); | ||
1124 | i++); | ||
1125 | |||
1126 | table->maxVDDCIndexInPPTable = | ||
1127 | pi->vddc_table[i].vddc_index; | ||
1128 | |||
1129 | return 0; | ||
1130 | } | ||
1131 | |||
1132 | static int rv770_populate_smc_mvdd_table(struct radeon_device *rdev, | ||
1133 | RV770_SMC_STATETABLE *table) | ||
1134 | { | ||
1135 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1136 | |||
1137 | if (pi->mvdd_control) { | ||
1138 | table->lowSMIO[MVDD_HIGH_INDEX] |= | ||
1139 | cpu_to_be32(pi->mvdd_low_smio[MVDD_HIGH_INDEX]); | ||
1140 | table->lowSMIO[MVDD_LOW_INDEX] |= | ||
1141 | cpu_to_be32(pi->mvdd_low_smio[MVDD_LOW_INDEX]); | ||
1142 | |||
1143 | table->voltageMaskTable.highMask[RV770_SMC_VOLTAGEMASK_MVDD] = 0; | ||
1144 | table->voltageMaskTable.lowMask[RV770_SMC_VOLTAGEMASK_MVDD] = | ||
1145 | cpu_to_be32(pi->mvdd_mask_low); | ||
1146 | } | ||
1147 | |||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | static int rv770_init_smc_table(struct radeon_device *rdev) | ||
1152 | { | ||
1153 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1154 | struct radeon_ps *radeon_boot_state = rdev->pm.dpm.boot_ps; | ||
1155 | struct rv7xx_ps *boot_state = rv770_get_ps(radeon_boot_state); | ||
1156 | RV770_SMC_STATETABLE *table = &pi->smc_statetable; | ||
1157 | int ret; | ||
1158 | |||
1159 | memset(table, 0, sizeof(RV770_SMC_STATETABLE)); | ||
1160 | |||
1161 | pi->boot_sclk = boot_state->low.sclk; | ||
1162 | |||
1163 | rv770_populate_smc_vddc_table(rdev, table); | ||
1164 | rv770_populate_smc_mvdd_table(rdev, table); | ||
1165 | |||
1166 | switch (rdev->pm.int_thermal_type) { | ||
1167 | case THERMAL_TYPE_RV770: | ||
1168 | case THERMAL_TYPE_ADT7473_WITH_INTERNAL: | ||
1169 | table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL; | ||
1170 | break; | ||
1171 | case THERMAL_TYPE_NONE: | ||
1172 | table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE; | ||
1173 | break; | ||
1174 | case THERMAL_TYPE_EXTERNAL_GPIO: | ||
1175 | default: | ||
1176 | table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL; | ||
1177 | break; | ||
1178 | } | ||
1179 | |||
1180 | if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC) { | ||
1181 | table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; | ||
1182 | |||
1183 | if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT) | ||
1184 | table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK; | ||
1185 | |||
1186 | if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT) | ||
1187 | table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE; | ||
1188 | } | ||
1189 | |||
1190 | if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC) | ||
1191 | table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; | ||
1192 | |||
1193 | if (pi->mem_gddr5) | ||
1194 | table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5; | ||
1195 | |||
1196 | if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
1197 | ret = rv730_populate_smc_initial_state(rdev, radeon_boot_state, table); | ||
1198 | else | ||
1199 | ret = rv770_populate_smc_initial_state(rdev, radeon_boot_state, table); | ||
1200 | if (ret) | ||
1201 | return ret; | ||
1202 | |||
1203 | if (rdev->family == CHIP_RV740) | ||
1204 | ret = rv740_populate_smc_acpi_state(rdev, table); | ||
1205 | else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
1206 | ret = rv730_populate_smc_acpi_state(rdev, table); | ||
1207 | else | ||
1208 | ret = rv770_populate_smc_acpi_state(rdev, table); | ||
1209 | if (ret) | ||
1210 | return ret; | ||
1211 | |||
1212 | table->driverState = table->initialState; | ||
1213 | |||
1214 | return rv770_copy_bytes_to_smc(rdev, | ||
1215 | pi->state_table_start, | ||
1216 | (const u8 *)table, | ||
1217 | sizeof(RV770_SMC_STATETABLE), | ||
1218 | pi->sram_end); | ||
1219 | } | ||
1220 | |||
1221 | static int rv770_construct_vddc_table(struct radeon_device *rdev) | ||
1222 | { | ||
1223 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1224 | u16 min, max, step; | ||
1225 | u32 steps = 0; | ||
1226 | u8 vddc_index = 0; | ||
1227 | u32 i; | ||
1228 | |||
1229 | radeon_atom_get_min_voltage(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, &min); | ||
1230 | radeon_atom_get_max_voltage(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, &max); | ||
1231 | radeon_atom_get_voltage_step(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, &step); | ||
1232 | |||
1233 | steps = (max - min) / step + 1; | ||
1234 | |||
1235 | if (steps > MAX_NO_VREG_STEPS) | ||
1236 | return -EINVAL; | ||
1237 | |||
1238 | for (i = 0; i < steps; i++) { | ||
1239 | u32 gpio_pins, gpio_mask; | ||
1240 | |||
1241 | pi->vddc_table[i].vddc = (u16)(min + i * step); | ||
1242 | radeon_atom_get_voltage_gpio_settings(rdev, | ||
1243 | pi->vddc_table[i].vddc, | ||
1244 | SET_VOLTAGE_TYPE_ASIC_VDDC, | ||
1245 | &gpio_pins, &gpio_mask); | ||
1246 | pi->vddc_table[i].low_smio = gpio_pins & gpio_mask; | ||
1247 | pi->vddc_table[i].high_smio = 0; | ||
1248 | pi->vddc_mask_low = gpio_mask; | ||
1249 | if (i > 0) { | ||
1250 | if ((pi->vddc_table[i].low_smio != | ||
1251 | pi->vddc_table[i - 1].low_smio ) || | ||
1252 | (pi->vddc_table[i].high_smio != | ||
1253 | pi->vddc_table[i - 1].high_smio)) | ||
1254 | vddc_index++; | ||
1255 | } | ||
1256 | pi->vddc_table[i].vddc_index = vddc_index; | ||
1257 | } | ||
1258 | |||
1259 | pi->valid_vddc_entries = (u8)steps; | ||
1260 | |||
1261 | return 0; | ||
1262 | } | ||
1263 | |||
1264 | static u32 rv770_get_mclk_split_point(struct atom_memory_info *memory_info) | ||
1265 | { | ||
1266 | if (memory_info->mem_type == MEM_TYPE_GDDR3) | ||
1267 | return 30000; | ||
1268 | |||
1269 | return 0; | ||
1270 | } | ||
1271 | |||
1272 | static int rv770_get_mvdd_pin_configuration(struct radeon_device *rdev) | ||
1273 | { | ||
1274 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1275 | u32 gpio_pins, gpio_mask; | ||
1276 | |||
1277 | radeon_atom_get_voltage_gpio_settings(rdev, | ||
1278 | MVDD_HIGH_VALUE, SET_VOLTAGE_TYPE_ASIC_MVDDC, | ||
1279 | &gpio_pins, &gpio_mask); | ||
1280 | pi->mvdd_mask_low = gpio_mask; | ||
1281 | pi->mvdd_low_smio[MVDD_HIGH_INDEX] = | ||
1282 | gpio_pins & gpio_mask; | ||
1283 | |||
1284 | radeon_atom_get_voltage_gpio_settings(rdev, | ||
1285 | MVDD_LOW_VALUE, SET_VOLTAGE_TYPE_ASIC_MVDDC, | ||
1286 | &gpio_pins, &gpio_mask); | ||
1287 | pi->mvdd_low_smio[MVDD_LOW_INDEX] = | ||
1288 | gpio_pins & gpio_mask; | ||
1289 | |||
1290 | return 0; | ||
1291 | } | ||
1292 | |||
1293 | u8 rv770_get_memory_module_index(struct radeon_device *rdev) | ||
1294 | { | ||
1295 | return (u8) ((RREG32(BIOS_SCRATCH_4) >> 16) & 0xff); | ||
1296 | } | ||
1297 | |||
1298 | static int rv770_get_mvdd_configuration(struct radeon_device *rdev) | ||
1299 | { | ||
1300 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1301 | u8 memory_module_index; | ||
1302 | struct atom_memory_info memory_info; | ||
1303 | |||
1304 | memory_module_index = rv770_get_memory_module_index(rdev); | ||
1305 | |||
1306 | if (radeon_atom_get_memory_info(rdev, memory_module_index, &memory_info)) { | ||
1307 | pi->mvdd_control = false; | ||
1308 | return 0; | ||
1309 | } | ||
1310 | |||
1311 | pi->mvdd_split_frequency = | ||
1312 | rv770_get_mclk_split_point(&memory_info); | ||
1313 | |||
1314 | if (pi->mvdd_split_frequency == 0) { | ||
1315 | pi->mvdd_control = false; | ||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1319 | return rv770_get_mvdd_pin_configuration(rdev); | ||
1320 | } | ||
1321 | |||
1322 | void rv770_enable_voltage_control(struct radeon_device *rdev, | ||
1323 | bool enable) | ||
1324 | { | ||
1325 | if (enable) | ||
1326 | WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN); | ||
1327 | else | ||
1328 | WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN); | ||
1329 | } | ||
1330 | |||
1331 | static void rv770_program_display_gap(struct radeon_device *rdev) | ||
1332 | { | ||
1333 | u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL); | ||
1334 | |||
1335 | tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK); | ||
1336 | if (RREG32(AVIVO_D1CRTC_CONTROL) & AVIVO_CRTC_EN) { | ||
1337 | tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK); | ||
1338 | tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE); | ||
1339 | } else if (RREG32(AVIVO_D2CRTC_CONTROL) & AVIVO_CRTC_EN) { | ||
1340 | tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE); | ||
1341 | tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK); | ||
1342 | } else { | ||
1343 | tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE); | ||
1344 | tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE); | ||
1345 | } | ||
1346 | WREG32(CG_DISPLAY_GAP_CNTL, tmp); | ||
1347 | } | ||
1348 | |||
1349 | static void rv770_enable_dynamic_pcie_gen2(struct radeon_device *rdev, | ||
1350 | bool enable) | ||
1351 | { | ||
1352 | rv770_enable_bif_dynamic_pcie_gen2(rdev, enable); | ||
1353 | |||
1354 | if (enable) | ||
1355 | WREG32_P(GENERAL_PWRMGT, ENABLE_GEN2PCIE, ~ENABLE_GEN2PCIE); | ||
1356 | else | ||
1357 | WREG32_P(GENERAL_PWRMGT, 0, ~ENABLE_GEN2PCIE); | ||
1358 | } | ||
1359 | |||
1360 | static void r7xx_program_memory_timing_parameters(struct radeon_device *rdev) | ||
1361 | { | ||
1362 | struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps; | ||
1363 | |||
1364 | if ((rdev->family == CHIP_RV730) || | ||
1365 | (rdev->family == CHIP_RV710) || | ||
1366 | (rdev->family == CHIP_RV740)) | ||
1367 | rv730_program_memory_timing_parameters(rdev, radeon_new_state); | ||
1368 | else | ||
1369 | rv770_program_memory_timing_parameters(rdev, radeon_new_state); | ||
1370 | } | ||
1371 | |||
1372 | static int rv770_upload_sw_state(struct radeon_device *rdev) | ||
1373 | { | ||
1374 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1375 | struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps; | ||
1376 | u16 address = pi->state_table_start + | ||
1377 | offsetof(RV770_SMC_STATETABLE, driverState); | ||
1378 | RV770_SMC_SWSTATE state = { 0 }; | ||
1379 | int ret; | ||
1380 | |||
1381 | ret = rv770_convert_power_state_to_smc(rdev, radeon_new_state, &state); | ||
1382 | if (ret) | ||
1383 | return ret; | ||
1384 | |||
1385 | return rv770_copy_bytes_to_smc(rdev, address, (const u8 *)&state, | ||
1386 | sizeof(RV770_SMC_SWSTATE), | ||
1387 | pi->sram_end); | ||
1388 | } | ||
1389 | |||
1390 | int rv770_halt_smc(struct radeon_device *rdev) | ||
1391 | { | ||
1392 | if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_Halt) != PPSMC_Result_OK) | ||
1393 | return -EINVAL; | ||
1394 | |||
1395 | if (rv770_wait_for_smc_inactive(rdev) != PPSMC_Result_OK) | ||
1396 | return -EINVAL; | ||
1397 | |||
1398 | return 0; | ||
1399 | } | ||
1400 | |||
1401 | int rv770_resume_smc(struct radeon_device *rdev) | ||
1402 | { | ||
1403 | if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_Resume) != PPSMC_Result_OK) | ||
1404 | return -EINVAL; | ||
1405 | return 0; | ||
1406 | } | ||
1407 | |||
1408 | int rv770_set_sw_state(struct radeon_device *rdev) | ||
1409 | { | ||
1410 | if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToSwState) != PPSMC_Result_OK) | ||
1411 | return -EINVAL; | ||
1412 | return 0; | ||
1413 | } | ||
1414 | |||
1415 | int rv770_set_boot_state(struct radeon_device *rdev) | ||
1416 | { | ||
1417 | if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToInitialState) != PPSMC_Result_OK) | ||
1418 | return -EINVAL; | ||
1419 | return 0; | ||
1420 | } | ||
1421 | |||
1422 | int rv770_restrict_performance_levels_before_switch(struct radeon_device *rdev) | ||
1423 | { | ||
1424 | if (rv770_send_msg_to_smc(rdev, (PPSMC_Msg)(PPSMC_MSG_NoForcedLevel)) != PPSMC_Result_OK) | ||
1425 | return -EINVAL; | ||
1426 | |||
1427 | if (rv770_send_msg_to_smc(rdev, (PPSMC_Msg)(PPSMC_MSG_TwoLevelsDisabled)) != PPSMC_Result_OK) | ||
1428 | return -EINVAL; | ||
1429 | |||
1430 | return 0; | ||
1431 | } | ||
1432 | |||
1433 | int rv770_unrestrict_performance_levels_after_switch(struct radeon_device *rdev) | ||
1434 | { | ||
1435 | if (rv770_send_msg_to_smc(rdev, (PPSMC_Msg)(PPSMC_MSG_NoForcedLevel)) != PPSMC_Result_OK) | ||
1436 | return -EINVAL; | ||
1437 | |||
1438 | if (rv770_send_msg_to_smc(rdev, (PPSMC_Msg)(PPSMC_MSG_ZeroLevelsDisabled)) != PPSMC_Result_OK) | ||
1439 | return -EINVAL; | ||
1440 | |||
1441 | return 0; | ||
1442 | } | ||
1443 | |||
1444 | void r7xx_start_smc(struct radeon_device *rdev) | ||
1445 | { | ||
1446 | rv770_start_smc(rdev); | ||
1447 | rv770_start_smc_clock(rdev); | ||
1448 | } | ||
1449 | |||
1450 | |||
1451 | void r7xx_stop_smc(struct radeon_device *rdev) | ||
1452 | { | ||
1453 | rv770_reset_smc(rdev); | ||
1454 | rv770_stop_smc_clock(rdev); | ||
1455 | } | ||
1456 | |||
1457 | static void rv770_read_clock_registers(struct radeon_device *rdev) | ||
1458 | { | ||
1459 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1460 | |||
1461 | pi->clk_regs.rv770.cg_spll_func_cntl = | ||
1462 | RREG32(CG_SPLL_FUNC_CNTL); | ||
1463 | pi->clk_regs.rv770.cg_spll_func_cntl_2 = | ||
1464 | RREG32(CG_SPLL_FUNC_CNTL_2); | ||
1465 | pi->clk_regs.rv770.cg_spll_func_cntl_3 = | ||
1466 | RREG32(CG_SPLL_FUNC_CNTL_3); | ||
1467 | pi->clk_regs.rv770.cg_spll_spread_spectrum = | ||
1468 | RREG32(CG_SPLL_SPREAD_SPECTRUM); | ||
1469 | pi->clk_regs.rv770.cg_spll_spread_spectrum_2 = | ||
1470 | RREG32(CG_SPLL_SPREAD_SPECTRUM_2); | ||
1471 | pi->clk_regs.rv770.mpll_ad_func_cntl = | ||
1472 | RREG32(MPLL_AD_FUNC_CNTL); | ||
1473 | pi->clk_regs.rv770.mpll_ad_func_cntl_2 = | ||
1474 | RREG32(MPLL_AD_FUNC_CNTL_2); | ||
1475 | pi->clk_regs.rv770.mpll_dq_func_cntl = | ||
1476 | RREG32(MPLL_DQ_FUNC_CNTL); | ||
1477 | pi->clk_regs.rv770.mpll_dq_func_cntl_2 = | ||
1478 | RREG32(MPLL_DQ_FUNC_CNTL_2); | ||
1479 | pi->clk_regs.rv770.mclk_pwrmgt_cntl = | ||
1480 | RREG32(MCLK_PWRMGT_CNTL); | ||
1481 | pi->clk_regs.rv770.dll_cntl = RREG32(DLL_CNTL); | ||
1482 | } | ||
1483 | |||
1484 | static void r7xx_read_clock_registers(struct radeon_device *rdev) | ||
1485 | { | ||
1486 | if (rdev->family == CHIP_RV740) | ||
1487 | rv740_read_clock_registers(rdev); | ||
1488 | else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
1489 | rv730_read_clock_registers(rdev); | ||
1490 | else | ||
1491 | rv770_read_clock_registers(rdev); | ||
1492 | } | ||
1493 | |||
1494 | void rv770_read_voltage_smio_registers(struct radeon_device *rdev) | ||
1495 | { | ||
1496 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1497 | |||
1498 | pi->s0_vid_lower_smio_cntl = | ||
1499 | RREG32(S0_VID_LOWER_SMIO_CNTL); | ||
1500 | } | ||
1501 | |||
1502 | void rv770_reset_smio_status(struct radeon_device *rdev) | ||
1503 | { | ||
1504 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1505 | u32 sw_smio_index, vid_smio_cntl; | ||
1506 | |||
1507 | sw_smio_index = | ||
1508 | (RREG32(GENERAL_PWRMGT) & SW_SMIO_INDEX_MASK) >> SW_SMIO_INDEX_SHIFT; | ||
1509 | switch (sw_smio_index) { | ||
1510 | case 3: | ||
1511 | vid_smio_cntl = RREG32(S3_VID_LOWER_SMIO_CNTL); | ||
1512 | break; | ||
1513 | case 2: | ||
1514 | vid_smio_cntl = RREG32(S2_VID_LOWER_SMIO_CNTL); | ||
1515 | break; | ||
1516 | case 1: | ||
1517 | vid_smio_cntl = RREG32(S1_VID_LOWER_SMIO_CNTL); | ||
1518 | break; | ||
1519 | case 0: | ||
1520 | return; | ||
1521 | default: | ||
1522 | vid_smio_cntl = pi->s0_vid_lower_smio_cntl; | ||
1523 | break; | ||
1524 | } | ||
1525 | |||
1526 | WREG32(S0_VID_LOWER_SMIO_CNTL, vid_smio_cntl); | ||
1527 | WREG32_P(GENERAL_PWRMGT, SW_SMIO_INDEX(0), ~SW_SMIO_INDEX_MASK); | ||
1528 | } | ||
1529 | |||
1530 | void rv770_get_memory_type(struct radeon_device *rdev) | ||
1531 | { | ||
1532 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1533 | u32 tmp; | ||
1534 | |||
1535 | tmp = RREG32(MC_SEQ_MISC0); | ||
1536 | |||
1537 | if (((tmp & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT) == | ||
1538 | MC_SEQ_MISC0_GDDR5_VALUE) | ||
1539 | pi->mem_gddr5 = true; | ||
1540 | else | ||
1541 | pi->mem_gddr5 = false; | ||
1542 | |||
1543 | } | ||
1544 | |||
1545 | void rv770_get_pcie_gen2_status(struct radeon_device *rdev) | ||
1546 | { | ||
1547 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1548 | u32 tmp; | ||
1549 | |||
1550 | tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); | ||
1551 | |||
1552 | if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) && | ||
1553 | (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2)) | ||
1554 | pi->pcie_gen2 = true; | ||
1555 | else | ||
1556 | pi->pcie_gen2 = false; | ||
1557 | |||
1558 | if (pi->pcie_gen2) { | ||
1559 | if (tmp & LC_CURRENT_DATA_RATE) | ||
1560 | pi->boot_in_gen2 = true; | ||
1561 | else | ||
1562 | pi->boot_in_gen2 = false; | ||
1563 | } else | ||
1564 | pi->boot_in_gen2 = false; | ||
1565 | } | ||
1566 | |||
1567 | #if 0 | ||
1568 | static int rv770_enter_ulp_state(struct radeon_device *rdev) | ||
1569 | { | ||
1570 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1571 | |||
1572 | if (pi->gfx_clock_gating) { | ||
1573 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN); | ||
1574 | WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON); | ||
1575 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON); | ||
1576 | RREG32(GB_TILING_CONFIG); | ||
1577 | } | ||
1578 | |||
1579 | WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_SwitchToMinimumPower), | ||
1580 | ~HOST_SMC_MSG_MASK); | ||
1581 | |||
1582 | udelay(7000); | ||
1583 | |||
1584 | return 0; | ||
1585 | } | ||
1586 | |||
1587 | static int rv770_exit_ulp_state(struct radeon_device *rdev) | ||
1588 | { | ||
1589 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1590 | int i; | ||
1591 | |||
1592 | WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_ResumeFromMinimumPower), | ||
1593 | ~HOST_SMC_MSG_MASK); | ||
1594 | |||
1595 | udelay(7000); | ||
1596 | |||
1597 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
1598 | if (((RREG32(SMC_MSG) & HOST_SMC_RESP_MASK) >> HOST_SMC_RESP_SHIFT) == 1) | ||
1599 | break; | ||
1600 | udelay(1000); | ||
1601 | } | ||
1602 | |||
1603 | if (pi->gfx_clock_gating) | ||
1604 | WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN); | ||
1605 | |||
1606 | return 0; | ||
1607 | } | ||
1608 | #endif | ||
1609 | |||
1610 | static void rv770_get_mclk_odt_threshold(struct radeon_device *rdev) | ||
1611 | { | ||
1612 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1613 | u8 memory_module_index; | ||
1614 | struct atom_memory_info memory_info; | ||
1615 | |||
1616 | pi->mclk_odt_threshold = 0; | ||
1617 | |||
1618 | if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) { | ||
1619 | memory_module_index = rv770_get_memory_module_index(rdev); | ||
1620 | |||
1621 | if (radeon_atom_get_memory_info(rdev, memory_module_index, &memory_info)) | ||
1622 | return; | ||
1623 | |||
1624 | if (memory_info.mem_type == MEM_TYPE_DDR2 || | ||
1625 | memory_info.mem_type == MEM_TYPE_DDR3) | ||
1626 | pi->mclk_odt_threshold = 30000; | ||
1627 | } | ||
1628 | } | ||
1629 | |||
1630 | void rv770_get_max_vddc(struct radeon_device *rdev) | ||
1631 | { | ||
1632 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1633 | u16 vddc; | ||
1634 | |||
1635 | if (radeon_atom_get_max_vddc(rdev, 0, 0, &vddc)) | ||
1636 | pi->max_vddc = 0; | ||
1637 | else | ||
1638 | pi->max_vddc = vddc; | ||
1639 | } | ||
1640 | |||
1641 | void rv770_program_response_times(struct radeon_device *rdev) | ||
1642 | { | ||
1643 | u32 voltage_response_time, backbias_response_time; | ||
1644 | u32 acpi_delay_time, vbi_time_out; | ||
1645 | u32 vddc_dly, bb_dly, acpi_dly, vbi_dly; | ||
1646 | u32 reference_clock; | ||
1647 | |||
1648 | voltage_response_time = (u32)rdev->pm.dpm.voltage_response_time; | ||
1649 | backbias_response_time = (u32)rdev->pm.dpm.backbias_response_time; | ||
1650 | |||
1651 | if (voltage_response_time == 0) | ||
1652 | voltage_response_time = 1000; | ||
1653 | |||
1654 | if (backbias_response_time == 0) | ||
1655 | backbias_response_time = 1000; | ||
1656 | |||
1657 | acpi_delay_time = 15000; | ||
1658 | vbi_time_out = 100000; | ||
1659 | |||
1660 | reference_clock = radeon_get_xclk(rdev); | ||
1661 | |||
1662 | vddc_dly = (voltage_response_time * reference_clock) / 1600; | ||
1663 | bb_dly = (backbias_response_time * reference_clock) / 1600; | ||
1664 | acpi_dly = (acpi_delay_time * reference_clock) / 1600; | ||
1665 | vbi_dly = (vbi_time_out * reference_clock) / 1600; | ||
1666 | |||
1667 | rv770_write_smc_soft_register(rdev, | ||
1668 | RV770_SMC_SOFT_REGISTER_delay_vreg, vddc_dly); | ||
1669 | rv770_write_smc_soft_register(rdev, | ||
1670 | RV770_SMC_SOFT_REGISTER_delay_bbias, bb_dly); | ||
1671 | rv770_write_smc_soft_register(rdev, | ||
1672 | RV770_SMC_SOFT_REGISTER_delay_acpi, acpi_dly); | ||
1673 | rv770_write_smc_soft_register(rdev, | ||
1674 | RV770_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly); | ||
1675 | #if 0 | ||
1676 | /* XXX look up hw revision */ | ||
1677 | if (WEKIVA_A21) | ||
1678 | rv770_write_smc_soft_register(rdev, | ||
1679 | RV770_SMC_SOFT_REGISTER_baby_step_timer, | ||
1680 | 0x10); | ||
1681 | #endif | ||
1682 | } | ||
1683 | |||
1684 | static void rv770_program_dcodt_before_state_switch(struct radeon_device *rdev) | ||
1685 | { | ||
1686 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1687 | struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps; | ||
1688 | struct radeon_ps *radeon_current_state = rdev->pm.dpm.current_ps; | ||
1689 | struct rv7xx_ps *new_state = rv770_get_ps(radeon_new_state); | ||
1690 | struct rv7xx_ps *current_state = rv770_get_ps(radeon_current_state); | ||
1691 | bool current_use_dc = false; | ||
1692 | bool new_use_dc = false; | ||
1693 | |||
1694 | if (pi->mclk_odt_threshold == 0) | ||
1695 | return; | ||
1696 | |||
1697 | if (current_state->high.mclk <= pi->mclk_odt_threshold) | ||
1698 | current_use_dc = true; | ||
1699 | |||
1700 | if (new_state->high.mclk <= pi->mclk_odt_threshold) | ||
1701 | new_use_dc = true; | ||
1702 | |||
1703 | if (current_use_dc == new_use_dc) | ||
1704 | return; | ||
1705 | |||
1706 | if (!current_use_dc && new_use_dc) | ||
1707 | return; | ||
1708 | |||
1709 | if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
1710 | rv730_program_dcodt(rdev, new_use_dc); | ||
1711 | } | ||
1712 | |||
1713 | static void rv770_program_dcodt_after_state_switch(struct radeon_device *rdev) | ||
1714 | { | ||
1715 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1716 | struct radeon_ps *radeon_new_state = rdev->pm.dpm.requested_ps; | ||
1717 | struct radeon_ps *radeon_current_state = rdev->pm.dpm.current_ps; | ||
1718 | struct rv7xx_ps *new_state = rv770_get_ps(radeon_new_state); | ||
1719 | struct rv7xx_ps *current_state = rv770_get_ps(radeon_current_state); | ||
1720 | bool current_use_dc = false; | ||
1721 | bool new_use_dc = false; | ||
1722 | |||
1723 | if (pi->mclk_odt_threshold == 0) | ||
1724 | return; | ||
1725 | |||
1726 | if (current_state->high.mclk <= pi->mclk_odt_threshold) | ||
1727 | current_use_dc = true; | ||
1728 | |||
1729 | if (new_state->high.mclk <= pi->mclk_odt_threshold) | ||
1730 | new_use_dc = true; | ||
1731 | |||
1732 | if (current_use_dc == new_use_dc) | ||
1733 | return; | ||
1734 | |||
1735 | if (current_use_dc && !new_use_dc) | ||
1736 | return; | ||
1737 | |||
1738 | if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
1739 | rv730_program_dcodt(rdev, new_use_dc); | ||
1740 | } | ||
1741 | |||
1742 | static void rv770_retrieve_odt_values(struct radeon_device *rdev) | ||
1743 | { | ||
1744 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1745 | |||
1746 | if (pi->mclk_odt_threshold == 0) | ||
1747 | return; | ||
1748 | |||
1749 | if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
1750 | rv730_get_odt_values(rdev); | ||
1751 | } | ||
1752 | |||
1753 | static void rv770_set_dpm_event_sources(struct radeon_device *rdev, u32 sources) | ||
1754 | { | ||
1755 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1756 | bool want_thermal_protection; | ||
1757 | enum radeon_dpm_event_src dpm_event_src; | ||
1758 | |||
1759 | switch (sources) { | ||
1760 | case 0: | ||
1761 | default: | ||
1762 | want_thermal_protection = false; | ||
1763 | break; | ||
1764 | case (1 << RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL): | ||
1765 | want_thermal_protection = true; | ||
1766 | dpm_event_src = RADEON_DPM_EVENT_SRC_DIGITAL; | ||
1767 | break; | ||
1768 | |||
1769 | case (1 << RADEON_DPM_AUTO_THROTTLE_SRC_EXTERNAL): | ||
1770 | want_thermal_protection = true; | ||
1771 | dpm_event_src = RADEON_DPM_EVENT_SRC_EXTERNAL; | ||
1772 | break; | ||
1773 | |||
1774 | case ((1 << RADEON_DPM_AUTO_THROTTLE_SRC_EXTERNAL) | | ||
1775 | (1 << RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL)): | ||
1776 | want_thermal_protection = true; | ||
1777 | dpm_event_src = RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL; | ||
1778 | break; | ||
1779 | } | ||
1780 | |||
1781 | if (want_thermal_protection) { | ||
1782 | WREG32_P(CG_THERMAL_CTRL, DPM_EVENT_SRC(dpm_event_src), ~DPM_EVENT_SRC_MASK); | ||
1783 | if (pi->thermal_protection) | ||
1784 | WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); | ||
1785 | } else { | ||
1786 | WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); | ||
1787 | } | ||
1788 | } | ||
1789 | |||
1790 | void rv770_enable_auto_throttle_source(struct radeon_device *rdev, | ||
1791 | enum radeon_dpm_auto_throttle_src source, | ||
1792 | bool enable) | ||
1793 | { | ||
1794 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1795 | |||
1796 | if (enable) { | ||
1797 | if (!(pi->active_auto_throttle_sources & (1 << source))) { | ||
1798 | pi->active_auto_throttle_sources |= 1 << source; | ||
1799 | rv770_set_dpm_event_sources(rdev, pi->active_auto_throttle_sources); | ||
1800 | } | ||
1801 | } else { | ||
1802 | if (pi->active_auto_throttle_sources & (1 << source)) { | ||
1803 | pi->active_auto_throttle_sources &= ~(1 << source); | ||
1804 | rv770_set_dpm_event_sources(rdev, pi->active_auto_throttle_sources); | ||
1805 | } | ||
1806 | } | ||
1807 | } | ||
1808 | |||
1809 | static int rv770_set_thermal_temperature_range(struct radeon_device *rdev, | ||
1810 | int min_temp, int max_temp) | ||
1811 | { | ||
1812 | int low_temp = 0 * 1000; | ||
1813 | int high_temp = 255 * 1000; | ||
1814 | |||
1815 | if (low_temp < min_temp) | ||
1816 | low_temp = min_temp; | ||
1817 | if (high_temp > max_temp) | ||
1818 | high_temp = max_temp; | ||
1819 | if (high_temp < low_temp) { | ||
1820 | DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); | ||
1821 | return -EINVAL; | ||
1822 | } | ||
1823 | |||
1824 | WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK); | ||
1825 | WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK); | ||
1826 | WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK); | ||
1827 | |||
1828 | rdev->pm.dpm.thermal.min_temp = low_temp; | ||
1829 | rdev->pm.dpm.thermal.max_temp = high_temp; | ||
1830 | |||
1831 | return 0; | ||
1832 | } | ||
1833 | |||
1834 | int rv770_dpm_enable(struct radeon_device *rdev) | ||
1835 | { | ||
1836 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1837 | |||
1838 | if (pi->gfx_clock_gating) | ||
1839 | rv770_restore_cgcg(rdev); | ||
1840 | |||
1841 | if (rv770_dpm_enabled(rdev)) | ||
1842 | return -EINVAL; | ||
1843 | |||
1844 | if (pi->voltage_control) { | ||
1845 | rv770_enable_voltage_control(rdev, true); | ||
1846 | rv770_construct_vddc_table(rdev); | ||
1847 | } | ||
1848 | |||
1849 | if (pi->dcodt) | ||
1850 | rv770_retrieve_odt_values(rdev); | ||
1851 | |||
1852 | if (pi->mvdd_control) | ||
1853 | rv770_get_mvdd_configuration(rdev); | ||
1854 | |||
1855 | if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS) | ||
1856 | rv770_enable_backbias(rdev, true); | ||
1857 | |||
1858 | rv770_enable_spread_spectrum(rdev, true); | ||
1859 | |||
1860 | if (pi->thermal_protection) | ||
1861 | rv770_enable_thermal_protection(rdev, true); | ||
1862 | |||
1863 | rv770_program_mpll_timing_parameters(rdev); | ||
1864 | rv770_setup_bsp(rdev); | ||
1865 | rv770_program_git(rdev); | ||
1866 | rv770_program_tp(rdev); | ||
1867 | rv770_program_tpp(rdev); | ||
1868 | rv770_program_sstp(rdev); | ||
1869 | rv770_program_engine_speed_parameters(rdev); | ||
1870 | rv770_enable_display_gap(rdev); | ||
1871 | rv770_program_vc(rdev); | ||
1872 | |||
1873 | if (pi->dynamic_pcie_gen2) | ||
1874 | rv770_enable_dynamic_pcie_gen2(rdev, true); | ||
1875 | |||
1876 | if (rv770_upload_firmware(rdev)) | ||
1877 | return -EINVAL; | ||
1878 | /* get ucode version ? */ | ||
1879 | if (rv770_init_smc_table(rdev)) | ||
1880 | return -EINVAL; | ||
1881 | rv770_program_response_times(rdev); | ||
1882 | r7xx_start_smc(rdev); | ||
1883 | |||
1884 | if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
1885 | rv730_start_dpm(rdev); | ||
1886 | else | ||
1887 | rv770_start_dpm(rdev); | ||
1888 | |||
1889 | if (pi->gfx_clock_gating) | ||
1890 | rv770_gfx_clock_gating_enable(rdev, true); | ||
1891 | |||
1892 | if (pi->mg_clock_gating) | ||
1893 | rv770_mg_clock_gating_enable(rdev, true); | ||
1894 | |||
1895 | if (rdev->irq.installed && | ||
1896 | r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { | ||
1897 | PPSMC_Result result; | ||
1898 | |||
1899 | rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); | ||
1900 | rdev->irq.dpm_thermal = true; | ||
1901 | radeon_irq_set(rdev); | ||
1902 | result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt); | ||
1903 | |||
1904 | if (result != PPSMC_Result_OK) | ||
1905 | DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); | ||
1906 | } | ||
1907 | |||
1908 | rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); | ||
1909 | |||
1910 | return 0; | ||
1911 | } | ||
1912 | |||
1913 | void rv770_dpm_disable(struct radeon_device *rdev) | ||
1914 | { | ||
1915 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1916 | |||
1917 | if (!rv770_dpm_enabled(rdev)) | ||
1918 | return; | ||
1919 | |||
1920 | rv770_clear_vc(rdev); | ||
1921 | |||
1922 | if (pi->thermal_protection) | ||
1923 | rv770_enable_thermal_protection(rdev, false); | ||
1924 | |||
1925 | rv770_enable_spread_spectrum(rdev, false); | ||
1926 | |||
1927 | if (pi->dynamic_pcie_gen2) | ||
1928 | rv770_enable_dynamic_pcie_gen2(rdev, false); | ||
1929 | |||
1930 | if (rdev->irq.installed && | ||
1931 | r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { | ||
1932 | rdev->irq.dpm_thermal = false; | ||
1933 | radeon_irq_set(rdev); | ||
1934 | } | ||
1935 | |||
1936 | if (pi->gfx_clock_gating) | ||
1937 | rv770_gfx_clock_gating_enable(rdev, false); | ||
1938 | |||
1939 | if (pi->mg_clock_gating) | ||
1940 | rv770_mg_clock_gating_enable(rdev, false); | ||
1941 | |||
1942 | if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) | ||
1943 | rv730_stop_dpm(rdev); | ||
1944 | else | ||
1945 | rv770_stop_dpm(rdev); | ||
1946 | |||
1947 | r7xx_stop_smc(rdev); | ||
1948 | rv770_reset_smio_status(rdev); | ||
1949 | } | ||
1950 | |||
1951 | int rv770_dpm_set_power_state(struct radeon_device *rdev) | ||
1952 | { | ||
1953 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1954 | |||
1955 | rv770_restrict_performance_levels_before_switch(rdev); | ||
1956 | rv770_halt_smc(rdev); | ||
1957 | rv770_upload_sw_state(rdev); | ||
1958 | r7xx_program_memory_timing_parameters(rdev); | ||
1959 | if (pi->dcodt) | ||
1960 | rv770_program_dcodt_before_state_switch(rdev); | ||
1961 | rv770_resume_smc(rdev); | ||
1962 | rv770_set_sw_state(rdev); | ||
1963 | if (pi->dcodt) | ||
1964 | rv770_program_dcodt_after_state_switch(rdev); | ||
1965 | rv770_unrestrict_performance_levels_after_switch(rdev); | ||
1966 | |||
1967 | return 0; | ||
1968 | } | ||
1969 | |||
1970 | void rv770_dpm_reset_asic(struct radeon_device *rdev) | ||
1971 | { | ||
1972 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1973 | |||
1974 | rv770_restrict_performance_levels_before_switch(rdev); | ||
1975 | if (pi->dcodt) | ||
1976 | rv770_program_dcodt_before_state_switch(rdev); | ||
1977 | rv770_set_boot_state(rdev); | ||
1978 | if (pi->dcodt) | ||
1979 | rv770_program_dcodt_after_state_switch(rdev); | ||
1980 | } | ||
1981 | |||
1982 | void rv770_dpm_setup_asic(struct radeon_device *rdev) | ||
1983 | { | ||
1984 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
1985 | |||
1986 | r7xx_read_clock_registers(rdev); | ||
1987 | rv770_read_voltage_smio_registers(rdev); | ||
1988 | rv770_get_memory_type(rdev); | ||
1989 | if (pi->dcodt) | ||
1990 | rv770_get_mclk_odt_threshold(rdev); | ||
1991 | rv770_get_pcie_gen2_status(rdev); | ||
1992 | |||
1993 | rv770_enable_acpi_pm(rdev); | ||
1994 | |||
1995 | if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s) | ||
1996 | rv770_enable_l0s(rdev); | ||
1997 | if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1) | ||
1998 | rv770_enable_l1(rdev); | ||
1999 | if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1) | ||
2000 | rv770_enable_pll_sleep_in_l1(rdev); | ||
2001 | } | ||
2002 | |||
2003 | void rv770_dpm_display_configuration_changed(struct radeon_device *rdev) | ||
2004 | { | ||
2005 | rv770_program_display_gap(rdev); | ||
2006 | } | ||
2007 | |||
2008 | union power_info { | ||
2009 | struct _ATOM_POWERPLAY_INFO info; | ||
2010 | struct _ATOM_POWERPLAY_INFO_V2 info_2; | ||
2011 | struct _ATOM_POWERPLAY_INFO_V3 info_3; | ||
2012 | struct _ATOM_PPLIB_POWERPLAYTABLE pplib; | ||
2013 | struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; | ||
2014 | struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; | ||
2015 | }; | ||
2016 | |||
2017 | union pplib_clock_info { | ||
2018 | struct _ATOM_PPLIB_R600_CLOCK_INFO r600; | ||
2019 | struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; | ||
2020 | struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; | ||
2021 | struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; | ||
2022 | }; | ||
2023 | |||
2024 | union pplib_power_state { | ||
2025 | struct _ATOM_PPLIB_STATE v1; | ||
2026 | struct _ATOM_PPLIB_STATE_V2 v2; | ||
2027 | }; | ||
2028 | |||
2029 | static void rv7xx_parse_pplib_non_clock_info(struct radeon_device *rdev, | ||
2030 | struct radeon_ps *rps, | ||
2031 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, | ||
2032 | u8 table_rev) | ||
2033 | { | ||
2034 | rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); | ||
2035 | rps->class = le16_to_cpu(non_clock_info->usClassification); | ||
2036 | rps->class2 = le16_to_cpu(non_clock_info->usClassification2); | ||
2037 | |||
2038 | if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { | ||
2039 | rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); | ||
2040 | rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); | ||
2041 | } else if (r600_is_uvd_state(rps->class, rps->class2)) { | ||
2042 | rps->vclk = RV770_DEFAULT_VCLK_FREQ; | ||
2043 | rps->dclk = RV770_DEFAULT_DCLK_FREQ; | ||
2044 | } else { | ||
2045 | rps->vclk = 0; | ||
2046 | rps->dclk = 0; | ||
2047 | } | ||
2048 | |||
2049 | if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) | ||
2050 | rdev->pm.dpm.boot_ps = rps; | ||
2051 | if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) | ||
2052 | rdev->pm.dpm.uvd_ps = rps; | ||
2053 | } | ||
2054 | |||
2055 | static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev, | ||
2056 | struct radeon_ps *rps, int index, | ||
2057 | union pplib_clock_info *clock_info) | ||
2058 | { | ||
2059 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | ||
2060 | struct rv7xx_ps *ps = rv770_get_ps(rps); | ||
2061 | u32 sclk, mclk; | ||
2062 | u16 vddc; | ||
2063 | struct rv7xx_pl *pl; | ||
2064 | |||
2065 | switch (index) { | ||
2066 | case 0: | ||
2067 | pl = &ps->low; | ||
2068 | break; | ||
2069 | case 1: | ||
2070 | pl = &ps->medium; | ||
2071 | break; | ||
2072 | case 2: | ||
2073 | default: | ||
2074 | pl = &ps->high; | ||
2075 | break; | ||
2076 | } | ||
2077 | |||
2078 | sclk = le16_to_cpu(clock_info->r600.usEngineClockLow); | ||
2079 | sclk |= clock_info->r600.ucEngineClockHigh << 16; | ||
2080 | mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow); | ||
2081 | mclk |= clock_info->r600.ucMemoryClockHigh << 16; | ||
2082 | |||
2083 | pl->vddc = le16_to_cpu(clock_info->r600.usVDDC); | ||
2084 | pl->flags = le32_to_cpu(clock_info->r600.ulFlags); | ||
2085 | |||
2086 | pl->mclk = mclk; | ||
2087 | pl->sclk = sclk; | ||
2088 | |||
2089 | /* patch up vddc if necessary */ | ||
2090 | if (pl->vddc == 0xff01) { | ||
2091 | if (radeon_atom_get_max_vddc(rdev, 0, 0, &vddc) == 0) | ||
2092 | pl->vddc = vddc; | ||
2093 | } | ||
2094 | |||
2095 | if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) { | ||
2096 | pi->acpi_vddc = pl->vddc; | ||
2097 | if (ps->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) | ||
2098 | pi->acpi_pcie_gen2 = true; | ||
2099 | else | ||
2100 | pi->acpi_pcie_gen2 = false; | ||
2101 | } | ||
2102 | |||
2103 | if (pi->min_vddc_in_table > pl->vddc) | ||
2104 | pi->min_vddc_in_table = pl->vddc; | ||
2105 | |||
2106 | if (pi->max_vddc_in_table < pl->vddc) | ||
2107 | pi->max_vddc_in_table = pl->vddc; | ||
2108 | |||
2109 | /* patch up boot state */ | ||
2110 | if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { | ||
2111 | u16 vddc, vddci; | ||
2112 | radeon_atombios_get_default_voltages(rdev, &vddc, &vddci); | ||
2113 | pl->mclk = rdev->clock.default_mclk; | ||
2114 | pl->sclk = rdev->clock.default_sclk; | ||
2115 | pl->vddc = vddc; | ||
2116 | pl->vddci = vddci; | ||
2117 | } | ||
2118 | } | ||
2119 | |||
2120 | int rv7xx_parse_power_table(struct radeon_device *rdev) | ||
2121 | { | ||
2122 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
2123 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; | ||
2124 | union pplib_power_state *power_state; | ||
2125 | int i, j; | ||
2126 | union pplib_clock_info *clock_info; | ||
2127 | union power_info *power_info; | ||
2128 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); | ||
2129 | u16 data_offset; | ||
2130 | u8 frev, crev; | ||
2131 | struct rv7xx_ps *ps; | ||
2132 | |||
2133 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, | ||
2134 | &frev, &crev, &data_offset)) | ||
2135 | return -EINVAL; | ||
2136 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); | ||
2137 | |||
2138 | rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * | ||
2139 | power_info->pplib.ucNumStates, GFP_KERNEL); | ||
2140 | if (!rdev->pm.dpm.ps) | ||
2141 | return -ENOMEM; | ||
2142 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
2143 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
2144 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
2145 | |||
2146 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { | ||
2147 | power_state = (union pplib_power_state *) | ||
2148 | (mode_info->atom_context->bios + data_offset + | ||
2149 | le16_to_cpu(power_info->pplib.usStateArrayOffset) + | ||
2150 | i * power_info->pplib.ucStateEntrySize); | ||
2151 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) | ||
2152 | (mode_info->atom_context->bios + data_offset + | ||
2153 | le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + | ||
2154 | (power_state->v1.ucNonClockStateIndex * | ||
2155 | power_info->pplib.ucNonClockSize)); | ||
2156 | if (power_info->pplib.ucStateEntrySize - 1) { | ||
2157 | ps = kzalloc(sizeof(struct rv7xx_ps), GFP_KERNEL); | ||
2158 | if (ps == NULL) { | ||
2159 | kfree(rdev->pm.dpm.ps); | ||
2160 | return -ENOMEM; | ||
2161 | } | ||
2162 | rdev->pm.dpm.ps[i].ps_priv = ps; | ||
2163 | rv7xx_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], | ||
2164 | non_clock_info, | ||
2165 | power_info->pplib.ucNonClockSize); | ||
2166 | for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { | ||
2167 | clock_info = (union pplib_clock_info *) | ||
2168 | (mode_info->atom_context->bios + data_offset + | ||
2169 | le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + | ||
2170 | (power_state->v1.ucClockStateIndices[j] * | ||
2171 | power_info->pplib.ucClockInfoSize)); | ||
2172 | rv7xx_parse_pplib_clock_info(rdev, | ||
2173 | &rdev->pm.dpm.ps[i], j, | ||
2174 | clock_info); | ||
2175 | } | ||
2176 | } | ||
2177 | } | ||
2178 | rdev->pm.dpm.num_ps = power_info->pplib.ucNumStates; | ||
2179 | return 0; | ||
2180 | } | ||
2181 | |||
2182 | int rv770_dpm_init(struct radeon_device *rdev) | ||
2183 | { | ||
2184 | struct rv7xx_power_info *pi; | ||
2185 | int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); | ||
2186 | uint16_t data_offset, size; | ||
2187 | uint8_t frev, crev; | ||
2188 | struct atom_clock_dividers dividers; | ||
2189 | int ret; | ||
2190 | |||
2191 | pi = kzalloc(sizeof(struct rv7xx_power_info), GFP_KERNEL); | ||
2192 | if (pi == NULL) | ||
2193 | return -ENOMEM; | ||
2194 | rdev->pm.dpm.priv = pi; | ||
2195 | |||
2196 | rv770_get_max_vddc(rdev); | ||
2197 | |||
2198 | pi->acpi_vddc = 0; | ||
2199 | pi->min_vddc_in_table = 0; | ||
2200 | pi->max_vddc_in_table = 0; | ||
2201 | |||
2202 | ret = rv7xx_parse_power_table(rdev); | ||
2203 | if (ret) | ||
2204 | return ret; | ||
2205 | |||
2206 | if (rdev->pm.dpm.voltage_response_time == 0) | ||
2207 | rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT; | ||
2208 | if (rdev->pm.dpm.backbias_response_time == 0) | ||
2209 | rdev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT; | ||
2210 | |||
2211 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, | ||
2212 | 0, false, ÷rs); | ||
2213 | if (ret) | ||
2214 | pi->ref_div = dividers.ref_div + 1; | ||
2215 | else | ||
2216 | pi->ref_div = R600_REFERENCEDIVIDER_DFLT; | ||
2217 | |||
2218 | pi->mclk_strobe_mode_threshold = 30000; | ||
2219 | pi->mclk_edc_enable_threshold = 30000; | ||
2220 | |||
2221 | pi->voltage_control = | ||
2222 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC); | ||
2223 | |||
2224 | pi->mvdd_control = | ||
2225 | radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC); | ||
2226 | |||
2227 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | ||
2228 | &frev, &crev, &data_offset)) { | ||
2229 | pi->sclk_ss = true; | ||
2230 | pi->mclk_ss = true; | ||
2231 | pi->dynamic_ss = true; | ||
2232 | } else { | ||
2233 | pi->sclk_ss = false; | ||
2234 | pi->mclk_ss = false; | ||
2235 | pi->dynamic_ss = false; | ||
2236 | } | ||
2237 | |||
2238 | pi->asi = RV770_ASI_DFLT; | ||
2239 | pi->pasi = RV770_HASI_DFLT; | ||
2240 | pi->vrc = RV770_VRC_DFLT; | ||
2241 | |||
2242 | pi->power_gating = false; | ||
2243 | |||
2244 | pi->gfx_clock_gating = true; | ||
2245 | |||
2246 | pi->mg_clock_gating = true; | ||
2247 | pi->mgcgtssm = true; | ||
2248 | |||
2249 | pi->dynamic_pcie_gen2 = true; | ||
2250 | |||
2251 | if (pi->gfx_clock_gating && | ||
2252 | (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)) | ||
2253 | pi->thermal_protection = true; | ||
2254 | else | ||
2255 | pi->thermal_protection = false; | ||
2256 | |||
2257 | pi->display_gap = true; | ||
2258 | |||
2259 | if (rdev->flags & RADEON_IS_MOBILITY) | ||
2260 | pi->dcodt = true; | ||
2261 | else | ||
2262 | pi->dcodt = false; | ||
2263 | |||
2264 | pi->ulps = true; | ||
2265 | |||
2266 | pi->mclk_stutter_mode_threshold = 0; | ||
2267 | |||
2268 | pi->sram_end = SMC_RAM_END; | ||
2269 | pi->state_table_start = RV770_SMC_TABLE_ADDRESS; | ||
2270 | pi->soft_regs_start = RV770_SMC_SOFT_REGISTERS_START; | ||
2271 | |||
2272 | return 0; | ||
2273 | } | ||
2274 | |||
2275 | void rv770_dpm_print_power_state(struct radeon_device *rdev, | ||
2276 | struct radeon_ps *rps) | ||
2277 | { | ||
2278 | struct rv7xx_ps *ps = rv770_get_ps(rps); | ||
2279 | struct rv7xx_pl *pl; | ||
2280 | |||
2281 | r600_dpm_print_class_info(rps->class, rps->class2); | ||
2282 | r600_dpm_print_cap_info(rps->caps); | ||
2283 | printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); | ||
2284 | if (rdev->family >= CHIP_CEDAR) { | ||
2285 | pl = &ps->low; | ||
2286 | printk("\t\tpower level 0 sclk: %u mclk: %u vddc: %u vddci: %u\n", | ||
2287 | pl->sclk, pl->mclk, pl->vddc, pl->vddci); | ||
2288 | pl = &ps->medium; | ||
2289 | printk("\t\tpower level 1 sclk: %u mclk: %u vddc: %u vddci: %u\n", | ||
2290 | pl->sclk, pl->mclk, pl->vddc, pl->vddci); | ||
2291 | pl = &ps->high; | ||
2292 | printk("\t\tpower level 2 sclk: %u mclk: %u vddc: %u vddci: %u\n", | ||
2293 | pl->sclk, pl->mclk, pl->vddc, pl->vddci); | ||
2294 | } else { | ||
2295 | pl = &ps->low; | ||
2296 | printk("\t\tpower level 0 sclk: %u mclk: %u vddc: %u\n", | ||
2297 | pl->sclk, pl->mclk, pl->vddc); | ||
2298 | pl = &ps->medium; | ||
2299 | printk("\t\tpower level 1 sclk: %u mclk: %u vddc: %u\n", | ||
2300 | pl->sclk, pl->mclk, pl->vddc); | ||
2301 | pl = &ps->high; | ||
2302 | printk("\t\tpower level 2 sclk: %u mclk: %u vddc: %u\n", | ||
2303 | pl->sclk, pl->mclk, pl->vddc); | ||
2304 | } | ||
2305 | r600_dpm_print_ps_status(rdev, rps); | ||
2306 | } | ||
2307 | |||
2308 | void rv770_dpm_fini(struct radeon_device *rdev) | ||
2309 | { | ||
2310 | int i; | ||
2311 | |||
2312 | for (i = 0; i < rdev->pm.dpm.num_ps; i++) { | ||
2313 | kfree(rdev->pm.dpm.ps[i].ps_priv); | ||
2314 | } | ||
2315 | kfree(rdev->pm.dpm.ps); | ||
2316 | kfree(rdev->pm.dpm.priv); | ||
2317 | } | ||
2318 | |||
2319 | u32 rv770_dpm_get_sclk(struct radeon_device *rdev, bool low) | ||
2320 | { | ||
2321 | struct rv7xx_ps *requested_state = rv770_get_ps(rdev->pm.dpm.requested_ps); | ||
2322 | |||
2323 | if (low) | ||
2324 | return requested_state->low.sclk; | ||
2325 | else | ||
2326 | return requested_state->high.sclk; | ||
2327 | } | ||
2328 | |||
2329 | u32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low) | ||
2330 | { | ||
2331 | struct rv7xx_ps *requested_state = rv770_get_ps(rdev->pm.dpm.requested_ps); | ||
2332 | |||
2333 | if (low) | ||
2334 | return requested_state->low.mclk; | ||
2335 | else | ||
2336 | return requested_state->high.mclk; | ||
2337 | } | ||
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.h b/drivers/gpu/drm/radeon/rv770_dpm.h new file mode 100644 index 000000000000..0f33f9bb244f --- /dev/null +++ b/drivers/gpu/drm/radeon/rv770_dpm.h | |||
@@ -0,0 +1,273 @@ | |||
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 __RV770_DPM_H__ | ||
24 | #define __RV770_DPM_H__ | ||
25 | |||
26 | #include "rv770_smc.h" | ||
27 | |||
28 | struct rv770_clock_registers { | ||
29 | u32 cg_spll_func_cntl; | ||
30 | u32 cg_spll_func_cntl_2; | ||
31 | u32 cg_spll_func_cntl_3; | ||
32 | u32 cg_spll_spread_spectrum; | ||
33 | u32 cg_spll_spread_spectrum_2; | ||
34 | u32 mpll_ad_func_cntl; | ||
35 | u32 mpll_ad_func_cntl_2; | ||
36 | u32 mpll_dq_func_cntl; | ||
37 | u32 mpll_dq_func_cntl_2; | ||
38 | u32 mclk_pwrmgt_cntl; | ||
39 | u32 dll_cntl; | ||
40 | u32 mpll_ss1; | ||
41 | u32 mpll_ss2; | ||
42 | }; | ||
43 | |||
44 | struct rv730_clock_registers { | ||
45 | u32 cg_spll_func_cntl; | ||
46 | u32 cg_spll_func_cntl_2; | ||
47 | u32 cg_spll_func_cntl_3; | ||
48 | u32 cg_spll_spread_spectrum; | ||
49 | u32 cg_spll_spread_spectrum_2; | ||
50 | u32 mclk_pwrmgt_cntl; | ||
51 | u32 dll_cntl; | ||
52 | u32 mpll_func_cntl; | ||
53 | u32 mpll_func_cntl2; | ||
54 | u32 mpll_func_cntl3; | ||
55 | u32 mpll_ss; | ||
56 | u32 mpll_ss2; | ||
57 | }; | ||
58 | |||
59 | union r7xx_clock_registers { | ||
60 | struct rv770_clock_registers rv770; | ||
61 | struct rv730_clock_registers rv730; | ||
62 | }; | ||
63 | |||
64 | struct vddc_table_entry { | ||
65 | u16 vddc; | ||
66 | u8 vddc_index; | ||
67 | u8 high_smio; | ||
68 | u32 low_smio; | ||
69 | }; | ||
70 | |||
71 | #define MAX_NO_OF_MVDD_VALUES 2 | ||
72 | #define MAX_NO_VREG_STEPS 32 | ||
73 | |||
74 | struct rv7xx_power_info { | ||
75 | /* flags */ | ||
76 | bool mem_gddr5; | ||
77 | bool pcie_gen2; | ||
78 | bool dynamic_pcie_gen2; | ||
79 | bool acpi_pcie_gen2; | ||
80 | bool boot_in_gen2; | ||
81 | bool voltage_control; /* vddc */ | ||
82 | bool mvdd_control; | ||
83 | bool sclk_ss; | ||
84 | bool mclk_ss; | ||
85 | bool dynamic_ss; | ||
86 | bool gfx_clock_gating; | ||
87 | bool mg_clock_gating; | ||
88 | bool mgcgtssm; | ||
89 | bool power_gating; | ||
90 | bool thermal_protection; | ||
91 | bool display_gap; | ||
92 | bool dcodt; | ||
93 | bool ulps; | ||
94 | /* registers */ | ||
95 | union r7xx_clock_registers clk_regs; | ||
96 | u32 s0_vid_lower_smio_cntl; | ||
97 | /* voltage */ | ||
98 | u32 vddc_mask_low; | ||
99 | u32 mvdd_mask_low; | ||
100 | u32 mvdd_split_frequency; | ||
101 | u32 mvdd_low_smio[MAX_NO_OF_MVDD_VALUES]; | ||
102 | u16 max_vddc; | ||
103 | u16 max_vddc_in_table; | ||
104 | u16 min_vddc_in_table; | ||
105 | struct vddc_table_entry vddc_table[MAX_NO_VREG_STEPS]; | ||
106 | u8 valid_vddc_entries; | ||
107 | /* dc odt */ | ||
108 | u32 mclk_odt_threshold; | ||
109 | u8 odt_value_0[2]; | ||
110 | u8 odt_value_1[2]; | ||
111 | /* stored values */ | ||
112 | u32 boot_sclk; | ||
113 | u16 acpi_vddc; | ||
114 | u32 ref_div; | ||
115 | u32 active_auto_throttle_sources; | ||
116 | u32 mclk_stutter_mode_threshold; | ||
117 | u32 mclk_strobe_mode_threshold; | ||
118 | u32 mclk_edc_enable_threshold; | ||
119 | u32 bsp; | ||
120 | u32 bsu; | ||
121 | u32 pbsp; | ||
122 | u32 pbsu; | ||
123 | u32 dsp; | ||
124 | u32 psp; | ||
125 | u32 asi; | ||
126 | u32 pasi; | ||
127 | u32 vrc; | ||
128 | u32 restricted_levels; | ||
129 | /* smc offsets */ | ||
130 | u16 state_table_start; | ||
131 | u16 soft_regs_start; | ||
132 | u16 sram_end; | ||
133 | /* scratch structs */ | ||
134 | RV770_SMC_STATETABLE smc_statetable; | ||
135 | }; | ||
136 | |||
137 | struct rv7xx_pl { | ||
138 | u32 sclk; | ||
139 | u32 mclk; | ||
140 | u16 vddc; | ||
141 | u16 vddci; /* eg+ only */ | ||
142 | u32 flags; | ||
143 | }; | ||
144 | |||
145 | struct rv7xx_ps { | ||
146 | struct rv7xx_pl high; | ||
147 | struct rv7xx_pl medium; | ||
148 | struct rv7xx_pl low; | ||
149 | bool dc_compatible; | ||
150 | }; | ||
151 | |||
152 | #define RV770_RLP_DFLT 10 | ||
153 | #define RV770_RMP_DFLT 25 | ||
154 | #define RV770_LHP_DFLT 25 | ||
155 | #define RV770_LMP_DFLT 10 | ||
156 | #define RV770_VRC_DFLT 0x003f | ||
157 | #define RV770_ASI_DFLT 1000 | ||
158 | #define RV770_HASI_DFLT 200000 | ||
159 | #define RV770_MGCGTTLOCAL0_DFLT 0x00100000 | ||
160 | #define RV7XX_MGCGTTLOCAL0_DFLT 0 | ||
161 | #define RV770_MGCGTTLOCAL1_DFLT 0xFFFF0000 | ||
162 | #define RV770_MGCGCGTSSMCTRL_DFLT 0x55940000 | ||
163 | |||
164 | #define MVDD_LOW_INDEX 0 | ||
165 | #define MVDD_HIGH_INDEX 1 | ||
166 | |||
167 | #define MVDD_LOW_VALUE 0 | ||
168 | #define MVDD_HIGH_VALUE 0xffff | ||
169 | |||
170 | #define RV770_DEFAULT_VCLK_FREQ 53300 /* 10 khz */ | ||
171 | #define RV770_DEFAULT_DCLK_FREQ 40000 /* 10 khz */ | ||
172 | |||
173 | /* rv730/rv710 */ | ||
174 | int rv730_populate_sclk_value(struct radeon_device *rdev, | ||
175 | u32 engine_clock, | ||
176 | RV770_SMC_SCLK_VALUE *sclk); | ||
177 | int rv730_populate_mclk_value(struct radeon_device *rdev, | ||
178 | u32 engine_clock, u32 memory_clock, | ||
179 | LPRV7XX_SMC_MCLK_VALUE mclk); | ||
180 | void rv730_read_clock_registers(struct radeon_device *rdev); | ||
181 | int rv730_populate_smc_acpi_state(struct radeon_device *rdev, | ||
182 | RV770_SMC_STATETABLE *table); | ||
183 | int rv730_populate_smc_initial_state(struct radeon_device *rdev, | ||
184 | struct radeon_ps *radeon_initial_state, | ||
185 | RV770_SMC_STATETABLE *table); | ||
186 | void rv730_program_memory_timing_parameters(struct radeon_device *rdev, | ||
187 | struct radeon_ps *radeon_state); | ||
188 | void rv730_power_gating_enable(struct radeon_device *rdev, | ||
189 | bool enable); | ||
190 | void rv730_start_dpm(struct radeon_device *rdev); | ||
191 | void rv730_stop_dpm(struct radeon_device *rdev); | ||
192 | void rv730_program_dcodt(struct radeon_device *rdev, bool use_dcodt); | ||
193 | void rv730_get_odt_values(struct radeon_device *rdev); | ||
194 | |||
195 | /* rv740 */ | ||
196 | int rv740_populate_sclk_value(struct radeon_device *rdev, u32 engine_clock, | ||
197 | RV770_SMC_SCLK_VALUE *sclk); | ||
198 | int rv740_populate_mclk_value(struct radeon_device *rdev, | ||
199 | u32 engine_clock, u32 memory_clock, | ||
200 | RV7XX_SMC_MCLK_VALUE *mclk); | ||
201 | void rv740_read_clock_registers(struct radeon_device *rdev); | ||
202 | int rv740_populate_smc_acpi_state(struct radeon_device *rdev, | ||
203 | RV770_SMC_STATETABLE *table); | ||
204 | void rv740_enable_mclk_spread_spectrum(struct radeon_device *rdev, | ||
205 | bool enable); | ||
206 | u8 rv740_get_mclk_frequency_ratio(u32 memory_clock); | ||
207 | u32 rv740_get_dll_speed(bool is_gddr5, u32 memory_clock); | ||
208 | u32 rv740_get_decoded_reference_divider(u32 encoded_ref); | ||
209 | |||
210 | /* rv770 */ | ||
211 | u32 rv770_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf); | ||
212 | int rv770_populate_vddc_value(struct radeon_device *rdev, u16 vddc, | ||
213 | RV770_SMC_VOLTAGE_VALUE *voltage); | ||
214 | int rv770_populate_mvdd_value(struct radeon_device *rdev, u32 mclk, | ||
215 | RV770_SMC_VOLTAGE_VALUE *voltage); | ||
216 | u8 rv770_get_seq_value(struct radeon_device *rdev, | ||
217 | struct rv7xx_pl *pl); | ||
218 | int rv770_populate_initial_mvdd_value(struct radeon_device *rdev, | ||
219 | RV770_SMC_VOLTAGE_VALUE *voltage); | ||
220 | u32 rv770_calculate_memory_refresh_rate(struct radeon_device *rdev, | ||
221 | u32 engine_clock); | ||
222 | void rv770_program_response_times(struct radeon_device *rdev); | ||
223 | int rv770_populate_smc_sp(struct radeon_device *rdev, | ||
224 | struct radeon_ps *radeon_state, | ||
225 | RV770_SMC_SWSTATE *smc_state); | ||
226 | int rv770_populate_smc_t(struct radeon_device *rdev, | ||
227 | struct radeon_ps *radeon_state, | ||
228 | RV770_SMC_SWSTATE *smc_state); | ||
229 | void rv770_read_voltage_smio_registers(struct radeon_device *rdev); | ||
230 | void rv770_get_memory_type(struct radeon_device *rdev); | ||
231 | void r7xx_start_smc(struct radeon_device *rdev); | ||
232 | u8 rv770_get_memory_module_index(struct radeon_device *rdev); | ||
233 | void rv770_get_max_vddc(struct radeon_device *rdev); | ||
234 | void rv770_get_pcie_gen2_status(struct radeon_device *rdev); | ||
235 | void rv770_enable_acpi_pm(struct radeon_device *rdev); | ||
236 | void rv770_restore_cgcg(struct radeon_device *rdev); | ||
237 | bool rv770_dpm_enabled(struct radeon_device *rdev); | ||
238 | void rv770_enable_voltage_control(struct radeon_device *rdev, | ||
239 | bool enable); | ||
240 | void rv770_enable_backbias(struct radeon_device *rdev, | ||
241 | bool enable); | ||
242 | void rv770_enable_thermal_protection(struct radeon_device *rdev, | ||
243 | bool enable); | ||
244 | void rv770_enable_auto_throttle_source(struct radeon_device *rdev, | ||
245 | enum radeon_dpm_auto_throttle_src source, | ||
246 | bool enable); | ||
247 | void rv770_setup_bsp(struct radeon_device *rdev); | ||
248 | void rv770_program_git(struct radeon_device *rdev); | ||
249 | void rv770_program_tp(struct radeon_device *rdev); | ||
250 | void rv770_program_tpp(struct radeon_device *rdev); | ||
251 | void rv770_program_sstp(struct radeon_device *rdev); | ||
252 | void rv770_program_engine_speed_parameters(struct radeon_device *rdev); | ||
253 | void rv770_program_vc(struct radeon_device *rdev); | ||
254 | void rv770_clear_vc(struct radeon_device *rdev); | ||
255 | int rv770_upload_firmware(struct radeon_device *rdev); | ||
256 | void rv770_stop_dpm(struct radeon_device *rdev); | ||
257 | void r7xx_stop_smc(struct radeon_device *rdev); | ||
258 | void rv770_reset_smio_status(struct radeon_device *rdev); | ||
259 | int rv770_restrict_performance_levels_before_switch(struct radeon_device *rdev); | ||
260 | int rv770_unrestrict_performance_levels_after_switch(struct radeon_device *rdev); | ||
261 | int rv770_halt_smc(struct radeon_device *rdev); | ||
262 | int rv770_resume_smc(struct radeon_device *rdev); | ||
263 | int rv770_set_sw_state(struct radeon_device *rdev); | ||
264 | int rv770_set_boot_state(struct radeon_device *rdev); | ||
265 | int rv7xx_parse_power_table(struct radeon_device *rdev); | ||
266 | |||
267 | /* smc */ | ||
268 | int rv770_read_smc_soft_register(struct radeon_device *rdev, | ||
269 | u16 reg_offset, u32 *value); | ||
270 | int rv770_write_smc_soft_register(struct radeon_device *rdev, | ||
271 | u16 reg_offset, u32 value); | ||
272 | |||
273 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/rv770_smc.c b/drivers/gpu/drm/radeon/rv770_smc.c new file mode 100644 index 000000000000..8e071530fe9d --- /dev/null +++ b/drivers/gpu/drm/radeon/rv770_smc.c | |||
@@ -0,0 +1,404 @@ | |||
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 <linux/firmware.h> | ||
26 | #include "drmP.h" | ||
27 | #include "radeon.h" | ||
28 | #include "rv770d.h" | ||
29 | #include "rv770_dpm.h" | ||
30 | #include "rv770_smc.h" | ||
31 | #include "atom.h" | ||
32 | #include "radeon_ucode.h" | ||
33 | |||
34 | #define FIRST_SMC_INT_VECT_REG 0xFFD8 | ||
35 | #define FIRST_INT_VECT_S19 0xFFC0 | ||
36 | |||
37 | static const u8 rv770_smc_int_vectors[] = | ||
38 | { | ||
39 | 0x08, 0x10, 0x08, 0x10, | ||
40 | 0x08, 0x10, 0x08, 0x10, | ||
41 | 0x08, 0x10, 0x08, 0x10, | ||
42 | 0x08, 0x10, 0x08, 0x10, | ||
43 | 0x08, 0x10, 0x08, 0x10, | ||
44 | 0x08, 0x10, 0x08, 0x10, | ||
45 | 0x08, 0x10, 0x08, 0x10, | ||
46 | 0x08, 0x10, 0x08, 0x10, | ||
47 | 0x08, 0x10, 0x08, 0x10, | ||
48 | 0x08, 0x10, 0x08, 0x10, | ||
49 | 0x08, 0x10, 0x08, 0x10, | ||
50 | 0x08, 0x10, 0x08, 0x10, | ||
51 | 0x08, 0x10, 0x0C, 0xD7, | ||
52 | 0x08, 0x2B, 0x08, 0x10, | ||
53 | 0x03, 0x51, 0x03, 0x51, | ||
54 | 0x03, 0x51, 0x03, 0x51 | ||
55 | }; | ||
56 | |||
57 | static const u8 rv730_smc_int_vectors[] = | ||
58 | { | ||
59 | 0x08, 0x15, 0x08, 0x15, | ||
60 | 0x08, 0x15, 0x08, 0x15, | ||
61 | 0x08, 0x15, 0x08, 0x15, | ||
62 | 0x08, 0x15, 0x08, 0x15, | ||
63 | 0x08, 0x15, 0x08, 0x15, | ||
64 | 0x08, 0x15, 0x08, 0x15, | ||
65 | 0x08, 0x15, 0x08, 0x15, | ||
66 | 0x08, 0x15, 0x08, 0x15, | ||
67 | 0x08, 0x15, 0x08, 0x15, | ||
68 | 0x08, 0x15, 0x08, 0x15, | ||
69 | 0x08, 0x15, 0x08, 0x15, | ||
70 | 0x08, 0x15, 0x08, 0x15, | ||
71 | 0x08, 0x15, 0x0C, 0xBB, | ||
72 | 0x08, 0x30, 0x08, 0x15, | ||
73 | 0x03, 0x56, 0x03, 0x56, | ||
74 | 0x03, 0x56, 0x03, 0x56 | ||
75 | }; | ||
76 | |||
77 | static const u8 rv710_smc_int_vectors[] = | ||
78 | { | ||
79 | 0x08, 0x04, 0x08, 0x04, | ||
80 | 0x08, 0x04, 0x08, 0x04, | ||
81 | 0x08, 0x04, 0x08, 0x04, | ||
82 | 0x08, 0x04, 0x08, 0x04, | ||
83 | 0x08, 0x04, 0x08, 0x04, | ||
84 | 0x08, 0x04, 0x08, 0x04, | ||
85 | 0x08, 0x04, 0x08, 0x04, | ||
86 | 0x08, 0x04, 0x08, 0x04, | ||
87 | 0x08, 0x04, 0x08, 0x04, | ||
88 | 0x08, 0x04, 0x08, 0x04, | ||
89 | 0x08, 0x04, 0x08, 0x04, | ||
90 | 0x08, 0x04, 0x08, 0x04, | ||
91 | 0x08, 0x04, 0x0C, 0xCB, | ||
92 | 0x08, 0x1F, 0x08, 0x04, | ||
93 | 0x03, 0x51, 0x03, 0x51, | ||
94 | 0x03, 0x51, 0x03, 0x51 | ||
95 | }; | ||
96 | |||
97 | static const u8 rv740_smc_int_vectors[] = | ||
98 | { | ||
99 | 0x08, 0x10, 0x08, 0x10, | ||
100 | 0x08, 0x10, 0x08, 0x10, | ||
101 | 0x08, 0x10, 0x08, 0x10, | ||
102 | 0x08, 0x10, 0x08, 0x10, | ||
103 | 0x08, 0x10, 0x08, 0x10, | ||
104 | 0x08, 0x10, 0x08, 0x10, | ||
105 | 0x08, 0x10, 0x08, 0x10, | ||
106 | 0x08, 0x10, 0x08, 0x10, | ||
107 | 0x08, 0x10, 0x08, 0x10, | ||
108 | 0x08, 0x10, 0x08, 0x10, | ||
109 | 0x08, 0x10, 0x08, 0x10, | ||
110 | 0x08, 0x10, 0x08, 0x10, | ||
111 | 0x08, 0x10, 0x0C, 0xD7, | ||
112 | 0x08, 0x2B, 0x08, 0x10, | ||
113 | 0x03, 0x51, 0x03, 0x51, | ||
114 | 0x03, 0x51, 0x03, 0x51 | ||
115 | }; | ||
116 | |||
117 | int rv770_set_smc_sram_address(struct radeon_device *rdev, | ||
118 | u16 smc_address, u16 limit) | ||
119 | { | ||
120 | u32 addr; | ||
121 | |||
122 | if (smc_address & 3) | ||
123 | return -EINVAL; | ||
124 | if ((smc_address + 3) > limit) | ||
125 | return -EINVAL; | ||
126 | |||
127 | addr = smc_address; | ||
128 | addr |= SMC_SRAM_AUTO_INC_DIS; | ||
129 | |||
130 | WREG32(SMC_SRAM_ADDR, addr); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | int rv770_copy_bytes_to_smc(struct radeon_device *rdev, | ||
136 | u16 smc_start_address, const u8 *src, | ||
137 | u16 byte_count, u16 limit) | ||
138 | { | ||
139 | u32 data, original_data, extra_shift; | ||
140 | u16 addr; | ||
141 | int ret; | ||
142 | |||
143 | if (smc_start_address & 3) | ||
144 | return -EINVAL; | ||
145 | if ((smc_start_address + byte_count) > limit) | ||
146 | return -EINVAL; | ||
147 | |||
148 | addr = smc_start_address; | ||
149 | |||
150 | while (byte_count >= 4) { | ||
151 | /* SMC address space is BE */ | ||
152 | data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; | ||
153 | |||
154 | ret = rv770_set_smc_sram_address(rdev, addr, limit); | ||
155 | if (ret) | ||
156 | return ret; | ||
157 | |||
158 | WREG32(SMC_SRAM_DATA, data); | ||
159 | |||
160 | src += 4; | ||
161 | byte_count -= 4; | ||
162 | addr += 4; | ||
163 | } | ||
164 | |||
165 | /* RMW for final bytes */ | ||
166 | if (byte_count > 0) { | ||
167 | data = 0; | ||
168 | |||
169 | ret = rv770_set_smc_sram_address(rdev, addr, limit); | ||
170 | if (ret) | ||
171 | return ret; | ||
172 | |||
173 | original_data = RREG32(SMC_SRAM_DATA); | ||
174 | |||
175 | extra_shift = 8 * (4 - byte_count); | ||
176 | |||
177 | while (byte_count > 0) { | ||
178 | /* SMC address space is BE */ | ||
179 | data = (data << 8) + *src++; | ||
180 | byte_count--; | ||
181 | } | ||
182 | |||
183 | data <<= extra_shift; | ||
184 | |||
185 | data |= (original_data & ~((~0UL) << extra_shift)); | ||
186 | |||
187 | ret = rv770_set_smc_sram_address(rdev, addr, limit); | ||
188 | if (ret) | ||
189 | return ret; | ||
190 | |||
191 | WREG32(SMC_SRAM_DATA, data); | ||
192 | } | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int rv770_program_interrupt_vectors(struct radeon_device *rdev, | ||
198 | u32 smc_first_vector, const u8 *src, | ||
199 | u32 byte_count) | ||
200 | { | ||
201 | u32 tmp, i; | ||
202 | |||
203 | if (byte_count % 4) | ||
204 | return -EINVAL; | ||
205 | |||
206 | if (smc_first_vector < FIRST_SMC_INT_VECT_REG) { | ||
207 | tmp = FIRST_SMC_INT_VECT_REG - smc_first_vector; | ||
208 | |||
209 | if (tmp > byte_count) | ||
210 | return 0; | ||
211 | |||
212 | byte_count -= tmp; | ||
213 | src += tmp; | ||
214 | smc_first_vector = FIRST_SMC_INT_VECT_REG; | ||
215 | } | ||
216 | |||
217 | for (i = 0; i < byte_count; i += 4) { | ||
218 | /* SMC address space is BE */ | ||
219 | tmp = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; | ||
220 | |||
221 | WREG32(SMC_ISR_FFD8_FFDB + i, tmp); | ||
222 | } | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | void rv770_start_smc(struct radeon_device *rdev) | ||
228 | { | ||
229 | WREG32_P(SMC_IO, SMC_RST_N, ~SMC_RST_N); | ||
230 | } | ||
231 | |||
232 | void rv770_reset_smc(struct radeon_device *rdev) | ||
233 | { | ||
234 | WREG32_P(SMC_IO, 0, ~SMC_RST_N); | ||
235 | } | ||
236 | |||
237 | void rv770_stop_smc_clock(struct radeon_device *rdev) | ||
238 | { | ||
239 | WREG32_P(SMC_IO, 0, ~SMC_CLK_EN); | ||
240 | } | ||
241 | |||
242 | void rv770_start_smc_clock(struct radeon_device *rdev) | ||
243 | { | ||
244 | WREG32_P(SMC_IO, SMC_CLK_EN, ~SMC_CLK_EN); | ||
245 | } | ||
246 | |||
247 | bool rv770_is_smc_running(struct radeon_device *rdev) | ||
248 | { | ||
249 | u32 tmp; | ||
250 | |||
251 | tmp = RREG32(SMC_IO); | ||
252 | |||
253 | if ((tmp & SMC_RST_N) && (tmp & SMC_CLK_EN)) | ||
254 | return true; | ||
255 | else | ||
256 | return false; | ||
257 | } | ||
258 | |||
259 | PPSMC_Result rv770_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg) | ||
260 | { | ||
261 | u32 tmp; | ||
262 | int i; | ||
263 | PPSMC_Result result; | ||
264 | |||
265 | if (!rv770_is_smc_running(rdev)) | ||
266 | return PPSMC_Result_Failed; | ||
267 | |||
268 | WREG32_P(SMC_MSG, HOST_SMC_MSG(msg), ~HOST_SMC_MSG_MASK); | ||
269 | |||
270 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
271 | tmp = RREG32(SMC_MSG) & HOST_SMC_RESP_MASK; | ||
272 | tmp >>= HOST_SMC_RESP_SHIFT; | ||
273 | if (tmp != 0) | ||
274 | break; | ||
275 | udelay(1); | ||
276 | } | ||
277 | |||
278 | tmp = RREG32(SMC_MSG) & HOST_SMC_RESP_MASK; | ||
279 | tmp >>= HOST_SMC_RESP_SHIFT; | ||
280 | |||
281 | result = (PPSMC_Result)tmp; | ||
282 | return result; | ||
283 | } | ||
284 | |||
285 | PPSMC_Result rv770_wait_for_smc_inactive(struct radeon_device *rdev) | ||
286 | { | ||
287 | int i; | ||
288 | PPSMC_Result result = PPSMC_Result_OK; | ||
289 | |||
290 | if (!rv770_is_smc_running(rdev)) | ||
291 | return result; | ||
292 | |||
293 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
294 | if (RREG32(SMC_IO) & SMC_STOP_MODE) | ||
295 | break; | ||
296 | udelay(1); | ||
297 | } | ||
298 | |||
299 | return result; | ||
300 | } | ||
301 | |||
302 | static void rv770_clear_smc_sram(struct radeon_device *rdev, u16 limit) | ||
303 | { | ||
304 | u16 i; | ||
305 | |||
306 | for (i = 0; i < limit; i += 4) { | ||
307 | rv770_set_smc_sram_address(rdev, i, limit); | ||
308 | WREG32(SMC_SRAM_DATA, 0); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | int rv770_load_smc_ucode(struct radeon_device *rdev, | ||
313 | u16 limit) | ||
314 | { | ||
315 | int ret; | ||
316 | const u8 *int_vect; | ||
317 | u16 int_vect_start_address; | ||
318 | u16 int_vect_size; | ||
319 | const u8 *ucode_data; | ||
320 | u16 ucode_start_address; | ||
321 | u16 ucode_size; | ||
322 | |||
323 | if (!rdev->smc_fw) | ||
324 | return -EINVAL; | ||
325 | |||
326 | rv770_clear_smc_sram(rdev, limit); | ||
327 | |||
328 | switch (rdev->family) { | ||
329 | case CHIP_RV770: | ||
330 | ucode_start_address = RV770_SMC_UCODE_START; | ||
331 | ucode_size = RV770_SMC_UCODE_SIZE; | ||
332 | int_vect = (const u8 *)&rv770_smc_int_vectors; | ||
333 | int_vect_start_address = RV770_SMC_INT_VECTOR_START; | ||
334 | int_vect_size = RV770_SMC_INT_VECTOR_SIZE; | ||
335 | break; | ||
336 | case CHIP_RV730: | ||
337 | ucode_start_address = RV730_SMC_UCODE_START; | ||
338 | ucode_size = RV730_SMC_UCODE_SIZE; | ||
339 | int_vect = (const u8 *)&rv730_smc_int_vectors; | ||
340 | int_vect_start_address = RV730_SMC_INT_VECTOR_START; | ||
341 | int_vect_size = RV730_SMC_INT_VECTOR_SIZE; | ||
342 | break; | ||
343 | case CHIP_RV710: | ||
344 | ucode_start_address = RV710_SMC_UCODE_START; | ||
345 | ucode_size = RV710_SMC_UCODE_SIZE; | ||
346 | int_vect = (const u8 *)&rv710_smc_int_vectors; | ||
347 | int_vect_start_address = RV710_SMC_INT_VECTOR_START; | ||
348 | int_vect_size = RV710_SMC_INT_VECTOR_SIZE; | ||
349 | break; | ||
350 | case CHIP_RV740: | ||
351 | ucode_start_address = RV740_SMC_UCODE_START; | ||
352 | ucode_size = RV740_SMC_UCODE_SIZE; | ||
353 | int_vect = (const u8 *)&rv740_smc_int_vectors; | ||
354 | int_vect_start_address = RV740_SMC_INT_VECTOR_START; | ||
355 | int_vect_size = RV740_SMC_INT_VECTOR_SIZE; | ||
356 | break; | ||
357 | default: | ||
358 | DRM_ERROR("unknown asic in smc ucode loader\n"); | ||
359 | BUG(); | ||
360 | } | ||
361 | |||
362 | /* load the ucode */ | ||
363 | ucode_data = (const u8 *)rdev->smc_fw->data; | ||
364 | ret = rv770_copy_bytes_to_smc(rdev, ucode_start_address, | ||
365 | ucode_data, ucode_size, limit); | ||
366 | if (ret) | ||
367 | return ret; | ||
368 | |||
369 | /* set up the int vectors */ | ||
370 | ret = rv770_program_interrupt_vectors(rdev, int_vect_start_address, | ||
371 | int_vect, int_vect_size); | ||
372 | if (ret) | ||
373 | return ret; | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | int rv770_read_smc_sram_dword(struct radeon_device *rdev, | ||
379 | u16 smc_address, u32 *value, u16 limit) | ||
380 | { | ||
381 | int ret; | ||
382 | |||
383 | ret = rv770_set_smc_sram_address(rdev, smc_address, limit); | ||
384 | if (ret) | ||
385 | return ret; | ||
386 | |||
387 | *value = RREG32(SMC_SRAM_DATA); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | int rv770_write_smc_sram_dword(struct radeon_device *rdev, | ||
393 | u16 smc_address, u32 value, u16 limit) | ||
394 | { | ||
395 | int ret; | ||
396 | |||
397 | ret = rv770_set_smc_sram_address(rdev, smc_address, limit); | ||
398 | if (ret) | ||
399 | return ret; | ||
400 | |||
401 | WREG32(SMC_SRAM_DATA, value); | ||
402 | |||
403 | return 0; | ||
404 | } | ||
diff --git a/drivers/gpu/drm/radeon/rv770_smc.h b/drivers/gpu/drm/radeon/rv770_smc.h new file mode 100644 index 000000000000..bdb652c90815 --- /dev/null +++ b/drivers/gpu/drm/radeon/rv770_smc.h | |||
@@ -0,0 +1,208 @@ | |||
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 __RV770_SMC_H__ | ||
24 | #define __RV770_SMC_H__ | ||
25 | |||
26 | #include "ppsmc.h" | ||
27 | |||
28 | #pragma pack(push, 1) | ||
29 | |||
30 | #define RV770_SMC_TABLE_ADDRESS 0xB000 | ||
31 | |||
32 | #define RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 3 | ||
33 | |||
34 | struct RV770_SMC_SCLK_VALUE | ||
35 | { | ||
36 | uint32_t vCG_SPLL_FUNC_CNTL; | ||
37 | uint32_t vCG_SPLL_FUNC_CNTL_2; | ||
38 | uint32_t vCG_SPLL_FUNC_CNTL_3; | ||
39 | uint32_t vCG_SPLL_SPREAD_SPECTRUM; | ||
40 | uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; | ||
41 | uint32_t sclk_value; | ||
42 | }; | ||
43 | |||
44 | typedef struct RV770_SMC_SCLK_VALUE RV770_SMC_SCLK_VALUE; | ||
45 | |||
46 | struct RV770_SMC_MCLK_VALUE | ||
47 | { | ||
48 | uint32_t vMPLL_AD_FUNC_CNTL; | ||
49 | uint32_t vMPLL_AD_FUNC_CNTL_2; | ||
50 | uint32_t vMPLL_DQ_FUNC_CNTL; | ||
51 | uint32_t vMPLL_DQ_FUNC_CNTL_2; | ||
52 | uint32_t vMCLK_PWRMGT_CNTL; | ||
53 | uint32_t vDLL_CNTL; | ||
54 | uint32_t vMPLL_SS; | ||
55 | uint32_t vMPLL_SS2; | ||
56 | uint32_t mclk_value; | ||
57 | }; | ||
58 | |||
59 | typedef struct RV770_SMC_MCLK_VALUE RV770_SMC_MCLK_VALUE; | ||
60 | |||
61 | |||
62 | struct RV730_SMC_MCLK_VALUE | ||
63 | { | ||
64 | uint32_t vMCLK_PWRMGT_CNTL; | ||
65 | uint32_t vDLL_CNTL; | ||
66 | uint32_t vMPLL_FUNC_CNTL; | ||
67 | uint32_t vMPLL_FUNC_CNTL2; | ||
68 | uint32_t vMPLL_FUNC_CNTL3; | ||
69 | uint32_t vMPLL_SS; | ||
70 | uint32_t vMPLL_SS2; | ||
71 | uint32_t mclk_value; | ||
72 | }; | ||
73 | |||
74 | typedef struct RV730_SMC_MCLK_VALUE RV730_SMC_MCLK_VALUE; | ||
75 | |||
76 | struct RV770_SMC_VOLTAGE_VALUE | ||
77 | { | ||
78 | uint16_t value; | ||
79 | uint8_t index; | ||
80 | uint8_t padding; | ||
81 | }; | ||
82 | |||
83 | typedef struct RV770_SMC_VOLTAGE_VALUE RV770_SMC_VOLTAGE_VALUE; | ||
84 | |||
85 | union RV7XX_SMC_MCLK_VALUE | ||
86 | { | ||
87 | RV770_SMC_MCLK_VALUE mclk770; | ||
88 | RV730_SMC_MCLK_VALUE mclk730; | ||
89 | }; | ||
90 | |||
91 | typedef union RV7XX_SMC_MCLK_VALUE RV7XX_SMC_MCLK_VALUE, *LPRV7XX_SMC_MCLK_VALUE; | ||
92 | |||
93 | struct RV770_SMC_HW_PERFORMANCE_LEVEL | ||
94 | { | ||
95 | uint8_t arbValue; | ||
96 | union{ | ||
97 | uint8_t seqValue; | ||
98 | uint8_t ACIndex; | ||
99 | }; | ||
100 | uint8_t displayWatermark; | ||
101 | uint8_t gen2PCIE; | ||
102 | uint8_t gen2XSP; | ||
103 | uint8_t backbias; | ||
104 | uint8_t strobeMode; | ||
105 | uint8_t mcFlags; | ||
106 | uint32_t aT; | ||
107 | uint32_t bSP; | ||
108 | RV770_SMC_SCLK_VALUE sclk; | ||
109 | RV7XX_SMC_MCLK_VALUE mclk; | ||
110 | RV770_SMC_VOLTAGE_VALUE vddc; | ||
111 | RV770_SMC_VOLTAGE_VALUE mvdd; | ||
112 | RV770_SMC_VOLTAGE_VALUE vddci; | ||
113 | uint8_t reserved1; | ||
114 | uint8_t reserved2; | ||
115 | uint8_t stateFlags; | ||
116 | uint8_t padding; | ||
117 | }; | ||
118 | |||
119 | #define SMC_STROBE_RATIO 0x0F | ||
120 | #define SMC_STROBE_ENABLE 0x10 | ||
121 | |||
122 | #define SMC_MC_EDC_RD_FLAG 0x01 | ||
123 | #define SMC_MC_EDC_WR_FLAG 0x02 | ||
124 | #define SMC_MC_RTT_ENABLE 0x04 | ||
125 | #define SMC_MC_STUTTER_EN 0x08 | ||
126 | |||
127 | typedef struct RV770_SMC_HW_PERFORMANCE_LEVEL RV770_SMC_HW_PERFORMANCE_LEVEL; | ||
128 | |||
129 | struct RV770_SMC_SWSTATE | ||
130 | { | ||
131 | uint8_t flags; | ||
132 | uint8_t padding1; | ||
133 | uint8_t padding2; | ||
134 | uint8_t padding3; | ||
135 | RV770_SMC_HW_PERFORMANCE_LEVEL levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE]; | ||
136 | }; | ||
137 | |||
138 | typedef struct RV770_SMC_SWSTATE RV770_SMC_SWSTATE; | ||
139 | |||
140 | #define RV770_SMC_VOLTAGEMASK_VDDC 0 | ||
141 | #define RV770_SMC_VOLTAGEMASK_MVDD 1 | ||
142 | #define RV770_SMC_VOLTAGEMASK_VDDCI 2 | ||
143 | #define RV770_SMC_VOLTAGEMASK_MAX 4 | ||
144 | |||
145 | struct RV770_SMC_VOLTAGEMASKTABLE | ||
146 | { | ||
147 | uint8_t highMask[RV770_SMC_VOLTAGEMASK_MAX]; | ||
148 | uint32_t lowMask[RV770_SMC_VOLTAGEMASK_MAX]; | ||
149 | }; | ||
150 | |||
151 | typedef struct RV770_SMC_VOLTAGEMASKTABLE RV770_SMC_VOLTAGEMASKTABLE; | ||
152 | |||
153 | #define MAX_NO_VREG_STEPS 32 | ||
154 | |||
155 | struct RV770_SMC_STATETABLE | ||
156 | { | ||
157 | uint8_t thermalProtectType; | ||
158 | uint8_t systemFlags; | ||
159 | uint8_t maxVDDCIndexInPPTable; | ||
160 | uint8_t extraFlags; | ||
161 | uint8_t highSMIO[MAX_NO_VREG_STEPS]; | ||
162 | uint32_t lowSMIO[MAX_NO_VREG_STEPS]; | ||
163 | RV770_SMC_VOLTAGEMASKTABLE voltageMaskTable; | ||
164 | RV770_SMC_SWSTATE initialState; | ||
165 | RV770_SMC_SWSTATE ACPIState; | ||
166 | RV770_SMC_SWSTATE driverState; | ||
167 | RV770_SMC_SWSTATE ULVState; | ||
168 | }; | ||
169 | |||
170 | typedef struct RV770_SMC_STATETABLE RV770_SMC_STATETABLE; | ||
171 | |||
172 | #define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 | ||
173 | |||
174 | #pragma pack(pop) | ||
175 | |||
176 | #define RV770_SMC_SOFT_REGISTERS_START 0x104 | ||
177 | |||
178 | #define RV770_SMC_SOFT_REGISTER_mclk_chg_timeout 0x0 | ||
179 | #define RV770_SMC_SOFT_REGISTER_baby_step_timer 0x8 | ||
180 | #define RV770_SMC_SOFT_REGISTER_delay_bbias 0xC | ||
181 | #define RV770_SMC_SOFT_REGISTER_delay_vreg 0x10 | ||
182 | #define RV770_SMC_SOFT_REGISTER_delay_acpi 0x2C | ||
183 | #define RV770_SMC_SOFT_REGISTER_seq_index 0x64 | ||
184 | #define RV770_SMC_SOFT_REGISTER_mvdd_chg_time 0x68 | ||
185 | #define RV770_SMC_SOFT_REGISTER_mclk_switch_lim 0x78 | ||
186 | #define RV770_SMC_SOFT_REGISTER_mc_block_delay 0x90 | ||
187 | #define RV770_SMC_SOFT_REGISTER_is_asic_lombok 0xA0 | ||
188 | |||
189 | int rv770_set_smc_sram_address(struct radeon_device *rdev, | ||
190 | u16 smc_address, u16 limit); | ||
191 | int rv770_copy_bytes_to_smc(struct radeon_device *rdev, | ||
192 | u16 smc_start_address, const u8 *src, | ||
193 | u16 byte_count, u16 limit); | ||
194 | void rv770_start_smc(struct radeon_device *rdev); | ||
195 | void rv770_reset_smc(struct radeon_device *rdev); | ||
196 | void rv770_stop_smc_clock(struct radeon_device *rdev); | ||
197 | void rv770_start_smc_clock(struct radeon_device *rdev); | ||
198 | bool rv770_is_smc_running(struct radeon_device *rdev); | ||
199 | PPSMC_Result rv770_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg); | ||
200 | PPSMC_Result rv770_wait_for_smc_inactive(struct radeon_device *rdev); | ||
201 | int rv770_read_smc_sram_dword(struct radeon_device *rdev, | ||
202 | u16 smc_address, u32 *value, u16 limit); | ||
203 | int rv770_write_smc_sram_dword(struct radeon_device *rdev, | ||
204 | u16 smc_address, u32 value, u16 limit); | ||
205 | int rv770_load_smc_ucode(struct radeon_device *rdev, | ||
206 | u16 limit); | ||
207 | |||
208 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 85b16266f748..784eeaf315c3 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h | |||
@@ -62,6 +62,242 @@ | |||
62 | # define UPLL_FB_DIV(x) ((x) << 0) | 62 | # define UPLL_FB_DIV(x) ((x) << 0) |
63 | # define UPLL_FB_DIV_MASK 0x01FFFFFF | 63 | # define UPLL_FB_DIV_MASK 0x01FFFFFF |
64 | 64 | ||
65 | /* pm registers */ | ||
66 | #define SMC_SRAM_ADDR 0x200 | ||
67 | #define SMC_SRAM_AUTO_INC_DIS (1 << 16) | ||
68 | #define SMC_SRAM_DATA 0x204 | ||
69 | #define SMC_IO 0x208 | ||
70 | #define SMC_RST_N (1 << 0) | ||
71 | #define SMC_STOP_MODE (1 << 2) | ||
72 | #define SMC_CLK_EN (1 << 11) | ||
73 | #define SMC_MSG 0x20c | ||
74 | #define HOST_SMC_MSG(x) ((x) << 0) | ||
75 | #define HOST_SMC_MSG_MASK (0xff << 0) | ||
76 | #define HOST_SMC_MSG_SHIFT 0 | ||
77 | #define HOST_SMC_RESP(x) ((x) << 8) | ||
78 | #define HOST_SMC_RESP_MASK (0xff << 8) | ||
79 | #define HOST_SMC_RESP_SHIFT 8 | ||
80 | #define SMC_HOST_MSG(x) ((x) << 16) | ||
81 | #define SMC_HOST_MSG_MASK (0xff << 16) | ||
82 | #define SMC_HOST_MSG_SHIFT 16 | ||
83 | #define SMC_HOST_RESP(x) ((x) << 24) | ||
84 | #define SMC_HOST_RESP_MASK (0xff << 24) | ||
85 | #define SMC_HOST_RESP_SHIFT 24 | ||
86 | |||
87 | #define SMC_ISR_FFD8_FFDB 0x218 | ||
88 | |||
89 | #define CG_SPLL_FUNC_CNTL 0x600 | ||
90 | #define SPLL_RESET (1 << 0) | ||
91 | #define SPLL_SLEEP (1 << 1) | ||
92 | #define SPLL_DIVEN (1 << 2) | ||
93 | #define SPLL_BYPASS_EN (1 << 3) | ||
94 | #define SPLL_REF_DIV(x) ((x) << 4) | ||
95 | #define SPLL_REF_DIV_MASK (0x3f << 4) | ||
96 | #define SPLL_HILEN(x) ((x) << 12) | ||
97 | #define SPLL_HILEN_MASK (0xf << 12) | ||
98 | #define SPLL_LOLEN(x) ((x) << 16) | ||
99 | #define SPLL_LOLEN_MASK (0xf << 16) | ||
100 | #define CG_SPLL_FUNC_CNTL_2 0x604 | ||
101 | #define SCLK_MUX_SEL(x) ((x) << 0) | ||
102 | #define SCLK_MUX_SEL_MASK (0x1ff << 0) | ||
103 | #define CG_SPLL_FUNC_CNTL_3 0x608 | ||
104 | #define SPLL_FB_DIV(x) ((x) << 0) | ||
105 | #define SPLL_FB_DIV_MASK (0x3ffffff << 0) | ||
106 | #define SPLL_DITHEN (1 << 28) | ||
107 | |||
108 | #define SPLL_CNTL_MODE 0x610 | ||
109 | #define SPLL_DIV_SYNC (1 << 5) | ||
110 | |||
111 | #define MPLL_AD_FUNC_CNTL 0x624 | ||
112 | #define CLKF(x) ((x) << 0) | ||
113 | #define CLKF_MASK (0x7f << 0) | ||
114 | #define CLKR(x) ((x) << 7) | ||
115 | #define CLKR_MASK (0x1f << 7) | ||
116 | #define CLKFRAC(x) ((x) << 12) | ||
117 | #define CLKFRAC_MASK (0x1f << 12) | ||
118 | #define YCLK_POST_DIV(x) ((x) << 17) | ||
119 | #define YCLK_POST_DIV_MASK (3 << 17) | ||
120 | #define IBIAS(x) ((x) << 20) | ||
121 | #define IBIAS_MASK (0x3ff << 20) | ||
122 | #define RESET (1 << 30) | ||
123 | #define PDNB (1 << 31) | ||
124 | #define MPLL_AD_FUNC_CNTL_2 0x628 | ||
125 | #define BYPASS (1 << 19) | ||
126 | #define BIAS_GEN_PDNB (1 << 24) | ||
127 | #define RESET_EN (1 << 25) | ||
128 | #define VCO_MODE (1 << 29) | ||
129 | #define MPLL_DQ_FUNC_CNTL 0x62c | ||
130 | #define MPLL_DQ_FUNC_CNTL_2 0x630 | ||
131 | |||
132 | #define GENERAL_PWRMGT 0x63c | ||
133 | # define GLOBAL_PWRMGT_EN (1 << 0) | ||
134 | # define STATIC_PM_EN (1 << 1) | ||
135 | # define THERMAL_PROTECTION_DIS (1 << 2) | ||
136 | # define THERMAL_PROTECTION_TYPE (1 << 3) | ||
137 | # define ENABLE_GEN2PCIE (1 << 4) | ||
138 | # define ENABLE_GEN2XSP (1 << 5) | ||
139 | # define SW_SMIO_INDEX(x) ((x) << 6) | ||
140 | # define SW_SMIO_INDEX_MASK (3 << 6) | ||
141 | # define SW_SMIO_INDEX_SHIFT 6 | ||
142 | # define LOW_VOLT_D2_ACPI (1 << 8) | ||
143 | # define LOW_VOLT_D3_ACPI (1 << 9) | ||
144 | # define VOLT_PWRMGT_EN (1 << 10) | ||
145 | # define BACKBIAS_PAD_EN (1 << 18) | ||
146 | # define BACKBIAS_VALUE (1 << 19) | ||
147 | # define DYN_SPREAD_SPECTRUM_EN (1 << 23) | ||
148 | # define AC_DC_SW (1 << 24) | ||
149 | |||
150 | #define CG_TPC 0x640 | ||
151 | #define SCLK_PWRMGT_CNTL 0x644 | ||
152 | # define SCLK_PWRMGT_OFF (1 << 0) | ||
153 | # define SCLK_LOW_D1 (1 << 1) | ||
154 | # define FIR_RESET (1 << 4) | ||
155 | # define FIR_FORCE_TREND_SEL (1 << 5) | ||
156 | # define FIR_TREND_MODE (1 << 6) | ||
157 | # define DYN_GFX_CLK_OFF_EN (1 << 7) | ||
158 | # define GFX_CLK_FORCE_ON (1 << 8) | ||
159 | # define GFX_CLK_REQUEST_OFF (1 << 9) | ||
160 | # define GFX_CLK_FORCE_OFF (1 << 10) | ||
161 | # define GFX_CLK_OFF_ACPI_D1 (1 << 11) | ||
162 | # define GFX_CLK_OFF_ACPI_D2 (1 << 12) | ||
163 | # define GFX_CLK_OFF_ACPI_D3 (1 << 13) | ||
164 | #define MCLK_PWRMGT_CNTL 0x648 | ||
165 | # define DLL_SPEED(x) ((x) << 0) | ||
166 | # define DLL_SPEED_MASK (0x1f << 0) | ||
167 | # define MPLL_PWRMGT_OFF (1 << 5) | ||
168 | # define DLL_READY (1 << 6) | ||
169 | # define MC_INT_CNTL (1 << 7) | ||
170 | # define MRDCKA0_SLEEP (1 << 8) | ||
171 | # define MRDCKA1_SLEEP (1 << 9) | ||
172 | # define MRDCKB0_SLEEP (1 << 10) | ||
173 | # define MRDCKB1_SLEEP (1 << 11) | ||
174 | # define MRDCKC0_SLEEP (1 << 12) | ||
175 | # define MRDCKC1_SLEEP (1 << 13) | ||
176 | # define MRDCKD0_SLEEP (1 << 14) | ||
177 | # define MRDCKD1_SLEEP (1 << 15) | ||
178 | # define MRDCKA0_RESET (1 << 16) | ||
179 | # define MRDCKA1_RESET (1 << 17) | ||
180 | # define MRDCKB0_RESET (1 << 18) | ||
181 | # define MRDCKB1_RESET (1 << 19) | ||
182 | # define MRDCKC0_RESET (1 << 20) | ||
183 | # define MRDCKC1_RESET (1 << 21) | ||
184 | # define MRDCKD0_RESET (1 << 22) | ||
185 | # define MRDCKD1_RESET (1 << 23) | ||
186 | # define DLL_READY_READ (1 << 24) | ||
187 | # define USE_DISPLAY_GAP (1 << 25) | ||
188 | # define USE_DISPLAY_URGENT_NORMAL (1 << 26) | ||
189 | # define MPLL_TURNOFF_D2 (1 << 28) | ||
190 | #define DLL_CNTL 0x64c | ||
191 | # define MRDCKA0_BYPASS (1 << 24) | ||
192 | # define MRDCKA1_BYPASS (1 << 25) | ||
193 | # define MRDCKB0_BYPASS (1 << 26) | ||
194 | # define MRDCKB1_BYPASS (1 << 27) | ||
195 | # define MRDCKC0_BYPASS (1 << 28) | ||
196 | # define MRDCKC1_BYPASS (1 << 29) | ||
197 | # define MRDCKD0_BYPASS (1 << 30) | ||
198 | # define MRDCKD1_BYPASS (1 << 31) | ||
199 | |||
200 | #define MPLL_TIME 0x654 | ||
201 | # define MPLL_LOCK_TIME(x) ((x) << 0) | ||
202 | # define MPLL_LOCK_TIME_MASK (0xffff << 0) | ||
203 | # define MPLL_RESET_TIME(x) ((x) << 16) | ||
204 | # define MPLL_RESET_TIME_MASK (0xffff << 16) | ||
205 | |||
206 | #define CG_CLKPIN_CNTL 0x660 | ||
207 | # define MUX_TCLK_TO_XCLK (1 << 8) | ||
208 | # define XTALIN_DIVIDE (1 << 9) | ||
209 | |||
210 | #define S0_VID_LOWER_SMIO_CNTL 0x678 | ||
211 | #define S1_VID_LOWER_SMIO_CNTL 0x67c | ||
212 | #define S2_VID_LOWER_SMIO_CNTL 0x680 | ||
213 | #define S3_VID_LOWER_SMIO_CNTL 0x684 | ||
214 | |||
215 | #define CG_FTV 0x690 | ||
216 | #define CG_FFCT_0 0x694 | ||
217 | # define UTC_0(x) ((x) << 0) | ||
218 | # define UTC_0_MASK (0x3ff << 0) | ||
219 | # define DTC_0(x) ((x) << 10) | ||
220 | # define DTC_0_MASK (0x3ff << 10) | ||
221 | |||
222 | #define CG_BSP 0x6d0 | ||
223 | # define BSP(x) ((x) << 0) | ||
224 | # define BSP_MASK (0xffff << 0) | ||
225 | # define BSU(x) ((x) << 16) | ||
226 | # define BSU_MASK (0xf << 16) | ||
227 | #define CG_AT 0x6d4 | ||
228 | # define CG_R(x) ((x) << 0) | ||
229 | # define CG_R_MASK (0xffff << 0) | ||
230 | # define CG_L(x) ((x) << 16) | ||
231 | # define CG_L_MASK (0xffff << 16) | ||
232 | #define CG_GIT 0x6d8 | ||
233 | # define CG_GICST(x) ((x) << 0) | ||
234 | # define CG_GICST_MASK (0xffff << 0) | ||
235 | # define CG_GIPOT(x) ((x) << 16) | ||
236 | # define CG_GIPOT_MASK (0xffff << 16) | ||
237 | |||
238 | #define CG_SSP 0x6e8 | ||
239 | # define SST(x) ((x) << 0) | ||
240 | # define SST_MASK (0xffff << 0) | ||
241 | # define SSTU(x) ((x) << 16) | ||
242 | # define SSTU_MASK (0xf << 16) | ||
243 | |||
244 | #define CG_DISPLAY_GAP_CNTL 0x714 | ||
245 | # define DISP1_GAP(x) ((x) << 0) | ||
246 | # define DISP1_GAP_MASK (3 << 0) | ||
247 | # define DISP2_GAP(x) ((x) << 2) | ||
248 | # define DISP2_GAP_MASK (3 << 2) | ||
249 | # define VBI_TIMER_COUNT(x) ((x) << 4) | ||
250 | # define VBI_TIMER_COUNT_MASK (0x3fff << 4) | ||
251 | # define VBI_TIMER_UNIT(x) ((x) << 20) | ||
252 | # define VBI_TIMER_UNIT_MASK (7 << 20) | ||
253 | # define DISP1_GAP_MCHG(x) ((x) << 24) | ||
254 | # define DISP1_GAP_MCHG_MASK (3 << 24) | ||
255 | # define DISP2_GAP_MCHG(x) ((x) << 26) | ||
256 | # define DISP2_GAP_MCHG_MASK (3 << 26) | ||
257 | |||
258 | #define CG_SPLL_SPREAD_SPECTRUM 0x790 | ||
259 | #define SSEN (1 << 0) | ||
260 | #define CLKS(x) ((x) << 4) | ||
261 | #define CLKS_MASK (0xfff << 4) | ||
262 | #define CG_SPLL_SPREAD_SPECTRUM_2 0x794 | ||
263 | #define CLKV(x) ((x) << 0) | ||
264 | #define CLKV_MASK (0x3ffffff << 0) | ||
265 | #define CG_MPLL_SPREAD_SPECTRUM 0x798 | ||
266 | #define CG_UPLL_SPREAD_SPECTRUM 0x79c | ||
267 | # define SSEN_MASK 0x00000001 | ||
268 | |||
269 | #define CG_CGTT_LOCAL_0 0x7d0 | ||
270 | #define CG_CGTT_LOCAL_1 0x7d4 | ||
271 | |||
272 | #define BIOS_SCRATCH_4 0x1734 | ||
273 | |||
274 | #define MC_SEQ_MISC0 0x2a00 | ||
275 | #define MC_SEQ_MISC0_GDDR5_SHIFT 28 | ||
276 | #define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000 | ||
277 | #define MC_SEQ_MISC0_GDDR5_VALUE 5 | ||
278 | |||
279 | #define MC_ARB_SQM_RATIO 0x2770 | ||
280 | #define STATE0(x) ((x) << 0) | ||
281 | #define STATE0_MASK (0xff << 0) | ||
282 | #define STATE1(x) ((x) << 8) | ||
283 | #define STATE1_MASK (0xff << 8) | ||
284 | #define STATE2(x) ((x) << 16) | ||
285 | #define STATE2_MASK (0xff << 16) | ||
286 | #define STATE3(x) ((x) << 24) | ||
287 | #define STATE3_MASK (0xff << 24) | ||
288 | |||
289 | #define MC_ARB_RFSH_RATE 0x27b0 | ||
290 | #define POWERMODE0(x) ((x) << 0) | ||
291 | #define POWERMODE0_MASK (0xff << 0) | ||
292 | #define POWERMODE1(x) ((x) << 8) | ||
293 | #define POWERMODE1_MASK (0xff << 8) | ||
294 | #define POWERMODE2(x) ((x) << 16) | ||
295 | #define POWERMODE2_MASK (0xff << 16) | ||
296 | #define POWERMODE3(x) ((x) << 24) | ||
297 | #define POWERMODE3_MASK (0xff << 24) | ||
298 | |||
299 | #define CGTS_SM_CTRL_REG 0x9150 | ||
300 | |||
65 | /* Registers */ | 301 | /* Registers */ |
66 | #define CB_COLOR0_BASE 0x28040 | 302 | #define CB_COLOR0_BASE 0x28040 |
67 | #define CB_COLOR1_BASE 0x28044 | 303 | #define CB_COLOR1_BASE 0x28044 |
@@ -86,8 +322,8 @@ | |||
86 | #define CONFIG_MEMSIZE 0x5428 | 322 | #define CONFIG_MEMSIZE 0x5428 |
87 | 323 | ||
88 | #define CP_ME_CNTL 0x86D8 | 324 | #define CP_ME_CNTL 0x86D8 |
89 | #define CP_ME_HALT (1<<28) | 325 | #define CP_ME_HALT (1 << 28) |
90 | #define CP_PFP_HALT (1<<26) | 326 | #define CP_PFP_HALT (1 << 26) |
91 | #define CP_ME_RAM_DATA 0xC160 | 327 | #define CP_ME_RAM_DATA 0xC160 |
92 | #define CP_ME_RAM_RADDR 0xC158 | 328 | #define CP_ME_RAM_RADDR 0xC158 |
93 | #define CP_ME_RAM_WADDR 0xC15C | 329 | #define CP_ME_RAM_WADDR 0xC15C |
@@ -157,9 +393,22 @@ | |||
157 | #define GUI_ACTIVE (1<<31) | 393 | #define GUI_ACTIVE (1<<31) |
158 | #define GRBM_STATUS2 0x8014 | 394 | #define GRBM_STATUS2 0x8014 |
159 | 395 | ||
160 | #define CG_CLKPIN_CNTL 0x660 | 396 | #define CG_THERMAL_CTRL 0x72C |
161 | # define MUX_TCLK_TO_XCLK (1 << 8) | 397 | #define DPM_EVENT_SRC(x) ((x) << 0) |
162 | # define XTALIN_DIVIDE (1 << 9) | 398 | #define DPM_EVENT_SRC_MASK (7 << 0) |
399 | #define DIG_THERM_DPM(x) ((x) << 14) | ||
400 | #define DIG_THERM_DPM_MASK 0x003FC000 | ||
401 | #define DIG_THERM_DPM_SHIFT 14 | ||
402 | |||
403 | #define CG_THERMAL_INT 0x734 | ||
404 | #define DIG_THERM_INTH(x) ((x) << 8) | ||
405 | #define DIG_THERM_INTH_MASK 0x0000FF00 | ||
406 | #define DIG_THERM_INTH_SHIFT 8 | ||
407 | #define DIG_THERM_INTL(x) ((x) << 16) | ||
408 | #define DIG_THERM_INTL_MASK 0x00FF0000 | ||
409 | #define DIG_THERM_INTL_SHIFT 16 | ||
410 | #define THERM_INT_MASK_HIGH (1 << 24) | ||
411 | #define THERM_INT_MASK_LOW (1 << 25) | ||
163 | 412 | ||
164 | #define CG_MULT_THERMAL_STATUS 0x740 | 413 | #define CG_MULT_THERMAL_STATUS 0x740 |
165 | #define ASIC_T(x) ((x) << 16) | 414 | #define ASIC_T(x) ((x) << 16) |
@@ -662,7 +911,22 @@ | |||
662 | #define D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x691c | 911 | #define D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x691c |
663 | #define D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x611c | 912 | #define D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x611c |
664 | 913 | ||
665 | /* PCIE link stuff */ | 914 | /* PCIE indirect regs */ |
915 | #define PCIE_P_CNTL 0x40 | ||
916 | # define P_PLL_PWRDN_IN_L1L23 (1 << 3) | ||
917 | # define P_PLL_BUF_PDNB (1 << 4) | ||
918 | # define P_PLL_PDNB (1 << 9) | ||
919 | # define P_ALLOW_PRX_FRONTEND_SHUTOFF (1 << 12) | ||
920 | /* PCIE PORT regs */ | ||
921 | #define PCIE_LC_CNTL 0xa0 | ||
922 | # define LC_L0S_INACTIVITY(x) ((x) << 8) | ||
923 | # define LC_L0S_INACTIVITY_MASK (0xf << 8) | ||
924 | # define LC_L0S_INACTIVITY_SHIFT 8 | ||
925 | # define LC_L1_INACTIVITY(x) ((x) << 12) | ||
926 | # define LC_L1_INACTIVITY_MASK (0xf << 12) | ||
927 | # define LC_L1_INACTIVITY_SHIFT 12 | ||
928 | # define LC_PMI_TO_L1_DIS (1 << 16) | ||
929 | # define LC_ASPM_TO_L1_DIS (1 << 24) | ||
666 | #define PCIE_LC_TRAINING_CNTL 0xa1 /* PCIE_P */ | 930 | #define PCIE_LC_TRAINING_CNTL 0xa1 /* PCIE_P */ |
667 | #define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */ | 931 | #define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */ |
668 | # define LC_LINK_WIDTH_SHIFT 0 | 932 | # define LC_LINK_WIDTH_SHIFT 0 |
@@ -690,6 +954,9 @@ | |||
690 | # define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 8) | 954 | # define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 8) |
691 | # define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 3 | 955 | # define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 3 |
692 | # define LC_CURRENT_DATA_RATE (1 << 11) | 956 | # define LC_CURRENT_DATA_RATE (1 << 11) |
957 | # define LC_HW_VOLTAGE_IF_CONTROL(x) ((x) << 12) | ||
958 | # define LC_HW_VOLTAGE_IF_CONTROL_MASK (3 << 12) | ||
959 | # define LC_HW_VOLTAGE_IF_CONTROL_SHIFT 12 | ||
693 | # define LC_VOLTAGE_TIMER_SEL_MASK (0xf << 14) | 960 | # define LC_VOLTAGE_TIMER_SEL_MASK (0xf << 14) |
694 | # define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 21) | 961 | # define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 21) |
695 | # define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23) | 962 | # define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 23) |