diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-06-30 18:07:09 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-06-30 18:07:09 -0400 |
commit | 08fa16b6b75005c120b59d00ae42a0b7cc68db45 (patch) | |
tree | c5f22412467f72dd0c7291bbb958a9485e894f02 /drivers/gpu/drm/radeon/radeon_pm.c | |
parent | 1796b983cc4cbbed5e9e478b03591609a2c21987 (diff) | |
parent | 7e27d6e778cd87b6f2415515d7127eba53fe5d02 (diff) |
Merge commit 'v2.6.35-rc3' into next
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_pm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 170 |
1 files changed, 102 insertions, 68 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index a8d162c6f82..63f679a04b2 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -33,6 +33,14 @@ | |||
33 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 | 33 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 |
34 | #define RADEON_WAIT_IDLE_TIMEOUT 200 | 34 | #define RADEON_WAIT_IDLE_TIMEOUT 200 |
35 | 35 | ||
36 | static const char *radeon_pm_state_type_name[5] = { | ||
37 | "Default", | ||
38 | "Powersave", | ||
39 | "Battery", | ||
40 | "Balanced", | ||
41 | "Performance", | ||
42 | }; | ||
43 | |||
36 | static void radeon_dynpm_idle_work_handler(struct work_struct *work); | 44 | static void radeon_dynpm_idle_work_handler(struct work_struct *work); |
37 | static int radeon_debugfs_pm_init(struct radeon_device *rdev); | 45 | static int radeon_debugfs_pm_init(struct radeon_device *rdev); |
38 | static bool radeon_pm_in_vbl(struct radeon_device *rdev); | 46 | static bool radeon_pm_in_vbl(struct radeon_device *rdev); |
@@ -84,9 +92,9 @@ static void radeon_pm_update_profile(struct radeon_device *rdev) | |||
84 | rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX; | 92 | rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX; |
85 | } else { | 93 | } else { |
86 | if (rdev->pm.active_crtc_count > 1) | 94 | if (rdev->pm.active_crtc_count > 1) |
87 | rdev->pm.profile_index = PM_PROFILE_LOW_MH_IDX; | 95 | rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX; |
88 | else | 96 | else |
89 | rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX; | 97 | rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX; |
90 | } | 98 | } |
91 | break; | 99 | break; |
92 | case PM_PROFILE_LOW: | 100 | case PM_PROFILE_LOW: |
@@ -95,6 +103,12 @@ static void radeon_pm_update_profile(struct radeon_device *rdev) | |||
95 | else | 103 | else |
96 | rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX; | 104 | rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX; |
97 | break; | 105 | break; |
106 | case PM_PROFILE_MID: | ||
107 | if (rdev->pm.active_crtc_count > 1) | ||
108 | rdev->pm.profile_index = PM_PROFILE_MID_MH_IDX; | ||
109 | else | ||
110 | rdev->pm.profile_index = PM_PROFILE_MID_SH_IDX; | ||
111 | break; | ||
98 | case PM_PROFILE_HIGH: | 112 | case PM_PROFILE_HIGH: |
99 | if (rdev->pm.active_crtc_count > 1) | 113 | if (rdev->pm.active_crtc_count > 1) |
100 | rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX; | 114 | rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX; |
@@ -127,15 +141,6 @@ static void radeon_unmap_vram_bos(struct radeon_device *rdev) | |||
127 | if (bo->tbo.mem.mem_type == TTM_PL_VRAM) | 141 | if (bo->tbo.mem.mem_type == TTM_PL_VRAM) |
128 | ttm_bo_unmap_virtual(&bo->tbo); | 142 | ttm_bo_unmap_virtual(&bo->tbo); |
129 | } | 143 | } |
130 | |||
131 | if (rdev->gart.table.vram.robj) | ||
132 | ttm_bo_unmap_virtual(&rdev->gart.table.vram.robj->tbo); | ||
133 | |||
134 | if (rdev->stollen_vga_memory) | ||
135 | ttm_bo_unmap_virtual(&rdev->stollen_vga_memory->tbo); | ||
136 | |||
137 | if (rdev->r600_blit.shader_obj) | ||
138 | ttm_bo_unmap_virtual(&rdev->r600_blit.shader_obj->tbo); | ||
139 | } | 144 | } |
140 | 145 | ||
141 | static void radeon_sync_with_vblank(struct radeon_device *rdev) | 146 | static void radeon_sync_with_vblank(struct radeon_device *rdev) |
@@ -151,6 +156,7 @@ static void radeon_sync_with_vblank(struct radeon_device *rdev) | |||
151 | static void radeon_set_power_state(struct radeon_device *rdev) | 156 | static void radeon_set_power_state(struct radeon_device *rdev) |
152 | { | 157 | { |
153 | u32 sclk, mclk; | 158 | u32 sclk, mclk; |
159 | bool misc_after = false; | ||
154 | 160 | ||
155 | if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && | 161 | if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && |
156 | (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index)) | 162 | (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index)) |
@@ -167,55 +173,47 @@ static void radeon_set_power_state(struct radeon_device *rdev) | |||
167 | if (mclk > rdev->clock.default_mclk) | 173 | if (mclk > rdev->clock.default_mclk) |
168 | mclk = rdev->clock.default_mclk; | 174 | mclk = rdev->clock.default_mclk; |
169 | 175 | ||
170 | /* voltage, pcie lanes, etc.*/ | 176 | /* upvolt before raising clocks, downvolt after lowering clocks */ |
171 | radeon_pm_misc(rdev); | 177 | if (sclk < rdev->pm.current_sclk) |
178 | misc_after = true; | ||
172 | 179 | ||
173 | if (rdev->pm.pm_method == PM_METHOD_DYNPM) { | 180 | radeon_sync_with_vblank(rdev); |
174 | radeon_sync_with_vblank(rdev); | ||
175 | 181 | ||
182 | if (rdev->pm.pm_method == PM_METHOD_DYNPM) { | ||
176 | if (!radeon_pm_in_vbl(rdev)) | 183 | if (!radeon_pm_in_vbl(rdev)) |
177 | return; | 184 | return; |
185 | } | ||
178 | 186 | ||
179 | radeon_pm_prepare(rdev); | 187 | radeon_pm_prepare(rdev); |
180 | /* set engine clock */ | ||
181 | if (sclk != rdev->pm.current_sclk) { | ||
182 | radeon_pm_debug_check_in_vbl(rdev, false); | ||
183 | radeon_set_engine_clock(rdev, sclk); | ||
184 | radeon_pm_debug_check_in_vbl(rdev, true); | ||
185 | rdev->pm.current_sclk = sclk; | ||
186 | DRM_DEBUG("Setting: e: %d\n", sclk); | ||
187 | } | ||
188 | 188 | ||
189 | /* set memory clock */ | 189 | if (!misc_after) |
190 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | 190 | /* voltage, pcie lanes, etc.*/ |
191 | radeon_pm_debug_check_in_vbl(rdev, false); | 191 | radeon_pm_misc(rdev); |
192 | radeon_set_memory_clock(rdev, mclk); | 192 | |
193 | radeon_pm_debug_check_in_vbl(rdev, true); | 193 | /* set engine clock */ |
194 | rdev->pm.current_mclk = mclk; | 194 | if (sclk != rdev->pm.current_sclk) { |
195 | DRM_DEBUG("Setting: m: %d\n", mclk); | 195 | radeon_pm_debug_check_in_vbl(rdev, false); |
196 | } | 196 | radeon_set_engine_clock(rdev, sclk); |
197 | radeon_pm_finish(rdev); | 197 | radeon_pm_debug_check_in_vbl(rdev, true); |
198 | } else { | 198 | rdev->pm.current_sclk = sclk; |
199 | /* set engine clock */ | 199 | DRM_DEBUG("Setting: e: %d\n", sclk); |
200 | if (sclk != rdev->pm.current_sclk) { | ||
201 | radeon_sync_with_vblank(rdev); | ||
202 | radeon_pm_prepare(rdev); | ||
203 | radeon_set_engine_clock(rdev, sclk); | ||
204 | radeon_pm_finish(rdev); | ||
205 | rdev->pm.current_sclk = sclk; | ||
206 | DRM_DEBUG("Setting: e: %d\n", sclk); | ||
207 | } | ||
208 | /* set memory clock */ | ||
209 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | ||
210 | radeon_sync_with_vblank(rdev); | ||
211 | radeon_pm_prepare(rdev); | ||
212 | radeon_set_memory_clock(rdev, mclk); | ||
213 | radeon_pm_finish(rdev); | ||
214 | rdev->pm.current_mclk = mclk; | ||
215 | DRM_DEBUG("Setting: m: %d\n", mclk); | ||
216 | } | ||
217 | } | 200 | } |
218 | 201 | ||
202 | /* set memory clock */ | ||
203 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | ||
204 | radeon_pm_debug_check_in_vbl(rdev, false); | ||
205 | radeon_set_memory_clock(rdev, mclk); | ||
206 | radeon_pm_debug_check_in_vbl(rdev, true); | ||
207 | rdev->pm.current_mclk = mclk; | ||
208 | DRM_DEBUG("Setting: m: %d\n", mclk); | ||
209 | } | ||
210 | |||
211 | if (misc_after) | ||
212 | /* voltage, pcie lanes, etc.*/ | ||
213 | radeon_pm_misc(rdev); | ||
214 | |||
215 | radeon_pm_finish(rdev); | ||
216 | |||
219 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; | 217 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; |
220 | rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; | 218 | rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; |
221 | } else | 219 | } else |
@@ -288,6 +286,42 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
288 | mutex_unlock(&rdev->ddev->struct_mutex); | 286 | mutex_unlock(&rdev->ddev->struct_mutex); |
289 | } | 287 | } |
290 | 288 | ||
289 | static void radeon_pm_print_states(struct radeon_device *rdev) | ||
290 | { | ||
291 | int i, j; | ||
292 | struct radeon_power_state *power_state; | ||
293 | struct radeon_pm_clock_info *clock_info; | ||
294 | |||
295 | DRM_DEBUG("%d Power State(s)\n", rdev->pm.num_power_states); | ||
296 | for (i = 0; i < rdev->pm.num_power_states; i++) { | ||
297 | power_state = &rdev->pm.power_state[i]; | ||
298 | DRM_DEBUG("State %d: %s\n", i, | ||
299 | radeon_pm_state_type_name[power_state->type]); | ||
300 | if (i == rdev->pm.default_power_state_index) | ||
301 | DRM_DEBUG("\tDefault"); | ||
302 | if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP)) | ||
303 | DRM_DEBUG("\t%d PCIE Lanes\n", power_state->pcie_lanes); | ||
304 | if (power_state->flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) | ||
305 | DRM_DEBUG("\tSingle display only\n"); | ||
306 | DRM_DEBUG("\t%d Clock Mode(s)\n", power_state->num_clock_modes); | ||
307 | for (j = 0; j < power_state->num_clock_modes; j++) { | ||
308 | clock_info = &(power_state->clock_info[j]); | ||
309 | if (rdev->flags & RADEON_IS_IGP) | ||
310 | DRM_DEBUG("\t\t%d e: %d%s\n", | ||
311 | j, | ||
312 | clock_info->sclk * 10, | ||
313 | clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : ""); | ||
314 | else | ||
315 | DRM_DEBUG("\t\t%d e: %d\tm: %d\tv: %d%s\n", | ||
316 | j, | ||
317 | clock_info->sclk * 10, | ||
318 | clock_info->mclk * 10, | ||
319 | clock_info->voltage.voltage, | ||
320 | clock_info->flags & RADEON_PM_MODE_NO_DISPLAY ? "\tNo display only" : ""); | ||
321 | } | ||
322 | } | ||
323 | } | ||
324 | |||
291 | static ssize_t radeon_get_pm_profile(struct device *dev, | 325 | static ssize_t radeon_get_pm_profile(struct device *dev, |
292 | struct device_attribute *attr, | 326 | struct device_attribute *attr, |
293 | char *buf) | 327 | char *buf) |
@@ -318,6 +352,8 @@ static ssize_t radeon_set_pm_profile(struct device *dev, | |||
318 | rdev->pm.profile = PM_PROFILE_AUTO; | 352 | rdev->pm.profile = PM_PROFILE_AUTO; |
319 | else if (strncmp("low", buf, strlen("low")) == 0) | 353 | else if (strncmp("low", buf, strlen("low")) == 0) |
320 | rdev->pm.profile = PM_PROFILE_LOW; | 354 | rdev->pm.profile = PM_PROFILE_LOW; |
355 | else if (strncmp("mid", buf, strlen("mid")) == 0) | ||
356 | rdev->pm.profile = PM_PROFILE_MID; | ||
321 | else if (strncmp("high", buf, strlen("high")) == 0) | 357 | else if (strncmp("high", buf, strlen("high")) == 0) |
322 | rdev->pm.profile = PM_PROFILE_HIGH; | 358 | rdev->pm.profile = PM_PROFILE_HIGH; |
323 | else { | 359 | else { |
@@ -384,15 +420,19 @@ void radeon_pm_suspend(struct radeon_device *rdev) | |||
384 | { | 420 | { |
385 | mutex_lock(&rdev->pm.mutex); | 421 | mutex_lock(&rdev->pm.mutex); |
386 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); | 422 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); |
387 | rdev->pm.current_power_state_index = -1; | ||
388 | rdev->pm.current_clock_mode_index = -1; | ||
389 | rdev->pm.current_sclk = 0; | ||
390 | rdev->pm.current_mclk = 0; | ||
391 | mutex_unlock(&rdev->pm.mutex); | 423 | mutex_unlock(&rdev->pm.mutex); |
392 | } | 424 | } |
393 | 425 | ||
394 | void radeon_pm_resume(struct radeon_device *rdev) | 426 | void radeon_pm_resume(struct radeon_device *rdev) |
395 | { | 427 | { |
428 | /* asic init will reset the default power state */ | ||
429 | mutex_lock(&rdev->pm.mutex); | ||
430 | rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; | ||
431 | rdev->pm.current_clock_mode_index = 0; | ||
432 | rdev->pm.current_sclk = rdev->clock.default_sclk; | ||
433 | rdev->pm.current_mclk = rdev->clock.default_mclk; | ||
434 | rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; | ||
435 | mutex_unlock(&rdev->pm.mutex); | ||
396 | radeon_pm_compute_clocks(rdev); | 436 | radeon_pm_compute_clocks(rdev); |
397 | } | 437 | } |
398 | 438 | ||
@@ -401,32 +441,24 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
401 | int ret; | 441 | int ret; |
402 | /* default to profile method */ | 442 | /* default to profile method */ |
403 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 443 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
444 | rdev->pm.profile = PM_PROFILE_DEFAULT; | ||
404 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; | 445 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; |
405 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; | 446 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; |
406 | rdev->pm.dynpm_can_upclock = true; | 447 | rdev->pm.dynpm_can_upclock = true; |
407 | rdev->pm.dynpm_can_downclock = true; | 448 | rdev->pm.dynpm_can_downclock = true; |
408 | rdev->pm.current_sclk = 0; | 449 | rdev->pm.current_sclk = rdev->clock.default_sclk; |
409 | rdev->pm.current_mclk = 0; | 450 | rdev->pm.current_mclk = rdev->clock.default_mclk; |
410 | 451 | ||
411 | if (rdev->bios) { | 452 | if (rdev->bios) { |
412 | if (rdev->is_atom_bios) | 453 | if (rdev->is_atom_bios) |
413 | radeon_atombios_get_power_modes(rdev); | 454 | radeon_atombios_get_power_modes(rdev); |
414 | else | 455 | else |
415 | radeon_combios_get_power_modes(rdev); | 456 | radeon_combios_get_power_modes(rdev); |
457 | radeon_pm_print_states(rdev); | ||
416 | radeon_pm_init_profile(rdev); | 458 | radeon_pm_init_profile(rdev); |
417 | rdev->pm.current_power_state_index = -1; | ||
418 | rdev->pm.current_clock_mode_index = -1; | ||
419 | } | 459 | } |
420 | 460 | ||
421 | if (rdev->pm.num_power_states > 1) { | 461 | if (rdev->pm.num_power_states > 1) { |
422 | if (rdev->pm.pm_method == PM_METHOD_PROFILE) { | ||
423 | mutex_lock(&rdev->pm.mutex); | ||
424 | rdev->pm.profile = PM_PROFILE_DEFAULT; | ||
425 | radeon_pm_update_profile(rdev); | ||
426 | radeon_pm_set_clocks(rdev); | ||
427 | mutex_unlock(&rdev->pm.mutex); | ||
428 | } | ||
429 | |||
430 | /* where's the best place to put these? */ | 462 | /* where's the best place to put these? */ |
431 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); | 463 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); |
432 | if (ret) | 464 | if (ret) |
@@ -712,6 +744,8 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) | |||
712 | seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk); | 744 | seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk); |
713 | if (rdev->asic->get_memory_clock) | 745 | if (rdev->asic->get_memory_clock) |
714 | seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); | 746 | seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); |
747 | if (rdev->pm.current_vddc) | ||
748 | seq_printf(m, "voltage: %u mV\n", rdev->pm.current_vddc); | ||
715 | if (rdev->asic->get_pcie_lanes) | 749 | if (rdev->asic->get_pcie_lanes) |
716 | seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev)); | 750 | seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev)); |
717 | 751 | ||