diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 258 |
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 | ||
3459 | static 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 | */ |
3564 | static bool sandybridge_check_srwm(struct drm_device *dev, int level, | 3466 | static 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 | */ |
3605 | static bool sandybridge_compute_srwm(struct drm_device *dev, int level, | 3509 | static 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 | |||
3554 | static 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 | ||
3649 | static void sandybridge_update_wm(struct drm_device *dev, | 3641 | static 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, |