diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-04-24 14:50:23 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-05-18 04:21:14 -0400 |
commit | a424816fb37f894a37585cf86dfdd6b8b1dc681f (patch) | |
tree | 7129cac19de9c9f5e008669f832ad2e09a3932d1 | |
parent | 49e02b7306cb7e01965fe5f41ba0f80085142f6e (diff) |
drm/radeon/kms/pm: rework power management
Add two new sysfs attributes:
- dynpm
- power_state
Echoing 0/1 to dynpm disables/enables dynamic power management.
The driver scales the sclk dynamically based on the number of
queued fences. dynpm only scales sclk dynamically in single head
mode.
Echoing x.y to power_state selects a static power state (x) and clock
mode (y). This allows you to statically select a power state and clock
mode. Selecting a static clock mode will disable dynpm.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 66 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 69 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 139 |
5 files changed, 229 insertions, 56 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 2106ac66eb32..7675827c3a8d 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -145,7 +145,7 @@ void r100_get_power_state(struct radeon_device *rdev, | |||
145 | pcie_lanes); | 145 | pcie_lanes); |
146 | } | 146 | } |
147 | 147 | ||
148 | void r100_set_power_state(struct radeon_device *rdev) | 148 | void r100_set_power_state(struct radeon_device *rdev, bool static_switch) |
149 | { | 149 | { |
150 | u32 sclk, mclk; | 150 | u32 sclk, mclk; |
151 | 151 | ||
@@ -167,33 +167,51 @@ void r100_set_power_state(struct radeon_device *rdev) | |||
167 | if (rdev->pm.active_crtc_count > 1) | 167 | if (rdev->pm.active_crtc_count > 1) |
168 | mclk = rdev->clock.default_mclk; | 168 | mclk = rdev->clock.default_mclk; |
169 | 169 | ||
170 | /* set pcie lanes */ | 170 | /* voltage, pcie lanes, etc.*/ |
171 | /* TODO */ | 171 | radeon_pm_misc(rdev); |
172 | 172 | ||
173 | /* set voltage */ | 173 | if (static_switch) { |
174 | /* TODO */ | 174 | radeon_pm_prepare(rdev); |
175 | 175 | /* set engine clock */ | |
176 | /* set engine clock */ | 176 | if (sclk != rdev->pm.current_sclk) { |
177 | if (sclk != rdev->pm.current_sclk) { | 177 | radeon_set_engine_clock(rdev, sclk); |
178 | radeon_sync_with_vblank(rdev); | 178 | rdev->pm.current_sclk = sclk; |
179 | radeon_pm_debug_check_in_vbl(rdev, false); | 179 | DRM_INFO("Setting: e: %d\n", sclk); |
180 | radeon_set_engine_clock(rdev, sclk); | 180 | } |
181 | radeon_pm_debug_check_in_vbl(rdev, true); | 181 | #if 0 |
182 | rdev->pm.current_sclk = sclk; | 182 | /* set memory clock */ |
183 | DRM_INFO("Setting: e: %d\n", sclk); | 183 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { |
184 | } | 184 | radeon_set_memory_clock(rdev, mclk); |
185 | rdev->pm.current_mclk = mclk; | ||
186 | DRM_INFO("Setting: m: %d\n", mclk); | ||
187 | } | ||
188 | #endif | ||
189 | radeon_pm_finish(rdev); | ||
190 | } else { | ||
191 | /* set engine clock */ | ||
192 | if (sclk != rdev->pm.current_sclk) { | ||
193 | radeon_sync_with_vblank(rdev); | ||
194 | radeon_pm_debug_check_in_vbl(rdev, false); | ||
195 | radeon_set_engine_clock(rdev, sclk); | ||
196 | radeon_pm_debug_check_in_vbl(rdev, true); | ||
197 | rdev->pm.current_sclk = sclk; | ||
198 | DRM_INFO("Setting: e: %d\n", sclk); | ||
199 | } | ||
185 | 200 | ||
186 | #if 0 | 201 | #if 0 |
187 | /* set memory clock */ | 202 | /* set memory clock */ |
188 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | 203 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { |
189 | radeon_sync_with_vblank(rdev); | 204 | radeon_sync_with_vblank(rdev); |
190 | radeon_pm_debug_check_in_vbl(rdev, false); | 205 | radeon_pm_debug_check_in_vbl(rdev, false); |
191 | radeon_set_memory_clock(rdev, mclk); | 206 | radeon_pm_prepare(rdev); |
192 | radeon_pm_debug_check_in_vbl(rdev, true); | 207 | radeon_set_memory_clock(rdev, mclk); |
193 | rdev->pm.current_mclk = mclk; | 208 | radeon_pm_finish(rdev); |
194 | DRM_INFO("Setting: m: %d\n", mclk); | 209 | radeon_pm_debug_check_in_vbl(rdev, true); |
195 | } | 210 | rdev->pm.current_mclk = mclk; |
211 | DRM_INFO("Setting: m: %d\n", mclk); | ||
212 | } | ||
196 | #endif | 213 | #endif |
214 | } | ||
197 | 215 | ||
198 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; | 216 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; |
199 | rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; | 217 | rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 38f75f54019b..469130994064 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -247,7 +247,7 @@ void r600_get_power_state(struct radeon_device *rdev, | |||
247 | pcie_lanes); | 247 | pcie_lanes); |
248 | } | 248 | } |
249 | 249 | ||
250 | void r600_set_power_state(struct radeon_device *rdev) | 250 | void r600_set_power_state(struct radeon_device *rdev, bool static_switch) |
251 | { | 251 | { |
252 | u32 sclk, mclk; | 252 | u32 sclk, mclk; |
253 | 253 | ||
@@ -266,37 +266,52 @@ void r600_set_power_state(struct radeon_device *rdev) | |||
266 | clock_info[rdev->pm.requested_clock_mode_index].mclk; | 266 | clock_info[rdev->pm.requested_clock_mode_index].mclk; |
267 | if (mclk > rdev->clock.default_mclk) | 267 | if (mclk > rdev->clock.default_mclk) |
268 | mclk = rdev->clock.default_mclk; | 268 | mclk = rdev->clock.default_mclk; |
269 | /* don't change the mclk with multiple crtcs */ | ||
270 | if (rdev->pm.active_crtc_count > 1) | ||
271 | mclk = rdev->clock.default_mclk; | ||
272 | |||
273 | /* set pcie lanes */ | ||
274 | /* TODO */ | ||
275 | 269 | ||
276 | /* set voltage */ | 270 | /* voltage, pcie lanes, etc.*/ |
277 | /* TODO */ | 271 | radeon_pm_misc(rdev); |
278 | 272 | ||
279 | /* set engine clock */ | 273 | if (static_switch) { |
280 | if (sclk != rdev->pm.current_sclk) { | 274 | radeon_pm_prepare(rdev); |
281 | radeon_sync_with_vblank(rdev); | 275 | /* set engine clock */ |
282 | radeon_pm_debug_check_in_vbl(rdev, false); | 276 | if (sclk != rdev->pm.current_sclk) { |
283 | radeon_set_engine_clock(rdev, sclk); | 277 | radeon_set_engine_clock(rdev, sclk); |
284 | radeon_pm_debug_check_in_vbl(rdev, true); | 278 | rdev->pm.current_sclk = sclk; |
285 | rdev->pm.current_sclk = sclk; | 279 | DRM_INFO("Setting: e: %d\n", sclk); |
286 | DRM_INFO("Setting: e: %d\n", sclk); | 280 | } |
287 | } | 281 | #if 0 |
282 | /* set memory clock */ | ||
283 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | ||
284 | radeon_set_memory_clock(rdev, mclk); | ||
285 | rdev->pm.current_mclk = mclk; | ||
286 | DRM_INFO("Setting: m: %d\n", mclk); | ||
287 | } | ||
288 | #endif | ||
289 | radeon_pm_finish(rdev); | ||
290 | } else { | ||
291 | /* set engine clock */ | ||
292 | if (sclk != rdev->pm.current_sclk) { | ||
293 | radeon_sync_with_vblank(rdev); | ||
294 | radeon_pm_debug_check_in_vbl(rdev, false); | ||
295 | radeon_set_engine_clock(rdev, sclk); | ||
296 | radeon_pm_debug_check_in_vbl(rdev, true); | ||
297 | rdev->pm.current_sclk = sclk; | ||
298 | DRM_INFO("Setting: e: %d\n", sclk); | ||
299 | } | ||
288 | 300 | ||
289 | #if 0 | 301 | #if 0 |
290 | /* set memory clock */ | 302 | /* set memory clock */ |
291 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | 303 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { |
292 | radeon_sync_with_vblank(rdev); | 304 | radeon_sync_with_vblank(rdev); |
293 | radeon_pm_debug_check_in_vbl(rdev, false); | 305 | radeon_pm_debug_check_in_vbl(rdev, false); |
294 | radeon_set_memory_clock(rdev, mclk); | 306 | radeon_pm_prepare(rdev); |
295 | radeon_pm_debug_check_in_vbl(rdev, true); | 307 | radeon_set_memory_clock(rdev, mclk); |
296 | rdev->pm.current_mclk = mclk; | 308 | radeon_pm_finish(rdev); |
297 | DRM_INFO("Setting: m: %d\n", mclk); | 309 | radeon_pm_debug_check_in_vbl(rdev, true); |
298 | } | 310 | rdev->pm.current_mclk = mclk; |
311 | DRM_INFO("Setting: m: %d\n", mclk); | ||
312 | } | ||
299 | #endif | 313 | #endif |
314 | } | ||
300 | 315 | ||
301 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; | 316 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; |
302 | rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; | 317 | rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 16f0ea78ea9d..cdcf5eaf6714 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -814,7 +814,7 @@ struct radeon_asic { | |||
814 | void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo); | 814 | void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo); |
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, bool static_switch); |
818 | void (*pm_misc)(struct radeon_device *rdev); | 818 | void (*pm_misc)(struct radeon_device *rdev); |
819 | void (*pm_prepare)(struct radeon_device *rdev); | 819 | void (*pm_prepare)(struct radeon_device *rdev); |
820 | void (*pm_finish)(struct radeon_device *rdev); | 820 | void (*pm_finish)(struct radeon_device *rdev); |
@@ -1226,7 +1226,10 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) | |||
1226 | #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd)) | 1226 | #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd)) |
1227 | #define radeon_gui_idle(rdev) (rdev)->asic->gui_idle((rdev)) | 1227 | #define radeon_gui_idle(rdev) (rdev)->asic->gui_idle((rdev)) |
1228 | #define radeon_get_power_state(rdev, a) (rdev)->asic->get_power_state((rdev), (a)) | 1228 | #define radeon_get_power_state(rdev, a) (rdev)->asic->get_power_state((rdev), (a)) |
1229 | #define radeon_set_power_state(rdev) (rdev)->asic->set_power_state((rdev)) | 1229 | #define radeon_set_power_state(rdev, s) (rdev)->asic->set_power_state((rdev), (s)) |
1230 | #define radeon_pm_misc(rdev) (rdev)->asic->pm_misc((rdev)) | ||
1231 | #define radeon_pm_prepare(rdev) (rdev)->asic->pm_prepare((rdev)) | ||
1232 | #define radeon_pm_finish(rdev) (rdev)->asic->pm_finish((rdev)) | ||
1230 | 1233 | ||
1231 | /* Common functions */ | 1234 | /* Common functions */ |
1232 | /* AGP */ | 1235 | /* AGP */ |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 378db67ba2d8..8a1278629994 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -127,7 +127,7 @@ void r100_enable_bm(struct radeon_device *rdev); | |||
127 | void r100_set_common_regs(struct radeon_device *rdev); | 127 | void r100_set_common_regs(struct radeon_device *rdev); |
128 | void r100_bm_disable(struct radeon_device *rdev); | 128 | void r100_bm_disable(struct radeon_device *rdev); |
129 | extern bool r100_gui_idle(struct radeon_device *rdev); | 129 | extern bool r100_gui_idle(struct radeon_device *rdev); |
130 | extern void r100_set_power_state(struct radeon_device *rdev); | 130 | extern void r100_set_power_state(struct radeon_device *rdev, bool static_switch); |
131 | extern void r100_get_power_state(struct radeon_device *rdev, | 131 | extern void r100_get_power_state(struct radeon_device *rdev, |
132 | enum radeon_pm_action action); | 132 | enum radeon_pm_action action); |
133 | extern void r100_pm_misc(struct radeon_device *rdev); | 133 | extern void r100_pm_misc(struct radeon_device *rdev); |
@@ -281,7 +281,7 @@ void r600_hpd_set_polarity(struct radeon_device *rdev, | |||
281 | enum radeon_hpd_id hpd); | 281 | enum radeon_hpd_id hpd); |
282 | extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo); | 282 | extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo); |
283 | extern bool r600_gui_idle(struct radeon_device *rdev); | 283 | extern bool r600_gui_idle(struct radeon_device *rdev); |
284 | extern void r600_set_power_state(struct radeon_device *rdev); | 284 | extern void r600_set_power_state(struct radeon_device *rdev, bool static_switch); |
285 | extern void r600_get_power_state(struct radeon_device *rdev, | 285 | extern void r600_get_power_state(struct radeon_device *rdev, |
286 | enum radeon_pm_action action); | 286 | enum radeon_pm_action action); |
287 | extern void r600_pm_misc(struct radeon_device *rdev); | 287 | extern void r600_pm_misc(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 23b79ebce6c1..c703ae326bc3 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -34,6 +34,128 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev); | |||
34 | static void radeon_pm_idle_work_handler(struct work_struct *work); | 34 | static void radeon_pm_idle_work_handler(struct work_struct *work); |
35 | static int radeon_debugfs_pm_init(struct radeon_device *rdev); | 35 | static int radeon_debugfs_pm_init(struct radeon_device *rdev); |
36 | 36 | ||
37 | static void radeon_pm_set_power_mode_static_locked(struct radeon_device *rdev) | ||
38 | { | ||
39 | mutex_lock(&rdev->cp.mutex); | ||
40 | |||
41 | /* wait for GPU idle */ | ||
42 | rdev->pm.gui_idle = false; | ||
43 | rdev->irq.gui_idle = true; | ||
44 | radeon_irq_set(rdev); | ||
45 | wait_event_interruptible_timeout( | ||
46 | rdev->irq.idle_queue, rdev->pm.gui_idle, | ||
47 | msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); | ||
48 | rdev->irq.gui_idle = false; | ||
49 | radeon_irq_set(rdev); | ||
50 | |||
51 | radeon_set_power_state(rdev, true); | ||
52 | |||
53 | /* update display watermarks based on new power state */ | ||
54 | radeon_update_bandwidth_info(rdev); | ||
55 | if (rdev->pm.active_crtc_count) | ||
56 | radeon_bandwidth_update(rdev); | ||
57 | |||
58 | mutex_unlock(&rdev->cp.mutex); | ||
59 | } | ||
60 | |||
61 | static ssize_t radeon_get_power_state_static(struct device *dev, | ||
62 | struct device_attribute *attr, | ||
63 | char *buf) | ||
64 | { | ||
65 | struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); | ||
66 | struct radeon_device *rdev = ddev->dev_private; | ||
67 | |||
68 | return snprintf(buf, PAGE_SIZE, "%d.%d\n", rdev->pm.current_power_state_index, | ||
69 | rdev->pm.current_clock_mode_index); | ||
70 | } | ||
71 | |||
72 | static ssize_t radeon_set_power_state_static(struct device *dev, | ||
73 | struct device_attribute *attr, | ||
74 | const char *buf, | ||
75 | size_t count) | ||
76 | { | ||
77 | struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); | ||
78 | struct radeon_device *rdev = ddev->dev_private; | ||
79 | int ps, cm; | ||
80 | |||
81 | if (sscanf(buf, "%u.%u", &ps, &cm) != 2) { | ||
82 | DRM_ERROR("Invalid power state!\n"); | ||
83 | return count; | ||
84 | } | ||
85 | |||
86 | mutex_lock(&rdev->pm.mutex); | ||
87 | if ((ps >= 0) && (ps < rdev->pm.num_power_states) && | ||
88 | (cm >= 0) && (cm < rdev->pm.power_state[ps].num_clock_modes)) { | ||
89 | if ((rdev->pm.active_crtc_count > 1) && | ||
90 | (rdev->pm.power_state[ps].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)) { | ||
91 | DRM_ERROR("Invalid power state for multi-head: %d.%d\n", ps, cm); | ||
92 | } else { | ||
93 | /* disable dynpm */ | ||
94 | rdev->pm.state = PM_STATE_DISABLED; | ||
95 | rdev->pm.planned_action = PM_ACTION_NONE; | ||
96 | rdev->pm.requested_power_state_index = ps; | ||
97 | rdev->pm.requested_clock_mode_index = cm; | ||
98 | radeon_pm_set_power_mode_static_locked(rdev); | ||
99 | } | ||
100 | } else | ||
101 | DRM_ERROR("Invalid power state: %d.%d\n\n", ps, cm); | ||
102 | mutex_unlock(&rdev->pm.mutex); | ||
103 | |||
104 | return count; | ||
105 | } | ||
106 | |||
107 | static ssize_t radeon_get_dynpm(struct device *dev, | ||
108 | struct device_attribute *attr, | ||
109 | char *buf) | ||
110 | { | ||
111 | struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); | ||
112 | struct radeon_device *rdev = ddev->dev_private; | ||
113 | |||
114 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
115 | (rdev->pm.state == PM_STATE_DISABLED) ? "disabled" : "enabled"); | ||
116 | } | ||
117 | |||
118 | static ssize_t radeon_set_dynpm(struct device *dev, | ||
119 | struct device_attribute *attr, | ||
120 | const char *buf, | ||
121 | size_t count) | ||
122 | { | ||
123 | struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); | ||
124 | struct radeon_device *rdev = ddev->dev_private; | ||
125 | int tmp = simple_strtoul(buf, NULL, 10); | ||
126 | |||
127 | if (tmp == 0) { | ||
128 | /* update power mode info */ | ||
129 | radeon_pm_compute_clocks(rdev); | ||
130 | /* disable dynpm */ | ||
131 | mutex_lock(&rdev->pm.mutex); | ||
132 | rdev->pm.state = PM_STATE_DISABLED; | ||
133 | rdev->pm.planned_action = PM_ACTION_NONE; | ||
134 | mutex_unlock(&rdev->pm.mutex); | ||
135 | DRM_INFO("radeon: dynamic power management disabled\n"); | ||
136 | } else if (tmp == 1) { | ||
137 | if (rdev->pm.num_power_states > 1) { | ||
138 | /* enable dynpm */ | ||
139 | mutex_lock(&rdev->pm.mutex); | ||
140 | rdev->pm.state = PM_STATE_PAUSED; | ||
141 | rdev->pm.planned_action = PM_ACTION_DEFAULT; | ||
142 | radeon_get_power_state(rdev, rdev->pm.planned_action); | ||
143 | mutex_unlock(&rdev->pm.mutex); | ||
144 | /* update power mode info */ | ||
145 | radeon_pm_compute_clocks(rdev); | ||
146 | DRM_INFO("radeon: dynamic power management enabled\n"); | ||
147 | } else | ||
148 | DRM_ERROR("dynpm not valid on this system\n"); | ||
149 | } else | ||
150 | DRM_ERROR("Invalid setting: %d\n", tmp); | ||
151 | |||
152 | return count; | ||
153 | } | ||
154 | |||
155 | static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, radeon_get_power_state_static, radeon_set_power_state_static); | ||
156 | static DEVICE_ATTR(dynpm, S_IRUGO | S_IWUSR, radeon_get_dynpm, radeon_set_dynpm); | ||
157 | |||
158 | |||
37 | static const char *pm_state_names[4] = { | 159 | static const char *pm_state_names[4] = { |
38 | "PM_STATE_DISABLED", | 160 | "PM_STATE_DISABLED", |
39 | "PM_STATE_MINIMUM", | 161 | "PM_STATE_MINIMUM", |
@@ -111,6 +233,10 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
111 | DRM_ERROR("Failed to register debugfs file for PM!\n"); | 233 | DRM_ERROR("Failed to register debugfs file for PM!\n"); |
112 | } | 234 | } |
113 | 235 | ||
236 | /* where's the best place to put this? */ | ||
237 | device_create_file(rdev->dev, &dev_attr_power_state); | ||
238 | device_create_file(rdev->dev, &dev_attr_dynpm); | ||
239 | |||
114 | INIT_DELAYED_WORK(&rdev->pm.idle_work, radeon_pm_idle_work_handler); | 240 | INIT_DELAYED_WORK(&rdev->pm.idle_work, radeon_pm_idle_work_handler); |
115 | 241 | ||
116 | if ((radeon_dynpm != -1 && radeon_dynpm) && (rdev->pm.num_power_states > 1)) { | 242 | if ((radeon_dynpm != -1 && radeon_dynpm) && (rdev->pm.num_power_states > 1)) { |
@@ -132,8 +258,19 @@ void radeon_pm_fini(struct radeon_device *rdev) | |||
132 | rdev->pm.state = PM_STATE_DISABLED; | 258 | rdev->pm.state = PM_STATE_DISABLED; |
133 | rdev->pm.planned_action = PM_ACTION_DEFAULT; | 259 | rdev->pm.planned_action = PM_ACTION_DEFAULT; |
134 | radeon_pm_set_clocks(rdev); | 260 | radeon_pm_set_clocks(rdev); |
261 | } else if ((rdev->pm.current_power_state_index != | ||
262 | rdev->pm.default_power_state_index) || | ||
263 | (rdev->pm.current_clock_mode_index != 0)) { | ||
264 | rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; | ||
265 | rdev->pm.requested_clock_mode_index = 0; | ||
266 | mutex_lock(&rdev->pm.mutex); | ||
267 | radeon_pm_set_power_mode_static_locked(rdev); | ||
268 | mutex_unlock(&rdev->pm.mutex); | ||
135 | } | 269 | } |
136 | 270 | ||
271 | device_remove_file(rdev->dev, &dev_attr_power_state); | ||
272 | device_remove_file(rdev->dev, &dev_attr_dynpm); | ||
273 | |||
137 | if (rdev->pm.i2c_bus) | 274 | if (rdev->pm.i2c_bus) |
138 | radeon_i2c_destroy(rdev->pm.i2c_bus); | 275 | radeon_i2c_destroy(rdev->pm.i2c_bus); |
139 | } | 276 | } |
@@ -267,7 +404,7 @@ static void radeon_pm_set_clocks_locked(struct radeon_device *rdev) | |||
267 | { | 404 | { |
268 | /*radeon_fence_wait_last(rdev);*/ | 405 | /*radeon_fence_wait_last(rdev);*/ |
269 | 406 | ||
270 | radeon_set_power_state(rdev); | 407 | radeon_set_power_state(rdev, false); |
271 | rdev->pm.planned_action = PM_ACTION_NONE; | 408 | rdev->pm.planned_action = PM_ACTION_NONE; |
272 | } | 409 | } |
273 | 410 | ||