aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2011-01-13 04:38:28 -0500
committerPaul Mundt <lethal@linux-sh.org>2011-01-13 04:38:28 -0500
commit8b6f08eaef16dfcfebc32fa9a017bf70336ad9ec (patch)
tree9f29f39de67b85baad5eca7d7165549a166c4367 /drivers/gpu/drm/i915/intel_display.c
parent4ae26f46c98f58ef19ad34f475617b40740d2faa (diff)
parent8a453cac94803910305f7e95cbd157b6bbd88811 (diff)
Merge branch 'sh/alphaproject' into sh-latest
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c434
1 files changed, 248 insertions, 186 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0abe79fb6385..25d96889d7d2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3418,15 +3418,16 @@ static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused,
3418static bool ironlake_compute_wm0(struct drm_device *dev, 3418static bool ironlake_compute_wm0(struct drm_device *dev,
3419 int pipe, 3419 int pipe,
3420 const struct intel_watermark_params *display, 3420 const struct intel_watermark_params *display,
3421 int display_latency, 3421 int display_latency_ns,
3422 const struct intel_watermark_params *cursor, 3422 const struct intel_watermark_params *cursor,
3423 int cursor_latency, 3423 int cursor_latency_ns,
3424 int *plane_wm, 3424 int *plane_wm,
3425 int *cursor_wm) 3425 int *cursor_wm)
3426{ 3426{
3427 struct drm_crtc *crtc; 3427 struct drm_crtc *crtc;
3428 int htotal, hdisplay, clock, pixel_size = 0; 3428 int htotal, hdisplay, clock, pixel_size;
3429 int line_time_us, line_count, entries; 3429 int line_time_us, line_count;
3430 int entries, tlb_miss;
3430 3431
3431 crtc = intel_get_crtc_for_pipe(dev, pipe); 3432 crtc = intel_get_crtc_for_pipe(dev, pipe);
3432 if (crtc->fb == NULL || !crtc->enabled) 3433 if (crtc->fb == NULL || !crtc->enabled)
@@ -3438,7 +3439,10 @@ static bool ironlake_compute_wm0(struct drm_device *dev,
3438 pixel_size = crtc->fb->bits_per_pixel / 8; 3439 pixel_size = crtc->fb->bits_per_pixel / 8;
3439 3440
3440 /* Use the small buffer method to calculate plane watermark */ 3441 /* Use the small buffer method to calculate plane watermark */
3441 entries = ((clock * pixel_size / 1000) * display_latency * 100) / 1000; 3442 entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
3443 tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8;
3444 if (tlb_miss > 0)
3445 entries += tlb_miss;
3442 entries = DIV_ROUND_UP(entries, display->cacheline_size); 3446 entries = DIV_ROUND_UP(entries, display->cacheline_size);
3443 *plane_wm = entries + display->guard_size; 3447 *plane_wm = entries + display->guard_size;
3444 if (*plane_wm > (int)display->max_wm) 3448 if (*plane_wm > (int)display->max_wm)
@@ -3446,8 +3450,11 @@ static bool ironlake_compute_wm0(struct drm_device *dev,
3446 3450
3447 /* Use the large buffer method to calculate cursor watermark */ 3451 /* Use the large buffer method to calculate cursor watermark */
3448 line_time_us = ((htotal * 1000) / clock); 3452 line_time_us = ((htotal * 1000) / clock);
3449 line_count = (cursor_latency * 100 / line_time_us + 1000) / 1000; 3453 line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
3450 entries = line_count * 64 * pixel_size; 3454 entries = line_count * 64 * pixel_size;
3455 tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
3456 if (tlb_miss > 0)
3457 entries += tlb_miss;
3451 entries = DIV_ROUND_UP(entries, cursor->cacheline_size); 3458 entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
3452 *cursor_wm = entries + cursor->guard_size; 3459 *cursor_wm = entries + cursor->guard_size;
3453 if (*cursor_wm > (int)cursor->max_wm) 3460 if (*cursor_wm > (int)cursor->max_wm)
@@ -3456,113 +3463,17 @@ static bool ironlake_compute_wm0(struct drm_device *dev,
3456 return true; 3463 return true;
3457} 3464}
3458 3465
3459static void ironlake_update_wm(struct drm_device *dev,
3460 int planea_clock, int planeb_clock,
3461 int sr_hdisplay, int sr_htotal,
3462 int pixel_size)
3463{
3464 struct drm_i915_private *dev_priv = dev->dev_private;
3465 int plane_wm, cursor_wm, enabled;
3466 int tmp;
3467
3468 enabled = 0;
3469 if (ironlake_compute_wm0(dev, 0,
3470 &ironlake_display_wm_info,
3471 ILK_LP0_PLANE_LATENCY,
3472 &ironlake_cursor_wm_info,
3473 ILK_LP0_CURSOR_LATENCY,
3474 &plane_wm, &cursor_wm)) {
3475 I915_WRITE(WM0_PIPEA_ILK,
3476 (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
3477 DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
3478 " plane %d, " "cursor: %d\n",
3479 plane_wm, cursor_wm);
3480 enabled++;
3481 }
3482
3483 if (ironlake_compute_wm0(dev, 1,
3484 &ironlake_display_wm_info,
3485 ILK_LP0_PLANE_LATENCY,
3486 &ironlake_cursor_wm_info,
3487 ILK_LP0_CURSOR_LATENCY,
3488 &plane_wm, &cursor_wm)) {
3489 I915_WRITE(WM0_PIPEB_ILK,
3490 (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
3491 DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
3492 " plane %d, cursor: %d\n",
3493 plane_wm, cursor_wm);
3494 enabled++;
3495 }
3496
3497 /*
3498 * Calculate and update the self-refresh watermark only when one
3499 * display plane is used.
3500 */
3501 tmp = 0;
3502 if (enabled == 1) {
3503 unsigned long line_time_us;
3504 int small, large, plane_fbc;
3505 int sr_clock, entries;
3506 int line_count, line_size;
3507 /* Read the self-refresh latency. The unit is 0.5us */
3508 int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK;
3509
3510 sr_clock = planea_clock ? planea_clock : planeb_clock;
3511 line_time_us = (sr_htotal * 1000) / sr_clock;
3512
3513 /* Use ns/us then divide to preserve precision */
3514 line_count = ((ilk_sr_latency * 500) / line_time_us + 1000)
3515 / 1000;
3516 line_size = sr_hdisplay * pixel_size;
3517
3518 /* Use the minimum of the small and large buffer method for primary */
3519 small = ((sr_clock * pixel_size / 1000) * (ilk_sr_latency * 500)) / 1000;
3520 large = line_count * line_size;
3521
3522 entries = DIV_ROUND_UP(min(small, large),
3523 ironlake_display_srwm_info.cacheline_size);
3524
3525 plane_fbc = entries * 64;
3526 plane_fbc = DIV_ROUND_UP(plane_fbc, line_size);
3527
3528 plane_wm = entries + ironlake_display_srwm_info.guard_size;
3529 if (plane_wm > (int)ironlake_display_srwm_info.max_wm)
3530 plane_wm = ironlake_display_srwm_info.max_wm;
3531
3532 /* calculate the self-refresh watermark for display cursor */
3533 entries = line_count * pixel_size * 64;
3534 entries = DIV_ROUND_UP(entries,
3535 ironlake_cursor_srwm_info.cacheline_size);
3536
3537 cursor_wm = entries + ironlake_cursor_srwm_info.guard_size;
3538 if (cursor_wm > (int)ironlake_cursor_srwm_info.max_wm)
3539 cursor_wm = ironlake_cursor_srwm_info.max_wm;
3540
3541 /* configure watermark and enable self-refresh */
3542 tmp = (WM1_LP_SR_EN |
3543 (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) |
3544 (plane_fbc << WM1_LP_FBC_SHIFT) |
3545 (plane_wm << WM1_LP_SR_SHIFT) |
3546 cursor_wm);
3547 DRM_DEBUG_KMS("self-refresh watermark: display plane %d, fbc lines %d,"
3548 " cursor %d\n", plane_wm, plane_fbc, cursor_wm);
3549 }
3550 I915_WRITE(WM1_LP_ILK, tmp);
3551 /* XXX setup WM2 and WM3 */
3552}
3553
3554/* 3466/*
3555 * Check the wm result. 3467 * Check the wm result.
3556 * 3468 *
3557 * If any calculated watermark values is larger than the maximum value that 3469 * If any calculated watermark values is larger than the maximum value that
3558 * can be programmed into the associated watermark register, that watermark 3470 * can be programmed into the associated watermark register, that watermark
3559 * must be disabled. 3471 * must be disabled.
3560 *
3561 * Also return true if all of those watermark values is 0, which is set by
3562 * sandybridge_compute_srwm, to indicate the latency is ZERO.
3563 */ 3472 */
3564static bool sandybridge_check_srwm(struct drm_device *dev, int level, 3473static bool ironlake_check_srwm(struct drm_device *dev, int level,
3565 int fbc_wm, int display_wm, int cursor_wm) 3474 int fbc_wm, int display_wm, int cursor_wm,
3475 const struct intel_watermark_params *display,
3476 const struct intel_watermark_params *cursor)
3566{ 3477{
3567 struct drm_i915_private *dev_priv = dev->dev_private; 3478 struct drm_i915_private *dev_priv = dev->dev_private;
3568 3479
@@ -3571,7 +3482,7 @@ static bool sandybridge_check_srwm(struct drm_device *dev, int level,
3571 3482
3572 if (fbc_wm > SNB_FBC_MAX_SRWM) { 3483 if (fbc_wm > SNB_FBC_MAX_SRWM) {
3573 DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n", 3484 DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n",
3574 fbc_wm, SNB_FBC_MAX_SRWM, level); 3485 fbc_wm, SNB_FBC_MAX_SRWM, level);
3575 3486
3576 /* fbc has it's own way to disable FBC WM */ 3487 /* fbc has it's own way to disable FBC WM */
3577 I915_WRITE(DISP_ARB_CTL, 3488 I915_WRITE(DISP_ARB_CTL,
@@ -3579,15 +3490,15 @@ static bool sandybridge_check_srwm(struct drm_device *dev, int level,
3579 return false; 3490 return false;
3580 } 3491 }
3581 3492
3582 if (display_wm > SNB_DISPLAY_MAX_SRWM) { 3493 if (display_wm > display->max_wm) {
3583 DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n", 3494 DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n",
3584 display_wm, SNB_DISPLAY_MAX_SRWM, level); 3495 display_wm, SNB_DISPLAY_MAX_SRWM, level);
3585 return false; 3496 return false;
3586 } 3497 }
3587 3498
3588 if (cursor_wm > SNB_CURSOR_MAX_SRWM) { 3499 if (cursor_wm > cursor->max_wm) {
3589 DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n", 3500 DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n",
3590 cursor_wm, SNB_CURSOR_MAX_SRWM, level); 3501 cursor_wm, SNB_CURSOR_MAX_SRWM, level);
3591 return false; 3502 return false;
3592 } 3503 }
3593 3504
@@ -3602,16 +3513,18 @@ static bool sandybridge_check_srwm(struct drm_device *dev, int level,
3602/* 3513/*
3603 * Compute watermark values of WM[1-3], 3514 * Compute watermark values of WM[1-3],
3604 */ 3515 */
3605static bool sandybridge_compute_srwm(struct drm_device *dev, int level, 3516static bool ironlake_compute_srwm(struct drm_device *dev, int level,
3606 int hdisplay, int htotal, int pixel_size, 3517 int hdisplay, int htotal,
3607 int clock, int latency_ns, int *fbc_wm, 3518 int pixel_size, int clock, int latency_ns,
3608 int *display_wm, int *cursor_wm) 3519 const struct intel_watermark_params *display,
3520 const struct intel_watermark_params *cursor,
3521 int *fbc_wm, int *display_wm, int *cursor_wm)
3609{ 3522{
3610 3523
3611 unsigned long line_time_us; 3524 unsigned long line_time_us;
3525 int line_count, line_size;
3612 int small, large; 3526 int small, large;
3613 int entries; 3527 int entries;
3614 int line_count, line_size;
3615 3528
3616 if (!latency_ns) { 3529 if (!latency_ns) {
3617 *fbc_wm = *display_wm = *cursor_wm = 0; 3530 *fbc_wm = *display_wm = *cursor_wm = 0;
@@ -3626,24 +3539,110 @@ static bool sandybridge_compute_srwm(struct drm_device *dev, int level,
3626 small = ((clock * pixel_size / 1000) * latency_ns) / 1000; 3539 small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
3627 large = line_count * line_size; 3540 large = line_count * line_size;
3628 3541
3629 entries = DIV_ROUND_UP(min(small, large), 3542 entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
3630 sandybridge_display_srwm_info.cacheline_size); 3543 *display_wm = entries + display->guard_size;
3631 *display_wm = entries + sandybridge_display_srwm_info.guard_size;
3632 3544
3633 /* 3545 /*
3634 * Spec said: 3546 * Spec says:
3635 * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2 3547 * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2
3636 */ 3548 */
3637 *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2; 3549 *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2;
3638 3550
3639 /* calculate the self-refresh watermark for display cursor */ 3551 /* calculate the self-refresh watermark for display cursor */
3640 entries = line_count * pixel_size * 64; 3552 entries = line_count * pixel_size * 64;
3641 entries = DIV_ROUND_UP(entries, 3553 entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
3642 sandybridge_cursor_srwm_info.cacheline_size); 3554 *cursor_wm = entries + cursor->guard_size;
3643 *cursor_wm = entries + sandybridge_cursor_srwm_info.guard_size;
3644 3555
3645 return sandybridge_check_srwm(dev, level, 3556 return ironlake_check_srwm(dev, level,
3646 *fbc_wm, *display_wm, *cursor_wm); 3557 *fbc_wm, *display_wm, *cursor_wm,
3558 display, cursor);
3559}
3560
3561static void ironlake_update_wm(struct drm_device *dev,
3562 int planea_clock, int planeb_clock,
3563 int hdisplay, int htotal,
3564 int pixel_size)
3565{
3566 struct drm_i915_private *dev_priv = dev->dev_private;
3567 int fbc_wm, plane_wm, cursor_wm, enabled;
3568 int clock;
3569
3570 enabled = 0;
3571 if (ironlake_compute_wm0(dev, 0,
3572 &ironlake_display_wm_info,
3573 ILK_LP0_PLANE_LATENCY,
3574 &ironlake_cursor_wm_info,
3575 ILK_LP0_CURSOR_LATENCY,
3576 &plane_wm, &cursor_wm)) {
3577 I915_WRITE(WM0_PIPEA_ILK,
3578 (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
3579 DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
3580 " plane %d, " "cursor: %d\n",
3581 plane_wm, cursor_wm);
3582 enabled++;
3583 }
3584
3585 if (ironlake_compute_wm0(dev, 1,
3586 &ironlake_display_wm_info,
3587 ILK_LP0_PLANE_LATENCY,
3588 &ironlake_cursor_wm_info,
3589 ILK_LP0_CURSOR_LATENCY,
3590 &plane_wm, &cursor_wm)) {
3591 I915_WRITE(WM0_PIPEB_ILK,
3592 (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
3593 DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
3594 " plane %d, cursor: %d\n",
3595 plane_wm, cursor_wm);
3596 enabled++;
3597 }
3598
3599 /*
3600 * Calculate and update the self-refresh watermark only when one
3601 * display plane is used.
3602 */
3603 I915_WRITE(WM3_LP_ILK, 0);
3604 I915_WRITE(WM2_LP_ILK, 0);
3605 I915_WRITE(WM1_LP_ILK, 0);
3606
3607 if (enabled != 1)
3608 return;
3609
3610 clock = planea_clock ? planea_clock : planeb_clock;
3611
3612 /* WM1 */
3613 if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
3614 clock, ILK_READ_WM1_LATENCY() * 500,
3615 &ironlake_display_srwm_info,
3616 &ironlake_cursor_srwm_info,
3617 &fbc_wm, &plane_wm, &cursor_wm))
3618 return;
3619
3620 I915_WRITE(WM1_LP_ILK,
3621 WM1_LP_SR_EN |
3622 (ILK_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
3623 (fbc_wm << WM1_LP_FBC_SHIFT) |
3624 (plane_wm << WM1_LP_SR_SHIFT) |
3625 cursor_wm);
3626
3627 /* WM2 */
3628 if (!ironlake_compute_srwm(dev, 2, hdisplay, htotal, pixel_size,
3629 clock, ILK_READ_WM2_LATENCY() * 500,
3630 &ironlake_display_srwm_info,
3631 &ironlake_cursor_srwm_info,
3632 &fbc_wm, &plane_wm, &cursor_wm))
3633 return;
3634
3635 I915_WRITE(WM2_LP_ILK,
3636 WM2_LP_EN |
3637 (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
3638 (fbc_wm << WM1_LP_FBC_SHIFT) |
3639 (plane_wm << WM1_LP_SR_SHIFT) |
3640 cursor_wm);
3641
3642 /*
3643 * WM3 is unsupported on ILK, probably because we don't have latency
3644 * data for that power state
3645 */
3647} 3646}
3648 3647
3649static void sandybridge_update_wm(struct drm_device *dev, 3648static void sandybridge_update_wm(struct drm_device *dev,
@@ -3652,7 +3651,7 @@ static void sandybridge_update_wm(struct drm_device *dev,
3652 int pixel_size) 3651 int pixel_size)
3653{ 3652{
3654 struct drm_i915_private *dev_priv = dev->dev_private; 3653 struct drm_i915_private *dev_priv = dev->dev_private;
3655 int latency = SNB_READ_WM0_LATENCY(); 3654 int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */
3656 int fbc_wm, plane_wm, cursor_wm, enabled; 3655 int fbc_wm, plane_wm, cursor_wm, enabled;
3657 int clock; 3656 int clock;
3658 3657
@@ -3701,9 +3700,11 @@ static void sandybridge_update_wm(struct drm_device *dev,
3701 clock = planea_clock ? planea_clock : planeb_clock; 3700 clock = planea_clock ? planea_clock : planeb_clock;
3702 3701
3703 /* WM1 */ 3702 /* WM1 */
3704 if (!sandybridge_compute_srwm(dev, 1, hdisplay, htotal, pixel_size, 3703 if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
3705 clock, SNB_READ_WM1_LATENCY() * 500, 3704 clock, SNB_READ_WM1_LATENCY() * 500,
3706 &fbc_wm, &plane_wm, &cursor_wm)) 3705 &sandybridge_display_srwm_info,
3706 &sandybridge_cursor_srwm_info,
3707 &fbc_wm, &plane_wm, &cursor_wm))
3707 return; 3708 return;
3708 3709
3709 I915_WRITE(WM1_LP_ILK, 3710 I915_WRITE(WM1_LP_ILK,
@@ -3714,10 +3715,12 @@ static void sandybridge_update_wm(struct drm_device *dev,
3714 cursor_wm); 3715 cursor_wm);
3715 3716
3716 /* WM2 */ 3717 /* WM2 */
3717 if (!sandybridge_compute_srwm(dev, 2, 3718 if (!ironlake_compute_srwm(dev, 2,
3718 hdisplay, htotal, pixel_size, 3719 hdisplay, htotal, pixel_size,
3719 clock, SNB_READ_WM2_LATENCY() * 500, 3720 clock, SNB_READ_WM2_LATENCY() * 500,
3720 &fbc_wm, &plane_wm, &cursor_wm)) 3721 &sandybridge_display_srwm_info,
3722 &sandybridge_cursor_srwm_info,
3723 &fbc_wm, &plane_wm, &cursor_wm))
3721 return; 3724 return;
3722 3725
3723 I915_WRITE(WM2_LP_ILK, 3726 I915_WRITE(WM2_LP_ILK,
@@ -3728,10 +3731,12 @@ static void sandybridge_update_wm(struct drm_device *dev,
3728 cursor_wm); 3731 cursor_wm);
3729 3732
3730 /* WM3 */ 3733 /* WM3 */
3731 if (!sandybridge_compute_srwm(dev, 3, 3734 if (!ironlake_compute_srwm(dev, 3,
3732 hdisplay, htotal, pixel_size, 3735 hdisplay, htotal, pixel_size,
3733 clock, SNB_READ_WM3_LATENCY() * 500, 3736 clock, SNB_READ_WM3_LATENCY() * 500,
3734 &fbc_wm, &plane_wm, &cursor_wm)) 3737 &sandybridge_display_srwm_info,
3738 &sandybridge_cursor_srwm_info,
3739 &fbc_wm, &plane_wm, &cursor_wm))
3735 return; 3740 return;
3736 3741
3737 I915_WRITE(WM3_LP_ILK, 3742 I915_WRITE(WM3_LP_ILK,
@@ -3951,7 +3956,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
3951 int lane = 0, link_bw, bpp; 3956 int lane = 0, link_bw, bpp;
3952 /* CPU eDP doesn't require FDI link, so just set DP M/N 3957 /* CPU eDP doesn't require FDI link, so just set DP M/N
3953 according to current link config */ 3958 according to current link config */
3954 if (has_edp_encoder && !intel_encoder_is_pch_edp(&encoder->base)) { 3959 if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
3955 target_clock = mode->clock; 3960 target_clock = mode->clock;
3956 intel_edp_link_config(has_edp_encoder, 3961 intel_edp_link_config(has_edp_encoder,
3957 &lane, &link_bw); 3962 &lane, &link_bw);
@@ -5038,8 +5043,8 @@ static void intel_increase_pllclock(struct drm_crtc *crtc)
5038 drm_i915_private_t *dev_priv = dev->dev_private; 5043 drm_i915_private_t *dev_priv = dev->dev_private;
5039 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 5044 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
5040 int pipe = intel_crtc->pipe; 5045 int pipe = intel_crtc->pipe;
5041 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; 5046 int dpll_reg = DPLL(pipe);
5042 int dpll = I915_READ(dpll_reg); 5047 int dpll;
5043 5048
5044 if (HAS_PCH_SPLIT(dev)) 5049 if (HAS_PCH_SPLIT(dev))
5045 return; 5050 return;
@@ -5047,17 +5052,19 @@ static void intel_increase_pllclock(struct drm_crtc *crtc)
5047 if (!dev_priv->lvds_downclock_avail) 5052 if (!dev_priv->lvds_downclock_avail)
5048 return; 5053 return;
5049 5054
5055 dpll = I915_READ(dpll_reg);
5050 if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) { 5056 if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
5051 DRM_DEBUG_DRIVER("upclocking LVDS\n"); 5057 DRM_DEBUG_DRIVER("upclocking LVDS\n");
5052 5058
5053 /* Unlock panel regs */ 5059 /* Unlock panel regs */
5054 I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | 5060 I915_WRITE(PP_CONTROL,
5055 PANEL_UNLOCK_REGS); 5061 I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
5056 5062
5057 dpll &= ~DISPLAY_RATE_SELECT_FPA1; 5063 dpll &= ~DISPLAY_RATE_SELECT_FPA1;
5058 I915_WRITE(dpll_reg, dpll); 5064 I915_WRITE(dpll_reg, dpll);
5059 dpll = I915_READ(dpll_reg); 5065 POSTING_READ(dpll_reg);
5060 intel_wait_for_vblank(dev, pipe); 5066 intel_wait_for_vblank(dev, pipe);
5067
5061 dpll = I915_READ(dpll_reg); 5068 dpll = I915_READ(dpll_reg);
5062 if (dpll & DISPLAY_RATE_SELECT_FPA1) 5069 if (dpll & DISPLAY_RATE_SELECT_FPA1)
5063 DRM_DEBUG_DRIVER("failed to upclock LVDS!\n"); 5070 DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
@@ -5802,6 +5809,8 @@ static void intel_setup_outputs(struct drm_device *dev)
5802 encoder->base.possible_clones = 5809 encoder->base.possible_clones =
5803 intel_encoder_clones(dev, encoder->clone_mask); 5810 intel_encoder_clones(dev, encoder->clone_mask);
5804 } 5811 }
5812
5813 intel_panel_setup_backlight(dev);
5805} 5814}
5806 5815
5807static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) 5816static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -6145,6 +6154,10 @@ void intel_init_emon(struct drm_device *dev)
6145 6154
6146void gen6_enable_rps(struct drm_i915_private *dev_priv) 6155void gen6_enable_rps(struct drm_i915_private *dev_priv)
6147{ 6156{
6157 u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
6158 u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
6159 u32 pcu_mbox;
6160 int cur_freq, min_freq, max_freq;
6148 int i; 6161 int i;
6149 6162
6150 /* Here begins a magic sequence of register writes to enable 6163 /* Here begins a magic sequence of register writes to enable
@@ -6216,6 +6229,29 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
6216 500)) 6229 500))
6217 DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); 6230 DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
6218 6231
6232 min_freq = (rp_state_cap & 0xff0000) >> 16;
6233 max_freq = rp_state_cap & 0xff;
6234 cur_freq = (gt_perf_status & 0xff00) >> 8;
6235
6236 /* Check for overclock support */
6237 if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
6238 500))
6239 DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
6240 I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_READ_OC_PARAMS);
6241 pcu_mbox = I915_READ(GEN6_PCODE_DATA);
6242 if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
6243 500))
6244 DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
6245 if (pcu_mbox & (1<<31)) { /* OC supported */
6246 max_freq = pcu_mbox & 0xff;
6247 DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 100);
6248 }
6249
6250 /* In units of 100MHz */
6251 dev_priv->max_delay = max_freq;
6252 dev_priv->min_delay = min_freq;
6253 dev_priv->cur_delay = cur_freq;
6254
6219 /* requires MSI enabled */ 6255 /* requires MSI enabled */
6220 I915_WRITE(GEN6_PMIER, 6256 I915_WRITE(GEN6_PMIER,
6221 GEN6_PM_MBOX_EVENT | 6257 GEN6_PM_MBOX_EVENT |
@@ -6386,42 +6422,6 @@ void intel_enable_clock_gating(struct drm_device *dev)
6386 } else if (IS_I830(dev)) { 6422 } else if (IS_I830(dev)) {
6387 I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); 6423 I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
6388 } 6424 }
6389
6390 /*
6391 * GPU can automatically power down the render unit if given a page
6392 * to save state.
6393 */
6394 if (IS_IRONLAKE_M(dev) && 0) { /* XXX causes a failure during suspend */
6395 if (dev_priv->renderctx == NULL)
6396 dev_priv->renderctx = intel_alloc_context_page(dev);
6397 if (dev_priv->renderctx) {
6398 struct drm_i915_gem_object *obj = dev_priv->renderctx;
6399 if (BEGIN_LP_RING(4) == 0) {
6400 OUT_RING(MI_SET_CONTEXT);
6401 OUT_RING(obj->gtt_offset |
6402 MI_MM_SPACE_GTT |
6403 MI_SAVE_EXT_STATE_EN |
6404 MI_RESTORE_EXT_STATE_EN |
6405 MI_RESTORE_INHIBIT);
6406 OUT_RING(MI_NOOP);
6407 OUT_RING(MI_FLUSH);
6408 ADVANCE_LP_RING();
6409 }
6410 } else
6411 DRM_DEBUG_KMS("Failed to allocate render context."
6412 "Disable RC6\n");
6413 }
6414
6415 if (IS_GEN4(dev) && IS_MOBILE(dev)) {
6416 if (dev_priv->pwrctx == NULL)
6417 dev_priv->pwrctx = intel_alloc_context_page(dev);
6418 if (dev_priv->pwrctx) {
6419 struct drm_i915_gem_object *obj = dev_priv->pwrctx;
6420 I915_WRITE(PWRCTXA, obj->gtt_offset | PWRCTX_EN);
6421 I915_WRITE(MCHBAR_RENDER_STANDBY,
6422 I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
6423 }
6424 }
6425} 6425}
6426 6426
6427void intel_disable_clock_gating(struct drm_device *dev) 6427void intel_disable_clock_gating(struct drm_device *dev)
@@ -6451,6 +6451,57 @@ void intel_disable_clock_gating(struct drm_device *dev)
6451 } 6451 }
6452} 6452}
6453 6453
6454static void ironlake_disable_rc6(struct drm_device *dev)
6455{
6456 struct drm_i915_private *dev_priv = dev->dev_private;
6457
6458 /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */
6459 I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT);
6460 wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON),
6461 10);
6462 POSTING_READ(CCID);
6463 I915_WRITE(PWRCTXA, 0);
6464 POSTING_READ(PWRCTXA);
6465 I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
6466 POSTING_READ(RSTDBYCTL);
6467 i915_gem_object_unpin(dev_priv->renderctx);
6468 drm_gem_object_unreference(&dev_priv->renderctx->base);
6469 dev_priv->renderctx = NULL;
6470 i915_gem_object_unpin(dev_priv->pwrctx);
6471 drm_gem_object_unreference(&dev_priv->pwrctx->base);
6472 dev_priv->pwrctx = NULL;
6473}
6474
6475void ironlake_enable_rc6(struct drm_device *dev)
6476{
6477 struct drm_i915_private *dev_priv = dev->dev_private;
6478 int ret;
6479
6480 /*
6481 * GPU can automatically power down the render unit if given a page
6482 * to save state.
6483 */
6484 ret = BEGIN_LP_RING(6);
6485 if (ret) {
6486 ironlake_disable_rc6(dev);
6487 return;
6488 }
6489 OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
6490 OUT_RING(MI_SET_CONTEXT);
6491 OUT_RING(dev_priv->renderctx->gtt_offset |
6492 MI_MM_SPACE_GTT |
6493 MI_SAVE_EXT_STATE_EN |
6494 MI_RESTORE_EXT_STATE_EN |
6495 MI_RESTORE_INHIBIT);
6496 OUT_RING(MI_SUSPEND_FLUSH);
6497 OUT_RING(MI_NOOP);
6498 OUT_RING(MI_FLUSH);
6499 ADVANCE_LP_RING();
6500
6501 I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN);
6502 I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
6503}
6504
6454/* Set up chip specific display functions */ 6505/* Set up chip specific display functions */
6455static void intel_init_display(struct drm_device *dev) 6506static void intel_init_display(struct drm_device *dev)
6456{ 6507{
@@ -6665,12 +6716,7 @@ void intel_modeset_init(struct drm_device *dev)
6665 dev->mode_config.max_width = 8192; 6716 dev->mode_config.max_width = 8192;
6666 dev->mode_config.max_height = 8192; 6717 dev->mode_config.max_height = 8192;
6667 } 6718 }
6668 6719 dev->mode_config.fb_base = dev->agp->base;
6669 /* set memory base */
6670 if (IS_GEN2(dev))
6671 dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0);
6672 else
6673 dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2);
6674 6720
6675 if (IS_MOBILE(dev) || !IS_GEN2(dev)) 6721 if (IS_MOBILE(dev) || !IS_GEN2(dev))
6676 dev_priv->num_pipe = 2; 6722 dev_priv->num_pipe = 2;
@@ -6698,6 +6744,21 @@ void intel_modeset_init(struct drm_device *dev)
6698 if (IS_GEN6(dev)) 6744 if (IS_GEN6(dev))
6699 gen6_enable_rps(dev_priv); 6745 gen6_enable_rps(dev_priv);
6700 6746
6747 if (IS_IRONLAKE_M(dev)) {
6748 dev_priv->renderctx = intel_alloc_context_page(dev);
6749 if (!dev_priv->renderctx)
6750 goto skip_rc6;
6751 dev_priv->pwrctx = intel_alloc_context_page(dev);
6752 if (!dev_priv->pwrctx) {
6753 i915_gem_object_unpin(dev_priv->renderctx);
6754 drm_gem_object_unreference(&dev_priv->renderctx->base);
6755 dev_priv->renderctx = NULL;
6756 goto skip_rc6;
6757 }
6758 ironlake_enable_rc6(dev);
6759 }
6760
6761skip_rc6:
6701 INIT_WORK(&dev_priv->idle_work, intel_idle_update); 6762 INIT_WORK(&dev_priv->idle_work, intel_idle_update);
6702 setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, 6763 setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
6703 (unsigned long)dev); 6764 (unsigned long)dev);
@@ -6734,7 +6795,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
6734 if (IS_GEN6(dev)) 6795 if (IS_GEN6(dev))
6735 gen6_disable_rps(dev); 6796 gen6_disable_rps(dev);
6736 6797
6737 intel_disable_clock_gating(dev); 6798 if (IS_IRONLAKE_M(dev))
6799 ironlake_disable_rc6(dev);
6738 6800
6739 mutex_unlock(&dev->struct_mutex); 6801 mutex_unlock(&dev->struct_mutex);
6740 6802