diff options
| author | Alex Deucher <alexdeucher@gmail.com> | 2010-04-29 00:22:43 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2010-05-18 04:21:35 -0400 |
| commit | 539d24181753e40174746d576d415bfb56131975 (patch) | |
| tree | 0aead71d6217f1e58a9a021c4c37131e930b6f6c /drivers | |
| parent | 68adac5e49436992e9c999fbae879d9ac5b72d4e (diff) | |
drm/radeon/kms: more pm fixes
- disable gui idle interrupt use
Seems to hang some r5xx chips
- move vbl range check into
existing vbl check function in
radeon_pm.c
- disable crtc mc acccess for the
whole reclocking process
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/radeon/evergreen_reg.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 35 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 65 |
4 files changed, 45 insertions, 63 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index 93aab2ebd9d0..af86af836f13 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h | |||
| @@ -164,10 +164,12 @@ | |||
| 164 | #define EVERGREEN_CRTC5_REGISTER_OFFSET (0x129f0 - 0x6df0) | 164 | #define EVERGREEN_CRTC5_REGISTER_OFFSET (0x129f0 - 0x6df0) |
| 165 | 165 | ||
| 166 | /* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */ | 166 | /* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */ |
| 167 | #define EVERGREEN_CRTC_V_BLANK_START_END 0x6e34 | ||
| 167 | #define EVERGREEN_CRTC_CONTROL 0x6e70 | 168 | #define EVERGREEN_CRTC_CONTROL 0x6e70 |
| 168 | # define EVERGREEN_CRTC_MASTER_EN (1 << 0) | 169 | # define EVERGREEN_CRTC_MASTER_EN (1 << 0) |
| 169 | # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) | 170 | # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) |
| 170 | #define EVERGREEN_CRTC_STATUS 0x6e8c | 171 | #define EVERGREEN_CRTC_STATUS 0x6e8c |
| 172 | #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 | ||
| 171 | #define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 | 173 | #define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 |
| 172 | 174 | ||
| 173 | #define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0 | 175 | #define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0 |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index a5f11c300f6a..493b9b48da30 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -178,14 +178,12 @@ void r100_set_power_state(struct radeon_device *rdev, bool static_switch) | |||
| 178 | rdev->pm.current_sclk = sclk; | 178 | rdev->pm.current_sclk = sclk; |
| 179 | DRM_INFO("Setting: e: %d\n", sclk); | 179 | DRM_INFO("Setting: e: %d\n", sclk); |
| 180 | } | 180 | } |
| 181 | #if 0 | ||
| 182 | /* set memory clock */ | 181 | /* set memory clock */ |
| 183 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | 182 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { |
| 184 | radeon_set_memory_clock(rdev, mclk); | 183 | radeon_set_memory_clock(rdev, mclk); |
| 185 | rdev->pm.current_mclk = mclk; | 184 | rdev->pm.current_mclk = mclk; |
| 186 | DRM_INFO("Setting: m: %d\n", mclk); | 185 | DRM_INFO("Setting: m: %d\n", mclk); |
| 187 | } | 186 | } |
| 188 | #endif | ||
| 189 | radeon_pm_finish(rdev); | 187 | radeon_pm_finish(rdev); |
| 190 | } else { | 188 | } else { |
| 191 | radeon_sync_with_vblank(rdev); | 189 | radeon_sync_with_vblank(rdev); |
| @@ -193,6 +191,7 @@ void r100_set_power_state(struct radeon_device *rdev, bool static_switch) | |||
| 193 | if (!radeon_pm_in_vbl(rdev)) | 191 | if (!radeon_pm_in_vbl(rdev)) |
| 194 | return; | 192 | return; |
| 195 | 193 | ||
| 194 | radeon_pm_prepare(rdev); | ||
| 196 | /* set engine clock */ | 195 | /* set engine clock */ |
| 197 | if (sclk != rdev->pm.current_sclk) { | 196 | if (sclk != rdev->pm.current_sclk) { |
| 198 | radeon_pm_debug_check_in_vbl(rdev, false); | 197 | radeon_pm_debug_check_in_vbl(rdev, false); |
| @@ -205,13 +204,12 @@ void r100_set_power_state(struct radeon_device *rdev, bool static_switch) | |||
| 205 | /* set memory clock */ | 204 | /* set memory clock */ |
| 206 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | 205 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { |
| 207 | radeon_pm_debug_check_in_vbl(rdev, false); | 206 | radeon_pm_debug_check_in_vbl(rdev, false); |
| 208 | radeon_pm_prepare(rdev); | ||
| 209 | radeon_set_memory_clock(rdev, mclk); | 207 | radeon_set_memory_clock(rdev, mclk); |
| 210 | radeon_pm_finish(rdev); | ||
| 211 | radeon_pm_debug_check_in_vbl(rdev, true); | 208 | radeon_pm_debug_check_in_vbl(rdev, true); |
| 212 | rdev->pm.current_mclk = mclk; | 209 | rdev->pm.current_mclk = mclk; |
| 213 | DRM_INFO("Setting: m: %d\n", mclk); | 210 | DRM_INFO("Setting: m: %d\n", mclk); |
| 214 | } | 211 | } |
| 212 | radeon_pm_finish(rdev); | ||
| 215 | } | 213 | } |
| 216 | 214 | ||
| 217 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; | 215 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index d3a79e0a9125..75c825cb8790 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -256,7 +256,6 @@ void r600_set_power_state(struct radeon_device *rdev, bool static_switch) | |||
| 256 | return; | 256 | return; |
| 257 | 257 | ||
| 258 | if (radeon_gui_idle(rdev)) { | 258 | if (radeon_gui_idle(rdev)) { |
| 259 | |||
| 260 | sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. | 259 | sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. |
| 261 | clock_info[rdev->pm.requested_clock_mode_index].sclk; | 260 | clock_info[rdev->pm.requested_clock_mode_index].sclk; |
| 262 | if (sclk > rdev->clock.default_sclk) | 261 | if (sclk > rdev->clock.default_sclk) |
| @@ -271,52 +270,27 @@ void r600_set_power_state(struct radeon_device *rdev, bool static_switch) | |||
| 271 | radeon_pm_misc(rdev); | 270 | radeon_pm_misc(rdev); |
| 272 | 271 | ||
| 273 | if (static_switch) { | 272 | if (static_switch) { |
| 274 | 273 | radeon_pm_prepare(rdev); | |
| 275 | /* set engine clock */ | 274 | /* set engine clock */ |
| 276 | if (sclk != rdev->pm.current_sclk) { | 275 | if (sclk != rdev->pm.current_sclk) { |
| 277 | radeon_set_engine_clock(rdev, sclk); | 276 | radeon_set_engine_clock(rdev, sclk); |
| 278 | rdev->pm.current_sclk = sclk; | 277 | rdev->pm.current_sclk = sclk; |
| 279 | DRM_INFO("Setting: e: %d\n", sclk); | 278 | DRM_INFO("Setting: e: %d\n", sclk); |
| 280 | } | 279 | } |
| 281 | |||
| 282 | /* set memory clock */ | 280 | /* set memory clock */ |
| 283 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | 281 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { |
| 284 | radeon_pm_prepare(rdev); | ||
| 285 | radeon_set_memory_clock(rdev, mclk); | 282 | radeon_set_memory_clock(rdev, mclk); |
| 286 | radeon_pm_finish(rdev); | ||
| 287 | rdev->pm.current_mclk = mclk; | 283 | rdev->pm.current_mclk = mclk; |
| 288 | DRM_INFO("Setting: m: %d\n", mclk); | 284 | DRM_INFO("Setting: m: %d\n", mclk); |
| 289 | } | 285 | } |
| 290 | 286 | radeon_pm_finish(rdev); | |
| 291 | } else { | 287 | } else { |
| 292 | u32 position; | ||
| 293 | u32 vbl; | ||
| 294 | |||
| 295 | radeon_sync_with_vblank(rdev); | 288 | radeon_sync_with_vblank(rdev); |
| 296 | 289 | ||
| 297 | if (!radeon_pm_in_vbl(rdev)) | 290 | if (!radeon_pm_in_vbl(rdev)) |
| 298 | return; | 291 | return; |
| 299 | 292 | ||
| 300 | if (rdev->pm.active_crtcs & (1 << 0)) { | 293 | radeon_pm_prepare(rdev); |
| 301 | vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END); | ||
| 302 | position = RREG32(AVIVO_D1CRTC_STATUS_POSITION); | ||
| 303 | position &= 0xfff; | ||
| 304 | vbl &= 0xfff; | ||
| 305 | |||
| 306 | if (position < vbl && position > 1) | ||
| 307 | return; | ||
| 308 | } | ||
| 309 | |||
| 310 | if (rdev->pm.active_crtcs & (1 << 1)) { | ||
| 311 | vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END); | ||
| 312 | position = RREG32(AVIVO_D2CRTC_STATUS_POSITION); | ||
| 313 | position &= 0xfff; | ||
| 314 | vbl &= 0xfff; | ||
| 315 | |||
| 316 | if (position < vbl && position > 1) | ||
| 317 | return; | ||
| 318 | } | ||
| 319 | |||
| 320 | if (sclk != rdev->pm.current_sclk) { | 294 | if (sclk != rdev->pm.current_sclk) { |
| 321 | radeon_pm_debug_check_in_vbl(rdev, false); | 295 | radeon_pm_debug_check_in_vbl(rdev, false); |
| 322 | radeon_set_engine_clock(rdev, sclk); | 296 | radeon_set_engine_clock(rdev, sclk); |
| @@ -328,13 +302,12 @@ void r600_set_power_state(struct radeon_device *rdev, bool static_switch) | |||
| 328 | /* set memory clock */ | 302 | /* set memory clock */ |
| 329 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { | 303 | if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { |
| 330 | radeon_pm_debug_check_in_vbl(rdev, false); | 304 | radeon_pm_debug_check_in_vbl(rdev, false); |
| 331 | radeon_pm_prepare(rdev); | ||
| 332 | radeon_set_memory_clock(rdev, mclk); | 305 | radeon_set_memory_clock(rdev, mclk); |
| 333 | radeon_pm_finish(rdev); | ||
| 334 | radeon_pm_debug_check_in_vbl(rdev, true); | 306 | radeon_pm_debug_check_in_vbl(rdev, true); |
| 335 | rdev->pm.current_mclk = mclk; | 307 | rdev->pm.current_mclk = mclk; |
| 336 | DRM_INFO("Setting: m: %d\n", mclk); | 308 | DRM_INFO("Setting: m: %d\n", mclk); |
| 337 | } | 309 | } |
| 310 | radeon_pm_finish(rdev); | ||
| 338 | } | 311 | } |
| 339 | 312 | ||
| 340 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; | 313 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 88163e043fcf..2eb675e78440 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -64,7 +64,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch) | |||
| 64 | mutex_lock(&rdev->ddev->struct_mutex); | 64 | mutex_lock(&rdev->ddev->struct_mutex); |
| 65 | mutex_lock(&rdev->vram_mutex); | 65 | mutex_lock(&rdev->vram_mutex); |
| 66 | mutex_lock(&rdev->cp.mutex); | 66 | mutex_lock(&rdev->cp.mutex); |
| 67 | 67 | #if 0 | |
| 68 | /* wait for GPU idle */ | 68 | /* wait for GPU idle */ |
| 69 | rdev->pm.gui_idle = false; | 69 | rdev->pm.gui_idle = false; |
| 70 | rdev->irq.gui_idle = true; | 70 | rdev->irq.gui_idle = true; |
| @@ -74,7 +74,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch) | |||
| 74 | msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); | 74 | msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); |
| 75 | rdev->irq.gui_idle = false; | 75 | rdev->irq.gui_idle = false; |
| 76 | radeon_irq_set(rdev); | 76 | radeon_irq_set(rdev); |
| 77 | 77 | #endif | |
| 78 | radeon_unmap_vram_bos(rdev); | 78 | radeon_unmap_vram_bos(rdev); |
| 79 | 79 | ||
| 80 | if (!static_switch) { | 80 | if (!static_switch) { |
| @@ -85,7 +85,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch) | |||
| 85 | } | 85 | } |
| 86 | } | 86 | } |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | radeon_set_power_state(rdev, static_switch); | 89 | radeon_set_power_state(rdev, static_switch); |
| 90 | 90 | ||
| 91 | if (!static_switch) { | 91 | if (!static_switch) { |
| @@ -389,51 +389,57 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) | |||
| 389 | 389 | ||
| 390 | bool radeon_pm_in_vbl(struct radeon_device *rdev) | 390 | bool radeon_pm_in_vbl(struct radeon_device *rdev) |
| 391 | { | 391 | { |
| 392 | u32 stat_crtc = 0; | 392 | u32 stat_crtc = 0, vbl = 0, position = 0; |
| 393 | bool in_vbl = true; | 393 | bool in_vbl = true; |
| 394 | 394 | ||
| 395 | if (ASIC_IS_DCE4(rdev)) { | 395 | if (ASIC_IS_DCE4(rdev)) { |
| 396 | if (rdev->pm.active_crtcs & (1 << 0)) { | 396 | if (rdev->pm.active_crtcs & (1 << 0)) { |
| 397 | stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); | 397 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
| 398 | if (!(stat_crtc & 1)) | 398 | EVERGREEN_CRTC0_REGISTER_OFFSET) & 0xfff; |
| 399 | in_vbl = false; | 399 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
| 400 | EVERGREEN_CRTC0_REGISTER_OFFSET) & 0xfff; | ||
| 400 | } | 401 | } |
| 401 | if (rdev->pm.active_crtcs & (1 << 1)) { | 402 | if (rdev->pm.active_crtcs & (1 << 1)) { |
| 402 | stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); | 403 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
| 403 | if (!(stat_crtc & 1)) | 404 | EVERGREEN_CRTC1_REGISTER_OFFSET) & 0xfff; |
| 404 | in_vbl = false; | 405 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
| 406 | EVERGREEN_CRTC1_REGISTER_OFFSET) & 0xfff; | ||
| 405 | } | 407 | } |
| 406 | if (rdev->pm.active_crtcs & (1 << 2)) { | 408 | if (rdev->pm.active_crtcs & (1 << 2)) { |
| 407 | stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); | 409 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
| 408 | if (!(stat_crtc & 1)) | 410 | EVERGREEN_CRTC2_REGISTER_OFFSET) & 0xfff; |
| 409 | in_vbl = false; | 411 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
| 412 | EVERGREEN_CRTC2_REGISTER_OFFSET) & 0xfff; | ||
| 410 | } | 413 | } |
| 411 | if (rdev->pm.active_crtcs & (1 << 3)) { | 414 | if (rdev->pm.active_crtcs & (1 << 3)) { |
| 412 | stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); | 415 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
| 413 | if (!(stat_crtc & 1)) | 416 | EVERGREEN_CRTC3_REGISTER_OFFSET) & 0xfff; |
| 414 | in_vbl = false; | 417 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
| 418 | EVERGREEN_CRTC3_REGISTER_OFFSET) & 0xfff; | ||
| 415 | } | 419 | } |
| 416 | if (rdev->pm.active_crtcs & (1 << 4)) { | 420 | if (rdev->pm.active_crtcs & (1 << 4)) { |
| 417 | stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); | 421 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
| 418 | if (!(stat_crtc & 1)) | 422 | EVERGREEN_CRTC4_REGISTER_OFFSET) & 0xfff; |
| 419 | in_vbl = false; | 423 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
| 424 | EVERGREEN_CRTC4_REGISTER_OFFSET) & 0xfff; | ||
| 420 | } | 425 | } |
| 421 | if (rdev->pm.active_crtcs & (1 << 5)) { | 426 | if (rdev->pm.active_crtcs & (1 << 5)) { |
| 422 | stat_crtc = RREG32(EVERGREEN_CRTC_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); | 427 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
| 423 | if (!(stat_crtc & 1)) | 428 | EVERGREEN_CRTC5_REGISTER_OFFSET) & 0xfff; |
| 424 | in_vbl = false; | 429 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
| 430 | EVERGREEN_CRTC5_REGISTER_OFFSET) & 0xfff; | ||
| 425 | } | 431 | } |
| 426 | } else if (ASIC_IS_AVIVO(rdev)) { | 432 | } else if (ASIC_IS_AVIVO(rdev)) { |
| 427 | if (rdev->pm.active_crtcs & (1 << 0)) { | 433 | if (rdev->pm.active_crtcs & (1 << 0)) { |
| 428 | stat_crtc = RREG32(D1CRTC_STATUS); | 434 | vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END) & 0xfff; |
| 429 | if (!(stat_crtc & 1)) | 435 | position = RREG32(AVIVO_D1CRTC_STATUS_POSITION) & 0xfff; |
| 430 | in_vbl = false; | ||
| 431 | } | 436 | } |
| 432 | if (rdev->pm.active_crtcs & (1 << 1)) { | 437 | if (rdev->pm.active_crtcs & (1 << 1)) { |
| 433 | stat_crtc = RREG32(D2CRTC_STATUS); | 438 | vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END) & 0xfff; |
| 434 | if (!(stat_crtc & 1)) | 439 | position = RREG32(AVIVO_D2CRTC_STATUS_POSITION) & 0xfff; |
| 435 | in_vbl = false; | ||
| 436 | } | 440 | } |
| 441 | if (position < vbl && position > 1) | ||
| 442 | in_vbl = false; | ||
| 437 | } else { | 443 | } else { |
| 438 | if (rdev->pm.active_crtcs & (1 << 0)) { | 444 | if (rdev->pm.active_crtcs & (1 << 0)) { |
| 439 | stat_crtc = RREG32(RADEON_CRTC_STATUS); | 445 | stat_crtc = RREG32(RADEON_CRTC_STATUS); |
| @@ -447,6 +453,9 @@ bool radeon_pm_in_vbl(struct radeon_device *rdev) | |||
| 447 | } | 453 | } |
| 448 | } | 454 | } |
| 449 | 455 | ||
| 456 | if (position < vbl && position > 1) | ||
| 457 | in_vbl = false; | ||
| 458 | |||
| 450 | return in_vbl; | 459 | return in_vbl; |
| 451 | } | 460 | } |
| 452 | 461 | ||
