diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 64 |
1 files changed, 44 insertions, 20 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8e79ff67ec98..d0ce2a5b1d3f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -2270,10 +2270,33 @@ void ironlake_disable_drps(struct drm_device *dev) | |||
2270 | void gen6_set_rps(struct drm_device *dev, u8 val) | 2270 | void gen6_set_rps(struct drm_device *dev, u8 val) |
2271 | { | 2271 | { |
2272 | struct drm_i915_private *dev_priv = dev->dev_private; | 2272 | struct drm_i915_private *dev_priv = dev->dev_private; |
2273 | u32 swreq; | 2273 | u32 limits; |
2274 | 2274 | ||
2275 | swreq = (val & 0x3ff) << 25; | 2275 | limits = 0; |
2276 | I915_WRITE(GEN6_RPNSWREQ, swreq); | 2276 | if (val >= dev_priv->max_delay) |
2277 | val = dev_priv->max_delay; | ||
2278 | else | ||
2279 | limits |= dev_priv->max_delay << 24; | ||
2280 | |||
2281 | if (val <= dev_priv->min_delay) | ||
2282 | val = dev_priv->min_delay; | ||
2283 | else | ||
2284 | limits |= dev_priv->min_delay << 16; | ||
2285 | |||
2286 | if (val == dev_priv->cur_delay) | ||
2287 | return; | ||
2288 | |||
2289 | I915_WRITE(GEN6_RPNSWREQ, | ||
2290 | GEN6_FREQUENCY(val) | | ||
2291 | GEN6_OFFSET(0) | | ||
2292 | GEN6_AGGRESSIVE_TURBO); | ||
2293 | |||
2294 | /* Make sure we continue to get interrupts | ||
2295 | * until we hit the minimum or maximum frequencies. | ||
2296 | */ | ||
2297 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); | ||
2298 | |||
2299 | dev_priv->cur_delay = val; | ||
2277 | } | 2300 | } |
2278 | 2301 | ||
2279 | void gen6_disable_rps(struct drm_device *dev) | 2302 | void gen6_disable_rps(struct drm_device *dev) |
@@ -2327,11 +2350,10 @@ int intel_enable_rc6(const struct drm_device *dev) | |||
2327 | void gen6_enable_rps(struct drm_i915_private *dev_priv) | 2350 | void gen6_enable_rps(struct drm_i915_private *dev_priv) |
2328 | { | 2351 | { |
2329 | struct intel_ring_buffer *ring; | 2352 | struct intel_ring_buffer *ring; |
2330 | u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | 2353 | u32 rp_state_cap; |
2331 | u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); | 2354 | u32 gt_perf_status; |
2332 | u32 pcu_mbox, rc6_mask = 0; | 2355 | u32 pcu_mbox, rc6_mask = 0; |
2333 | u32 gtfifodbg; | 2356 | u32 gtfifodbg; |
2334 | int cur_freq, min_freq, max_freq; | ||
2335 | int rc6_mode; | 2357 | int rc6_mode; |
2336 | int i; | 2358 | int i; |
2337 | 2359 | ||
@@ -2352,6 +2374,14 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
2352 | 2374 | ||
2353 | gen6_gt_force_wake_get(dev_priv); | 2375 | gen6_gt_force_wake_get(dev_priv); |
2354 | 2376 | ||
2377 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | ||
2378 | gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); | ||
2379 | |||
2380 | /* In units of 100MHz */ | ||
2381 | dev_priv->max_delay = rp_state_cap & 0xff; | ||
2382 | dev_priv->min_delay = (rp_state_cap & 0xff0000) >> 16; | ||
2383 | dev_priv->cur_delay = 0; | ||
2384 | |||
2355 | /* disable the counters and set deterministic thresholds */ | 2385 | /* disable the counters and set deterministic thresholds */ |
2356 | I915_WRITE(GEN6_RC_CONTROL, 0); | 2386 | I915_WRITE(GEN6_RC_CONTROL, 0); |
2357 | 2387 | ||
@@ -2399,8 +2429,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
2399 | 2429 | ||
2400 | I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); | 2430 | I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); |
2401 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, | 2431 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, |
2402 | 18 << 24 | | 2432 | dev_priv->max_delay << 24 | |
2403 | 6 << 16); | 2433 | dev_priv->min_delay << 16); |
2404 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); | 2434 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); |
2405 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); | 2435 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); |
2406 | I915_WRITE(GEN6_RP_UP_EI, 100000); | 2436 | I915_WRITE(GEN6_RP_UP_EI, 100000); |
@@ -2408,7 +2438,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
2408 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); | 2438 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); |
2409 | I915_WRITE(GEN6_RP_CONTROL, | 2439 | I915_WRITE(GEN6_RP_CONTROL, |
2410 | GEN6_RP_MEDIA_TURBO | | 2440 | GEN6_RP_MEDIA_TURBO | |
2411 | GEN6_RP_MEDIA_HW_MODE | | 2441 | GEN6_RP_MEDIA_HW_NORMAL_MODE | |
2412 | GEN6_RP_MEDIA_IS_GFX | | 2442 | GEN6_RP_MEDIA_IS_GFX | |
2413 | GEN6_RP_ENABLE | | 2443 | GEN6_RP_ENABLE | |
2414 | GEN6_RP_UP_BUSY_AVG | | 2444 | GEN6_RP_UP_BUSY_AVG | |
@@ -2426,10 +2456,6 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
2426 | 500)) | 2456 | 500)) |
2427 | DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); | 2457 | DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); |
2428 | 2458 | ||
2429 | min_freq = (rp_state_cap & 0xff0000) >> 16; | ||
2430 | max_freq = rp_state_cap & 0xff; | ||
2431 | cur_freq = (gt_perf_status & 0xff00) >> 8; | ||
2432 | |||
2433 | /* Check for overclock support */ | 2459 | /* Check for overclock support */ |
2434 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, | 2460 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, |
2435 | 500)) | 2461 | 500)) |
@@ -2440,14 +2466,11 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
2440 | 500)) | 2466 | 500)) |
2441 | DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); | 2467 | DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); |
2442 | if (pcu_mbox & (1<<31)) { /* OC supported */ | 2468 | if (pcu_mbox & (1<<31)) { /* OC supported */ |
2443 | max_freq = pcu_mbox & 0xff; | 2469 | dev_priv->max_delay = pcu_mbox & 0xff; |
2444 | DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50); | 2470 | DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50); |
2445 | } | 2471 | } |
2446 | 2472 | ||
2447 | /* In units of 100MHz */ | 2473 | gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); |
2448 | dev_priv->max_delay = max_freq; | ||
2449 | dev_priv->min_delay = min_freq; | ||
2450 | dev_priv->cur_delay = cur_freq; | ||
2451 | 2474 | ||
2452 | /* requires MSI enabled */ | 2475 | /* requires MSI enabled */ |
2453 | I915_WRITE(GEN6_PMIER, | 2476 | I915_WRITE(GEN6_PMIER, |
@@ -3580,8 +3603,9 @@ static void gen6_sanitize_pm(struct drm_device *dev) | |||
3580 | limits |= (dev_priv->min_delay & 0x3f) << 16; | 3603 | limits |= (dev_priv->min_delay & 0x3f) << 16; |
3581 | 3604 | ||
3582 | if (old != limits) { | 3605 | if (old != limits) { |
3583 | DRM_ERROR("Power management discrepancy: GEN6_RP_INTERRUPT_LIMITS expected %08x, was %08x\n", | 3606 | /* Note that the known failure case is to read back 0. */ |
3584 | limits, old); | 3607 | DRM_DEBUG_DRIVER("Power management discrepancy: GEN6_RP_INTERRUPT_LIMITS " |
3608 | "expected %08x, was %08x\n", limits, old); | ||
3585 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); | 3609 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); |
3586 | } | 3610 | } |
3587 | 3611 | ||