aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c174
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
918static void assert_pipe(struct drm_i915_private *dev_priv, 918void 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
935static void assert_plane_enabled(struct drm_i915_private *dev_priv, 933static 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
4512static void sandybridge_update_wm(struct drm_device *dev) 4510void 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
4621static bool
4622sandybridge_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
4653static bool
4654sandybridge_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
4688static 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
4804void 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
4662static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) 4814static 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)
8827void intel_modeset_init(struct drm_device *dev) 8981void 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 */