diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 174 |
1 files changed, 167 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ff99fa267bf6..30397b74a4a3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -915,8 +915,8 @@ static void assert_panel_unlocked(struct drm_i915_private *dev_priv, | |||
915 | pipe_name(pipe)); | 915 | pipe_name(pipe)); |
916 | } | 916 | } |
917 | 917 | ||
918 | static void assert_pipe(struct drm_i915_private *dev_priv, | 918 | void assert_pipe(struct drm_i915_private *dev_priv, |
919 | enum pipe pipe, bool state) | 919 | enum pipe pipe, bool state) |
920 | { | 920 | { |
921 | int reg; | 921 | int reg; |
922 | u32 val; | 922 | u32 val; |
@@ -929,8 +929,6 @@ static void assert_pipe(struct drm_i915_private *dev_priv, | |||
929 | "pipe %c assertion failure (expected %s, current %s)\n", | 929 | "pipe %c assertion failure (expected %s, current %s)\n", |
930 | pipe_name(pipe), state_string(state), state_string(cur_state)); | 930 | pipe_name(pipe), state_string(state), state_string(cur_state)); |
931 | } | 931 | } |
932 | #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) | ||
933 | #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) | ||
934 | 932 | ||
935 | static void assert_plane_enabled(struct drm_i915_private *dev_priv, | 933 | static void assert_plane_enabled(struct drm_i915_private *dev_priv, |
936 | enum plane plane) | 934 | enum plane plane) |
@@ -4509,7 +4507,7 @@ static void ironlake_update_wm(struct drm_device *dev) | |||
4509 | */ | 4507 | */ |
4510 | } | 4508 | } |
4511 | 4509 | ||
4512 | static void sandybridge_update_wm(struct drm_device *dev) | 4510 | void sandybridge_update_wm(struct drm_device *dev) |
4513 | { | 4511 | { |
4514 | struct drm_i915_private *dev_priv = dev->dev_private; | 4512 | struct drm_i915_private *dev_priv = dev->dev_private; |
4515 | int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ | 4513 | int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ |
@@ -4569,7 +4567,8 @@ static void sandybridge_update_wm(struct drm_device *dev) | |||
4569 | I915_WRITE(WM2_LP_ILK, 0); | 4567 | I915_WRITE(WM2_LP_ILK, 0); |
4570 | I915_WRITE(WM1_LP_ILK, 0); | 4568 | I915_WRITE(WM1_LP_ILK, 0); |
4571 | 4569 | ||
4572 | if (!single_plane_enabled(enabled)) | 4570 | if (!single_plane_enabled(enabled) || |
4571 | dev_priv->sprite_scaling_enabled) | ||
4573 | return; | 4572 | return; |
4574 | enabled = ffs(enabled) - 1; | 4573 | enabled = ffs(enabled) - 1; |
4575 | 4574 | ||
@@ -4619,6 +4618,149 @@ static void sandybridge_update_wm(struct drm_device *dev) | |||
4619 | cursor_wm); | 4618 | cursor_wm); |
4620 | } | 4619 | } |
4621 | 4620 | ||
4621 | static bool | ||
4622 | sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, | ||
4623 | uint32_t sprite_width, int pixel_size, | ||
4624 | const struct intel_watermark_params *display, | ||
4625 | int display_latency_ns, int *sprite_wm) | ||
4626 | { | ||
4627 | struct drm_crtc *crtc; | ||
4628 | int clock; | ||
4629 | int entries, tlb_miss; | ||
4630 | |||
4631 | crtc = intel_get_crtc_for_plane(dev, plane); | ||
4632 | if (crtc->fb == NULL || !crtc->enabled) { | ||
4633 | *sprite_wm = display->guard_size; | ||
4634 | return false; | ||
4635 | } | ||
4636 | |||
4637 | clock = crtc->mode.clock; | ||
4638 | |||
4639 | /* Use the small buffer method to calculate the sprite watermark */ | ||
4640 | entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; | ||
4641 | tlb_miss = display->fifo_size*display->cacheline_size - | ||
4642 | sprite_width * 8; | ||
4643 | if (tlb_miss > 0) | ||
4644 | entries += tlb_miss; | ||
4645 | entries = DIV_ROUND_UP(entries, display->cacheline_size); | ||
4646 | *sprite_wm = entries + display->guard_size; | ||
4647 | if (*sprite_wm > (int)display->max_wm) | ||
4648 | *sprite_wm = display->max_wm; | ||
4649 | |||
4650 | return true; | ||
4651 | } | ||
4652 | |||
4653 | static bool | ||
4654 | sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, | ||
4655 | uint32_t sprite_width, int pixel_size, | ||
4656 | const struct intel_watermark_params *display, | ||
4657 | int latency_ns, int *sprite_wm) | ||
4658 | { | ||
4659 | struct drm_crtc *crtc; | ||
4660 | unsigned long line_time_us; | ||
4661 | int clock; | ||
4662 | int line_count, line_size; | ||
4663 | int small, large; | ||
4664 | int entries; | ||
4665 | |||
4666 | if (!latency_ns) { | ||
4667 | *sprite_wm = 0; | ||
4668 | return false; | ||
4669 | } | ||
4670 | |||
4671 | crtc = intel_get_crtc_for_plane(dev, plane); | ||
4672 | clock = crtc->mode.clock; | ||
4673 | |||
4674 | line_time_us = (sprite_width * 1000) / clock; | ||
4675 | line_count = (latency_ns / line_time_us + 1000) / 1000; | ||
4676 | line_size = sprite_width * pixel_size; | ||
4677 | |||
4678 | /* Use the minimum of the small and large buffer method for primary */ | ||
4679 | small = ((clock * pixel_size / 1000) * latency_ns) / 1000; | ||
4680 | large = line_count * line_size; | ||
4681 | |||
4682 | entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); | ||
4683 | *sprite_wm = entries + display->guard_size; | ||
4684 | |||
4685 | return *sprite_wm > 0x3ff ? false : true; | ||
4686 | } | ||
4687 | |||
4688 | static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe, | ||
4689 | uint32_t sprite_width, int pixel_size) | ||
4690 | { | ||
4691 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
4692 | int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ | ||
4693 | int sprite_wm, reg; | ||
4694 | int ret; | ||
4695 | |||
4696 | switch (pipe) { | ||
4697 | case 0: | ||
4698 | reg = WM0_PIPEA_ILK; | ||
4699 | break; | ||
4700 | case 1: | ||
4701 | reg = WM0_PIPEB_ILK; | ||
4702 | break; | ||
4703 | case 2: | ||
4704 | reg = WM0_PIPEC_IVB; | ||
4705 | break; | ||
4706 | default: | ||
4707 | return; /* bad pipe */ | ||
4708 | } | ||
4709 | |||
4710 | ret = sandybridge_compute_sprite_wm(dev, pipe, sprite_width, pixel_size, | ||
4711 | &sandybridge_display_wm_info, | ||
4712 | latency, &sprite_wm); | ||
4713 | if (!ret) { | ||
4714 | DRM_DEBUG_KMS("failed to compute sprite wm for pipe %d\n", | ||
4715 | pipe); | ||
4716 | return; | ||
4717 | } | ||
4718 | |||
4719 | I915_WRITE(reg, I915_READ(reg) | (sprite_wm << WM0_PIPE_SPRITE_SHIFT)); | ||
4720 | DRM_DEBUG_KMS("sprite watermarks For pipe %d - %d\n", pipe, sprite_wm); | ||
4721 | |||
4722 | |||
4723 | ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, | ||
4724 | pixel_size, | ||
4725 | &sandybridge_display_srwm_info, | ||
4726 | SNB_READ_WM1_LATENCY() * 500, | ||
4727 | &sprite_wm); | ||
4728 | if (!ret) { | ||
4729 | DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %d\n", | ||
4730 | pipe); | ||
4731 | return; | ||
4732 | } | ||
4733 | I915_WRITE(WM1S_LP_ILK, sprite_wm); | ||
4734 | |||
4735 | /* Only IVB has two more LP watermarks for sprite */ | ||
4736 | if (!IS_IVYBRIDGE(dev)) | ||
4737 | return; | ||
4738 | |||
4739 | ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, | ||
4740 | pixel_size, | ||
4741 | &sandybridge_display_srwm_info, | ||
4742 | SNB_READ_WM2_LATENCY() * 500, | ||
4743 | &sprite_wm); | ||
4744 | if (!ret) { | ||
4745 | DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %d\n", | ||
4746 | pipe); | ||
4747 | return; | ||
4748 | } | ||
4749 | I915_WRITE(WM2S_LP_IVB, sprite_wm); | ||
4750 | |||
4751 | ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, | ||
4752 | pixel_size, | ||
4753 | &sandybridge_display_srwm_info, | ||
4754 | SNB_READ_WM3_LATENCY() * 500, | ||
4755 | &sprite_wm); | ||
4756 | if (!ret) { | ||
4757 | DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %d\n", | ||
4758 | pipe); | ||
4759 | return; | ||
4760 | } | ||
4761 | I915_WRITE(WM3S_LP_IVB, sprite_wm); | ||
4762 | } | ||
4763 | |||
4622 | /** | 4764 | /** |
4623 | * intel_update_watermarks - update FIFO watermark values based on current modes | 4765 | * intel_update_watermarks - update FIFO watermark values based on current modes |
4624 | * | 4766 | * |
@@ -4659,6 +4801,16 @@ static void intel_update_watermarks(struct drm_device *dev) | |||
4659 | dev_priv->display.update_wm(dev); | 4801 | dev_priv->display.update_wm(dev); |
4660 | } | 4802 | } |
4661 | 4803 | ||
4804 | void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, | ||
4805 | uint32_t sprite_width, int pixel_size) | ||
4806 | { | ||
4807 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
4808 | |||
4809 | if (dev_priv->display.update_sprite_wm) | ||
4810 | dev_priv->display.update_sprite_wm(dev, pipe, sprite_width, | ||
4811 | pixel_size); | ||
4812 | } | ||
4813 | |||
4662 | static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) | 4814 | static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) |
4663 | { | 4815 | { |
4664 | if (i915_panel_use_ssc >= 0) | 4816 | if (i915_panel_use_ssc >= 0) |
@@ -8631,6 +8783,7 @@ static void intel_init_display(struct drm_device *dev) | |||
8631 | } else if (IS_GEN6(dev)) { | 8783 | } else if (IS_GEN6(dev)) { |
8632 | if (SNB_READ_WM0_LATENCY()) { | 8784 | if (SNB_READ_WM0_LATENCY()) { |
8633 | dev_priv->display.update_wm = sandybridge_update_wm; | 8785 | dev_priv->display.update_wm = sandybridge_update_wm; |
8786 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; | ||
8634 | } else { | 8787 | } else { |
8635 | DRM_DEBUG_KMS("Failed to read display plane latency. " | 8788 | DRM_DEBUG_KMS("Failed to read display plane latency. " |
8636 | "Disable CxSR\n"); | 8789 | "Disable CxSR\n"); |
@@ -8644,6 +8797,7 @@ static void intel_init_display(struct drm_device *dev) | |||
8644 | dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; | 8797 | dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; |
8645 | if (SNB_READ_WM0_LATENCY()) { | 8798 | if (SNB_READ_WM0_LATENCY()) { |
8646 | dev_priv->display.update_wm = sandybridge_update_wm; | 8799 | dev_priv->display.update_wm = sandybridge_update_wm; |
8800 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; | ||
8647 | } else { | 8801 | } else { |
8648 | DRM_DEBUG_KMS("Failed to read display plane latency. " | 8802 | DRM_DEBUG_KMS("Failed to read display plane latency. " |
8649 | "Disable CxSR\n"); | 8803 | "Disable CxSR\n"); |
@@ -8827,7 +8981,7 @@ static void i915_disable_vga(struct drm_device *dev) | |||
8827 | void intel_modeset_init(struct drm_device *dev) | 8981 | void intel_modeset_init(struct drm_device *dev) |
8828 | { | 8982 | { |
8829 | struct drm_i915_private *dev_priv = dev->dev_private; | 8983 | struct drm_i915_private *dev_priv = dev->dev_private; |
8830 | int i; | 8984 | int i, ret; |
8831 | 8985 | ||
8832 | drm_mode_config_init(dev); | 8986 | drm_mode_config_init(dev); |
8833 | 8987 | ||
@@ -8857,6 +9011,12 @@ void intel_modeset_init(struct drm_device *dev) | |||
8857 | 9011 | ||
8858 | for (i = 0; i < dev_priv->num_pipe; i++) { | 9012 | for (i = 0; i < dev_priv->num_pipe; i++) { |
8859 | intel_crtc_init(dev, i); | 9013 | intel_crtc_init(dev, i); |
9014 | if (HAS_PCH_SPLIT(dev)) { | ||
9015 | ret = intel_plane_init(dev, i); | ||
9016 | if (ret) | ||
9017 | DRM_ERROR("plane %d init failed: %d\n", | ||
9018 | i, ret); | ||
9019 | } | ||
8860 | } | 9020 | } |
8861 | 9021 | ||
8862 | /* Just disable it once at startup */ | 9022 | /* Just disable it once at startup */ |