aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-04-23 17:57:27 -0400
committerDave Airlie <airlied@redhat.com>2010-05-18 04:21:12 -0400
commit49e02b7306cb7e01965fe5f41ba0f80085142f6e (patch)
tree6faaa8069fae9b4768d727274df94c2a5298b1b2
parent58e21dff53b9063563e7bb5f5a795ab2d8f61dda (diff)
drm/radeon/kms/pm: add additional asic callbacks
- pm_misc() - handles voltage, pcie lanes, and other non clock related power mode settings. Currently disabled. Needs further debugging - pm_prepare() - disables crtc mem requests right now. All memory clients need to be disabled when changing memory clocks. This function can be expanded to include disabling fb access as well. - pm_finish() - enable active memory clients. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c41
-rw-r--r--drivers/gpu/drm/radeon/evergreen_reg.h1
-rw-r--r--drivers/gpu/drm/radeon/r100.c142
-rw-r--r--drivers/gpu/drm/radeon/r100d.h36
-rw-r--r--drivers/gpu/drm/radeon/r500_reg.h1
-rw-r--r--drivers/gpu/drm/radeon/r600.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon.h3
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c42
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h11
-rw-r--r--drivers/gpu/drm/radeon/rs600.c123
-rw-r--r--drivers/gpu/drm/radeon/rs600d.h32
-rw-r--r--drivers/gpu/drm/radeon/rv770.c4
12 files changed, 441 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 0137a4cd90f5..8d86d0568d97 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -39,6 +39,47 @@
39static void evergreen_gpu_init(struct radeon_device *rdev); 39static void evergreen_gpu_init(struct radeon_device *rdev);
40void evergreen_fini(struct radeon_device *rdev); 40void evergreen_fini(struct radeon_device *rdev);
41 41
42void evergreen_pm_misc(struct radeon_device *rdev)
43{
44
45}
46
47void evergreen_pm_prepare(struct radeon_device *rdev)
48{
49 struct drm_device *ddev = rdev->ddev;
50 struct drm_crtc *crtc;
51 struct radeon_crtc *radeon_crtc;
52 u32 tmp;
53
54 /* disable any active CRTCs */
55 list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
56 radeon_crtc = to_radeon_crtc(crtc);
57 if (radeon_crtc->enabled) {
58 tmp = RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset);
59 tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
60 WREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
61 }
62 }
63}
64
65void evergreen_pm_finish(struct radeon_device *rdev)
66{
67 struct drm_device *ddev = rdev->ddev;
68 struct drm_crtc *crtc;
69 struct radeon_crtc *radeon_crtc;
70 u32 tmp;
71
72 /* enable any active CRTCs */
73 list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
74 radeon_crtc = to_radeon_crtc(crtc);
75 if (radeon_crtc->enabled) {
76 tmp = RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset);
77 tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
78 WREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
79 }
80 }
81}
82
42bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) 83bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
43{ 84{
44 bool connected = false; 85 bool connected = false;
diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h
index 9dba6d97d9b7..93aab2ebd9d0 100644
--- a/drivers/gpu/drm/radeon/evergreen_reg.h
+++ b/drivers/gpu/drm/radeon/evergreen_reg.h
@@ -166,6 +166,7 @@
166/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */ 166/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */
167#define EVERGREEN_CRTC_CONTROL 0x6e70 167#define EVERGREEN_CRTC_CONTROL 0x6e70
168# define EVERGREEN_CRTC_MASTER_EN (1 << 0) 168# define EVERGREEN_CRTC_MASTER_EN (1 << 0)
169# define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24)
169#define EVERGREEN_CRTC_STATUS 0x6e8c 170#define EVERGREEN_CRTC_STATUS 0x6e8c
170#define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 171#define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4
171 172
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 6443d9ea6c11..2106ac66eb32 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -37,6 +37,7 @@
37#include "rs100d.h" 37#include "rs100d.h"
38#include "rv200d.h" 38#include "rv200d.h"
39#include "rv250d.h" 39#include "rv250d.h"
40#include "atom.h"
40 41
41#include <linux/firmware.h> 42#include <linux/firmware.h>
42#include <linux/platform_device.h> 43#include <linux/platform_device.h>
@@ -200,6 +201,147 @@ void r100_set_power_state(struct radeon_device *rdev)
200 DRM_INFO("GUI not idle!!!\n"); 201 DRM_INFO("GUI not idle!!!\n");
201} 202}
202 203
204void r100_pm_misc(struct radeon_device *rdev)
205{
206#if 0
207 int requested_index = rdev->pm.requested_power_state_index;
208 struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
209 struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
210 u32 tmp, sclk_cntl, sclk_cntl2, sclk_more_cntl;
211
212 if ((voltage->type == VOLTAGE_GPIO) && (voltage->gpio.valid)) {
213 if (ps->misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
214 tmp = RREG32(voltage->gpio.reg);
215 if (voltage->active_high)
216 tmp |= voltage->gpio.mask;
217 else
218 tmp &= ~(voltage->gpio.mask);
219 WREG32(voltage->gpio.reg, tmp);
220 if (voltage->delay)
221 udelay(voltage->delay);
222 } else {
223 tmp = RREG32(voltage->gpio.reg);
224 if (voltage->active_high)
225 tmp &= ~voltage->gpio.mask;
226 else
227 tmp |= voltage->gpio.mask;
228 WREG32(voltage->gpio.reg, tmp);
229 if (voltage->delay)
230 udelay(voltage->delay);
231 }
232 }
233
234 sclk_cntl = RREG32_PLL(SCLK_CNTL);
235 sclk_cntl2 = RREG32_PLL(SCLK_CNTL2);
236 sclk_cntl2 &= ~REDUCED_SPEED_SCLK_SEL(3);
237 sclk_more_cntl = RREG32_PLL(SCLK_MORE_CNTL);
238 sclk_more_cntl &= ~VOLTAGE_DELAY_SEL(3);
239 if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) {
240 sclk_more_cntl |= REDUCED_SPEED_SCLK_EN;
241 if (ps->misc & ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE)
242 sclk_cntl2 |= REDUCED_SPEED_SCLK_MODE;
243 else
244 sclk_cntl2 &= ~REDUCED_SPEED_SCLK_MODE;
245 if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2)
246 sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(0);
247 else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4)
248 sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(2);
249 } else
250 sclk_more_cntl &= ~REDUCED_SPEED_SCLK_EN;
251
252 if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) {
253 sclk_more_cntl |= IO_CG_VOLTAGE_DROP;
254 if (voltage->delay) {
255 sclk_more_cntl |= VOLTAGE_DROP_SYNC;
256 switch (voltage->delay) {
257 case 33:
258 sclk_more_cntl |= VOLTAGE_DELAY_SEL(0);
259 break;
260 case 66:
261 sclk_more_cntl |= VOLTAGE_DELAY_SEL(1);
262 break;
263 case 99:
264 sclk_more_cntl |= VOLTAGE_DELAY_SEL(2);
265 break;
266 case 132:
267 sclk_more_cntl |= VOLTAGE_DELAY_SEL(3);
268 break;
269 }
270 } else
271 sclk_more_cntl &= ~VOLTAGE_DROP_SYNC;
272 } else
273 sclk_more_cntl &= ~IO_CG_VOLTAGE_DROP;
274
275 if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN)
276 sclk_cntl &= ~FORCE_HDP;
277 else
278 sclk_cntl |= FORCE_HDP;
279
280 WREG32_PLL(SCLK_CNTL, sclk_cntl);
281 WREG32_PLL(SCLK_CNTL2, sclk_cntl2);
282 WREG32_PLL(SCLK_MORE_CNTL, sclk_more_cntl);
283
284 /* set pcie lanes */
285 if ((rdev->flags & RADEON_IS_PCIE) &&
286 !(rdev->flags & RADEON_IS_IGP) &&
287 rdev->asic->set_pcie_lanes &&
288 (ps->pcie_lanes !=
289 rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) {
290 radeon_set_pcie_lanes(rdev,
291 ps->pcie_lanes);
292 DRM_INFO("Setting: p: %d\n", ps->pcie_lanes);
293 }
294#endif
295}
296
297void r100_pm_prepare(struct radeon_device *rdev)
298{
299 struct drm_device *ddev = rdev->ddev;
300 struct drm_crtc *crtc;
301 struct radeon_crtc *radeon_crtc;
302 u32 tmp;
303
304 /* disable any active CRTCs */
305 list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
306 radeon_crtc = to_radeon_crtc(crtc);
307 if (radeon_crtc->enabled) {
308 if (radeon_crtc->crtc_id) {
309 tmp = RREG32(RADEON_CRTC2_GEN_CNTL);
310 tmp |= RADEON_CRTC2_DISP_REQ_EN_B;
311 WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
312 } else {
313 tmp = RREG32(RADEON_CRTC_GEN_CNTL);
314 tmp |= RADEON_CRTC_DISP_REQ_EN_B;
315 WREG32(RADEON_CRTC_GEN_CNTL, tmp);
316 }
317 }
318 }
319}
320
321void r100_pm_finish(struct radeon_device *rdev)
322{
323 struct drm_device *ddev = rdev->ddev;
324 struct drm_crtc *crtc;
325 struct radeon_crtc *radeon_crtc;
326 u32 tmp;
327
328 /* enable any active CRTCs */
329 list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
330 radeon_crtc = to_radeon_crtc(crtc);
331 if (radeon_crtc->enabled) {
332 if (radeon_crtc->crtc_id) {
333 tmp = RREG32(RADEON_CRTC2_GEN_CNTL);
334 tmp &= ~RADEON_CRTC2_DISP_REQ_EN_B;
335 WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
336 } else {
337 tmp = RREG32(RADEON_CRTC_GEN_CNTL);
338 tmp &= ~RADEON_CRTC_DISP_REQ_EN_B;
339 WREG32(RADEON_CRTC_GEN_CNTL, tmp);
340 }
341 }
342 }
343}
344
203bool r100_gui_idle(struct radeon_device *rdev) 345bool r100_gui_idle(struct radeon_device *rdev)
204{ 346{
205 if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) 347 if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)
diff --git a/drivers/gpu/drm/radeon/r100d.h b/drivers/gpu/drm/radeon/r100d.h
index de8abd104ab7..d016b16fa116 100644
--- a/drivers/gpu/drm/radeon/r100d.h
+++ b/drivers/gpu/drm/radeon/r100d.h
@@ -838,5 +838,41 @@
838#define G_00000D_FORCE_RB(x) (((x) >> 28) & 0x1) 838#define G_00000D_FORCE_RB(x) (((x) >> 28) & 0x1)
839#define C_00000D_FORCE_RB 0xEFFFFFFF 839#define C_00000D_FORCE_RB 0xEFFFFFFF
840 840
841/* PLL regs */
842#define SCLK_CNTL 0xd
843#define FORCE_HDP (1 << 17)
844#define CLK_PWRMGT_CNTL 0x14
845#define GLOBAL_PMAN_EN (1 << 10)
846#define DISP_PM (1 << 20)
847#define PLL_PWRMGT_CNTL 0x15
848#define MPLL_TURNOFF (1 << 0)
849#define SPLL_TURNOFF (1 << 1)
850#define PPLL_TURNOFF (1 << 2)
851#define P2PLL_TURNOFF (1 << 3)
852#define TVPLL_TURNOFF (1 << 4)
853#define MOBILE_SU (1 << 16)
854#define SU_SCLK_USE_BCLK (1 << 17)
855#define SCLK_CNTL2 0x1e
856#define REDUCED_SPEED_SCLK_MODE (1 << 16)
857#define REDUCED_SPEED_SCLK_SEL(x) ((x) << 17)
858#define MCLK_MISC 0x1f
859#define EN_MCLK_TRISTATE_IN_SUSPEND (1 << 18)
860#define SCLK_MORE_CNTL 0x35
861#define REDUCED_SPEED_SCLK_EN (1 << 16)
862#define IO_CG_VOLTAGE_DROP (1 << 17)
863#define VOLTAGE_DELAY_SEL(x) ((x) << 20)
864#define VOLTAGE_DROP_SYNC (1 << 19)
865
866/* mmreg */
867#define DISP_PWR_MAN 0xd08
868#define DISP_D3_GRPH_RST (1 << 18)
869#define DISP_D3_SUBPIC_RST (1 << 19)
870#define DISP_D3_OV0_RST (1 << 20)
871#define DISP_D1D2_GRPH_RST (1 << 21)
872#define DISP_D1D2_SUBPIC_RST (1 << 22)
873#define DISP_D1D2_OV0_RST (1 << 23)
874#define DISP_DVO_ENABLE_RST (1 << 24)
875#define TV_ENABLE_RST (1 << 25)
876#define AUTO_PWRUP_EN (1 << 26)
841 877
842#endif 878#endif
diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h
index 0cf2ad2a5585..f5adf42a9d15 100644
--- a/drivers/gpu/drm/radeon/r500_reg.h
+++ b/drivers/gpu/drm/radeon/r500_reg.h
@@ -347,6 +347,7 @@
347 347
348#define AVIVO_D1CRTC_CONTROL 0x6080 348#define AVIVO_D1CRTC_CONTROL 0x6080
349# define AVIVO_CRTC_EN (1 << 0) 349# define AVIVO_CRTC_EN (1 << 0)
350# define AVIVO_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24)
350#define AVIVO_D1CRTC_BLANK_CONTROL 0x6084 351#define AVIVO_D1CRTC_BLANK_CONTROL 0x6084
351#define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088 352#define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088
352#define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c 353#define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 4f7f318b5437..38f75f54019b 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -304,6 +304,11 @@ void r600_set_power_state(struct radeon_device *rdev)
304 DRM_INFO("GUI not idle!!!\n"); 304 DRM_INFO("GUI not idle!!!\n");
305} 305}
306 306
307void r600_pm_misc(struct radeon_device *rdev)
308{
309
310}
311
307bool r600_gui_idle(struct radeon_device *rdev) 312bool r600_gui_idle(struct radeon_device *rdev)
308{ 313{
309 if (RREG32(GRBM_STATUS) & GUI_ACTIVE) 314 if (RREG32(GRBM_STATUS) & GUI_ACTIVE)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 5ffb29597af7..16f0ea78ea9d 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -815,6 +815,9 @@ struct radeon_asic {
815 bool (*gui_idle)(struct radeon_device *rdev); 815 bool (*gui_idle)(struct radeon_device *rdev);
816 void (*get_power_state)(struct radeon_device *rdev, enum radeon_pm_action action); 816 void (*get_power_state)(struct radeon_device *rdev, enum radeon_pm_action action);
817 void (*set_power_state)(struct radeon_device *rdev); 817 void (*set_power_state)(struct radeon_device *rdev);
818 void (*pm_misc)(struct radeon_device *rdev);
819 void (*pm_prepare)(struct radeon_device *rdev);
820 void (*pm_finish)(struct radeon_device *rdev);
818}; 821};
819 822
820/* 823/*
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 1053115ba652..1e6f17bf54fd 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -168,6 +168,9 @@ static struct radeon_asic r100_asic = {
168 .gui_idle = &r100_gui_idle, 168 .gui_idle = &r100_gui_idle,
169 .get_power_state = &r100_get_power_state, 169 .get_power_state = &r100_get_power_state,
170 .set_power_state = &r100_set_power_state, 170 .set_power_state = &r100_set_power_state,
171 .pm_misc = &r100_pm_misc,
172 .pm_prepare = &r100_pm_prepare,
173 .pm_finish = &r100_pm_finish,
171}; 174};
172 175
173static struct radeon_asic r200_asic = { 176static struct radeon_asic r200_asic = {
@@ -209,6 +212,9 @@ static struct radeon_asic r200_asic = {
209 .gui_idle = &r100_gui_idle, 212 .gui_idle = &r100_gui_idle,
210 .get_power_state = &r100_get_power_state, 213 .get_power_state = &r100_get_power_state,
211 .set_power_state = &r100_set_power_state, 214 .set_power_state = &r100_set_power_state,
215 .pm_misc = &r100_pm_misc,
216 .pm_prepare = &r100_pm_prepare,
217 .pm_finish = &r100_pm_finish,
212}; 218};
213 219
214static struct radeon_asic r300_asic = { 220static struct radeon_asic r300_asic = {
@@ -251,6 +257,9 @@ static struct radeon_asic r300_asic = {
251 .gui_idle = &r100_gui_idle, 257 .gui_idle = &r100_gui_idle,
252 .get_power_state = &r100_get_power_state, 258 .get_power_state = &r100_get_power_state,
253 .set_power_state = &r100_set_power_state, 259 .set_power_state = &r100_set_power_state,
260 .pm_misc = &r100_pm_misc,
261 .pm_prepare = &r100_pm_prepare,
262 .pm_finish = &r100_pm_finish,
254}; 263};
255 264
256static struct radeon_asic r300_asic_pcie = { 265static struct radeon_asic r300_asic_pcie = {
@@ -292,6 +301,9 @@ static struct radeon_asic r300_asic_pcie = {
292 .gui_idle = &r100_gui_idle, 301 .gui_idle = &r100_gui_idle,
293 .get_power_state = &r100_get_power_state, 302 .get_power_state = &r100_get_power_state,
294 .set_power_state = &r100_set_power_state, 303 .set_power_state = &r100_set_power_state,
304 .pm_misc = &r100_pm_misc,
305 .pm_prepare = &r100_pm_prepare,
306 .pm_finish = &r100_pm_finish,
295}; 307};
296 308
297static struct radeon_asic r420_asic = { 309static struct radeon_asic r420_asic = {
@@ -334,6 +346,9 @@ static struct radeon_asic r420_asic = {
334 .gui_idle = &r100_gui_idle, 346 .gui_idle = &r100_gui_idle,
335 .get_power_state = &r100_get_power_state, 347 .get_power_state = &r100_get_power_state,
336 .set_power_state = &r100_set_power_state, 348 .set_power_state = &r100_set_power_state,
349 .pm_misc = &r100_pm_misc,
350 .pm_prepare = &r100_pm_prepare,
351 .pm_finish = &r100_pm_finish,
337}; 352};
338 353
339static struct radeon_asic rs400_asic = { 354static struct radeon_asic rs400_asic = {
@@ -376,6 +391,9 @@ static struct radeon_asic rs400_asic = {
376 .gui_idle = &r100_gui_idle, 391 .gui_idle = &r100_gui_idle,
377 .get_power_state = &r100_get_power_state, 392 .get_power_state = &r100_get_power_state,
378 .set_power_state = &r100_set_power_state, 393 .set_power_state = &r100_set_power_state,
394 .pm_misc = &r100_pm_misc,
395 .pm_prepare = &r100_pm_prepare,
396 .pm_finish = &r100_pm_finish,
379}; 397};
380 398
381static struct radeon_asic rs600_asic = { 399static struct radeon_asic rs600_asic = {
@@ -418,6 +436,9 @@ static struct radeon_asic rs600_asic = {
418 .gui_idle = &r100_gui_idle, 436 .gui_idle = &r100_gui_idle,
419 .get_power_state = &r100_get_power_state, 437 .get_power_state = &r100_get_power_state,
420 .set_power_state = &r100_set_power_state, 438 .set_power_state = &r100_set_power_state,
439 .pm_misc = &rs600_pm_misc,
440 .pm_prepare = &rs600_pm_prepare,
441 .pm_finish = &rs600_pm_finish,
421}; 442};
422 443
423static struct radeon_asic rs690_asic = { 444static struct radeon_asic rs690_asic = {
@@ -460,6 +481,9 @@ static struct radeon_asic rs690_asic = {
460 .gui_idle = &r100_gui_idle, 481 .gui_idle = &r100_gui_idle,
461 .get_power_state = &r100_get_power_state, 482 .get_power_state = &r100_get_power_state,
462 .set_power_state = &r100_set_power_state, 483 .set_power_state = &r100_set_power_state,
484 .pm_misc = &rs600_pm_misc,
485 .pm_prepare = &rs600_pm_prepare,
486 .pm_finish = &rs600_pm_finish,
463}; 487};
464 488
465static struct radeon_asic rv515_asic = { 489static struct radeon_asic rv515_asic = {
@@ -502,6 +526,9 @@ static struct radeon_asic rv515_asic = {
502 .gui_idle = &r100_gui_idle, 526 .gui_idle = &r100_gui_idle,
503 .get_power_state = &r100_get_power_state, 527 .get_power_state = &r100_get_power_state,
504 .set_power_state = &r100_set_power_state, 528 .set_power_state = &r100_set_power_state,
529 .pm_misc = &rs600_pm_misc,
530 .pm_prepare = &rs600_pm_prepare,
531 .pm_finish = &rs600_pm_finish,
505}; 532};
506 533
507static struct radeon_asic r520_asic = { 534static struct radeon_asic r520_asic = {
@@ -544,6 +571,9 @@ static struct radeon_asic r520_asic = {
544 .gui_idle = &r100_gui_idle, 571 .gui_idle = &r100_gui_idle,
545 .get_power_state = &r100_get_power_state, 572 .get_power_state = &r100_get_power_state,
546 .set_power_state = &r100_set_power_state, 573 .set_power_state = &r100_set_power_state,
574 .pm_misc = &rs600_pm_misc,
575 .pm_prepare = &rs600_pm_prepare,
576 .pm_finish = &rs600_pm_finish,
547}; 577};
548 578
549static struct radeon_asic r600_asic = { 579static struct radeon_asic r600_asic = {
@@ -585,6 +615,9 @@ static struct radeon_asic r600_asic = {
585 .gui_idle = &r600_gui_idle, 615 .gui_idle = &r600_gui_idle,
586 .get_power_state = &r600_get_power_state, 616 .get_power_state = &r600_get_power_state,
587 .set_power_state = &r600_set_power_state, 617 .set_power_state = &r600_set_power_state,
618 .pm_misc = &r600_pm_misc,
619 .pm_prepare = &rs600_pm_prepare,
620 .pm_finish = &rs600_pm_finish,
588}; 621};
589 622
590static struct radeon_asic rs780_asic = { 623static struct radeon_asic rs780_asic = {
@@ -626,6 +659,9 @@ static struct radeon_asic rs780_asic = {
626 .gui_idle = &r600_gui_idle, 659 .gui_idle = &r600_gui_idle,
627 .get_power_state = &r600_get_power_state, 660 .get_power_state = &r600_get_power_state,
628 .set_power_state = &r600_set_power_state, 661 .set_power_state = &r600_set_power_state,
662 .pm_misc = &r600_pm_misc,
663 .pm_prepare = &rs600_pm_prepare,
664 .pm_finish = &rs600_pm_finish,
629}; 665};
630 666
631static struct radeon_asic rv770_asic = { 667static struct radeon_asic rv770_asic = {
@@ -667,6 +703,9 @@ static struct radeon_asic rv770_asic = {
667 .gui_idle = &r600_gui_idle, 703 .gui_idle = &r600_gui_idle,
668 .get_power_state = &r600_get_power_state, 704 .get_power_state = &r600_get_power_state,
669 .set_power_state = &r600_set_power_state, 705 .set_power_state = &r600_set_power_state,
706 .pm_misc = &rv770_pm_misc,
707 .pm_prepare = &rs600_pm_prepare,
708 .pm_finish = &rs600_pm_finish,
670}; 709};
671 710
672static struct radeon_asic evergreen_asic = { 711static struct radeon_asic evergreen_asic = {
@@ -706,6 +745,9 @@ static struct radeon_asic evergreen_asic = {
706 .gui_idle = &r600_gui_idle, 745 .gui_idle = &r600_gui_idle,
707 .get_power_state = &r600_get_power_state, 746 .get_power_state = &r600_get_power_state,
708 .set_power_state = &r600_set_power_state, 747 .set_power_state = &r600_set_power_state,
748 .pm_misc = &evergreen_pm_misc,
749 .pm_prepare = &evergreen_pm_prepare,
750 .pm_finish = &evergreen_pm_finish,
709}; 751};
710 752
711int radeon_asic_init(struct radeon_device *rdev) 753int radeon_asic_init(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 71b21bb4e5f3..378db67ba2d8 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -130,6 +130,9 @@ extern bool r100_gui_idle(struct radeon_device *rdev);
130extern void r100_set_power_state(struct radeon_device *rdev); 130extern void r100_set_power_state(struct radeon_device *rdev);
131extern void r100_get_power_state(struct radeon_device *rdev, 131extern void r100_get_power_state(struct radeon_device *rdev,
132 enum radeon_pm_action action); 132 enum radeon_pm_action action);
133extern void r100_pm_misc(struct radeon_device *rdev);
134extern void r100_pm_prepare(struct radeon_device *rdev);
135extern void r100_pm_finish(struct radeon_device *rdev);
133 136
134/* 137/*
135 * r200,rv250,rs300,rv280 138 * r200,rv250,rs300,rv280
@@ -201,6 +204,9 @@ void rs600_hpd_fini(struct radeon_device *rdev);
201bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); 204bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
202void rs600_hpd_set_polarity(struct radeon_device *rdev, 205void rs600_hpd_set_polarity(struct radeon_device *rdev,
203 enum radeon_hpd_id hpd); 206 enum radeon_hpd_id hpd);
207extern void rs600_pm_misc(struct radeon_device *rdev);
208extern void rs600_pm_prepare(struct radeon_device *rdev);
209extern void rs600_pm_finish(struct radeon_device *rdev);
204 210
205/* 211/*
206 * rs690,rs740 212 * rs690,rs740
@@ -278,6 +284,7 @@ extern bool r600_gui_idle(struct radeon_device *rdev);
278extern void r600_set_power_state(struct radeon_device *rdev); 284extern void r600_set_power_state(struct radeon_device *rdev);
279extern void r600_get_power_state(struct radeon_device *rdev, 285extern void r600_get_power_state(struct radeon_device *rdev,
280 enum radeon_pm_action action); 286 enum radeon_pm_action action);
287extern void r600_pm_misc(struct radeon_device *rdev);
281 288
282/* 289/*
283 * rv770,rv730,rv710,rv740 290 * rv770,rv730,rv710,rv740
@@ -286,6 +293,7 @@ int rv770_init(struct radeon_device *rdev);
286void rv770_fini(struct radeon_device *rdev); 293void rv770_fini(struct radeon_device *rdev);
287int rv770_suspend(struct radeon_device *rdev); 294int rv770_suspend(struct radeon_device *rdev);
288int rv770_resume(struct radeon_device *rdev); 295int rv770_resume(struct radeon_device *rdev);
296extern void rv770_pm_misc(struct radeon_device *rdev);
289 297
290/* 298/*
291 * evergreen 299 * evergreen
@@ -306,5 +314,8 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev,
306u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc); 314u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc);
307int evergreen_irq_set(struct radeon_device *rdev); 315int evergreen_irq_set(struct radeon_device *rdev);
308int evergreen_irq_process(struct radeon_device *rdev); 316int evergreen_irq_process(struct radeon_device *rdev);
317extern void evergreen_pm_misc(struct radeon_device *rdev);
318extern void evergreen_pm_prepare(struct radeon_device *rdev);
319extern void evergreen_pm_finish(struct radeon_device *rdev);
309 320
310#endif 321#endif
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index b312b72d76ce..c3890b76a1c0 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -46,6 +46,129 @@
46void rs600_gpu_init(struct radeon_device *rdev); 46void rs600_gpu_init(struct radeon_device *rdev);
47int rs600_mc_wait_for_idle(struct radeon_device *rdev); 47int rs600_mc_wait_for_idle(struct radeon_device *rdev);
48 48
49void rs600_pm_misc(struct radeon_device *rdev)
50{
51#if 0
52 int requested_index = rdev->pm.requested_power_state_index;
53 struct radeon_power_state *ps = &rdev->pm.power_state[requested_index];
54 struct radeon_voltage *voltage = &ps->clock_info[0].voltage;
55 u32 tmp, dyn_pwrmgt_sclk_length, dyn_sclk_vol_cntl;
56 u32 hdp_dyn_cntl, mc_host_dyn_cntl;
57
58 if ((voltage->type == VOLTAGE_GPIO) && (voltage->gpio.valid)) {
59 if (ps->misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
60 tmp = RREG32(voltage->gpio.reg);
61 if (voltage->active_high)
62 tmp |= voltage->gpio.mask;
63 else
64 tmp &= ~(voltage->gpio.mask);
65 WREG32(voltage->gpio.reg, tmp);
66 if (voltage->delay)
67 udelay(voltage->delay);
68 } else {
69 tmp = RREG32(voltage->gpio.reg);
70 if (voltage->active_high)
71 tmp &= ~voltage->gpio.mask;
72 else
73 tmp |= voltage->gpio.mask;
74 WREG32(voltage->gpio.reg, tmp);
75 if (voltage->delay)
76 udelay(voltage->delay);
77 }
78 }
79
80 dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH);
81 dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf);
82 dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_LOLEN(0xf);
83 if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) {
84 if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2) {
85 dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(2);
86 dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(2);
87 } else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4) {
88 dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(4);
89 dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(4);
90 }
91 } else {
92 dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_HILEN(1);
93 dyn_pwrmgt_sclk_length |= REDUCED_POWER_SCLK_LOLEN(1);
94 }
95 WREG32_PLL(DYN_PWRMGT_SCLK_LENGTH, dyn_pwrmgt_sclk_length);
96
97 dyn_sclk_vol_cntl = RREG32_PLL(DYN_SCLK_VOL_CNTL);
98 if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) {
99 dyn_sclk_vol_cntl |= IO_CG_VOLTAGE_DROP;
100 if (voltage->delay) {
101 dyn_sclk_vol_cntl |= VOLTAGE_DROP_SYNC;
102 dyn_sclk_vol_cntl |= VOLTAGE_DELAY_SEL(voltage->delay);
103 } else
104 dyn_sclk_vol_cntl &= ~VOLTAGE_DROP_SYNC;
105 } else
106 dyn_sclk_vol_cntl &= ~IO_CG_VOLTAGE_DROP;
107 WREG32_PLL(DYN_SCLK_VOL_CNTL, dyn_sclk_vol_cntl);
108
109 hdp_dyn_cntl = RREG32_PLL(HDP_DYN_CNTL);
110 if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN)
111 hdp_dyn_cntl &= ~HDP_FORCEON;
112 else
113 hdp_dyn_cntl |= HDP_FORCEON;
114 WREG32_PLL(HDP_DYN_CNTL, hdp_dyn_cntl);
115
116 mc_host_dyn_cntl = RREG32_PLL(MC_HOST_DYN_CNTL);
117 if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN)
118 mc_host_dyn_cntl &= ~MC_HOST_FORCEON;
119 else
120 mc_host_dyn_cntl |= MC_HOST_FORCEON;
121 WREG32_PLL(MC_HOST_DYN_CNTL, mc_host_dyn_cntl);
122
123 /* set pcie lanes */
124 if ((rdev->flags & RADEON_IS_PCIE) &&
125 !(rdev->flags & RADEON_IS_IGP) &&
126 rdev->asic->set_pcie_lanes &&
127 (ps->pcie_lanes !=
128 rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) {
129 radeon_set_pcie_lanes(rdev,
130 ps->pcie_lanes);
131 DRM_INFO("Setting: p: %d\n", ps->pcie_lanes);
132 }
133#endif
134}
135
136void rs600_pm_prepare(struct radeon_device *rdev)
137{
138 struct drm_device *ddev = rdev->ddev;
139 struct drm_crtc *crtc;
140 struct radeon_crtc *radeon_crtc;
141 u32 tmp;
142
143 /* disable any active CRTCs */
144 list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
145 radeon_crtc = to_radeon_crtc(crtc);
146 if (radeon_crtc->enabled) {
147 tmp = RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset);
148 tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
149 WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
150 }
151 }
152}
153
154void rs600_pm_finish(struct radeon_device *rdev)
155{
156 struct drm_device *ddev = rdev->ddev;
157 struct drm_crtc *crtc;
158 struct radeon_crtc *radeon_crtc;
159 u32 tmp;
160
161 /* enable any active CRTCs */
162 list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
163 radeon_crtc = to_radeon_crtc(crtc);
164 if (radeon_crtc->enabled) {
165 tmp = RREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset);
166 tmp &= ~AVIVO_CRTC_DISP_READ_REQUEST_DISABLE;
167 WREG32(AVIVO_D1CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
168 }
169 }
170}
171
49/* hpd for digital panel detect/disconnect */ 172/* hpd for digital panel detect/disconnect */
50bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) 173bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
51{ 174{
diff --git a/drivers/gpu/drm/radeon/rs600d.h b/drivers/gpu/drm/radeon/rs600d.h
index 08c4bebd3011..8f624342927a 100644
--- a/drivers/gpu/drm/radeon/rs600d.h
+++ b/drivers/gpu/drm/radeon/rs600d.h
@@ -634,4 +634,36 @@
634#define G_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x) (((x) >> 24) & 0x1) 634#define G_006D4C_D2MODE_PRIORITY_B_FORCE_MASK(x) (((x) >> 24) & 0x1)
635#define C_006D4C_D2MODE_PRIORITY_B_FORCE_MASK 0xFEFFFFFF 635#define C_006D4C_D2MODE_PRIORITY_B_FORCE_MASK 0xFEFFFFFF
636 636
637/* PLL regs */
638#define GENERAL_PWRMGT 0x8
639#define GLOBAL_PWRMGT_EN (1 << 0)
640#define MOBILE_SU (1 << 2)
641#define DYN_PWRMGT_SCLK_LENGTH 0xc
642#define NORMAL_POWER_SCLK_HILEN(x) ((x) << 0)
643#define NORMAL_POWER_SCLK_LOLEN(x) ((x) << 4)
644#define REDUCED_POWER_SCLK_HILEN(x) ((x) << 8)
645#define REDUCED_POWER_SCLK_LOLEN(x) ((x) << 12)
646#define POWER_D1_SCLK_HILEN(x) ((x) << 16)
647#define POWER_D1_SCLK_LOLEN(x) ((x) << 20)
648#define STATIC_SCREEN_HILEN(x) ((x) << 24)
649#define STATIC_SCREEN_LOLEN(x) ((x) << 28)
650#define DYN_SCLK_VOL_CNTL 0xe
651#define IO_CG_VOLTAGE_DROP (1 << 0)
652#define VOLTAGE_DROP_SYNC (1 << 2)
653#define VOLTAGE_DELAY_SEL(x) ((x) << 3)
654#define HDP_DYN_CNTL 0x10
655#define HDP_FORCEON (1 << 0)
656#define MC_HOST_DYN_CNTL 0x1e
657#define MC_HOST_FORCEON (1 << 0)
658
659/* mmreg */
660#define DOUT_POWER_MANAGEMENT_CNTL 0x7ee0
661#define PWRDN_WAIT_BUSY_OFF (1 << 0)
662#define PWRDN_WAIT_PWRSEQ_OFF (1 << 4)
663#define PWRDN_WAIT_PPLL_OFF (1 << 8)
664#define PWRUP_WAIT_PPLL_ON (1 << 12)
665#define PWRUP_WAIT_MEM_INIT_DONE (1 << 16)
666#define PM_ASSERT_RESET (1 << 20)
667#define PM_PWRDN_PPLL (1 << 24)
668
637#endif 669#endif
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index a74683e18612..7c55182a9dd7 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -42,6 +42,10 @@
42static void rv770_gpu_init(struct radeon_device *rdev); 42static void rv770_gpu_init(struct radeon_device *rdev);
43void rv770_fini(struct radeon_device *rdev); 43void rv770_fini(struct radeon_device *rdev);
44 44
45void rv770_pm_misc(struct radeon_device *rdev)
46{
47
48}
45 49
46/* 50/*
47 * GART 51 * GART