diff options
author | Dave Airlie <airlied@redhat.com> | 2013-11-10 03:35:33 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-11-10 03:35:33 -0500 |
commit | ab0169bb5cc4a5c86756dde662087f9d12302eb0 (patch) | |
tree | 495e668337410f6763480ea1f010213f6399e38c /drivers/gpu/drm/i915/intel_pm.c | |
parent | 8d0a2215931f1ffd77aef65cae2c0becc3f5d560 (diff) | |
parent | 13b3a0a77625c09c84825ef6ba81d957ec207841 (diff) |
Merge tag 'bdw-stage1-2013-11-08-v2' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
So here's the Broadwell pull request. From a kernel driver pov there's
two areas with big changes in Broadwell:
- Completely new enumerated interrupt bits. On the plus side it now looks
fairly unform and sane.
- Completely new pagetable layout.
To ensure minimal impact on existing platforms we've refactored both the
irq and low-level gtt handling code a lot in anticipation of the bdw push.
So now bdw enabling in these areas just plugs in a bunch of vfuncs.
Otherwise it's all fairly harmless adjusting of switch cases and
if-ladders to shovel bdw into the right blocks. So minimized impact on
existing platforms. I've also merged the bdw-stage1 branch into our
-nightly integration branch for the past week to make sure we don't break
anything.
Note that there's still quite a flurry or patches floating around, but
I've figured I'll push this out. I plan to keep the bdw fixes separate
from my usual -fixes stream so that you can reject them easily in case it
still looks like too much churn. Also, bdw is for now hidden behind the
preliminary hw enabling module option. So there's no real pressure to get
follow-up patches all into 3.13.
* tag 'bdw-stage1-2013-11-08-v2' of git://people.freedesktop.org/~danvet/drm-intel: (75 commits)
drm/i915: Mask the vblank interrupt on bdw by default
drm/i915: Wire up cpu fifo underrun reporting support for bdw
drm/i915: Optimize gen8_enable|disable_vblank functions
drm/i915: Wire up pipe CRC support for bdw
drm/i915: Wire up PCH interrupts for bdw
drm/i915: Wire up port A aux channel
drm/i915: Fix up the bdw pipe interrupt enable lists
drm/i915: Optimize pipe irq handling on bdw
drm/i915/bdw: Take render error interrupt out of the mask
drm/i915/bdw: Add BDW PCH check first
drm/i915: Use hsw_crt_get_config on BDW
drm/i915/bdw: Change dp aux timeout to 600us on DDIA
drm/i915/bdw: Enable trickle feed on Broadwell
drm/i915/bdw: WaSingleSubspanDispatchOnAALinesAndPoints
drm/i915/bdw: conservative SBE VUE cache mode
drm/i915/bdw: Limit SDE poly depth FIFO to 2
drm/i915/bdw: Sampler power bypass disable
ddrm/i915/bdw: Disable centroid pixel perf optimization
drm/i915/bdw: BWGTLB clock gate disable
drm/i915/bdw: Implement edp PSR workarounds
...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 164 |
1 files changed, 152 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 09ac9e79830f..0a07d7c9cafc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -2291,7 +2291,9 @@ static uint32_t ilk_compute_fbc_wm(const struct hsw_pipe_wm_parameters *params, | |||
2291 | 2291 | ||
2292 | static unsigned int ilk_display_fifo_size(const struct drm_device *dev) | 2292 | static unsigned int ilk_display_fifo_size(const struct drm_device *dev) |
2293 | { | 2293 | { |
2294 | if (INTEL_INFO(dev)->gen >= 7) | 2294 | if (INTEL_INFO(dev)->gen >= 8) |
2295 | return 3072; | ||
2296 | else if (INTEL_INFO(dev)->gen >= 7) | ||
2295 | return 768; | 2297 | return 768; |
2296 | else | 2298 | else |
2297 | return 512; | 2299 | return 512; |
@@ -2336,7 +2338,9 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev, | |||
2336 | } | 2338 | } |
2337 | 2339 | ||
2338 | /* clamp to max that the registers can hold */ | 2340 | /* clamp to max that the registers can hold */ |
2339 | if (INTEL_INFO(dev)->gen >= 7) | 2341 | if (INTEL_INFO(dev)->gen >= 8) |
2342 | max = level == 0 ? 255 : 2047; | ||
2343 | else if (INTEL_INFO(dev)->gen >= 7) | ||
2340 | /* IVB/HSW primary/sprite plane watermarks */ | 2344 | /* IVB/HSW primary/sprite plane watermarks */ |
2341 | max = level == 0 ? 127 : 1023; | 2345 | max = level == 0 ? 127 : 1023; |
2342 | else if (!is_sprite) | 2346 | else if (!is_sprite) |
@@ -2366,10 +2370,13 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev, | |||
2366 | } | 2370 | } |
2367 | 2371 | ||
2368 | /* Calculate the maximum FBC watermark */ | 2372 | /* Calculate the maximum FBC watermark */ |
2369 | static unsigned int ilk_fbc_wm_max(void) | 2373 | static unsigned int ilk_fbc_wm_max(struct drm_device *dev) |
2370 | { | 2374 | { |
2371 | /* max that registers can hold */ | 2375 | /* max that registers can hold */ |
2372 | return 15; | 2376 | if (INTEL_INFO(dev)->gen >= 8) |
2377 | return 31; | ||
2378 | else | ||
2379 | return 15; | ||
2373 | } | 2380 | } |
2374 | 2381 | ||
2375 | static void ilk_compute_wm_maximums(struct drm_device *dev, | 2382 | static void ilk_compute_wm_maximums(struct drm_device *dev, |
@@ -2381,7 +2388,7 @@ static void ilk_compute_wm_maximums(struct drm_device *dev, | |||
2381 | max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false); | 2388 | max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false); |
2382 | max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true); | 2389 | max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true); |
2383 | max->cur = ilk_cursor_wm_max(dev, level, config); | 2390 | max->cur = ilk_cursor_wm_max(dev, level, config); |
2384 | max->fbc = ilk_fbc_wm_max(); | 2391 | max->fbc = ilk_fbc_wm_max(dev); |
2385 | } | 2392 | } |
2386 | 2393 | ||
2387 | static bool ilk_validate_wm_level(int level, | 2394 | static bool ilk_validate_wm_level(int level, |
@@ -2722,10 +2729,18 @@ static void hsw_compute_wm_results(struct drm_device *dev, | |||
2722 | if (!r->enable) | 2729 | if (!r->enable) |
2723 | break; | 2730 | break; |
2724 | 2731 | ||
2725 | results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2, | 2732 | results->wm_lp[wm_lp - 1] = WM3_LP_EN | |
2726 | r->fbc_val, | 2733 | ((level * 2) << WM1_LP_LATENCY_SHIFT) | |
2727 | r->pri_val, | 2734 | (r->pri_val << WM1_LP_SR_SHIFT) | |
2728 | r->cur_val); | 2735 | r->cur_val; |
2736 | |||
2737 | if (INTEL_INFO(dev)->gen >= 8) | ||
2738 | results->wm_lp[wm_lp - 1] |= | ||
2739 | r->fbc_val << WM1_LP_FBC_SHIFT_BDW; | ||
2740 | else | ||
2741 | results->wm_lp[wm_lp - 1] |= | ||
2742 | r->fbc_val << WM1_LP_FBC_SHIFT; | ||
2743 | |||
2729 | results->wm_lp_spr[wm_lp - 1] = r->spr_val; | 2744 | results->wm_lp_spr[wm_lp - 1] = r->spr_val; |
2730 | } | 2745 | } |
2731 | 2746 | ||
@@ -3747,6 +3762,78 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev) | |||
3747 | I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs); | 3762 | I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs); |
3748 | } | 3763 | } |
3749 | 3764 | ||
3765 | static void gen8_enable_rps(struct drm_device *dev) | ||
3766 | { | ||
3767 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
3768 | struct intel_ring_buffer *ring; | ||
3769 | uint32_t rc6_mask = 0, rp_state_cap; | ||
3770 | int unused; | ||
3771 | |||
3772 | /* 1a: Software RC state - RC0 */ | ||
3773 | I915_WRITE(GEN6_RC_STATE, 0); | ||
3774 | |||
3775 | /* 1c & 1d: Get forcewake during program sequence. Although the driver | ||
3776 | * hasn't enabled a state yet where we need forcewake, BIOS may have.*/ | ||
3777 | gen6_gt_force_wake_get(dev_priv); | ||
3778 | |||
3779 | /* 2a: Disable RC states. */ | ||
3780 | I915_WRITE(GEN6_RC_CONTROL, 0); | ||
3781 | |||
3782 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | ||
3783 | |||
3784 | /* 2b: Program RC6 thresholds.*/ | ||
3785 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); | ||
3786 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ | ||
3787 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ | ||
3788 | for_each_ring(ring, dev_priv, unused) | ||
3789 | I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); | ||
3790 | I915_WRITE(GEN6_RC_SLEEP, 0); | ||
3791 | I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ | ||
3792 | |||
3793 | /* 3: Enable RC6 */ | ||
3794 | if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) | ||
3795 | rc6_mask = GEN6_RC_CTL_RC6_ENABLE; | ||
3796 | DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off"); | ||
3797 | I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | | ||
3798 | GEN6_RC_CTL_EI_MODE(1) | | ||
3799 | rc6_mask); | ||
3800 | |||
3801 | /* 4 Program defaults and thresholds for RPS*/ | ||
3802 | I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */ | ||
3803 | I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(12)); /* Request 600 MHz */ | ||
3804 | /* NB: Docs say 1s, and 1000000 - which aren't equivalent */ | ||
3805 | I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */ | ||
3806 | |||
3807 | /* Docs recommend 900MHz, and 300 MHz respectively */ | ||
3808 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, | ||
3809 | dev_priv->rps.max_delay << 24 | | ||
3810 | dev_priv->rps.min_delay << 16); | ||
3811 | |||
3812 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 7600000 / 128); /* 76ms busyness per EI, 90% */ | ||
3813 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 31300000 / 128); /* 313ms busyness per EI, 70%*/ | ||
3814 | I915_WRITE(GEN6_RP_UP_EI, 66000); /* 84.48ms, XXX: random? */ | ||
3815 | I915_WRITE(GEN6_RP_DOWN_EI, 350000); /* 448ms, XXX: random? */ | ||
3816 | |||
3817 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); | ||
3818 | |||
3819 | /* 5: Enable RPS */ | ||
3820 | I915_WRITE(GEN6_RP_CONTROL, | ||
3821 | GEN6_RP_MEDIA_TURBO | | ||
3822 | GEN6_RP_MEDIA_HW_NORMAL_MODE | | ||
3823 | GEN6_RP_MEDIA_IS_GFX | | ||
3824 | GEN6_RP_ENABLE | | ||
3825 | GEN6_RP_UP_BUSY_AVG | | ||
3826 | GEN6_RP_DOWN_IDLE_AVG); | ||
3827 | |||
3828 | /* 6: Ring frequency + overclocking (our driver does this later */ | ||
3829 | |||
3830 | gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8); | ||
3831 | |||
3832 | gen6_enable_rps_interrupts(dev); | ||
3833 | |||
3834 | gen6_gt_force_wake_put(dev_priv); | ||
3835 | } | ||
3836 | |||
3750 | static void gen6_enable_rps(struct drm_device *dev) | 3837 | static void gen6_enable_rps(struct drm_device *dev) |
3751 | { | 3838 | { |
3752 | struct drm_i915_private *dev_priv = dev->dev_private; | 3839 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -3909,7 +3996,10 @@ void gen6_update_ring_freq(struct drm_device *dev) | |||
3909 | int diff = dev_priv->rps.max_delay - gpu_freq; | 3996 | int diff = dev_priv->rps.max_delay - gpu_freq; |
3910 | unsigned int ia_freq = 0, ring_freq = 0; | 3997 | unsigned int ia_freq = 0, ring_freq = 0; |
3911 | 3998 | ||
3912 | if (IS_HASWELL(dev)) { | 3999 | if (INTEL_INFO(dev)->gen >= 8) { |
4000 | /* max(2 * GT, DDR). NB: GT is 50MHz units */ | ||
4001 | ring_freq = max(min_ring_freq, gpu_freq); | ||
4002 | } else if (IS_HASWELL(dev)) { | ||
3913 | ring_freq = mult_frac(gpu_freq, 5, 4); | 4003 | ring_freq = mult_frac(gpu_freq, 5, 4); |
3914 | ring_freq = max(min_ring_freq, ring_freq); | 4004 | ring_freq = max(min_ring_freq, ring_freq); |
3915 | /* leave ia_freq as the default, chosen by cpufreq */ | 4005 | /* leave ia_freq as the default, chosen by cpufreq */ |
@@ -4873,6 +4963,9 @@ static void intel_gen6_powersave_work(struct work_struct *work) | |||
4873 | 4963 | ||
4874 | if (IS_VALLEYVIEW(dev)) { | 4964 | if (IS_VALLEYVIEW(dev)) { |
4875 | valleyview_enable_rps(dev); | 4965 | valleyview_enable_rps(dev); |
4966 | } else if (IS_BROADWELL(dev)) { | ||
4967 | gen8_enable_rps(dev); | ||
4968 | gen6_update_ring_freq(dev); | ||
4876 | } else { | 4969 | } else { |
4877 | gen6_enable_rps(dev); | 4970 | gen6_enable_rps(dev); |
4878 | gen6_update_ring_freq(dev); | 4971 | gen6_update_ring_freq(dev); |
@@ -5181,6 +5274,50 @@ static void lpt_suspend_hw(struct drm_device *dev) | |||
5181 | } | 5274 | } |
5182 | } | 5275 | } |
5183 | 5276 | ||
5277 | static void gen8_init_clock_gating(struct drm_device *dev) | ||
5278 | { | ||
5279 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
5280 | enum pipe i; | ||
5281 | |||
5282 | I915_WRITE(WM3_LP_ILK, 0); | ||
5283 | I915_WRITE(WM2_LP_ILK, 0); | ||
5284 | I915_WRITE(WM1_LP_ILK, 0); | ||
5285 | |||
5286 | /* FIXME(BDW): Check all the w/a, some might only apply to | ||
5287 | * pre-production hw. */ | ||
5288 | |||
5289 | WARN(!i915_preliminary_hw_support, | ||
5290 | "GEN8_CENTROID_PIXEL_OPT_DIS not be needed for production\n"); | ||
5291 | I915_WRITE(HALF_SLICE_CHICKEN3, | ||
5292 | _MASKED_BIT_ENABLE(GEN8_CENTROID_PIXEL_OPT_DIS)); | ||
5293 | I915_WRITE(HALF_SLICE_CHICKEN3, | ||
5294 | _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); | ||
5295 | I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE)); | ||
5296 | |||
5297 | I915_WRITE(_3D_CHICKEN3, | ||
5298 | _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2)); | ||
5299 | |||
5300 | I915_WRITE(COMMON_SLICE_CHICKEN2, | ||
5301 | _MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE)); | ||
5302 | |||
5303 | I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, | ||
5304 | _MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE)); | ||
5305 | |||
5306 | /* WaSwitchSolVfFArbitrationPriority */ | ||
5307 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); | ||
5308 | |||
5309 | /* WaPsrDPAMaskVBlankInSRD */ | ||
5310 | I915_WRITE(CHICKEN_PAR1_1, | ||
5311 | I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD); | ||
5312 | |||
5313 | /* WaPsrDPRSUnmaskVBlankInSRD */ | ||
5314 | for_each_pipe(i) { | ||
5315 | I915_WRITE(CHICKEN_PIPESL_1(i), | ||
5316 | I915_READ(CHICKEN_PIPESL_1(i) | | ||
5317 | DPRS_MASK_VBLANK_SRD)); | ||
5318 | } | ||
5319 | } | ||
5320 | |||
5184 | static void haswell_init_clock_gating(struct drm_device *dev) | 5321 | static void haswell_init_clock_gating(struct drm_device *dev) |
5185 | { | 5322 | { |
5186 | struct drm_i915_private *dev_priv = dev->dev_private; | 5323 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -5511,7 +5648,9 @@ static bool is_always_on_power_domain(struct drm_device *dev, | |||
5511 | 5648 | ||
5512 | BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK); | 5649 | BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK); |
5513 | 5650 | ||
5514 | if (IS_HASWELL(dev)) { | 5651 | if (IS_BROADWELL(dev)) { |
5652 | always_on_domains = BDW_ALWAYS_ON_POWER_DOMAINS; | ||
5653 | } else if (IS_HASWELL(dev)) { | ||
5515 | always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS; | 5654 | always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS; |
5516 | } else { | 5655 | } else { |
5517 | WARN_ON(1); | 5656 | WARN_ON(1); |
@@ -5833,6 +5972,8 @@ void intel_init_pm(struct drm_device *dev) | |||
5833 | dev_priv->display.update_wm = NULL; | 5972 | dev_priv->display.update_wm = NULL; |
5834 | } | 5973 | } |
5835 | dev_priv->display.init_clock_gating = haswell_init_clock_gating; | 5974 | dev_priv->display.init_clock_gating = haswell_init_clock_gating; |
5975 | } else if (INTEL_INFO(dev)->gen == 8) { | ||
5976 | dev_priv->display.init_clock_gating = gen8_init_clock_gating; | ||
5836 | } else | 5977 | } else |
5837 | dev_priv->display.update_wm = NULL; | 5978 | dev_priv->display.update_wm = NULL; |
5838 | } else if (IS_VALLEYVIEW(dev)) { | 5979 | } else if (IS_VALLEYVIEW(dev)) { |
@@ -5995,4 +6136,3 @@ void intel_pm_init(struct drm_device *dev) | |||
5995 | INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, | 6136 | INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, |
5996 | intel_gen6_powersave_work); | 6137 | intel_gen6_powersave_work); |
5997 | } | 6138 | } |
5998 | |||