aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahesh Kumar <mahesh1.kumar@intel.com>2018-04-26 10:25:16 -0400
committerRodrigo Vivi <rodrigo.vivi@intel.com>2018-04-27 20:11:51 -0400
commitaa9664ffe863f470efdbe40ea20ce96f2887ebcd (patch)
treee903e51518892208579adadee50c0008aacfa34f
parent74bd8004e475d67eb41f6795cda5efac03d010b8 (diff)
drm/i915/icl: Enable 2nd DBuf slice only when needed
ICL has two slices of DBuf, each slice of size 1024 blocks. We should not always enable slice-2. It should be enabled only if display total required BW is > 12GBps OR more than 1 pipes are enabled. Changes since V1: - typecast total_data_rate to u64 before multiplication to solve any possible overflow (Rodrigo) - fix where skl_wm_get_hw_state was memsetting ddb, resulting enabled_slices to become zero - Fix the logic of calculating ddb_size Changes since V2: - If no-crtc is part of commit required_slices will have value "0", don't try to disable DBuf slice. Changes since V3: - Create a generic helper to enable/disable slice - don't return early if total_data_rate is 0, it may be cursor only commit, or atomic modeset without any plane. Changes since V4: - Solve checkpatch warnings - use kernel types u8/u64 instead of uint8_t/uint64_t Changes since V5: - Rebase Signed-off-by: Mahesh Kumar <mahesh1.kumar@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180426142517.16643-3-mahesh1.kumar@intel.com
-rw-r--r--drivers/gpu/drm/i915/intel_display.c10
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h6
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c57
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c65
4 files changed, 113 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 338570e61a1f..84ce66be88f2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12258,6 +12258,8 @@ static void skl_update_crtcs(struct drm_atomic_state *state)
12258 bool progress; 12258 bool progress;
12259 enum pipe pipe; 12259 enum pipe pipe;
12260 int i; 12260 int i;
12261 u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
12262 u8 required_slices = intel_state->wm_results.ddb.enabled_slices;
12261 12263
12262 const struct skl_ddb_entry *entries[I915_MAX_PIPES] = {}; 12264 const struct skl_ddb_entry *entries[I915_MAX_PIPES] = {};
12263 12265
@@ -12266,6 +12268,10 @@ static void skl_update_crtcs(struct drm_atomic_state *state)
12266 if (new_crtc_state->active) 12268 if (new_crtc_state->active)
12267 entries[i] = &to_intel_crtc_state(old_crtc_state)->wm.skl.ddb; 12269 entries[i] = &to_intel_crtc_state(old_crtc_state)->wm.skl.ddb;
12268 12270
12271 /* If 2nd DBuf slice required, enable it here */
12272 if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices)
12273 icl_dbuf_slices_update(dev_priv, required_slices);
12274
12269 /* 12275 /*
12270 * Whenever the number of active pipes changes, we need to make sure we 12276 * Whenever the number of active pipes changes, we need to make sure we
12271 * update the pipes in the right order so that their ddb allocations 12277 * update the pipes in the right order so that their ddb allocations
@@ -12316,6 +12322,10 @@ static void skl_update_crtcs(struct drm_atomic_state *state)
12316 progress = true; 12322 progress = true;
12317 } 12323 }
12318 } while (progress); 12324 } while (progress);
12325
12326 /* If 2nd DBuf slice is no more required disable it */
12327 if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices)
12328 icl_dbuf_slices_update(dev_priv, required_slices);
12319} 12329}
12320 12330
12321static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv) 12331static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9bba0354ccd3..11a1932cde6e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -144,6 +144,10 @@
144#define KHz(x) (1000 * (x)) 144#define KHz(x) (1000 * (x))
145#define MHz(x) KHz(1000 * (x)) 145#define MHz(x) KHz(1000 * (x))
146 146
147#define KBps(x) (1000 * (x))
148#define MBps(x) KBps(1000 * (x))
149#define GBps(x) ((u64)1000 * MBps((x)))
150
147/* 151/*
148 * Display related stuff 152 * Display related stuff
149 */ 153 */
@@ -1931,6 +1935,8 @@ bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
1931 enum intel_display_power_domain domain); 1935 enum intel_display_power_domain domain);
1932void intel_display_power_put(struct drm_i915_private *dev_priv, 1936void intel_display_power_put(struct drm_i915_private *dev_priv,
1933 enum intel_display_power_domain domain); 1937 enum intel_display_power_domain domain);
1938void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
1939 u8 req_slices);
1934 1940
1935static inline void 1941static inline void
1936assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv) 1942assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index a29e6d512771..3e72e9eb736e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3771,9 +3771,42 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state)
3771 return true; 3771 return true;
3772} 3772}
3773 3773
3774static unsigned int intel_get_ddb_size(struct drm_i915_private *dev_priv,
3775 const struct intel_crtc_state *cstate,
3776 const unsigned int total_data_rate,
3777 const int num_active,
3778 struct skl_ddb_allocation *ddb)
3779{
3780 const struct drm_display_mode *adjusted_mode;
3781 u64 total_data_bw;
3782 u16 ddb_size = INTEL_INFO(dev_priv)->ddb_size;
3783
3784 WARN_ON(ddb_size == 0);
3785
3786 if (INTEL_GEN(dev_priv) < 11)
3787 return ddb_size - 4; /* 4 blocks for bypass path allocation */
3788
3789 adjusted_mode = &cstate->base.adjusted_mode;
3790 total_data_bw = (u64)total_data_rate * drm_mode_vrefresh(adjusted_mode);
3791
3792 /*
3793 * 12GB/s is maximum BW supported by single DBuf slice.
3794 */
3795 if (total_data_bw >= GBps(12) || num_active > 1) {
3796 ddb->enabled_slices = 2;
3797 } else {
3798 ddb->enabled_slices = 1;
3799 ddb_size /= 2;
3800 }
3801
3802 return ddb_size;
3803}
3804
3774static void 3805static void
3775skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, 3806skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
3776 const struct intel_crtc_state *cstate, 3807 const struct intel_crtc_state *cstate,
3808 const unsigned int total_data_rate,
3809 struct skl_ddb_allocation *ddb,
3777 struct skl_ddb_entry *alloc, /* out */ 3810 struct skl_ddb_entry *alloc, /* out */
3778 int *num_active /* out */) 3811 int *num_active /* out */)
3779{ 3812{
@@ -3796,11 +3829,8 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
3796 else 3829 else
3797 *num_active = hweight32(dev_priv->active_crtcs); 3830 *num_active = hweight32(dev_priv->active_crtcs);
3798 3831
3799 ddb_size = INTEL_INFO(dev_priv)->ddb_size; 3832 ddb_size = intel_get_ddb_size(dev_priv, cstate, total_data_rate,
3800 WARN_ON(ddb_size == 0); 3833 *num_active, ddb);
3801
3802 if (INTEL_GEN(dev_priv) < 11)
3803 ddb_size -= 4; /* 4 blocks for bypass path allocation */
3804 3834
3805 /* 3835 /*
3806 * If the state doesn't change the active CRTC's, then there's 3836 * If the state doesn't change the active CRTC's, then there's
@@ -4261,7 +4291,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
4261 return 0; 4291 return 0;
4262 } 4292 }
4263 4293
4264 skl_ddb_get_pipe_allocation_limits(dev, cstate, alloc, &num_active); 4294 total_data_rate = skl_get_total_relative_data_rate(cstate,
4295 plane_data_rate,
4296 uv_plane_data_rate);
4297 skl_ddb_get_pipe_allocation_limits(dev, cstate, total_data_rate, ddb,
4298 alloc, &num_active);
4265 alloc_size = skl_ddb_entry_size(alloc); 4299 alloc_size = skl_ddb_entry_size(alloc);
4266 if (alloc_size == 0) 4300 if (alloc_size == 0)
4267 return 0; 4301 return 0;
@@ -4296,9 +4330,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
4296 * 4330 *
4297 * FIXME: we may not allocate every single block here. 4331 * FIXME: we may not allocate every single block here.
4298 */ 4332 */
4299 total_data_rate = skl_get_total_relative_data_rate(cstate,
4300 plane_data_rate,
4301 uv_plane_data_rate);
4302 if (total_data_rate == 0) 4333 if (total_data_rate == 0)
4303 return 0; 4334 return 0;
4304 4335
@@ -5492,8 +5523,12 @@ void skl_wm_get_hw_state(struct drm_device *dev)
5492 /* Fully recompute DDB on first atomic commit */ 5523 /* Fully recompute DDB on first atomic commit */
5493 dev_priv->wm.distrust_bios_wm = true; 5524 dev_priv->wm.distrust_bios_wm = true;
5494 } else { 5525 } else {
5495 /* Easy/common case; just sanitize DDB now if everything off */ 5526 /*
5496 memset(ddb, 0, sizeof(*ddb)); 5527 * Easy/common case; just sanitize DDB now if everything off
5528 * Keep dbuf slice info intact
5529 */
5530 memset(ddb->plane, 0, sizeof(ddb->plane));
5531 memset(ddb->uv_plane, 0, sizeof(ddb->uv_plane));
5497 } 5532 }
5498} 5533}
5499 5534
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index afc6ef81ca0c..3fffbfe4521d 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -2619,32 +2619,69 @@ static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
2619 mutex_unlock(&power_domains->lock); 2619 mutex_unlock(&power_domains->lock);
2620} 2620}
2621 2621
2622static void gen9_dbuf_enable(struct drm_i915_private *dev_priv) 2622static inline
2623bool intel_dbuf_slice_set(struct drm_i915_private *dev_priv,
2624 i915_reg_t reg, bool enable)
2623{ 2625{
2624 I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST); 2626 u32 val, status;
2625 POSTING_READ(DBUF_CTL);
2626 2627
2628 val = I915_READ(reg);
2629 val = enable ? (val | DBUF_POWER_REQUEST) : (val & ~DBUF_POWER_REQUEST);
2630 I915_WRITE(reg, val);
2631 POSTING_READ(reg);
2627 udelay(10); 2632 udelay(10);
2628 2633
2629 if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE)) 2634 status = I915_READ(reg) & DBUF_POWER_STATE;
2630 DRM_ERROR("DBuf power enable timeout\n"); 2635 if ((enable && !status) || (!enable && status)) {
2636 DRM_ERROR("DBus power %s timeout!\n",
2637 enable ? "enable" : "disable");
2638 return false;
2639 }
2640 return true;
2641}
2642
2643static void gen9_dbuf_enable(struct drm_i915_private *dev_priv)
2644{
2645 intel_dbuf_slice_set(dev_priv, DBUF_CTL, true);
2631} 2646}
2632 2647
2633static void gen9_dbuf_disable(struct drm_i915_private *dev_priv) 2648static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
2634{ 2649{
2635 I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST); 2650 intel_dbuf_slice_set(dev_priv, DBUF_CTL, false);
2636 POSTING_READ(DBUF_CTL); 2651}
2637 2652
2638 udelay(10); 2653static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
2654{
2655 if (INTEL_GEN(dev_priv) < 11)
2656 return 1;
2657 return 2;
2658}
2639 2659
2640 if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE) 2660void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
2641 DRM_ERROR("DBuf power disable timeout!\n"); 2661 u8 req_slices)
2662{
2663 u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
2664 u32 val;
2665 bool ret;
2666
2667 if (req_slices > intel_dbuf_max_slices(dev_priv)) {
2668 DRM_ERROR("Invalid number of dbuf slices requested\n");
2669 return;
2670 }
2671
2672 if (req_slices == hw_enabled_slices || req_slices == 0)
2673 return;
2674
2675 val = I915_READ(DBUF_CTL_S2);
2676 if (req_slices > hw_enabled_slices)
2677 ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, true);
2678 else
2679 ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, false);
2680
2681 if (ret)
2682 dev_priv->wm.skl_hw.ddb.enabled_slices = req_slices;
2642} 2683}
2643 2684
2644/*
2645 * TODO: we shouldn't always enable DBUF_CTL_S2, we should only enable it when
2646 * needed and keep it disabled as much as possible.
2647 */
2648static void icl_dbuf_enable(struct drm_i915_private *dev_priv) 2685static void icl_dbuf_enable(struct drm_i915_private *dev_priv)
2649{ 2686{
2650 I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST); 2687 I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST);