aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h5
-rw-r--r--drivers/gpu/drm/i915/intel_display.c258
2 files changed, 133 insertions, 130 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 1bc816f3934b..ecfb0023f60d 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2345,8 +2345,13 @@
2345 2345
2346/* Memory latency timer register */ 2346/* Memory latency timer register */
2347#define MLTR_ILK 0x11222 2347#define MLTR_ILK 0x11222
2348#define MLTR_WM1_SHIFT 0
2349#define MLTR_WM2_SHIFT 8
2348/* the unit of memory self-refresh latency time is 0.5us */ 2350/* the unit of memory self-refresh latency time is 0.5us */
2349#define ILK_SRLT_MASK 0x3f 2351#define ILK_SRLT_MASK 0x3f
2352#define ILK_LATENCY(shift) (I915_READ(MLTR_ILK) >> (shift) & ILK_SRLT_MASK)
2353#define ILK_READ_WM1_LATENCY() ILK_LATENCY(MLTR_WM1_SHIFT)
2354#define ILK_READ_WM2_LATENCY() ILK_LATENCY(MLTR_WM2_SHIFT)
2350 2355
2351/* define the fifo size on Ironlake */ 2356/* define the fifo size on Ironlake */
2352#define ILK_DISPLAY_FIFO 128 2357#define ILK_DISPLAY_FIFO 128
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9d97fd4e5558..79753b8ac797 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3456,113 +3456,17 @@ static bool ironlake_compute_wm0(struct drm_device *dev,
3456 return true; 3456 return true;
3457} 3457}
3458 3458
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/* 3459/*
3555 * Check the wm result. 3460 * Check the wm result.
3556 * 3461 *
3557 * If any calculated watermark values is larger than the maximum value that 3462 * If any calculated watermark values is larger than the maximum value that
3558 * can be programmed into the associated watermark register, that watermark 3463 * can be programmed into the associated watermark register, that watermark
3559 * must be disabled. 3464 * 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 */ 3465 */
3564static bool sandybridge_check_srwm(struct drm_device *dev, int level, 3466static bool ironlake_check_srwm(struct drm_device *dev, int level,
3565 int fbc_wm, int display_wm, int cursor_wm) 3467 int fbc_wm, int display_wm, int cursor_wm,
3468 const struct intel_watermark_params *display,
3469 const struct intel_watermark_params *cursor)
3566{ 3470{
3567 struct drm_i915_private *dev_priv = dev->dev_private; 3471 struct drm_i915_private *dev_priv = dev->dev_private;
3568 3472
@@ -3571,7 +3475,7 @@ static bool sandybridge_check_srwm(struct drm_device *dev, int level,
3571 3475
3572 if (fbc_wm > SNB_FBC_MAX_SRWM) { 3476 if (fbc_wm > SNB_FBC_MAX_SRWM) {
3573 DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n", 3477 DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n",
3574 fbc_wm, SNB_FBC_MAX_SRWM, level); 3478 fbc_wm, SNB_FBC_MAX_SRWM, level);
3575 3479
3576 /* fbc has it's own way to disable FBC WM */ 3480 /* fbc has it's own way to disable FBC WM */
3577 I915_WRITE(DISP_ARB_CTL, 3481 I915_WRITE(DISP_ARB_CTL,
@@ -3579,15 +3483,15 @@ static bool sandybridge_check_srwm(struct drm_device *dev, int level,
3579 return false; 3483 return false;
3580 } 3484 }
3581 3485
3582 if (display_wm > SNB_DISPLAY_MAX_SRWM) { 3486 if (display_wm > display->max_wm) {
3583 DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n", 3487 DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n",
3584 display_wm, SNB_DISPLAY_MAX_SRWM, level); 3488 display_wm, SNB_DISPLAY_MAX_SRWM, level);
3585 return false; 3489 return false;
3586 } 3490 }
3587 3491
3588 if (cursor_wm > SNB_CURSOR_MAX_SRWM) { 3492 if (cursor_wm > cursor->max_wm) {
3589 DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n", 3493 DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n",
3590 cursor_wm, SNB_CURSOR_MAX_SRWM, level); 3494 cursor_wm, SNB_CURSOR_MAX_SRWM, level);
3591 return false; 3495 return false;
3592 } 3496 }
3593 3497
@@ -3602,16 +3506,18 @@ static bool sandybridge_check_srwm(struct drm_device *dev, int level,
3602/* 3506/*
3603 * Compute watermark values of WM[1-3], 3507 * Compute watermark values of WM[1-3],
3604 */ 3508 */
3605static bool sandybridge_compute_srwm(struct drm_device *dev, int level, 3509static bool ironlake_compute_srwm(struct drm_device *dev, int level,
3606 int hdisplay, int htotal, int pixel_size, 3510 int hdisplay, int htotal,
3607 int clock, int latency_ns, int *fbc_wm, 3511 int pixel_size, int clock, int latency_ns,
3608 int *display_wm, int *cursor_wm) 3512 const struct intel_watermark_params *display,
3513 const struct intel_watermark_params *cursor,
3514 int *fbc_wm, int *display_wm, int *cursor_wm)
3609{ 3515{
3610 3516
3611 unsigned long line_time_us; 3517 unsigned long line_time_us;
3518 int line_count, line_size;
3612 int small, large; 3519 int small, large;
3613 int entries; 3520 int entries;
3614 int line_count, line_size;
3615 3521
3616 if (!latency_ns) { 3522 if (!latency_ns) {
3617 *fbc_wm = *display_wm = *cursor_wm = 0; 3523 *fbc_wm = *display_wm = *cursor_wm = 0;
@@ -3626,24 +3532,110 @@ static bool sandybridge_compute_srwm(struct drm_device *dev, int level,
3626 small = ((clock * pixel_size / 1000) * latency_ns) / 1000; 3532 small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
3627 large = line_count * line_size; 3533 large = line_count * line_size;
3628 3534
3629 entries = DIV_ROUND_UP(min(small, large), 3535 entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
3630 sandybridge_display_srwm_info.cacheline_size); 3536 *display_wm = entries + display->guard_size;
3631 *display_wm = entries + sandybridge_display_srwm_info.guard_size;
3632 3537
3633 /* 3538 /*
3634 * Spec said: 3539 * Spec says:
3635 * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2 3540 * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2
3636 */ 3541 */
3637 *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2; 3542 *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2;
3638 3543
3639 /* calculate the self-refresh watermark for display cursor */ 3544 /* calculate the self-refresh watermark for display cursor */
3640 entries = line_count * pixel_size * 64; 3545 entries = line_count * pixel_size * 64;
3641 entries = DIV_ROUND_UP(entries, 3546 entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
3642 sandybridge_cursor_srwm_info.cacheline_size); 3547 *cursor_wm = entries + cursor->guard_size;
3643 *cursor_wm = entries + sandybridge_cursor_srwm_info.guard_size;
3644 3548
3645 return sandybridge_check_srwm(dev, level, 3549 return ironlake_check_srwm(dev, level,
3646 *fbc_wm, *display_wm, *cursor_wm); 3550 *fbc_wm, *display_wm, *cursor_wm,
3551 display, cursor);
3552}
3553
3554static void ironlake_update_wm(struct drm_device *dev,
3555 int planea_clock, int planeb_clock,
3556 int hdisplay, int htotal,
3557 int pixel_size)
3558{
3559 struct drm_i915_private *dev_priv = dev->dev_private;
3560 int fbc_wm, plane_wm, cursor_wm, enabled;
3561 int clock;
3562
3563 enabled = 0;
3564 if (ironlake_compute_wm0(dev, 0,
3565 &ironlake_display_wm_info,
3566 ILK_LP0_PLANE_LATENCY,
3567 &ironlake_cursor_wm_info,
3568 ILK_LP0_CURSOR_LATENCY,
3569 &plane_wm, &cursor_wm)) {
3570 I915_WRITE(WM0_PIPEA_ILK,
3571 (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
3572 DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
3573 " plane %d, " "cursor: %d\n",
3574 plane_wm, cursor_wm);
3575 enabled++;
3576 }
3577
3578 if (ironlake_compute_wm0(dev, 1,
3579 &ironlake_display_wm_info,
3580 ILK_LP0_PLANE_LATENCY,
3581 &ironlake_cursor_wm_info,
3582 ILK_LP0_CURSOR_LATENCY,
3583 &plane_wm, &cursor_wm)) {
3584 I915_WRITE(WM0_PIPEB_ILK,
3585 (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
3586 DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
3587 " plane %d, cursor: %d\n",
3588 plane_wm, cursor_wm);
3589 enabled++;
3590 }
3591
3592 /*
3593 * Calculate and update the self-refresh watermark only when one
3594 * display plane is used.
3595 */
3596 I915_WRITE(WM3_LP_ILK, 0);
3597 I915_WRITE(WM2_LP_ILK, 0);
3598 I915_WRITE(WM1_LP_ILK, 0);
3599
3600 if (enabled != 1)
3601 return;
3602
3603 clock = planea_clock ? planea_clock : planeb_clock;
3604
3605 /* WM1 */
3606 if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
3607 clock, ILK_READ_WM1_LATENCY() * 500,
3608 &ironlake_display_srwm_info,
3609 &ironlake_cursor_srwm_info,
3610 &fbc_wm, &plane_wm, &cursor_wm))
3611 return;
3612
3613 I915_WRITE(WM1_LP_ILK,
3614 WM1_LP_SR_EN |
3615 (ILK_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) |
3616 (fbc_wm << WM1_LP_FBC_SHIFT) |
3617 (plane_wm << WM1_LP_SR_SHIFT) |
3618 cursor_wm);
3619
3620 /* WM2 */
3621 if (!ironlake_compute_srwm(dev, 2, hdisplay, htotal, pixel_size,
3622 clock, ILK_READ_WM2_LATENCY() * 500,
3623 &ironlake_display_srwm_info,
3624 &ironlake_cursor_srwm_info,
3625 &fbc_wm, &plane_wm, &cursor_wm))
3626 return;
3627
3628 I915_WRITE(WM2_LP_ILK,
3629 WM2_LP_EN |
3630 (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
3631 (fbc_wm << WM1_LP_FBC_SHIFT) |
3632 (plane_wm << WM1_LP_SR_SHIFT) |
3633 cursor_wm);
3634
3635 /*
3636 * WM3 is unsupported on ILK, probably because we don't have latency
3637 * data for that power state
3638 */
3647} 3639}
3648 3640
3649static void sandybridge_update_wm(struct drm_device *dev, 3641static void sandybridge_update_wm(struct drm_device *dev,
@@ -3701,9 +3693,11 @@ static void sandybridge_update_wm(struct drm_device *dev,
3701 clock = planea_clock ? planea_clock : planeb_clock; 3693 clock = planea_clock ? planea_clock : planeb_clock;
3702 3694
3703 /* WM1 */ 3695 /* WM1 */
3704 if (!sandybridge_compute_srwm(dev, 1, hdisplay, htotal, pixel_size, 3696 if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
3705 clock, SNB_READ_WM1_LATENCY() * 500, 3697 clock, SNB_READ_WM1_LATENCY() * 500,
3706 &fbc_wm, &plane_wm, &cursor_wm)) 3698 &sandybridge_display_srwm_info,
3699 &sandybridge_cursor_srwm_info,
3700 &fbc_wm, &plane_wm, &cursor_wm))
3707 return; 3701 return;
3708 3702
3709 I915_WRITE(WM1_LP_ILK, 3703 I915_WRITE(WM1_LP_ILK,
@@ -3714,10 +3708,12 @@ static void sandybridge_update_wm(struct drm_device *dev,
3714 cursor_wm); 3708 cursor_wm);
3715 3709
3716 /* WM2 */ 3710 /* WM2 */
3717 if (!sandybridge_compute_srwm(dev, 2, 3711 if (!ironlake_compute_srwm(dev, 2,
3718 hdisplay, htotal, pixel_size, 3712 hdisplay, htotal, pixel_size,
3719 clock, SNB_READ_WM2_LATENCY() * 500, 3713 clock, SNB_READ_WM2_LATENCY() * 500,
3720 &fbc_wm, &plane_wm, &cursor_wm)) 3714 &sandybridge_display_srwm_info,
3715 &sandybridge_cursor_srwm_info,
3716 &fbc_wm, &plane_wm, &cursor_wm))
3721 return; 3717 return;
3722 3718
3723 I915_WRITE(WM2_LP_ILK, 3719 I915_WRITE(WM2_LP_ILK,
@@ -3728,10 +3724,12 @@ static void sandybridge_update_wm(struct drm_device *dev,
3728 cursor_wm); 3724 cursor_wm);
3729 3725
3730 /* WM3 */ 3726 /* WM3 */
3731 if (!sandybridge_compute_srwm(dev, 3, 3727 if (!ironlake_compute_srwm(dev, 3,
3732 hdisplay, htotal, pixel_size, 3728 hdisplay, htotal, pixel_size,
3733 clock, SNB_READ_WM3_LATENCY() * 500, 3729 clock, SNB_READ_WM3_LATENCY() * 500,
3734 &fbc_wm, &plane_wm, &cursor_wm)) 3730 &sandybridge_display_srwm_info,
3731 &sandybridge_cursor_srwm_info,
3732 &fbc_wm, &plane_wm, &cursor_wm))
3735 return; 3733 return;
3736 3734
3737 I915_WRITE(WM3_LP_ILK, 3735 I915_WRITE(WM3_LP_ILK,