From 38807746fa2ce44b79957ff07813d10fcaf3d311 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Fri, 23 May 2014 21:00:15 +0530 Subject: drm/i915/chv: Enable Render Standby (RC6) for Cherryview v2: Configure PCBR if BIOS fails allocate pcbr (deepak) v3: Fix PCBR condition check during CHV RC6 Enable flag set v4: Fixup PCBR comment msg. (Chris) Rebase against latest code (Deak) Fixup Spurious hunk (Ben) v5: Fix PCBR and commentis msg (mika) v6: Rebase patch on latest nightly (Deepak) Signed-off-by: Deepak S Acked-by: Ben Widawsky Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 115 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 109 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d1e53abec1b..92092907808 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3341,6 +3341,13 @@ static void gen6_disable_rps(struct drm_device *dev) gen6_disable_rps_interrupts(dev); } +static void cherryview_disable_rps(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(GEN6_RC_CONTROL, 0); +} + static void valleyview_disable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3763,6 +3770,35 @@ static void valleyview_check_pctx(struct drm_i915_private *dev_priv) dev_priv->vlv_pctx->stolen->start); } + +/* Check that the pcbr address is not empty. */ +static void cherryview_check_pctx(struct drm_i915_private *dev_priv) +{ + unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095; + + WARN_ON((pctx_addr >> VLV_PCBR_ADDR_SHIFT) == 0); +} + +static void cherryview_setup_pctx(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long pctx_paddr, paddr; + struct i915_gtt *gtt = &dev_priv->gtt; + u32 pcbr; + int pctx_size = 32*1024; + + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + + pcbr = I915_READ(VLV_PCBR); + if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) { + paddr = (dev_priv->mm.stolen_base + + (gtt->stolen_size - pctx_size)); + + pctx_paddr = (paddr & (~4095)); + I915_WRITE(VLV_PCBR, pctx_paddr); + } +} + static void valleyview_setup_pctx(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3852,11 +3888,70 @@ static void valleyview_init_gt_powersave(struct drm_device *dev) mutex_unlock(&dev_priv->rps.hw_lock); } +static void cherryview_init_gt_powersave(struct drm_device *dev) +{ + cherryview_setup_pctx(dev); +} + static void valleyview_cleanup_gt_powersave(struct drm_device *dev) { valleyview_cleanup_pctx(dev); } +static void cherryview_enable_rps(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_engine_cs *ring; + u32 gtfifodbg, rc6_mode = 0, pcbr; + int i; + + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + + gtfifodbg = I915_READ(GTFIFODBG); + if (gtfifodbg) { + DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n", + gtfifodbg); + I915_WRITE(GTFIFODBG, gtfifodbg); + } + + cherryview_check_pctx(dev_priv); + + /* 1a & 1b: Get forcewake during program sequence. Although the driver + * hasn't enabled a state yet where we need forcewake, BIOS may have.*/ + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); + + /* 2a: Program RC6 thresholds.*/ + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); + I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ + I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ + + for_each_ring(ring, dev_priv, i) + I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + I915_WRITE(GEN6_RC_SLEEP, 0); + + I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ + + /* allows RC6 residency counter to work */ + I915_WRITE(VLV_COUNTER_CONTROL, + _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH | + VLV_MEDIA_RC6_COUNT_EN | + VLV_RENDER_RC6_COUNT_EN)); + + /* For now we assume BIOS is allocating and populating the PCBR */ + pcbr = I915_READ(VLV_PCBR); + + DRM_DEBUG_DRIVER("PCBR offset : 0x%x\n", pcbr); + + /* 3: Enable RC6 */ + if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) && + (pcbr >> VLV_PCBR_ADDR_SHIFT)) + rc6_mode = GEN6_RC_CTL_EI_MODE(1); + + I915_WRITE(GEN6_RC_CONTROL, rc6_mode); + + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); +} + static void valleyview_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -4665,13 +4760,17 @@ void intel_init_gt_powersave(struct drm_device *dev) { i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6); - if (IS_VALLEYVIEW(dev)) + if (IS_CHERRYVIEW(dev)) + cherryview_init_gt_powersave(dev); + else if (IS_VALLEYVIEW(dev)) valleyview_init_gt_powersave(dev); } void intel_cleanup_gt_powersave(struct drm_device *dev) { - if (IS_VALLEYVIEW(dev)) + if (IS_CHERRYVIEW(dev)) + return; + else if (IS_VALLEYVIEW(dev)) valleyview_cleanup_gt_powersave(dev); } @@ -4685,13 +4784,15 @@ void intel_disable_gt_powersave(struct drm_device *dev) if (IS_IRONLAKE_M(dev)) { ironlake_disable_drps(dev); ironlake_disable_rc6(dev); - } else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) { + } else if (INTEL_INFO(dev)->gen >= 6) { if (cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work)) intel_runtime_pm_put(dev_priv); cancel_work_sync(&dev_priv->rps.work); mutex_lock(&dev_priv->rps.hw_lock); - if (IS_VALLEYVIEW(dev)) + if (IS_CHERRYVIEW(dev)) + cherryview_disable_rps(dev); + else if (IS_VALLEYVIEW(dev)) valleyview_disable_rps(dev); else gen6_disable_rps(dev); @@ -4709,7 +4810,9 @@ static void intel_gen6_powersave_work(struct work_struct *work) mutex_lock(&dev_priv->rps.hw_lock); - if (IS_VALLEYVIEW(dev)) { + if (IS_CHERRYVIEW(dev)) { + cherryview_enable_rps(dev); + } else if (IS_VALLEYVIEW(dev)) { valleyview_enable_rps(dev); } else if (IS_BROADWELL(dev)) { gen8_enable_rps(dev); @@ -4734,7 +4837,7 @@ void intel_enable_gt_powersave(struct drm_device *dev) ironlake_enable_rc6(dev); intel_init_emon(dev); mutex_unlock(&dev->struct_mutex); - } else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) { + } else if (INTEL_INFO(dev)->gen >= 6) { /* * PCU communication is slow and this doesn't need to be * done at any specific time, so do this out of our fast path -- cgit v1.2.3-70-g09d2 From 2b6b3a09915f852ecca4317af6b55d2610e6b8d6 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Tue, 27 May 2014 15:59:30 +0530 Subject: drm/i915/chv: Enable RPS (Turbo) for Cherryview v2: Disable media turbo and Add DOWN_IDLE_AVG support (Ville) v3: Mass rename of the dev_priv->rps variables in upstream. v4: Rebase against latest code. (Deepak) v5: Rebase against latest nightly code. (Deepak) v6: Rename the variables to match the spec (Mika) v7: change min/max freq variable naming to match spec (Mika) Signed-off-by: Deepak S Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 11 +++++ drivers/gpu/drm/i915/intel_pm.c | 92 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 15653d47e07..53db3a2db3d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -529,6 +529,16 @@ enum punit_power_well { #define PUNIT_FUSE_BUS2 0xf6 /* bits 47:40 */ #define PUNIT_FUSE_BUS1 0xf5 /* bits 55:48 */ +#define PUNIT_GPU_STATUS_REG 0xdb +#define PUNIT_GPU_STATUS_MAX_FREQ_SHIFT 16 +#define PUNIT_GPU_STATUS_MAX_FREQ_MASK 0xff +#define PUNIT_GPU_STATIS_GFX_MIN_FREQ_SHIFT 8 +#define PUNIT_GPU_STATUS_GFX_MIN_FREQ_MASK 0xff + +#define PUNIT_GPU_DUTYCYCLE_REG 0xdf +#define PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT 8 +#define PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK 0xff + #define IOSF_NC_FB_GFX_FREQ_FUSE 0x1c #define FB_GFX_MAX_FREQ_FUSE_SHIFT 3 #define FB_GFX_MAX_FREQ_FUSE_MASK 0x000007f8 @@ -933,6 +943,7 @@ enum punit_power_well { #define SANDYBRIDGE_FENCE_PITCH_SHIFT 32 #define GEN7_FENCE_MAX_PITCH_VAL 0x0800 + /* control register for cpu gtt access */ #define TILECTL 0x101000 #define TILECTL_SWZCTL (1 << 0) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 92092907808..ee27d747701 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3731,6 +3731,35 @@ void gen6_update_ring_freq(struct drm_device *dev) mutex_unlock(&dev_priv->rps.hw_lock); } +int cherryview_rps_max_freq(struct drm_i915_private *dev_priv) +{ + u32 val, rp0; + + val = vlv_punit_read(dev_priv, PUNIT_GPU_STATUS_REG); + rp0 = (val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) & PUNIT_GPU_STATUS_MAX_FREQ_MASK; + + return rp0; +} + +static int cherryview_rps_rpe_freq(struct drm_i915_private *dev_priv) +{ + u32 val, rpe; + + val = vlv_punit_read(dev_priv, PUNIT_GPU_DUTYCYCLE_REG); + rpe = (val >> PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT) & PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK; + + return rpe; +} + +int cherryview_rps_min_freq(struct drm_i915_private *dev_priv) +{ + u32 val, rpn; + + val = vlv_punit_read(dev_priv, PUNIT_GPU_STATUS_REG); + rpn = (val >> PUNIT_GPU_STATIS_GFX_MIN_FREQ_SHIFT) & PUNIT_GPU_STATUS_GFX_MIN_FREQ_MASK; + return rpn; +} + int valleyview_rps_max_freq(struct drm_i915_private *dev_priv) { u32 val, rp0; @@ -3890,7 +3919,36 @@ static void valleyview_init_gt_powersave(struct drm_device *dev) static void cherryview_init_gt_powersave(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; + cherryview_setup_pctx(dev); + + mutex_lock(&dev_priv->rps.hw_lock); + + dev_priv->rps.max_freq = cherryview_rps_max_freq(dev_priv); + dev_priv->rps.rp0_freq = dev_priv->rps.max_freq; + DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n", + vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq), + dev_priv->rps.max_freq); + + dev_priv->rps.efficient_freq = cherryview_rps_rpe_freq(dev_priv); + DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n", + vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq), + dev_priv->rps.efficient_freq); + + dev_priv->rps.min_freq = cherryview_rps_min_freq(dev_priv); + DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n", + vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq), + dev_priv->rps.min_freq); + + /* Preserve min/max settings in case of re-init */ + if (dev_priv->rps.max_freq_softlimit == 0) + dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq; + + if (dev_priv->rps.min_freq_softlimit == 0) + dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq; + + mutex_unlock(&dev_priv->rps.hw_lock); } static void valleyview_cleanup_gt_powersave(struct drm_device *dev) @@ -3902,7 +3960,7 @@ static void cherryview_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; - u32 gtfifodbg, rc6_mode = 0, pcbr; + u32 gtfifodbg, val, rc6_mode = 0, pcbr; int i; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); @@ -3949,6 +4007,38 @@ static void cherryview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_CONTROL, rc6_mode); + /* 4 Program defaults and thresholds for RPS*/ + I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); + I915_WRITE(GEN6_RP_UP_EI, 66000); + I915_WRITE(GEN6_RP_DOWN_EI, 350000); + + I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + + /* 5: Enable RPS */ + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_AVG); + + val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); + + DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no"); + DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val); + + dev_priv->rps.cur_freq = (val >> 8) & 0xff; + DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n", + vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq), + dev_priv->rps.cur_freq); + + DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n", + vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq), + dev_priv->rps.efficient_freq); + + valleyview_set_rps(dev_priv->dev, dev_priv->rps.efficient_freq); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } -- cgit v1.2.3-70-g09d2 From 156c7ca08185886329113f20249446af4fb07f60 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 12 Jun 2014 08:35:45 -0700 Subject: drm/i915: leave rc6 enabled at suspend time v4 This allows the system to enter the lowest power mode during system freeze. v2: delete force wake timer at suspend (Imre) v3: add GT work suspend function (Imre) v4: use uncore forcewake reset (Daniel) Reviewed-by: Imre Deak Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 20 ++++++++++++++++++++ drivers/gpu/drm/i915/intel_uncore.c | 2 +- 5 files changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 458b778cd49..704dfe36c2e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -529,7 +529,7 @@ static int i915_drm_freeze(struct drm_device *dev) drm_irq_uninstall(dev); dev_priv->enable_hotplug_processing = false; - intel_disable_gt_powersave(dev); + intel_suspend_gt_powersave(dev); /* * Disable CRTCs directly since we want to preserve sw state @@ -548,8 +548,8 @@ static int i915_drm_freeze(struct drm_device *dev) i915_save_state(dev); + intel_uncore_forcewake_reset(dev, false); intel_opregion_fini(dev); - intel_uncore_fini(dev); console_lock(); intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 49414d30e8d..be4cd5e9653 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2085,6 +2085,7 @@ extern void intel_uncore_early_sanitize(struct drm_device *dev); extern void intel_uncore_init(struct drm_device *dev); extern void intel_uncore_check_errors(struct drm_device *dev); extern void intel_uncore_fini(struct drm_device *dev); +extern void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore); void i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bda0ae3d80c..a23b83d3bc0 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -961,6 +961,7 @@ void intel_init_gt_powersave(struct drm_device *dev); void intel_cleanup_gt_powersave(struct drm_device *dev); void intel_enable_gt_powersave(struct drm_device *dev); void intel_disable_gt_powersave(struct drm_device *dev); +void intel_suspend_gt_powersave(struct drm_device *dev); void intel_reset_gt_powersave(struct drm_device *dev); void ironlake_teardown_rc6(struct drm_device *dev); void gen6_update_ring_freq(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d1e53abec1b..685b4910eb9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4675,6 +4675,26 @@ void intel_cleanup_gt_powersave(struct drm_device *dev) valleyview_cleanup_gt_powersave(dev); } +/** + * intel_suspend_gt_powersave - suspend PM work and helper threads + * @dev: drm device + * + * We don't want to disable RC6 or other features here, we just want + * to make sure any work we've queued has finished and won't bother + * us while we're suspended. + */ +void intel_suspend_gt_powersave(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + /* Interrupts should be disabled already to avoid re-arming. */ + WARN_ON(dev->irq_enabled); + + flush_delayed_work(&dev_priv->rps.delayed_resume_work); + + cancel_work_sync(&dev_priv->rps.work); +} + void intel_disable_gt_powersave(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 79cba593df0..53e13ae6126 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -315,7 +315,7 @@ static void gen6_force_wake_timer(unsigned long arg) intel_runtime_pm_put(dev_priv); } -static void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) +void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) { struct drm_i915_private *dev_priv = dev->dev_private; unsigned long irqflags; -- cgit v1.2.3-70-g09d2 From 10d8d366790ff8da28c1853b2c795f3a74a4fdaa Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 12 Jun 2014 17:48:52 +0200 Subject: drm/i915: Unifiy GT powersave suspend logic Jesse's patch to only quiescent our rps work and Imre's fix to address a race with runtime pm and the forcewake reference held by the used diverging means to address the same bug: Jesse's patch uses flush_delayed_work while (since we want to make sure rps is set up) while Imre's used a cancel+manuel refcount adjustment. Unify them again by simply reusing intel_suspend_gt_powersave in intel_disable_gt_powersave. Cc: Imre Deak Cc: Jesse Barnes Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 685b4910eb9..49122204a00 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4706,10 +4706,8 @@ void intel_disable_gt_powersave(struct drm_device *dev) ironlake_disable_drps(dev); ironlake_disable_rc6(dev); } else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) { - if (cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work)) - intel_runtime_pm_put(dev_priv); + intel_suspend_gt_powersave(dev); - cancel_work_sync(&dev_priv->rps.work); mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev)) valleyview_disable_rps(dev); -- cgit v1.2.3-70-g09d2 From e0f0273eb9a61a99fed3e49c1e673bb73a45d8c7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 5 Jun 2014 19:15:50 +0300 Subject: drm/i915: Use named initializers for gmch wm params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using names initializers when filling out the watermark structs saves you from having go look up the struct definition every single time. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 130 ++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 65 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ee27d747701..f83d1ffad12 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -865,95 +865,95 @@ static int i845_get_fifo_size(struct drm_device *dev, int plane) /* Pineview has different values for various configs */ static const struct intel_watermark_params pineview_display_wm = { - PINEVIEW_DISPLAY_FIFO, - PINEVIEW_MAX_WM, - PINEVIEW_DFT_WM, - PINEVIEW_GUARD_WM, - PINEVIEW_FIFO_LINE_SIZE + .fifo_size = PINEVIEW_DISPLAY_FIFO, + .max_wm = PINEVIEW_MAX_WM, + .default_wm = PINEVIEW_DFT_WM, + .guard_size = PINEVIEW_GUARD_WM, + .cacheline_size = PINEVIEW_FIFO_LINE_SIZE, }; static const struct intel_watermark_params pineview_display_hplloff_wm = { - PINEVIEW_DISPLAY_FIFO, - PINEVIEW_MAX_WM, - PINEVIEW_DFT_HPLLOFF_WM, - PINEVIEW_GUARD_WM, - PINEVIEW_FIFO_LINE_SIZE + .fifo_size = PINEVIEW_DISPLAY_FIFO, + .max_wm = PINEVIEW_MAX_WM, + .default_wm = PINEVIEW_DFT_HPLLOFF_WM, + .guard_size = PINEVIEW_GUARD_WM, + .cacheline_size = PINEVIEW_FIFO_LINE_SIZE, }; static const struct intel_watermark_params pineview_cursor_wm = { - PINEVIEW_CURSOR_FIFO, - PINEVIEW_CURSOR_MAX_WM, - PINEVIEW_CURSOR_DFT_WM, - PINEVIEW_CURSOR_GUARD_WM, - PINEVIEW_FIFO_LINE_SIZE, + .fifo_size = PINEVIEW_CURSOR_FIFO, + .max_wm = PINEVIEW_CURSOR_MAX_WM, + .default_wm = PINEVIEW_CURSOR_DFT_WM, + .guard_size = PINEVIEW_CURSOR_GUARD_WM, + .cacheline_size = PINEVIEW_FIFO_LINE_SIZE, }; static const struct intel_watermark_params pineview_cursor_hplloff_wm = { - PINEVIEW_CURSOR_FIFO, - PINEVIEW_CURSOR_MAX_WM, - PINEVIEW_CURSOR_DFT_WM, - PINEVIEW_CURSOR_GUARD_WM, - PINEVIEW_FIFO_LINE_SIZE + .fifo_size = PINEVIEW_CURSOR_FIFO, + .max_wm = PINEVIEW_CURSOR_MAX_WM, + .default_wm = PINEVIEW_CURSOR_DFT_WM, + .guard_size = PINEVIEW_CURSOR_GUARD_WM, + .cacheline_size = PINEVIEW_FIFO_LINE_SIZE, }; static const struct intel_watermark_params g4x_wm_info = { - G4X_FIFO_SIZE, - G4X_MAX_WM, - G4X_MAX_WM, - 2, - G4X_FIFO_LINE_SIZE, + .fifo_size = G4X_FIFO_SIZE, + .max_wm = G4X_MAX_WM, + .default_wm = G4X_MAX_WM, + .guard_size = 2, + .cacheline_size = G4X_FIFO_LINE_SIZE, }; static const struct intel_watermark_params g4x_cursor_wm_info = { - I965_CURSOR_FIFO, - I965_CURSOR_MAX_WM, - I965_CURSOR_DFT_WM, - 2, - G4X_FIFO_LINE_SIZE, + .fifo_size = I965_CURSOR_FIFO, + .max_wm = I965_CURSOR_MAX_WM, + .default_wm = I965_CURSOR_DFT_WM, + .guard_size = 2, + .cacheline_size = G4X_FIFO_LINE_SIZE, }; static const struct intel_watermark_params valleyview_wm_info = { - VALLEYVIEW_FIFO_SIZE, - VALLEYVIEW_MAX_WM, - VALLEYVIEW_MAX_WM, - 2, - G4X_FIFO_LINE_SIZE, + .fifo_size = VALLEYVIEW_FIFO_SIZE, + .max_wm = VALLEYVIEW_MAX_WM, + .default_wm = VALLEYVIEW_MAX_WM, + .guard_size = 2, + .cacheline_size = G4X_FIFO_LINE_SIZE, }; static const struct intel_watermark_params valleyview_cursor_wm_info = { - I965_CURSOR_FIFO, - VALLEYVIEW_CURSOR_MAX_WM, - I965_CURSOR_DFT_WM, - 2, - G4X_FIFO_LINE_SIZE, + .fifo_size = I965_CURSOR_FIFO, + .max_wm = VALLEYVIEW_CURSOR_MAX_WM, + .default_wm = I965_CURSOR_DFT_WM, + .guard_size = 2, + .cacheline_size = G4X_FIFO_LINE_SIZE, }; static const struct intel_watermark_params i965_cursor_wm_info = { - I965_CURSOR_FIFO, - I965_CURSOR_MAX_WM, - I965_CURSOR_DFT_WM, - 2, - I915_FIFO_LINE_SIZE, + .fifo_size = I965_CURSOR_FIFO, + .max_wm = I965_CURSOR_MAX_WM, + .default_wm = I965_CURSOR_DFT_WM, + .guard_size = 2, + .cacheline_size = I915_FIFO_LINE_SIZE, }; static const struct intel_watermark_params i945_wm_info = { - I945_FIFO_SIZE, - I915_MAX_WM, - 1, - 2, - I915_FIFO_LINE_SIZE + .fifo_size = I945_FIFO_SIZE, + .max_wm = I915_MAX_WM, + .default_wm = 1, + .guard_size = 2, + .cacheline_size = I915_FIFO_LINE_SIZE, }; static const struct intel_watermark_params i915_wm_info = { - I915_FIFO_SIZE, - I915_MAX_WM, - 1, - 2, - I915_FIFO_LINE_SIZE + .fifo_size = I915_FIFO_SIZE, + .max_wm = I915_MAX_WM, + .default_wm = 1, + .guard_size = 2, + .cacheline_size = I915_FIFO_LINE_SIZE, }; static const struct intel_watermark_params i830_wm_info = { - I855GM_FIFO_SIZE, - I915_MAX_WM, - 1, - 2, - I830_FIFO_LINE_SIZE + .fifo_size = I855GM_FIFO_SIZE, + .max_wm = I915_MAX_WM, + .default_wm = 1, + .guard_size = 2, + .cacheline_size = I830_FIFO_LINE_SIZE, }; static const struct intel_watermark_params i845_wm_info = { - I830_FIFO_SIZE, - I915_MAX_WM, - 1, - 2, - I830_FIFO_LINE_SIZE + .fifo_size = I830_FIFO_SIZE, + .max_wm = I915_MAX_WM, + .default_wm = 1, + .guard_size = 2, + .cacheline_size = I830_FIFO_LINE_SIZE, }; /** -- cgit v1.2.3-70-g09d2 From 7405f42c790f123f5301dbd2a9ebb69ccd909f47 Mon Sep 17 00:00:00 2001 From: Tom O'Rourke Date: Tue, 10 Jun 2014 16:26:34 -0700 Subject: drm/i915/chv: Fix "drm/i915/chv: Add a bunch of pre production workarounds" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct a merge mishap in commit e4443e459ccf43f2c139358400365fd6a839d40d. Wa*:chv belongs in cherryview_enable_rps, not gen8_enable_rps. Signed-off-by: Tom O'Rourke Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f83d1ffad12..537a7ee8e5c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3513,15 +3513,11 @@ static void gen8_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); - /* WaDisablePwrmtrEvent:chv (pre-production hw) */ - I915_WRITE(0xA80C, I915_READ(0xA80C) & 0x00ffffff); - I915_WRITE(0xA810, I915_READ(0xA810) & 0xffffff00); - /* 5: Enable RPS */ I915_WRITE(GEN6_RP_CONTROL, GEN6_RP_MEDIA_TURBO | GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | /* WaSetMaskForGfxBusyness:chv (pre-production hw ?) */ + GEN6_RP_MEDIA_IS_GFX | GEN6_RP_ENABLE | GEN6_RP_UP_BUSY_AVG | GEN6_RP_DOWN_IDLE_AVG); @@ -4015,10 +4011,14 @@ static void cherryview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + /* WaDisablePwrmtrEvent:chv (pre-production hw) */ + I915_WRITE(0xA80C, I915_READ(0xA80C) & 0x00ffffff); + I915_WRITE(0xA810, I915_READ(0xA810) & 0xffffff00); + /* 5: Enable RPS */ I915_WRITE(GEN6_RP_CONTROL, GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_MEDIA_IS_GFX | /* WaSetMaskForGfxBusyness:chv (pre-production hw ?) */ GEN6_RP_ENABLE | GEN6_RP_UP_BUSY_AVG | GEN6_RP_DOWN_IDLE_AVG); -- cgit v1.2.3-70-g09d2 From 032843a5a5733cbb50daca20a76ead2c55d8f51a Mon Sep 17 00:00:00 2001 From: Daisy Sun Date: Mon, 16 Jun 2014 15:48:18 -0700 Subject: drm/i915: Broaden FBC resolution limit to 4096*4096 Staring from HSW, the resolution limit of FBC has increased to 4096*4096 Issue: VIZ-2813 Change-Id: I842f64e3cf2c0d18d29ef1bcfef3b9bb1f1764ac Signed-off-by: Daisy Sun Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 537a7ee8e5c..6cd11aaf0bb 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -530,7 +530,10 @@ void intel_update_fbc(struct drm_device *dev) goto out_disable; } - if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { + if (INTEL_INFO(dev)->gen >= 8 || IS_HASWELL(dev)) { + max_width = 4096; + max_height = 4096; + } else if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { max_width = 4096; max_height = 2048; } else { -- cgit v1.2.3-70-g09d2 From e11aa362308f5de467ce355a2a2471321b15a35c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 18 Jun 2014 09:52:55 -0700 Subject: drm/i915: use runtime irq suspend/resume in freeze/thaw We don't need to uninstall the full handler, simply disabling interrupts ought to be enough. Signed-off-by: Jesse Barnes Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 5 ++--- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7ae4e2a2049..be977414842 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -522,7 +522,7 @@ static int i915_drm_freeze(struct drm_device *dev) return error; } - drm_irq_uninstall(dev); + intel_runtime_pm_disable_interrupts(dev); dev_priv->enable_hotplug_processing = false; intel_suspend_gt_powersave(dev); @@ -646,8 +646,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) } mutex_unlock(&dev->struct_mutex); - /* We need working interrupts for modeset enabling ... */ - drm_irq_install(dev, dev->pdev->irq); + intel_runtime_pm_restore_interrupts(dev); intel_modeset_init_hw(dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8148d06b5b5..1cce0a59097 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4880,7 +4880,7 @@ void intel_suspend_gt_powersave(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; /* Interrupts should be disabled already to avoid re-arming. */ - WARN_ON(dev->irq_enabled); + WARN_ON(dev->irq_enabled && !dev_priv->pm.irqs_disabled); flush_delayed_work(&dev_priv->rps.delayed_resume_work); @@ -4892,7 +4892,7 @@ void intel_disable_gt_powersave(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; /* Interrupts should be disabled already to avoid re-arming. */ - WARN_ON(dev->irq_enabled); + WARN_ON(dev->irq_enabled && !dev_priv->pm.irqs_disabled); if (IS_IRONLAKE_M(dev)) { ironlake_disable_drps(dev); -- cgit v1.2.3-70-g09d2 From 0d68b25e9ceb344fe2f93373b1c0311d33814265 Mon Sep 17 00:00:00 2001 From: Tom O'Rourke Date: Wed, 9 Apr 2014 11:44:06 -0700 Subject: drm/i915/bdw: Use timeout mode for RC6 on bdw Higher RC6 residency is observed using timeout mode instead of EI mode. This applies to Broadwell only. The difference is particularly noticeable with video playback. Signed-off-by: Tom O'Rourke Reviewed-by: Ben Widawsky Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1cce0a59097..cb261457bfd 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3486,15 +3486,23 @@ static void gen8_enable_rps(struct drm_device *dev) for_each_ring(ring, dev_priv, unused) I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); - I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ + if (IS_BROADWELL(dev)) + I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */ + else + I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ /* 3: Enable RC6 */ if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) rc6_mask = GEN6_RC_CTL_RC6_ENABLE; intel_print_rc6_info(dev, rc6_mask); - I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | - GEN6_RC_CTL_EI_MODE(1) | - rc6_mask); + if (IS_BROADWELL(dev)) + I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | + GEN7_RC_CTL_TO_MODE | + rc6_mask); + else + I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | + GEN6_RC_CTL_EI_MODE(1) | + rc6_mask); /* 4 Program defaults and thresholds for RPS*/ I915_WRITE(GEN6_RPNSWREQ, -- cgit v1.2.3-70-g09d2 From 5e59f7175f96550ede91f58d267d2b551cb6fbba Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 30 Jun 2014 10:41:24 -0700 Subject: drm/i915: Try harder to get FBC The GEN FBC unit provides the ability to set a low pass on frames it attempts to compress. If a frame is less than a certain amount compressibility (2:1, 4:1) it will not bother. This allows the driver to reduce the size it requests out of stolen memory. Unluckily, a few months ago, Ville actually began using this feature for framebuffers that are 16bpp (not sure why not 8bpp). In those cases, we are already using this mechanism for a different purpose, and so we can only achieve one further level of compression (2:1 -> 4:1) FBC GEN1, ie. pre-G45 is ignored. The cleverness of the patch is Art's. The bugs are mine. v2: Update message and including missing threshold case 3 (Spotted by Arthur). Cc: Art Runyan Signed-off-by: Ben Widawsky Signed-off-by: Rodrigo Vivi Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 54 +++++++++++++++++++++++++--------- drivers/gpu/drm/i915/intel_pm.c | 30 +++++++++++++++++-- 3 files changed, 69 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7aeaaaabf30..07982e301b5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -600,6 +600,7 @@ struct intel_context { struct i915_fbc { unsigned long size; + unsigned threshold; unsigned int fb_id; enum plane plane; int y; @@ -2487,7 +2488,7 @@ static inline void i915_gem_chipset_flush(struct drm_device *dev) /* i915_gem_stolen.c */ int i915_gem_init_stolen(struct drm_device *dev); -int i915_gem_stolen_setup_compression(struct drm_device *dev, int size); +int i915_gem_stolen_setup_compression(struct drm_device *dev, int size, int fb_cpp); void i915_gem_stolen_cleanup_compression(struct drm_device *dev); void i915_gem_cleanup_stolen(struct drm_device *dev); struct drm_i915_gem_object * diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index a86b33193d9..b695d184c48 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -105,35 +105,61 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) static int find_compression_threshold(struct drm_device *dev, struct drm_mm_node *node, - int size) + int size, + int fb_cpp) { struct drm_i915_private *dev_priv = dev->dev_private; - const int compression_threshold = 1; + int compression_threshold = 1; int ret; - /* Try to over-allocate to reduce reallocations and fragmentation */ + /* HACK: This code depends on what we will do in *_enable_fbc. If that + * code changes, this code needs to change as well. + * + * The enable_fbc code will attempt to use one of our 2 compression + * thresholds, therefore, in that case, we only have 1 resort. + */ + + /* Try to over-allocate to reduce reallocations and fragmentation. */ ret = drm_mm_insert_node(&dev_priv->mm.stolen, node, size <<= 1, 4096, DRM_MM_SEARCH_DEFAULT); - if (ret) - ret = drm_mm_insert_node(&dev_priv->mm.stolen, node, - size >>= 1, 4096, - DRM_MM_SEARCH_DEFAULT); - if (ret) + if (ret == 0) + return compression_threshold; + +again: + /* HW's ability to limit the CFB is 1:4 */ + if (compression_threshold > 4 || + (fb_cpp == 2 && compression_threshold == 2)) return 0; - else + + ret = drm_mm_insert_node(&dev_priv->mm.stolen, node, + size >>= 1, 4096, + DRM_MM_SEARCH_DEFAULT); + if (ret && INTEL_INFO(dev)->gen <= 4) { + return 0; + } else if (ret) { + compression_threshold <<= 1; + goto again; + } else { return compression_threshold; + } } -static int i915_setup_compression(struct drm_device *dev, int size) +static int i915_setup_compression(struct drm_device *dev, int size, int fb_cpp) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_mm_node *uninitialized_var(compressed_llb); int ret; ret = find_compression_threshold(dev, &dev_priv->fbc.compressed_fb, - size); + size, fb_cpp); if (!ret) goto err_llb; + else if (ret > 1) { + DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n"); + + } + + dev_priv->fbc.threshold = ret; if (HAS_PCH_SPLIT(dev)) I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start); @@ -157,7 +183,7 @@ static int i915_setup_compression(struct drm_device *dev, int size) dev_priv->mm.stolen_base + compressed_llb->start); } - dev_priv->fbc.size = size; + dev_priv->fbc.size = size / dev_priv->fbc.threshold; DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n", size); @@ -172,7 +198,7 @@ err_llb: return -ENOSPC; } -int i915_gem_stolen_setup_compression(struct drm_device *dev, int size) +int i915_gem_stolen_setup_compression(struct drm_device *dev, int size, int fb_cpp) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -185,7 +211,7 @@ int i915_gem_stolen_setup_compression(struct drm_device *dev, int size) /* Release any current block */ i915_gem_stolen_cleanup_compression(dev); - return i915_setup_compression(dev, size); + return i915_setup_compression(dev, size, fb_cpp); } void i915_gem_stolen_cleanup_compression(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cb261457bfd..2ce96364bac 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -229,9 +229,20 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc) dpfc_ctl = DPFC_CTL_PLANE(intel_crtc->plane); if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) + dev_priv->fbc.threshold++; + + switch (dev_priv->fbc.threshold) { + case 4: + case 3: + dpfc_ctl |= DPFC_CTL_LIMIT_4X; + break; + case 2: dpfc_ctl |= DPFC_CTL_LIMIT_2X; - else + break; + case 1: dpfc_ctl |= DPFC_CTL_LIMIT_1X; + break; + } dpfc_ctl |= DPFC_CTL_FENCE_EN; if (IS_GEN5(dev)) dpfc_ctl |= obj->fence_reg; @@ -285,9 +296,21 @@ static void gen7_enable_fbc(struct drm_crtc *crtc) dpfc_ctl = IVB_DPFC_CTL_PLANE(intel_crtc->plane); if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) + dev_priv->fbc.threshold++; + + switch (dev_priv->fbc.threshold) { + case 4: + case 3: + dpfc_ctl |= DPFC_CTL_LIMIT_4X; + break; + case 2: dpfc_ctl |= DPFC_CTL_LIMIT_2X; - else + break; + case 1: dpfc_ctl |= DPFC_CTL_LIMIT_1X; + break; + } + dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); @@ -567,7 +590,8 @@ void intel_update_fbc(struct drm_device *dev) if (in_dbg_master()) goto out_disable; - if (i915_gem_stolen_setup_compression(dev, intel_fb->obj->base.size)) { + if (i915_gem_stolen_setup_compression(dev, intel_fb->obj->base.size, + drm_format_plane_cpp(fb->pixel_format, 0))) { if (set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL)) DRM_DEBUG_KMS("framebuffer too large, disabling compression\n"); goto out_disable; -- cgit v1.2.3-70-g09d2 From dfcab17e57aa784f174bc3f6beb6086f9956575a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Jun 2014 13:37:47 +0300 Subject: drm/i915: Change vlv cdclk to use kHz units MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use kHz units in vlv cdclk code since that's more customary. Also replace the precomputed 90% values with *9/10 computation for extra clarity. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 27 ++++++++++++++------------- drivers/gpu/drm/i915/intel_i2c.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 2 +- 3 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6d038c56746..11a303ecb05 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4465,6 +4465,7 @@ static void modeset_update_crtc_power_domains(struct drm_device *dev) intel_display_set_init_power(dev_priv, false); } +/* returns HPLL frequency in kHz */ int valleyview_get_vco(struct drm_i915_private *dev_priv) { int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; @@ -4475,7 +4476,7 @@ int valleyview_get_vco(struct drm_i915_private *dev_priv) CCK_FUSE_HPLL_FREQ_MASK; mutex_unlock(&dev_priv->dpio_lock); - return vco_freq[hpll_freq]; + return vco_freq[hpll_freq] * 1000; } /* Adjust CDclk dividers to allow high res or save power if possible */ @@ -4487,9 +4488,9 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) WARN_ON(valleyview_cur_cdclk(dev_priv) != dev_priv->vlv_cdclk_freq); dev_priv->vlv_cdclk_freq = cdclk; - if (cdclk >= 320) /* jump to highest voltage for 400MHz too */ + if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ cmd = 2; - else if (cdclk == 266) + else if (cdclk == 266667) cmd = 1; else cmd = 0; @@ -4506,11 +4507,11 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) } mutex_unlock(&dev_priv->rps.hw_lock); - if (cdclk == 400) { + if (cdclk == 400000) { u32 divider, vco; vco = valleyview_get_vco(dev_priv); - divider = ((vco << 1) / cdclk) - 1; + divider = DIV_ROUND_CLOSEST(vco << 1, cdclk) - 1; mutex_lock(&dev_priv->dpio_lock); /* adjust cdclk divider */ @@ -4530,7 +4531,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) * For high bandwidth configs, we set a higher latency in the bunit * so that the core display fetch happens in time to avoid underruns. */ - if (cdclk == 400) + if (cdclk == 400000) val |= 4500 / 250; /* 4.5 usec */ else val |= 3000 / 250; /* 3.0 usec */ @@ -4554,7 +4555,7 @@ int valleyview_cur_cdclk(struct drm_i915_private *dev_priv) divider &= 0xf; - cur_cdclk = (vco << 1) / (divider + 1); + cur_cdclk = DIV_ROUND_CLOSEST(vco << 1, divider + 1); return cur_cdclk; } @@ -4571,12 +4572,12 @@ static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, * So we check to see whether we're above 90% of the lower bin and * adjust if needed. */ - if (max_pixclk > 288000) { - return 400; - } else if (max_pixclk > 240000) { - return 320; - } else - return 266; + if (max_pixclk > 320000*9/10) + return 400000; + else if (max_pixclk > 266667*9/10) + return 320000; + else + return 266667; /* Looks like the 200MHz CDclk freq doesn't work on some configs */ } diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index d33b61d0dd3..9ce4f0945f9 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -86,7 +86,7 @@ static void gmbus_set_freq(struct drm_i915_private *dev_priv) BUG_ON(!IS_VALLEYVIEW(dev_priv->dev)); - vco = valleyview_get_vco(dev_priv); + vco = valleyview_get_vco(dev_priv) / 1000; /* Get the CDCLK divide ratio */ cdclk_div = get_disp_clk_div(dev_priv, CDCLK); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d2facba16aa..b907ee6f259 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5596,7 +5596,7 @@ static void valleyview_init_clock_gating(struct drm_device *dev) DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); dev_priv->vlv_cdclk_freq = valleyview_cur_cdclk(dev_priv); - DRM_DEBUG_DRIVER("Current CD clock rate: %d MHz", + DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz", dev_priv->vlv_cdclk_freq); I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE); -- cgit v1.2.3-70-g09d2 From d197b7d3480b5c9a3c33b224684fa942d76d1e59 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Jun 2014 13:37:49 +0300 Subject: drm/i915: Move vlv cdclk code to .get_display_clock_speed() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a standard hook for reading out the current cdclk. Move the VLV code from valleyview_cur_cdclk() to .get_display_clock_speed(). Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 33 +++++++++++++-------------------- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 2 +- 3 files changed, 14 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3feaaba3616..310218afe9c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4485,7 +4485,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) struct drm_i915_private *dev_priv = dev->dev_private; u32 val, cmd; - WARN_ON(valleyview_cur_cdclk(dev_priv) != dev_priv->vlv_cdclk_freq); + WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq); dev_priv->vlv_cdclk_freq = cdclk; if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ @@ -4542,24 +4542,6 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) intel_i2c_reset(dev); } -int valleyview_cur_cdclk(struct drm_i915_private *dev_priv) -{ - int cur_cdclk, vco; - int divider; - - vco = valleyview_get_vco(dev_priv); - - mutex_lock(&dev_priv->dpio_lock); - divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); - mutex_unlock(&dev_priv->dpio_lock); - - divider &= DISPLAY_FREQUENCY_VALUES; - - cur_cdclk = DIV_ROUND_CLOSEST(vco << 1, divider + 1); - - return cur_cdclk; -} - static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, int max_pixclk) { @@ -5269,7 +5251,18 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, static int valleyview_get_display_clock_speed(struct drm_device *dev) { - return 400000; /* FIXME */ + struct drm_i915_private *dev_priv = dev->dev_private; + int vco = valleyview_get_vco(dev_priv); + u32 val; + int divider; + + mutex_lock(&dev_priv->dpio_lock); + val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL); + mutex_unlock(&dev_priv->dpio_lock); + + divider = val & DISPLAY_FREQUENCY_VALUES; + + return DIV_ROUND_CLOSEST(vco << 1, divider + 1); } static int i945_get_display_clock_speed(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5f7c7bd94d9..056fca96b14 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -722,7 +722,6 @@ void intel_ddi_get_config(struct intel_encoder *encoder, const char *intel_output_name(int output); bool intel_has_pending_fb_unpin(struct drm_device *dev); int intel_pch_rawclk(struct drm_device *dev); -int valleyview_cur_cdclk(struct drm_i915_private *dev_priv); void intel_mark_busy(struct drm_device *dev); void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, struct intel_engine_cs *ring); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b907ee6f259..146101c9476 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5595,7 +5595,7 @@ static void valleyview_init_clock_gating(struct drm_device *dev) } DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); - dev_priv->vlv_cdclk_freq = valleyview_cur_cdclk(dev_priv); + dev_priv->vlv_cdclk_freq = dev_priv->display.get_display_clock_speed(dev); DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz", dev_priv->vlv_cdclk_freq); -- cgit v1.2.3-70-g09d2 From f8bf63fdcb1f82459dae7a3f22ee5ce92f3ea727 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Jun 2014 13:37:54 +0300 Subject: drm/i915: Kill duplicated cdclk readout code from i2c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a slightly different way of readoing out the cdclk in gmbus_set_freq(). Kill that and just call .get_display_clock_speed(). Also need to remove the GMBUSFREQ update from intel_i2c_reset() since that gets called way too early. Let's do it in intel_modeset_init_hw() instead, and also pull the initial vlv_cdclk_freq update there from init_clock gating. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 25 ++++++++++++++--- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_i2c.c | 54 ------------------------------------ drivers/gpu/drm/i915/intel_pm.c | 4 --- 4 files changed, 21 insertions(+), 63 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ac3ee2cee4b..5155811768c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4466,7 +4466,7 @@ static void modeset_update_crtc_power_domains(struct drm_device *dev) } /* returns HPLL frequency in kHz */ -int valleyview_get_vco(struct drm_i915_private *dev_priv) +static int valleyview_get_vco(struct drm_i915_private *dev_priv) { int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; @@ -4479,6 +4479,22 @@ int valleyview_get_vco(struct drm_i915_private *dev_priv) return vco_freq[hpll_freq] * 1000; } +static void vlv_update_cdclk(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + dev_priv->vlv_cdclk_freq = dev_priv->display.get_display_clock_speed(dev); + DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz", + dev_priv->vlv_cdclk_freq); + + /* + * Program the gmbus_freq based on the cdclk frequency. + * BSpec erroneously claims we should aim for 4MHz, but + * in fact 1MHz is the correct frequency. + */ + I915_WRITE(GMBUSFREQ_VLV, dev_priv->vlv_cdclk_freq); +} + /* Adjust CDclk dividers to allow high res or save power if possible */ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) { @@ -4486,7 +4502,6 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) u32 val, cmd; WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq); - dev_priv->vlv_cdclk_freq = cdclk; if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ cmd = 2; @@ -4543,8 +4558,7 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val); mutex_unlock(&dev_priv->dpio_lock); - /* Since we changed the CDclk, we need to update the GMBUSFREQ too */ - intel_i2c_reset(dev); + vlv_update_cdclk(dev); } static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, @@ -12440,6 +12454,9 @@ void intel_modeset_init_hw(struct drm_device *dev) { intel_prepare_ddi(dev); + if (IS_VALLEYVIEW(dev)) + vlv_update_cdclk(dev); + intel_init_clock_gating(dev); intel_reset_dpio(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 056fca96b14..4d4f735a8ad 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -830,7 +830,6 @@ void hsw_disable_ips(struct intel_crtc *crtc); void intel_display_set_init_power(struct drm_i915_private *dev, bool enable); enum intel_display_power_domain intel_display_port_power_domain(struct intel_encoder *intel_encoder); -int valleyview_get_vco(struct drm_i915_private *dev_priv); void intel_mode_from_pipe_config(struct drm_display_mode *mode, struct intel_crtc_config *pipe_config); int intel_format_to_fourcc(int format); diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 9ce4f0945f9..b31088a551f 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -34,11 +34,6 @@ #include #include "i915_drv.h" -enum disp_clk { - CDCLK, - CZCLK -}; - struct gmbus_port { const char *name; int reg; @@ -63,60 +58,11 @@ to_intel_gmbus(struct i2c_adapter *i2c) return container_of(i2c, struct intel_gmbus, adapter); } -static int get_disp_clk_div(struct drm_i915_private *dev_priv, - enum disp_clk clk) -{ - u32 reg_val; - int clk_ratio; - - reg_val = I915_READ(CZCLK_CDCLK_FREQ_RATIO); - - if (clk == CDCLK) - clk_ratio = - ((reg_val & CDCLK_FREQ_MASK) >> CDCLK_FREQ_SHIFT) + 1; - else - clk_ratio = (reg_val & CZCLK_FREQ_MASK) + 1; - - return clk_ratio; -} - -static void gmbus_set_freq(struct drm_i915_private *dev_priv) -{ - int vco, gmbus_freq = 0, cdclk_div; - - BUG_ON(!IS_VALLEYVIEW(dev_priv->dev)); - - vco = valleyview_get_vco(dev_priv) / 1000; - - /* Get the CDCLK divide ratio */ - cdclk_div = get_disp_clk_div(dev_priv, CDCLK); - - /* - * Program the gmbus_freq based on the cdclk frequency. - * BSpec erroneously claims we should aim for 4MHz, but - * in fact 1MHz is the correct frequency. - */ - if (cdclk_div) - gmbus_freq = (vco << 1) / cdclk_div; - - if (WARN_ON(gmbus_freq == 0)) - return; - - I915_WRITE(GMBUSFREQ_VLV, gmbus_freq); -} - void intel_i2c_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - /* - * In BIOS-less system, program the correct gmbus frequency - * before reading edid. - */ - if (IS_VALLEYVIEW(dev)) - gmbus_set_freq(dev_priv); - I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0); I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0); } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 146101c9476..719db710561 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5595,10 +5595,6 @@ static void valleyview_init_clock_gating(struct drm_device *dev) } DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); - dev_priv->vlv_cdclk_freq = dev_priv->display.get_display_clock_speed(dev); - DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz", - dev_priv->vlv_cdclk_freq); - I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE); /* WaDisableEarlyCull:vlv */ -- cgit v1.2.3-70-g09d2 From aa519f231d4ce3ad20932cbd2bb1aae4010ff6a5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Jun 2014 13:37:55 +0300 Subject: drm/i915: Pull the cmnlane tricks into its own power well ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the clutter in __vlv_set_power_well() by moving the cmnlane handling into custom enable/disable hooks for the cmnlane. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 92 ++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 37 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 719db710561..16a94e118df 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6013,31 +6013,9 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv, void __vlv_set_power_well(struct drm_i915_private *dev_priv, enum punit_power_well power_well_id, bool enable) { - struct drm_device *dev = dev_priv->dev; u32 mask; u32 state; u32 ctrl; - enum pipe pipe; - - if (power_well_id == PUNIT_POWER_WELL_DPIO_CMN_BC) { - if (enable) { - /* - * Enable the CRI clock source so we can get at the - * display and the reference clock for VGA - * hotplug / manual detection. - */ - I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | - DPLL_REFA_CLK_ENABLE_VLV | - DPLL_INTEGRATED_CRI_CLK_VLV); - udelay(1); /* >10ns for cmnreset, >0ns for sidereset */ - } else { - for_each_pipe(pipe) - assert_pll_disabled(dev_priv, pipe); - /* Assert common reset */ - I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) & - ~DPIO_CMNRST); - } - } mask = PUNIT_PWRGT_MASK(power_well_id); state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) : @@ -6065,20 +6043,6 @@ void __vlv_set_power_well(struct drm_i915_private *dev_priv, out: mutex_unlock(&dev_priv->rps.hw_lock); - - /* - * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx - - * 6. De-assert cmn_reset/side_reset. Same as VLV X0. - * a. GUnit 0x2110 bit[0] set to 1 (def 0) - * b. The other bits such as sfr settings / modesel may all - * be set to 0. - * - * This should only be done on init and resume from S3 with - * both PLLs disabled, or we risk losing DPIO and PLL - * synchronization. - */ - if (power_well_id == PUNIT_POWER_WELL_DPIO_CMN_BC && enable) - I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST); } static void vlv_set_power_well(struct drm_i915_private *dev_priv, @@ -6178,6 +6142,53 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv, vlv_set_power_well(dev_priv, power_well, false); } +static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC); + + /* + * Enable the CRI clock source so we can get at the + * display and the reference clock for VGA + * hotplug / manual detection. + */ + I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | + DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV); + udelay(1); /* >10ns for cmnreset, >0ns for sidereset */ + + vlv_set_power_well(dev_priv, power_well, true); + + /* + * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx - + * 6. De-assert cmn_reset/side_reset. Same as VLV X0. + * a. GUnit 0x2110 bit[0] set to 1 (def 0) + * b. The other bits such as sfr settings / modesel may all + * be set to 0. + * + * This should only be done on init and resume from S3 with + * both PLLs disabled, or we risk losing DPIO and PLL + * synchronization. + */ + I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST); +} + +static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + struct drm_device *dev = dev_priv->dev; + enum pipe pipe; + + WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC); + + for_each_pipe(pipe) + assert_pll_disabled(dev_priv, pipe); + + /* Assert common reset */ + I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) & ~DPIO_CMNRST); + + vlv_set_power_well(dev_priv, power_well, false); +} + static void check_power_well_state(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -6426,6 +6437,13 @@ static const struct i915_power_well_ops vlv_display_power_well_ops = { .is_enabled = vlv_power_well_enabled, }; +static const struct i915_power_well_ops vlv_dpio_cmn_power_well_ops = { + .sync_hw = vlv_power_well_sync_hw, + .enable = vlv_dpio_cmn_power_well_enable, + .disable = vlv_dpio_cmn_power_well_disable, + .is_enabled = vlv_power_well_enabled, +}; + static const struct i915_power_well_ops vlv_dpio_power_well_ops = { .sync_hw = vlv_power_well_sync_hw, .enable = vlv_power_well_enable, @@ -6486,7 +6504,7 @@ static struct i915_power_well vlv_power_wells[] = { .name = "dpio-common", .domains = VLV_DPIO_CMN_BC_POWER_DOMAINS, .data = PUNIT_POWER_WELL_DPIO_CMN_BC, - .ops = &vlv_dpio_power_well_ops, + .ops = &vlv_dpio_cmn_power_well_ops, }, }; -- cgit v1.2.3-70-g09d2 From d2011dc8d41b20dc0ec0bf741c61fe500dc8d0bc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Jun 2014 13:37:56 +0300 Subject: drm/i915: Move VLV cmnlane workaround to intel_power_domains_init_hw() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the CMNRESET deassert is part of the cmnlane power well, intel_reset_dpio() is called too late to make any difference. We've deasserted CMNRESET by that time, and so the off+on toggle w/a will never kick in. Move the workaround to intel_power_domains_init_hw() where it gets called before we enable the init power domain. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 23 ------------- drivers/gpu/drm/i915/intel_drv.h | 3 +- drivers/gpu/drm/i915/intel_pm.c | 67 ++++++++++++++++++++++++++++++------ 3 files changed, 58 insertions(+), 35 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5155811768c..d675df8b268 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1514,9 +1514,6 @@ static void intel_reset_dpio(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (!IS_VALLEYVIEW(dev)) - return; - if (IS_CHERRYVIEW(dev)) { enum dpio_phy phy; u32 val; @@ -1538,26 +1535,6 @@ static void intel_reset_dpio(struct drm_device *dev) I915_WRITE(DISPLAY_PHY_CONTROL, PHY_COM_LANE_RESET_DEASSERT(phy, val)); } - - } else { - /* - * If DPIO has already been reset, e.g. by BIOS, just skip all - * this. - */ - if (I915_READ(DPIO_CTL) & DPIO_CMNRST) - return; - - /* - * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx: - * Need to assert and de-assert PHY SB reset by gating the - * common lane power, then un-gating it. - * Simply ungating isn't enough to reset the PHY enough to get - * ports and lanes running. - */ - __vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC, - false); - __vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC, - true); } } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4d4f735a8ad..0ef04ea6871 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1003,8 +1003,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv); void intel_init_runtime_pm(struct drm_i915_private *dev_priv); void intel_fini_runtime_pm(struct drm_i915_private *dev_priv); void ilk_wm_get_hw_state(struct drm_device *dev); -void __vlv_set_power_well(struct drm_i915_private *dev_priv, - enum punit_power_well power_well_id, bool enable); + /* intel_sdvo.c */ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 16a94e118df..01498fabd0f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6010,9 +6010,10 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv, return true; } -void __vlv_set_power_well(struct drm_i915_private *dev_priv, - enum punit_power_well power_well_id, bool enable) +static void vlv_set_power_well(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well, bool enable) { + enum punit_power_well power_well_id = power_well->data; u32 mask; u32 state; u32 ctrl; @@ -6045,14 +6046,6 @@ out: mutex_unlock(&dev_priv->rps.hw_lock); } -static void vlv_set_power_well(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well, bool enable) -{ - enum punit_power_well power_well_id = power_well->data; - - __vlv_set_power_well(dev_priv, power_well_id, enable); -} - static void vlv_power_well_sync_hw(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -6508,6 +6501,21 @@ static struct i915_power_well vlv_power_wells[] = { }, }; +static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv, + enum punit_power_well power_well_id) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; + int i; + + for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) { + if (power_well->data == power_well_id) + return power_well; + } + + return NULL; +} + #define set_power_wells(power_domains, __power_wells) ({ \ (power_domains)->power_wells = (__power_wells); \ (power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \ @@ -6558,11 +6566,50 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv) mutex_unlock(&power_domains->lock); } +static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) +{ + struct i915_power_well *cmn = + lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC); + struct i915_power_well *disp2d = + lookup_power_well(dev_priv, PUNIT_POWER_WELL_DISP2D); + + /* nothing to do if common lane is already off */ + if (!cmn->ops->is_enabled(dev_priv, cmn)) + return; + + /* If the display might be already active skip this */ + if (disp2d->ops->is_enabled(dev_priv, disp2d) && + I915_READ(DPIO_CTL) & DPIO_CMNRST) + return; + + DRM_DEBUG_KMS("toggling display PHY side reset\n"); + + /* cmnlane needs DPLL registers */ + disp2d->ops->enable(dev_priv, disp2d); + + /* + * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx: + * Need to assert and de-assert PHY SB reset by gating the + * common lane power, then un-gating it. + * Simply ungating isn't enough to reset the PHY enough to get + * ports and lanes running. + */ + cmn->ops->disable(dev_priv, cmn); +} + void intel_power_domains_init_hw(struct drm_i915_private *dev_priv) { + struct drm_device *dev = dev_priv->dev; struct i915_power_domains *power_domains = &dev_priv->power_domains; power_domains->initializing = true; + + if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { + mutex_lock(&power_domains->lock); + vlv_cmnlane_wa(dev_priv); + mutex_unlock(&power_domains->lock); + } + /* For now, we need the power well to be always enabled. */ intel_display_set_init_power(dev_priv, true); intel_power_domains_resume(dev_priv); -- cgit v1.2.3-70-g09d2 From 5209b1f4c4f8036f52f5ac2df2afc806254f247f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 1 Jul 2014 12:36:17 +0300 Subject: drm/i915: gmch: factor out intel_set_memory_cxsr This functionality will be also needed by an upcoming patch, so factor it out. As a bonus this also makes things a bit more uniform across platforms. Note that this also changes the register read-modify-write to a simple write during disabling. This is what we do during enabling anyway and according to the spec all the relevant bits are reserved-MBZ or reserved with a 0 default value. v2: - unchanged v3: - fix missing cxsr disabling on pineview (Deepak) Signed-off-by: Imre Deak Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 76 ++++++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 38 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a503a5301de..38362863b1d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2649,6 +2649,8 @@ extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void valleyview_set_rps(struct drm_device *dev, u8 val); extern int valleyview_rps_max_freq(struct drm_i915_private *dev_priv); extern int valleyview_rps_min_freq(struct drm_i915_private *dev_priv); +extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, + bool enable); extern void intel_detect_pch(struct drm_device *dev); extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); extern int intel_enable_rc6(const struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 01498fabd0f..ded42945934 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -816,12 +816,33 @@ static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, return NULL; } -static void pineview_disable_cxsr(struct drm_device *dev) +void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_device *dev = dev_priv->dev; + u32 val; - /* deactivate cxsr */ - I915_WRITE(DSPFW3, I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN); + if (IS_VALLEYVIEW(dev)) { + I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0); + } else if (IS_G4X(dev) || IS_CRESTLINE(dev)) { + I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0); + } else if (IS_PINEVIEW(dev)) { + val = I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN; + val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0; + I915_WRITE(DSPFW3, val); + } else if (IS_I945G(dev) || IS_I945GM(dev)) { + val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) : + _MASKED_BIT_DISABLE(FW_BLC_SELF_EN); + I915_WRITE(FW_BLC_SELF, val); + } else if (IS_I915GM(dev)) { + val = enable ? _MASKED_BIT_ENABLE(INSTPM_SELF_EN) : + _MASKED_BIT_DISABLE(INSTPM_SELF_EN); + I915_WRITE(INSTPM, val); + } else { + return; + } + + DRM_DEBUG_KMS("memory self-refresh is %s\n", + enable ? "enabled" : "disabled"); } /* @@ -1060,7 +1081,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) dev_priv->fsb_freq, dev_priv->mem_freq); if (!latency) { DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); - pineview_disable_cxsr(dev); + intel_set_memory_cxsr(dev_priv, false); return; } @@ -1111,13 +1132,9 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) I915_WRITE(DSPFW3, reg); DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg); - /* activate cxsr */ - I915_WRITE(DSPFW3, - I915_READ(DSPFW3) | PINEVIEW_SELF_REFRESH_EN); - DRM_DEBUG_KMS("Self-refresh is enabled\n"); + intel_set_memory_cxsr(dev_priv, true); } else { - pineview_disable_cxsr(dev); - DRM_DEBUG_KMS("Self-refresh is disabled\n"); + intel_set_memory_cxsr(dev_priv, false); } } @@ -1369,10 +1386,9 @@ static void valleyview_update_wm(struct drm_crtc *crtc) &valleyview_wm_info, &valleyview_cursor_wm_info, &ignore_plane_sr, &cursor_sr)) { - I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN); + intel_set_memory_cxsr(dev_priv, true); } else { - I915_WRITE(FW_BLC_SELF_VLV, - I915_READ(FW_BLC_SELF_VLV) & ~FW_CSPWRDWNEN); + intel_set_memory_cxsr(dev_priv, false); plane_sr = cursor_sr = 0; } @@ -1421,10 +1437,9 @@ static void g4x_update_wm(struct drm_crtc *crtc) &g4x_wm_info, &g4x_cursor_wm_info, &plane_sr, &cursor_sr)) { - I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); + intel_set_memory_cxsr(dev_priv, true); } else { - I915_WRITE(FW_BLC_SELF, - I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN); + intel_set_memory_cxsr(dev_priv, false); plane_sr = cursor_sr = 0; } @@ -1495,13 +1510,10 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) DRM_DEBUG_KMS("self-refresh watermark: display plane %d " "cursor %d\n", srwm, cursor_sr); - if (IS_CRESTLINE(dev)) - I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); + intel_set_memory_cxsr(dev_priv, true); } else { /* Turn off self refresh if both pipes are enabled */ - if (IS_CRESTLINE(dev)) - I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) - & ~FW_BLC_SELF_EN); + intel_set_memory_cxsr(dev_priv, false); } DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n", @@ -1587,10 +1599,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) cwm = 2; /* Play safe and disable self-refresh before adjusting watermarks. */ - if (IS_I945G(dev) || IS_I945GM(dev)) - I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0); - else if (IS_I915GM(dev)) - I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_SELF_EN)); + intel_set_memory_cxsr(dev_priv, false); /* Calc sr entries for one plane configs */ if (HAS_FW_BLC(dev) && enabled) { @@ -1636,17 +1645,8 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) I915_WRITE(FW_BLC, fwater_lo); I915_WRITE(FW_BLC2, fwater_hi); - if (HAS_FW_BLC(dev)) { - if (enabled) { - if (IS_I945G(dev) || IS_I945GM(dev)) - I915_WRITE(FW_BLC_SELF, - FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN); - else if (IS_I915GM(dev)) - I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_SELF_EN)); - DRM_DEBUG_KMS("memory self refresh enabled\n"); - } else - DRM_DEBUG_KMS("memory self refresh disabled\n"); - } + if (enabled) + intel_set_memory_cxsr(dev_priv, true); } static void i845_update_wm(struct drm_crtc *unused_crtc) @@ -6782,7 +6782,7 @@ void intel_init_pm(struct drm_device *dev) (dev_priv->is_ddr3 == 1) ? "3" : "2", dev_priv->fsb_freq, dev_priv->mem_freq); /* Disable CxSR and never update its watermark again */ - pineview_disable_cxsr(dev); + intel_set_memory_cxsr(dev_priv, false); dev_priv->display.update_wm = NULL; } else dev_priv->display.update_wm = pineview_update_wm; -- cgit v1.2.3-70-g09d2 From 9858425c8fe631673ef325b59bac38c26c08b004 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 13 Jun 2014 14:54:20 +0300 Subject: drm/i915: gmch: set SR WMs to valid values before enabling them Atm it's possible that we enable the memory self-refresh mode before the watermark levels used by this mode are programmed with valid values. So move the enabling after we programmed the WM levels. Signed-off-by: Imre Deak Reviewed-by: Vijay Purushothaman Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ded42945934..41c1b79959f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1360,6 +1360,7 @@ static void valleyview_update_wm(struct drm_crtc *crtc) int plane_sr, cursor_sr; int ignore_plane_sr, ignore_cursor_sr; unsigned int enabled = 0; + bool cxsr_enabled; vlv_update_drain_latency(dev); @@ -1386,8 +1387,9 @@ static void valleyview_update_wm(struct drm_crtc *crtc) &valleyview_wm_info, &valleyview_cursor_wm_info, &ignore_plane_sr, &cursor_sr)) { - intel_set_memory_cxsr(dev_priv, true); + cxsr_enabled = true; } else { + cxsr_enabled = false; intel_set_memory_cxsr(dev_priv, false); plane_sr = cursor_sr = 0; } @@ -1408,6 +1410,9 @@ static void valleyview_update_wm(struct drm_crtc *crtc) I915_WRITE(DSPFW3, (I915_READ(DSPFW3) & ~DSPFW_CURSOR_SR_MASK) | (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); + + if (cxsr_enabled) + intel_set_memory_cxsr(dev_priv, true); } static void g4x_update_wm(struct drm_crtc *crtc) @@ -1418,6 +1423,7 @@ static void g4x_update_wm(struct drm_crtc *crtc) int planea_wm, planeb_wm, cursora_wm, cursorb_wm; int plane_sr, cursor_sr; unsigned int enabled = 0; + bool cxsr_enabled; if (g4x_compute_wm0(dev, PIPE_A, &g4x_wm_info, latency_ns, @@ -1437,8 +1443,9 @@ static void g4x_update_wm(struct drm_crtc *crtc) &g4x_wm_info, &g4x_cursor_wm_info, &plane_sr, &cursor_sr)) { - intel_set_memory_cxsr(dev_priv, true); + cxsr_enabled = true; } else { + cxsr_enabled = false; intel_set_memory_cxsr(dev_priv, false); plane_sr = cursor_sr = 0; } @@ -1460,6 +1467,9 @@ static void g4x_update_wm(struct drm_crtc *crtc) I915_WRITE(DSPFW3, (I915_READ(DSPFW3) & ~(DSPFW_HPLL_SR_EN | DSPFW_CURSOR_SR_MASK)) | (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); + + if (cxsr_enabled) + intel_set_memory_cxsr(dev_priv, true); } static void i965_update_wm(struct drm_crtc *unused_crtc) @@ -1469,6 +1479,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) struct drm_crtc *crtc; int srwm = 1; int cursor_sr = 16; + bool cxsr_enabled; /* Calc sr entries for one plane configs */ crtc = single_enabled_crtc(dev); @@ -1510,8 +1521,9 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) DRM_DEBUG_KMS("self-refresh watermark: display plane %d " "cursor %d\n", srwm, cursor_sr); - intel_set_memory_cxsr(dev_priv, true); + cxsr_enabled = true; } else { + cxsr_enabled = false; /* Turn off self refresh if both pipes are enabled */ intel_set_memory_cxsr(dev_priv, false); } @@ -1525,6 +1537,9 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); /* update cursor SR watermark */ I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); + + if (cxsr_enabled) + intel_set_memory_cxsr(dev_priv, true); } static void i9xx_update_wm(struct drm_crtc *unused_crtc) -- cgit v1.2.3-70-g09d2 From b3f9ad93b7621364ed51f9c37b9cf9abc9855991 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Mon, 7 Jul 2014 12:40:17 +0100 Subject: drm/i915/bdw: 3D_CHICKEN3 has write mask bits The workaround to limit SDE poly depth FIFO to 2 is not applied because 3D Chicken-3 mask bit is not set. WaLimitSizeOfSDEPolyFifo is only for BDW-A and could be removed. Signed-off-by: Michel Thierry Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 41c1b79959f..f2a40565ef9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5375,7 +5375,7 @@ static void gen8_init_clock_gating(struct drm_device *dev) I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE)); I915_WRITE(_3D_CHICKEN3, - _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2)); + _MASKED_BIT_ENABLE(_3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2))); I915_WRITE(COMMON_SLICE_CHICKEN2, _MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE)); -- cgit v1.2.3-70-g09d2 From 31685c258e0b0ad6aa486c5ec001382cf8a64212 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Thu, 3 Jul 2014 17:33:01 -0400 Subject: drm/i915/vlv: WA for Turbo and RC6 to work together. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With RC6 enabled, BYT has an HW issue in determining the right Gfx busyness. WA for Turbo + RC6: Use SW based Gfx busy-ness detection to decide on increasing/decreasing the freq. This logic will monitor C0 counters of render/media power-wells over EI period and takes necessary action based on these values v2: Refactor duplicate code. (Ville) v3: Reformat the comments. (Ville) v4: Enable required counters and remove unwanted code (Ville) v5: Added frequency change acceleration support and remove kernel-doc style comments. (Ville) v6: Updated comment section and Fix w/a comment. (Ville) Signed-off-by: Deepak S Reviewed-by: Ville Syrjälä Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 15 +++++ drivers/gpu/drm/i915/i915_irq.c | 133 +++++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_reg.h | 11 ++++ drivers/gpu/drm/i915/intel_pm.c | 12 +++- 4 files changed, 167 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8fa8172fcfb..41191f11af6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -902,6 +902,12 @@ struct vlv_s0ix_state { u32 clock_gate_dis2; }; +struct intel_rps_ei_calc { + u32 cz_ts_ei; + u32 render_ei_c0; + u32 media_ei_c0; +}; + struct intel_gen6_power_mgmt { /* work and pm_iir are protected by dev_priv->irq_lock */ struct work_struct work; @@ -926,6 +932,8 @@ struct intel_gen6_power_mgmt { u8 rp1_freq; /* "less than" RP0 power/freqency */ u8 rp0_freq; /* Non-overclocked max frequency. */ + u32 ei_interrupt_count; + int last_adj; enum { LOW_POWER, BETWEEN, HIGH_POWER } power; @@ -1527,6 +1535,13 @@ struct drm_i915_private { /* gen6+ rps state */ struct intel_gen6_power_mgmt rps; + /* rps wa up ei calculation */ + struct intel_rps_ei_calc rps_up_ei; + + /* rps wa down ei calculation */ + struct intel_rps_ei_calc rps_down_ei; + + /* ilk-only ips/rps state. Everything in here is protected by the global * mchdev_lock in intel_pm.c */ struct intel_ilk_power_mgmt ips; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d672053fdb1..0b4a8ed76a5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1272,6 +1272,131 @@ static void notify_ring(struct drm_device *dev, i915_queue_hangcheck(dev); } +static u32 vlv_c0_residency(struct drm_i915_private *dev_priv, + struct intel_rps_ei_calc *rps_ei) +{ + u32 cz_ts, cz_freq_khz; + u32 render_count, media_count; + u32 elapsed_render, elapsed_media, elapsed_time; + u32 residency = 0; + + cz_ts = vlv_punit_read(dev_priv, PUNIT_REG_CZ_TIMESTAMP); + cz_freq_khz = DIV_ROUND_CLOSEST(dev_priv->mem_freq * 1000, 4); + + render_count = I915_READ(VLV_RENDER_C0_COUNT_REG); + media_count = I915_READ(VLV_MEDIA_C0_COUNT_REG); + + if (rps_ei->cz_ts_ei == 0) { + rps_ei->cz_ts_ei = cz_ts; + rps_ei->render_ei_c0 = render_count; + rps_ei->media_ei_c0 = media_count; + + return dev_priv->rps.cur_freq; + } + + elapsed_time = cz_ts - rps_ei->cz_ts_ei; + rps_ei->cz_ts_ei = cz_ts; + + elapsed_render = render_count - rps_ei->render_ei_c0; + rps_ei->render_ei_c0 = render_count; + + elapsed_media = media_count - rps_ei->media_ei_c0; + rps_ei->media_ei_c0 = media_count; + + /* Convert all the counters into common unit of milli sec */ + elapsed_time /= VLV_CZ_CLOCK_TO_MILLI_SEC; + elapsed_render /= cz_freq_khz; + elapsed_media /= cz_freq_khz; + + /* + * Calculate overall C0 residency percentage + * only if elapsed time is non zero + */ + if (elapsed_time) { + residency = + ((max(elapsed_render, elapsed_media) * 100) + / elapsed_time); + } + + return residency; +} + +/** + * vlv_calc_delay_from_C0_counters - Increase/Decrease freq based on GPU + * busy-ness calculated from C0 counters of render & media power wells + * @dev_priv: DRM device private + * + */ +static u32 vlv_calc_delay_from_C0_counters(struct drm_i915_private *dev_priv) +{ + u32 residency_C0_up = 0, residency_C0_down = 0; + u8 new_delay, adj; + + dev_priv->rps.ei_interrupt_count++; + + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + + + if (dev_priv->rps_up_ei.cz_ts_ei == 0) { + vlv_c0_residency(dev_priv, &dev_priv->rps_up_ei); + vlv_c0_residency(dev_priv, &dev_priv->rps_down_ei); + return dev_priv->rps.cur_freq; + } + + + /* + * To down throttle, C0 residency should be less than down threshold + * for continous EI intervals. So calculate down EI counters + * once in VLV_INT_COUNT_FOR_DOWN_EI + */ + if (dev_priv->rps.ei_interrupt_count == VLV_INT_COUNT_FOR_DOWN_EI) { + + dev_priv->rps.ei_interrupt_count = 0; + + residency_C0_down = vlv_c0_residency(dev_priv, + &dev_priv->rps_down_ei); + } else { + residency_C0_up = vlv_c0_residency(dev_priv, + &dev_priv->rps_up_ei); + } + + new_delay = dev_priv->rps.cur_freq; + + adj = dev_priv->rps.last_adj; + /* C0 residency is greater than UP threshold. Increase Frequency */ + if (residency_C0_up >= VLV_RP_UP_EI_THRESHOLD) { + if (adj > 0) + adj *= 2; + else + adj = 1; + + if (dev_priv->rps.cur_freq < dev_priv->rps.max_freq_softlimit) + new_delay = dev_priv->rps.cur_freq + adj; + + /* + * For better performance, jump directly + * to RPe if we're below it. + */ + if (new_delay < dev_priv->rps.efficient_freq) + new_delay = dev_priv->rps.efficient_freq; + + } else if (!dev_priv->rps.ei_interrupt_count && + (residency_C0_down < VLV_RP_DOWN_EI_THRESHOLD)) { + if (adj < 0) + adj *= 2; + else + adj = -1; + /* + * This means, C0 residency is less than down threshold over + * a period of VLV_INT_COUNT_FOR_DOWN_EI. So, reduce the freq + */ + if (dev_priv->rps.cur_freq > dev_priv->rps.min_freq_softlimit) + new_delay = dev_priv->rps.cur_freq + adj; + } + + return new_delay; +} + static void gen6_pm_rps_work(struct work_struct *work) { struct drm_i915_private *dev_priv = @@ -1320,6 +1445,8 @@ static void gen6_pm_rps_work(struct work_struct *work) else new_delay = dev_priv->rps.min_freq_softlimit; adj = 0; + } else if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) { + new_delay = vlv_calc_delay_from_C0_counters(dev_priv); } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) { if (adj < 0) adj *= 2; @@ -4511,7 +4638,11 @@ void intel_irq_init(struct drm_device *dev) INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); /* Let's track the enabled rps events */ - dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; + if (IS_VALLEYVIEW(dev)) + /* WaGsvRC0ResidenncyMethod:VLV */ + dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED; + else + dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; setup_timer(&dev_priv->gpu_error.hangcheck_timer, i915_hangcheck_elapsed, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8c0f70de9fd..190d4bb5ad5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -531,6 +531,7 @@ enum punit_power_well { #define PUNIT_REG_GPU_FREQ_STS 0xd8 #define GENFREQSTATUS (1<<0) #define PUNIT_REG_MEDIA_TURBO_FREQ_REQ 0xdc +#define PUNIT_REG_CZ_TIMESTAMP 0xce #define PUNIT_FUSE_BUS2 0xf6 /* bits 47:40 */ #define PUNIT_FUSE_BUS1 0xf5 /* bits 55:48 */ @@ -556,6 +557,11 @@ enum punit_power_well { #define FB_FMAX_VMIN_FREQ_LO_SHIFT 27 #define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000 +#define VLV_CZ_CLOCK_TO_MILLI_SEC 100000 +#define VLV_RP_UP_EI_THRESHOLD 90 +#define VLV_RP_DOWN_EI_THRESHOLD 70 +#define VLV_INT_COUNT_FOR_DOWN_EI 5 + /* vlv2 north clock has */ #define CCK_FUSE_REG 0x8 #define CCK_FUSE_HPLL_FREQ_MASK 0x3 @@ -5394,6 +5400,7 @@ enum punit_power_well { #define VLV_GTLC_ALLOWWAKEERR (1 << 1) #define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5) #define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7) +#define VLV_GTLC_SURVIVABILITY_REG 0x130098 #define FORCEWAKE_MT 0xa188 /* multi-threaded */ #define FORCEWAKE_KERNEL 0x1 #define FORCEWAKE_USER 0x2 @@ -5541,6 +5548,8 @@ enum punit_power_well { #define GEN6_GT_GFX_RC6_LOCKED 0x138104 #define VLV_COUNTER_CONTROL 0x138104 #define VLV_COUNT_RANGE_HIGH (1<<15) +#define VLV_MEDIA_RC0_COUNT_EN (1<<5) +#define VLV_RENDER_RC0_COUNT_EN (1<<4) #define VLV_MEDIA_RC6_COUNT_EN (1<<1) #define VLV_RENDER_RC6_COUNT_EN (1<<0) #define GEN6_GT_GFX_RC6 0x138108 @@ -5549,6 +5558,8 @@ enum punit_power_well { #define GEN6_GT_GFX_RC6p 0x13810C #define GEN6_GT_GFX_RC6pp 0x138110 +#define VLV_RENDER_C0_COUNT_REG 0x138118 +#define VLV_MEDIA_C0_COUNT_REG 0x13811C #define GEN6_PCODE_MAILBOX 0x138124 #define GEN6_PCODE_READY (1<<31) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f2a40565ef9..d1af6419ec7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3282,8 +3282,11 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) vlv_force_gfx_clock(dev_priv, false); - I915_WRITE(GEN6_PMINTRMSK, - gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq)); + if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED) + I915_WRITE(GEN6_PMINTRMSK, ~dev_priv->pm_rps_events); + else + I915_WRITE(GEN6_PMINTRMSK, + gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq)); } void gen6_rps_idle(struct drm_i915_private *dev_priv) @@ -4125,6 +4128,7 @@ static void valleyview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RP_DOWN_EI, 350000); I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 0xf4240); I915_WRITE(GEN6_RP_CONTROL, GEN6_RP_MEDIA_TURBO | @@ -4145,9 +4149,11 @@ static void valleyview_enable_rps(struct drm_device *dev) /* allows RC6 residency counter to work */ I915_WRITE(VLV_COUNTER_CONTROL, - _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH | + _MASKED_BIT_ENABLE(VLV_MEDIA_RC0_COUNT_EN | + VLV_RENDER_RC0_COUNT_EN | VLV_MEDIA_RC6_COUNT_EN | VLV_RENDER_RC6_COUNT_EN)); + if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL; -- cgit v1.2.3-70-g09d2 From 2ff8fde1ea0992dfd735dce94f8cae2aacff8e5c Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 8 Jul 2014 07:50:07 -0700 Subject: drm/i915: Make use of intel_fb_obj() (v2) This should hopefully simplify the display code slightly and also solves at least one mistake in intel_pipe_set_base() where to_intel_framebuffer(fb)->obj is referenced during local variable initialization, before 'if (!fb)' gets checked. Potential uses of this macro were identified via the following Coccinelle patch: @@ expression E; @@ * to_intel_framebuffer(E)->obj @@ expression E; identifier I; @@ I = to_intel_framebuffer(E); ... * I->obj v2: Rewrite some NULL tests in terms of the obj rather than the fb. Also add a WARN() if trying to pageflip with a disabled primary plane. [Suggested by Chris Wilson] Signed-off-by: Matt Roper Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 84 ++++++++++++++++-------------------- drivers/gpu/drm/i915/intel_dp.c | 3 +- drivers/gpu/drm/i915/intel_pm.c | 24 ++++------- 3 files changed, 48 insertions(+), 63 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8e738d4315a..71430a05ba8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2356,7 +2356,7 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc, struct drm_device *dev = intel_crtc->base.dev; struct drm_crtc *c; struct intel_crtc *i; - struct intel_framebuffer *fb; + struct drm_i915_gem_object *obj; if (!intel_crtc->base.primary->fb) return; @@ -2377,14 +2377,17 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc, if (c == &intel_crtc->base) continue; - if (!i->active || !c->primary->fb) + if (!i->active) + continue; + + obj = intel_fb_obj(c->primary->fb); + if (obj == NULL) continue; - fb = to_intel_framebuffer(c->primary->fb); - if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) { + if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) { drm_framebuffer_reference(c->primary->fb); intel_crtc->base.primary->fb = c->primary->fb; - fb->obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); + obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); break; } } @@ -2397,16 +2400,12 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_framebuffer *intel_fb; - struct drm_i915_gem_object *obj; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); int plane = intel_crtc->plane; unsigned long linear_offset; u32 dspcntr; u32 reg; - intel_fb = to_intel_framebuffer(fb); - obj = intel_fb->obj; - reg = DSPCNTR(plane); dspcntr = I915_READ(reg); /* Mask out pixel format bits in case we change it */ @@ -2487,16 +2486,12 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_framebuffer *intel_fb; - struct drm_i915_gem_object *obj; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); int plane = intel_crtc->plane; unsigned long linear_offset; u32 dspcntr; u32 reg; - intel_fb = to_intel_framebuffer(fb); - obj = intel_fb->obj; - reg = DSPCNTR(plane); dspcntr = I915_READ(reg); /* Mask out pixel format bits in case we change it */ @@ -2627,7 +2622,7 @@ void intel_display_handle_reset(struct drm_device *dev) static int intel_finish_fb(struct drm_framebuffer *old_fb) { - struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj; + struct drm_i915_gem_object *obj = intel_fb_obj(old_fb); struct drm_i915_private *dev_priv = obj->base.dev->dev_private; bool was_interruptible = dev_priv->mm.interruptible; int ret; @@ -2674,9 +2669,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; - struct drm_framebuffer *old_fb; - struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj; - struct drm_i915_gem_object *old_obj; + struct drm_framebuffer *old_fb = crtc->primary->fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb); int ret; if (intel_crtc_has_pending_flip(crtc)) { @@ -2697,9 +2692,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return -EINVAL; } - old_fb = crtc->primary->fb; - old_obj = old_fb ? to_intel_framebuffer(old_fb)->obj : NULL; - mutex_lock(&dev->struct_mutex); ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); if (ret == 0) @@ -2755,7 +2747,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, if (intel_crtc->active && old_fb != fb) intel_wait_for_vblank(dev, intel_crtc->pipe); mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj); + intel_unpin_fb_obj(old_obj); mutex_unlock(&dev->struct_mutex); } @@ -4929,7 +4921,7 @@ static void intel_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_connector *connector; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *old_obj; + struct drm_i915_gem_object *old_obj = intel_fb_obj(crtc->primary->fb); enum pipe pipe = to_intel_crtc(crtc)->pipe; /* crtc should still be enabled when we disable it. */ @@ -4944,7 +4936,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc) assert_pipe_disabled(dev->dev_private, pipe); if (crtc->primary->fb) { - old_obj = to_intel_framebuffer(crtc->primary->fb)->obj; mutex_lock(&dev->struct_mutex); intel_unpin_fb_obj(old_obj); i915_gem_track_fb(old_obj, NULL, @@ -9586,7 +9577,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *old_fb = crtc->primary->fb; - struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; struct intel_unpin_work *work; @@ -9594,6 +9585,14 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, unsigned long flags; int ret; + /* + * drm_mode_page_flip_ioctl() should already catch this, but double + * check to be safe. In the future we may enable pageflipping from + * a disabled primary plane. + */ + if (WARN_ON(intel_fb_obj(old_fb) == NULL)) + return -EBUSY; + /* Can't change pixel format via MI display flips. */ if (fb->pixel_format != crtc->primary->fb->pixel_format) return -EINVAL; @@ -9616,7 +9615,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->event = event; work->crtc = crtc; - work->old_fb_obj = to_intel_framebuffer(old_fb)->obj; + work->old_fb_obj = intel_fb_obj(old_fb); INIT_WORK(&work->work, intel_unpin_work_fn); ret = drm_crtc_vblank_get(crtc); @@ -10758,10 +10757,9 @@ static int __intel_set_mode(struct drm_crtc *crtc, * on the DPLL. */ for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { - struct drm_framebuffer *old_fb; - struct drm_i915_gem_object *old_obj = NULL; - struct drm_i915_gem_object *obj = - to_intel_framebuffer(fb)->obj; + struct drm_framebuffer *old_fb = crtc->primary->fb; + struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb); + struct drm_i915_gem_object *obj = intel_fb_obj(fb); mutex_lock(&dev->struct_mutex); ret = intel_pin_and_fence_fb_obj(dev, @@ -10772,11 +10770,8 @@ static int __intel_set_mode(struct drm_crtc *crtc, mutex_unlock(&dev->struct_mutex); goto done; } - old_fb = crtc->primary->fb; - if (old_fb) { - old_obj = to_intel_framebuffer(old_fb)->obj; + if (old_fb) intel_unpin_fb_obj(old_obj); - } i915_gem_track_fb(old_obj, obj, INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); mutex_unlock(&dev->struct_mutex); @@ -11394,9 +11389,9 @@ intel_primary_plane_disable(struct drm_plane *plane) intel_disable_primary_hw_plane(dev_priv, intel_plane->plane, intel_plane->pipe); disable_unpin: - i915_gem_track_fb(to_intel_framebuffer(plane->fb)->obj, NULL, + i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); - intel_unpin_fb_obj(to_intel_framebuffer(plane->fb)->obj); + intel_unpin_fb_obj(intel_fb_obj(plane->fb)); plane->fb = NULL; return 0; @@ -11413,7 +11408,8 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); - struct drm_i915_gem_object *obj, *old_obj = NULL; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); struct drm_rect dest = { /* integer pixels */ .x1 = crtc_x, @@ -11445,10 +11441,6 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, if (ret) return ret; - if (plane->fb) - old_obj = to_intel_framebuffer(plane->fb)->obj; - obj = to_intel_framebuffer(fb)->obj; - /* * If the CRTC isn't enabled, we're just pinning the framebuffer, * updating the fb pointer, and returning without touching the @@ -12945,7 +12937,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, void intel_modeset_gem_init(struct drm_device *dev) { struct drm_crtc *c; - struct intel_framebuffer *fb; + struct drm_i915_gem_object *obj; mutex_lock(&dev->struct_mutex); intel_init_gt_powersave(dev); @@ -12962,11 +12954,11 @@ void intel_modeset_gem_init(struct drm_device *dev) */ mutex_lock(&dev->struct_mutex); for_each_crtc(dev, c) { - if (!c->primary->fb) + obj = intel_fb_obj(c->primary->fb); + if (obj == NULL) continue; - fb = to_intel_framebuffer(c->primary->fb); - if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) { + if (intel_pin_and_fence_fb_obj(dev, obj, NULL)) { DRM_ERROR("failed to pin boot fb on pipe %d\n", to_intel_crtc(c)->pipe); drm_framebuffer_unreference(c->primary->fb); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e0f1bd125d8..3ca6c7c77e0 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1752,7 +1752,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = dig_port->base.base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->primary->fb)->obj; + struct drm_i915_gem_object *obj = intel_fb_obj(crtc->primary->fb); struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; dev_priv->psr.source_ok = false; @@ -1785,7 +1785,6 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) return false; } - obj = to_intel_framebuffer(crtc->primary->fb)->obj; if (obj->tiling_mode != I915_TILING_X || obj->fence_reg == I915_FENCE_REG_NONE) { DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n"); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d1af6419ec7..19c5c26bada 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -93,8 +93,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb = crtc->primary->fb; - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj = intel_fb->obj; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int cfb_pitch; int i; @@ -150,8 +149,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb = crtc->primary->fb; - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj = intel_fb->obj; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); u32 dpfc_ctl; @@ -222,8 +220,7 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb = crtc->primary->fb; - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj = intel_fb->obj; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); u32 dpfc_ctl; @@ -289,8 +286,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb = crtc->primary->fb; - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj = intel_fb->obj; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); u32 dpfc_ctl; @@ -485,7 +481,6 @@ void intel_update_fbc(struct drm_device *dev) struct drm_crtc *crtc = NULL, *tmp_crtc; struct intel_crtc *intel_crtc; struct drm_framebuffer *fb; - struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; const struct drm_display_mode *adjusted_mode; unsigned int max_width, max_height; @@ -530,8 +525,7 @@ void intel_update_fbc(struct drm_device *dev) intel_crtc = to_intel_crtc(crtc); fb = crtc->primary->fb; - intel_fb = to_intel_framebuffer(fb); - obj = intel_fb->obj; + obj = intel_fb_obj(fb); adjusted_mode = &intel_crtc->config.adjusted_mode; if (i915.enable_fbc < 0) { @@ -589,7 +583,7 @@ void intel_update_fbc(struct drm_device *dev) if (in_dbg_master()) goto out_disable; - if (i915_gem_stolen_setup_compression(dev, intel_fb->obj->base.size, + if (i915_gem_stolen_setup_compression(dev, obj->base.size, drm_format_plane_cpp(fb->pixel_format, 0))) { if (set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL)) DRM_DEBUG_KMS("framebuffer too large, disabling compression\n"); @@ -1599,12 +1593,12 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); if (IS_I915GM(dev) && enabled) { - struct intel_framebuffer *fb; + struct drm_i915_gem_object *obj; - fb = to_intel_framebuffer(enabled->primary->fb); + obj = intel_fb_obj(enabled->primary->fb); /* self-refresh seems busted with untiled */ - if (fb->obj->tiling_mode == I915_TILING_NONE) + if (obj->tiling_mode == I915_TILING_NONE) enabled = NULL; } -- cgit v1.2.3-70-g09d2 From bd2bb1b9a1c8b8f7b673db22d628ffd491669deb Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 4 Jul 2014 11:27:38 -0300 Subject: drm/i915: add POWER_DOMAIN_PLLS And get/put it when needed. The special thing about this commit is that it will now return false in ibx_pch_dpll_get_hw_state() in case the power domain is not enabled. This will fix some WARNs we have when we run pm_rpm on SNB. Testcase: igt/pm_rpm Bugzilla:https://bugs.freedesktop.org/show_bug.cgi?id=80463 Signed-off-by: Paulo Zanoni Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 ++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++ drivers/gpu/drm/i915/intel_pm.c | 1 + 4 files changed, 14 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f22a81dba64..2effe1a3781 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2043,6 +2043,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain) return "VGA"; case POWER_DOMAIN_AUDIO: return "AUDIO"; + case POWER_DOMAIN_PLLS: + return "PLLS"; case POWER_DOMAIN_INIT: return "INIT"; default: diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 26982d12039..479a9aa77ee 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -129,6 +129,7 @@ enum intel_display_power_domain { POWER_DOMAIN_PORT_OTHER, POWER_DOMAIN_VGA, POWER_DOMAIN_AUDIO, + POWER_DOMAIN_PLLS, POWER_DOMAIN_INIT, POWER_DOMAIN_NUM, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0874f358972..d61c5e43fc1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1814,6 +1814,8 @@ static void intel_enable_shared_dpll(struct intel_crtc *crtc) } WARN_ON(pll->on); + intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + DRM_DEBUG_KMS("enabling %s\n", pll->name); pll->enable(dev_priv, pll); pll->on = true; @@ -1850,6 +1852,8 @@ static void intel_disable_shared_dpll(struct intel_crtc *crtc) DRM_DEBUG_KMS("disabling %s\n", pll->name); pll->disable(dev_priv, pll); pll->on = false; + + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); } static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, @@ -11302,6 +11306,9 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, { uint32_t val; + if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + val = I915_READ(PCH_DPLL(pll->id)); hw_state->dpll = val; hw_state->fp0 = I915_READ(PCH_FP0(pll->id)); @@ -12867,6 +12874,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) DRM_DEBUG_KMS("%s hw state readout: refcount %i, on %i\n", pll->name, pll->refcount, pll->on); + + if (pll->refcount) + intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); } list_for_each_entry(encoder, &dev->mode_config.encoder_list, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 19c5c26bada..55228df5cf2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6346,6 +6346,7 @@ EXPORT_SYMBOL_GPL(i915_get_cdclk_freq); BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \ BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ BIT(POWER_DOMAIN_PORT_CRT) | \ + BIT(POWER_DOMAIN_PLLS) | \ BIT(POWER_DOMAIN_INIT)) #define HSW_DISPLAY_POWER_DOMAINS ( \ (POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) | \ -- cgit v1.2.3-70-g09d2 From 7b3c29f6fd374640266d82aafe6929761469e27b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 10 Jul 2014 20:31:19 +0100 Subject: drm/i915: Make the RPS interrupt generation mask handle the vlv wa We can eliminate a lot of special case code by making the computation of the interrupt mask be correct for all callers. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 55228df5cf2..780c3ab26f4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3183,6 +3183,9 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val) if (val < dev_priv->rps.max_freq_softlimit) mask |= GEN6_PM_RP_UP_THRESHOLD; + mask |= dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED); + mask &= dev_priv->pm_rps_events; + /* IVB and SNB hard hangs on looping batchbuffer * if GEN6_PM_UP_EI_EXPIRED is masked. */ @@ -3276,11 +3279,8 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) vlv_force_gfx_clock(dev_priv, false); - if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED) - I915_WRITE(GEN6_PMINTRMSK, ~dev_priv->pm_rps_events); - else - I915_WRITE(GEN6_PMINTRMSK, - gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq)); + I915_WRITE(GEN6_PMINTRMSK, + gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq)); } void gen6_rps_idle(struct drm_i915_private *dev_priv) -- cgit v1.2.3-70-g09d2 From 03af20458a57a50735b12c1e3c23abc7ff70c6fa Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 28 Jun 2014 02:03:53 +0300 Subject: drm/i915: Use the cached min/min/rpe values in the vlv debugfs code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need to re-read the hardware rps fuses when we already have all the values tucked away in dev_priv->rps. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 19 ++++++++++--------- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/intel_pm.c | 8 ++++---- 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4a5b0f80e05..981ca4243bd 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1108,20 +1108,21 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "Max overclocked frequency: %dMHz\n", dev_priv->rps.max_freq * GT_FREQUENCY_MULTIPLIER); } else if (IS_VALLEYVIEW(dev)) { - u32 freq_sts, val; + u32 freq_sts; mutex_lock(&dev_priv->rps.hw_lock); freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq); - val = valleyview_rps_max_freq(dev_priv); seq_printf(m, "max GPU freq: %d MHz\n", - vlv_gpu_freq(dev_priv, val)); + dev_priv->rps.max_freq); - val = valleyview_rps_min_freq(dev_priv); seq_printf(m, "min GPU freq: %d MHz\n", - vlv_gpu_freq(dev_priv, val)); + dev_priv->rps.min_freq); + + seq_printf(m, "efficient (RPe) frequency: %d MHz\n", + dev_priv->rps.efficient_freq); seq_printf(m, "current GPU freq: %d MHz\n", vlv_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff)); @@ -3632,8 +3633,8 @@ i915_max_freq_set(void *data, u64 val) if (IS_VALLEYVIEW(dev)) { val = vlv_freq_opcode(dev_priv, val); - hw_max = valleyview_rps_max_freq(dev_priv); - hw_min = valleyview_rps_min_freq(dev_priv); + hw_max = dev_priv->rps.max_freq; + hw_min = dev_priv->rps.min_freq; } else { do_div(val, GT_FREQUENCY_MULTIPLIER); @@ -3713,8 +3714,8 @@ i915_min_freq_set(void *data, u64 val) if (IS_VALLEYVIEW(dev)) { val = vlv_freq_opcode(dev_priv, val); - hw_max = valleyview_rps_max_freq(dev_priv); - hw_min = valleyview_rps_min_freq(dev_priv); + hw_max = dev_priv->rps.max_freq; + hw_min = dev_priv->rps.min_freq; } else { do_div(val, GT_FREQUENCY_MULTIPLIER); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 263a8799eb5..7031757628f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2684,8 +2684,6 @@ extern bool ironlake_set_drps(struct drm_device *dev, u8 val); extern void intel_init_pch_refclk(struct drm_device *dev); extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void valleyview_set_rps(struct drm_device *dev, u8 val); -extern int valleyview_rps_max_freq(struct drm_i915_private *dev_priv); -extern int valleyview_rps_min_freq(struct drm_i915_private *dev_priv); extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable); extern void intel_detect_pch(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 780c3ab26f4..2bc08a28268 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3781,7 +3781,7 @@ void gen6_update_ring_freq(struct drm_device *dev) mutex_unlock(&dev_priv->rps.hw_lock); } -int cherryview_rps_max_freq(struct drm_i915_private *dev_priv) +static int cherryview_rps_max_freq(struct drm_i915_private *dev_priv) { u32 val, rp0; @@ -3801,7 +3801,7 @@ static int cherryview_rps_rpe_freq(struct drm_i915_private *dev_priv) return rpe; } -int cherryview_rps_min_freq(struct drm_i915_private *dev_priv) +static int cherryview_rps_min_freq(struct drm_i915_private *dev_priv) { u32 val, rpn; @@ -3810,7 +3810,7 @@ int cherryview_rps_min_freq(struct drm_i915_private *dev_priv) return rpn; } -int valleyview_rps_max_freq(struct drm_i915_private *dev_priv) +static int valleyview_rps_max_freq(struct drm_i915_private *dev_priv) { u32 val, rp0; @@ -3835,7 +3835,7 @@ static int valleyview_rps_rpe_freq(struct drm_i915_private *dev_priv) return rpe; } -int valleyview_rps_min_freq(struct drm_i915_private *dev_priv) +static int valleyview_rps_min_freq(struct drm_i915_private *dev_priv) { return vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff; } -- cgit v1.2.3-70-g09d2 From f8f2b001a1247b54ece090c1c86193b1f3f997fe Mon Sep 17 00:00:00 2001 From: Deepak S Date: Thu, 10 Jul 2014 13:16:21 +0530 Subject: drm/i915: Read guaranteed freq for valleyview Reading RP1 for valleyview to help us enable "pm_rps" i-g-t testcase execution. Signed-off-by: Deepak S Reviewed-by: Mika Kuoppala [danvet: Add missing static.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2bc08a28268..8066ca5e271 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3810,6 +3810,17 @@ static int cherryview_rps_min_freq(struct drm_i915_private *dev_priv) return rpn; } +static int valleyview_rps_guar_freq(struct drm_i915_private *dev_priv) +{ + u32 val, rp1; + + val = vlv_nc_read(dev_priv, IOSF_NC_FB_GFX_FREQ_FUSE); + + rp1 = (val & FB_GFX_FGUARANTEED_FREQ_FUSE_MASK) >> FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT; + + return rp1; +} + static int valleyview_rps_max_freq(struct drm_i915_private *dev_priv) { u32 val, rp0; @@ -3952,6 +3963,11 @@ static void valleyview_init_gt_powersave(struct drm_device *dev) vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq), dev_priv->rps.efficient_freq); + dev_priv->rps.rp1_freq = valleyview_rps_guar_freq(dev_priv); + DRM_DEBUG_DRIVER("RP1(Guar Freq) GPU freq: %d MHz (%u)\n", + vlv_gpu_freq(dev_priv, dev_priv->rps.rp1_freq), + dev_priv->rps.rp1_freq); + dev_priv->rps.min_freq = valleyview_rps_min_freq(dev_priv); DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n", vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq), -- cgit v1.2.3-70-g09d2 From 67c3bf6f55a97a0915a0f9ea07278a3073cc9601 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Thu, 10 Jul 2014 13:16:24 +0530 Subject: drm/i915: populate mem_freq/cz_clock for chv We need mem_freq or cz clock for freq/opcode conversion Signed-off-by: Deepak S Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ drivers/gpu/drm/i915/intel_pm.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7031757628f..8620ea91e10 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -931,6 +931,7 @@ struct intel_gen6_power_mgmt { u8 efficient_freq; /* AKA RPe. Pre-determined balanced frequency */ u8 rp1_freq; /* "less than" RP0 power/freqency */ u8 rp0_freq; /* Non-overclocked max frequency. */ + u32 cz_freq; u32 ei_interrupt_count; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2d2c4deb3e8..0ebe0f49db2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5538,6 +5538,12 @@ enum punit_power_well { GEN6_PM_RP_DOWN_THRESHOLD | \ GEN6_PM_RP_DOWN_TIMEOUT) +#define CHV_CZ_CLOCK_FREQ_MODE_200 200 +#define CHV_CZ_CLOCK_FREQ_MODE_267 267 +#define CHV_CZ_CLOCK_FREQ_MODE_320 320 +#define CHV_CZ_CLOCK_FREQ_MODE_333 333 +#define CHV_CZ_CLOCK_FREQ_MODE_400 400 + #define GEN7_GT_SCRATCH_BASE 0x4F100 #define GEN7_GT_SCRATCH_REG_NUM 8 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8066ca5e271..32ccd7a9378 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5700,6 +5700,35 @@ static void valleyview_init_clock_gating(struct drm_device *dev) static void cherryview_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; + + mutex_lock(&dev_priv->rps.hw_lock); + val = vlv_punit_read(dev_priv, CCK_FUSE_REG); + mutex_unlock(&dev_priv->rps.hw_lock); + switch ((val >> 2) & 0x7) { + case 0: + case 1: + dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_200; + dev_priv->mem_freq = 1600; + break; + case 2: + dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_267; + dev_priv->mem_freq = 1600; + break; + case 3: + dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_333; + dev_priv->mem_freq = 2000; + break; + case 4: + dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_320; + dev_priv->mem_freq = 1600; + break; + case 5: + dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_400; + dev_priv->mem_freq = 1600; + break; + } + DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE); -- cgit v1.2.3-70-g09d2 From 22b1b2f866b2089d8264e367121c9c9ee0689da4 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sat, 12 Jul 2014 14:54:33 +0530 Subject: drm/i915: CHV GPU frequency to opcode functions Adding chv specific fre/encode conversion. v2: Remove generic function and platform check (Daniel) Signed-off-by: Deepak S Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 78 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 32ccd7a9378..1ec777a3914 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6926,7 +6926,7 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) return 0; } -int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val) +int byt_gpu_freq(struct drm_i915_private *dev_priv, int val) { int div; @@ -6948,7 +6948,7 @@ int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val) return DIV_ROUND_CLOSEST(dev_priv->mem_freq * (val + 6 - 0xbd), 4 * div); } -int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val) +int byt_freq_opcode(struct drm_i915_private *dev_priv, int val) { int mul; @@ -6970,6 +6970,80 @@ int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val) return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6; } +int chv_gpu_freq(struct drm_i915_private *dev_priv, int val) +{ + int div, freq; + + switch (dev_priv->rps.cz_freq) { + case 200: + div = 5; + break; + case 267: + div = 6; + break; + case 320: + case 333: + case 400: + div = 8; + break; + default: + return -1; + } + + freq = (DIV_ROUND_CLOSEST((dev_priv->rps.cz_freq * val), 2 * div) / 2); + + return freq; +} + +int chv_freq_opcode(struct drm_i915_private *dev_priv, int val) +{ + int mul, opcode; + + switch (dev_priv->rps.cz_freq) { + case 200: + mul = 5; + break; + case 267: + mul = 6; + break; + case 320: + case 333: + case 400: + mul = 8; + break; + default: + return -1; + } + + opcode = (DIV_ROUND_CLOSEST((val * 2 * mul), dev_priv->rps.cz_freq) * 2); + + return opcode; +} + +int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val) +{ + int ret = -1; + + if (IS_CHERRYVIEW(dev_priv->dev)) + ret = chv_gpu_freq(dev_priv, val); + else if (IS_VALLEYVIEW(dev_priv->dev)) + ret = byt_gpu_freq(dev_priv, val); + + return ret; +} + +int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val) +{ + int ret = -1; + + if (IS_CHERRYVIEW(dev_priv->dev)) + ret = chv_freq_opcode(dev_priv, val); + else if (IS_VALLEYVIEW(dev_priv->dev)) + ret = byt_freq_opcode(dev_priv, val); + + return ret; +} + void intel_pm_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; -- cgit v1.2.3-70-g09d2 From 3497a5620caec0ae25e3fa3b6828f1cdeac80ec0 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Thu, 10 Jul 2014 13:16:26 +0530 Subject: drm/i915/chv: Add basic PM interrupt support for CHV Enabled PM interrupt programming for CHV. Re-using gen8 code and extending same for CHV. Signed-off-by: Deepak S Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 30fd63708b1..188fe04c4f8 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1407,7 +1407,7 @@ static void gen6_pm_rps_work(struct work_struct *work) spin_lock_irq(&dev_priv->irq_lock); pm_iir = dev_priv->rps.pm_iir; dev_priv->rps.pm_iir = 0; - if (IS_BROADWELL(dev_priv->dev)) + if (IS_BROADWELL(dev_priv->dev) || IS_CHERRYVIEW(dev_priv->dev)) bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); else { /* Make sure not to corrupt PMIMR state used by ringbuffer */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1ec777a3914..58a03f86337 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3392,6 +3392,8 @@ static void cherryview_disable_rps(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; I915_WRITE(GEN6_RC_CONTROL, 0); + + gen8_disable_rps_interrupts(dev); } static void valleyview_disable_rps(struct drm_device *dev) @@ -4109,6 +4111,8 @@ static void cherryview_enable_rps(struct drm_device *dev) valleyview_set_rps(dev_priv->dev, dev_priv->rps.efficient_freq); + gen8_enable_rps_interrupts(dev); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } -- cgit v1.2.3-70-g09d2 From 7707df4ad6c73e005098c4b4db2f86494e9d404d Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sat, 12 Jul 2014 18:46:14 +0530 Subject: drm/i915: Add RP1 render P state thresholds in CHV This is useful for userspace utilities to verify and micromanaging the increase/decrease frequncy. v2: Use vlv_gpu_freq to get freq (Deepak) Signed-off-by: Deepak S Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 58a03f86337..97be125992d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3803,6 +3803,16 @@ static int cherryview_rps_rpe_freq(struct drm_i915_private *dev_priv) return rpe; } +static int cherryview_rps_guar_freq(struct drm_i915_private *dev_priv) +{ + u32 val, rp1; + + val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); + rp1 = (val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) & PUNIT_GPU_STATUS_MAX_FREQ_MASK; + + return rp1; +} + static int cherryview_rps_min_freq(struct drm_i915_private *dev_priv) { u32 val, rpn; @@ -4004,6 +4014,11 @@ static void cherryview_init_gt_powersave(struct drm_device *dev) vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq), dev_priv->rps.efficient_freq); + dev_priv->rps.rp1_freq = cherryview_rps_guar_freq(dev_priv); + DRM_DEBUG_DRIVER("RP1(Guar) GPU freq: %d MHz (%u)\n", + vlv_gpu_freq(dev_priv, dev_priv->rps.rp1_freq), + dev_priv->rps.rp1_freq); + dev_priv->rps.min_freq = cherryview_rps_min_freq(dev_priv); DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n", vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq), -- cgit v1.2.3-70-g09d2 From b55dd64720919ba8d6830fbaec9e779e4bdb0ae0 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Sat, 12 Jul 2014 11:21:39 +0200 Subject: drm/i915: byt_gpu_freq() can be static CC: Deepak S CC: Daniel Vetter Signed-off-by: Fengguang Wu Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 97be125992d..9585f1517fa 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6945,7 +6945,7 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) return 0; } -int byt_gpu_freq(struct drm_i915_private *dev_priv, int val) +static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val) { int div; @@ -6967,7 +6967,7 @@ int byt_gpu_freq(struct drm_i915_private *dev_priv, int val) return DIV_ROUND_CLOSEST(dev_priv->mem_freq * (val + 6 - 0xbd), 4 * div); } -int byt_freq_opcode(struct drm_i915_private *dev_priv, int val) +static int byt_freq_opcode(struct drm_i915_private *dev_priv, int val) { int mul; @@ -6989,7 +6989,7 @@ int byt_freq_opcode(struct drm_i915_private *dev_priv, int val) return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6; } -int chv_gpu_freq(struct drm_i915_private *dev_priv, int val) +static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val) { int div, freq; @@ -7014,7 +7014,7 @@ int chv_gpu_freq(struct drm_i915_private *dev_priv, int val) return freq; } -int chv_freq_opcode(struct drm_i915_private *dev_priv, int val) +static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val) { int mul, opcode; -- cgit v1.2.3-70-g09d2 From b47adc1792422f4caf6c1db0a2b235bfd4f02521 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Fri, 20 Jun 2014 20:03:02 +0530 Subject: drm/i915: Force GPU Freq to lowest while suspending. We might be leaving the GPU Frequency (and thus vnn) high during the suspend. Force gt to move to lowest freq while suspending. v2: Fixed typo in commit message (Deepak) v3: Force gt to lowest freq in suspend_gt_powersave (Daniel) v4: Add GPU min freq set _after_ we've cancelled the rps works (Daniel) Signed-off-by: Deepak S Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9585f1517fa..f55347f3ac7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4974,6 +4974,9 @@ void intel_suspend_gt_powersave(struct drm_device *dev) flush_delayed_work(&dev_priv->rps.delayed_resume_work); cancel_work_sync(&dev_priv->rps.work); + + /* Force GPU to min freq during suspend */ + gen6_rps_idle(dev_priv); } void intel_disable_gt_powersave(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 34638118f987c3f4136e442b65de22d73a0458cb Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sat, 28 Jun 2014 11:26:26 +0530 Subject: drm/i915/chv: Drop WaGsvBringDownFreqInRc6 Drop WaGsvBringDownFreq on CHV. When in RC6 requesting the min freq should be fine to bring the voltage down. Signed-off-by: Deepak S Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f55347f3ac7..be2d5bf7f53 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3289,7 +3289,9 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) mutex_lock(&dev_priv->rps.hw_lock); if (dev_priv->rps.enabled) { - if (IS_VALLEYVIEW(dev)) + if (IS_CHERRYVIEW(dev)) + valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); + else if (IS_VALLEYVIEW(dev)) vlv_set_rps_idle(dev_priv); else gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); -- cgit v1.2.3-70-g09d2 From ed57cb8a5c697680cdac3bc7ddfafff7594bd98e Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 15 Jul 2014 09:21:24 +0200 Subject: drm/i915: Also give the sprite width for WM computation In the future, we'll need the height of the fb to fetch from memory for WM computation. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/intel_drv.h | 5 ++++- drivers/gpu/drm/i915/intel_pm.c | 17 +++++++++++------ drivers/gpu/drm/i915/intel_sprite.c | 15 +++++++++------ 4 files changed, 26 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0b9f7894ee8..7f4f2b74592 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -440,8 +440,8 @@ struct drm_i915_display_funcs { void (*update_wm)(struct drm_crtc *crtc); void (*update_sprite_wm)(struct drm_plane *plane, struct drm_crtc *crtc, - uint32_t sprite_width, int pixel_size, - bool enable, bool scaled); + uint32_t sprite_width, uint32_t sprite_height, + int pixel_size, bool enable, bool scaled); void (*modeset_global_resources)(struct drm_device *dev); /* Returns the active state of the crtc, and if the crtc is active, * fills out the pipe-config with the hw state. */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 719f8d2d620..6093ebdeb7c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -423,6 +423,7 @@ struct intel_crtc { struct intel_plane_wm_parameters { uint32_t horiz_pixels; + uint32_t vert_pixels; uint8_t bytes_per_pixel; bool enabled; bool scaled; @@ -979,7 +980,9 @@ int ilk_wm_max_level(const struct drm_device *dev); void intel_update_watermarks(struct drm_crtc *crtc); void intel_update_sprite_watermarks(struct drm_plane *plane, struct drm_crtc *crtc, - uint32_t sprite_width, int pixel_size, + uint32_t sprite_width, + uint32_t sprite_height, + int pixel_size, bool enabled, bool scaled); void intel_init_pm(struct drm_device *dev); void intel_pm_setup(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index be2d5bf7f53..6e03851a4fa 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2743,10 +2743,11 @@ static void ilk_update_wm(struct drm_crtc *crtc) ilk_write_wm_values(dev_priv, &results); } -static void ilk_update_sprite_wm(struct drm_plane *plane, - struct drm_crtc *crtc, - uint32_t sprite_width, int pixel_size, - bool enabled, bool scaled) +static void +ilk_update_sprite_wm(struct drm_plane *plane, + struct drm_crtc *crtc, + uint32_t sprite_width, uint32_t sprite_height, + int pixel_size, bool enabled, bool scaled) { struct drm_device *dev = plane->dev; struct intel_plane *intel_plane = to_intel_plane(plane); @@ -2754,6 +2755,7 @@ static void ilk_update_sprite_wm(struct drm_plane *plane, intel_plane->wm.enabled = enabled; intel_plane->wm.scaled = scaled; intel_plane->wm.horiz_pixels = sprite_width; + intel_plane->wm.vert_pixels = sprite_width; intel_plane->wm.bytes_per_pixel = pixel_size; /* @@ -2888,13 +2890,16 @@ void intel_update_watermarks(struct drm_crtc *crtc) void intel_update_sprite_watermarks(struct drm_plane *plane, struct drm_crtc *crtc, - uint32_t sprite_width, int pixel_size, + uint32_t sprite_width, + uint32_t sprite_height, + int pixel_size, bool enabled, bool scaled) { struct drm_i915_private *dev_priv = plane->dev->dev_private; if (dev_priv->display.update_sprite_wm) - dev_priv->display.update_sprite_wm(plane, crtc, sprite_width, + dev_priv->display.update_sprite_wm(plane, crtc, + sprite_width, sprite_height, pixel_size, enabled, scaled); } diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 985317eb1dc..396c1e84395 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -218,7 +218,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, sprctl |= SP_ENABLE; - intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true, + intel_update_sprite_watermarks(dplane, crtc, src_w, src_h, + pixel_size, true, src_w != crtc_w || src_h != crtc_h); /* Sizes are 0 based */ @@ -283,7 +284,7 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) if (atomic_update) intel_pipe_update_end(intel_crtc, start_vbl_count); - intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false); + intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false); } static int @@ -406,7 +407,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (IS_HASWELL(dev) || IS_BROADWELL(dev)) sprctl |= SPRITE_PIPE_CSC_ENABLE; - intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true, + intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size, + true, src_w != crtc_w || src_h != crtc_h); /* Sizes are 0 based */ @@ -486,7 +488,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) */ intel_wait_for_vblank(dev, pipe); - intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); + intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false); } static int @@ -606,7 +608,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ dvscntr |= DVS_ENABLE; - intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true, + intel_update_sprite_watermarks(plane, crtc, src_w, src_h, + pixel_size, true, src_w != crtc_w || src_h != crtc_h); /* Sizes are 0 based */ @@ -681,7 +684,7 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) */ intel_wait_for_vblank(dev, pipe); - intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); + intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false); } static void -- cgit v1.2.3-70-g09d2 From 480c80338618867851659710d1a27c9cc85833d2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 16 Jul 2014 09:49:40 +0200 Subject: drm/i915: Use genX_ prefix for gt irq enable/disable functions Traditionally we use genX_ for GT/render stuff and the codenames for display stuff. But the gt and pm interrupt handling functions on gen5/6+ stuck out as exceptions, so convert them. Looking at the diff this nicely realigns our ducks since almost all the callers are already platform-specific functions following the genX_ pattern. Spotted while reviewing some internal rps patches. No function change in this patch. Acked-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 24 ++++++++++++------------ drivers/gpu/drm/i915/intel_drv.h | 12 ++++++------ drivers/gpu/drm/i915/intel_pm.c | 4 ++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 12 ++++++------ 4 files changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7d61ca2a01d..dfe923a3cb9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -182,12 +182,12 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv, POSTING_READ(GTIMR); } -void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask) +void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask) { ilk_update_gt_irq(dev_priv, mask, mask); } -void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask) +void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask) { ilk_update_gt_irq(dev_priv, mask, 0); } @@ -220,12 +220,12 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv, } } -void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) +void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) { snb_update_pm_irq(dev_priv, mask, mask); } -void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) +void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) { snb_update_pm_irq(dev_priv, mask, 0); } @@ -278,12 +278,12 @@ static void bdw_update_pm_irq(struct drm_i915_private *dev_priv, } } -void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) +void gen8_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) { bdw_update_pm_irq(dev_priv, mask, mask); } -void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) +void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask) { bdw_update_pm_irq(dev_priv, mask, 0); } @@ -1408,10 +1408,10 @@ static void gen6_pm_rps_work(struct work_struct *work) pm_iir = dev_priv->rps.pm_iir; dev_priv->rps.pm_iir = 0; if (INTEL_INFO(dev_priv->dev)->gen >= 8) - bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); + gen8_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); else { /* Make sure not to corrupt PMIMR state used by ringbuffer */ - snb_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); + gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); } spin_unlock_irq(&dev_priv->irq_lock); @@ -1553,7 +1553,7 @@ static void ivybridge_parity_work(struct work_struct *work) out: WARN_ON(dev_priv->l3_parity.which_slice); spin_lock_irqsave(&dev_priv->irq_lock, flags); - ilk_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev)); + gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev)); spin_unlock_irqrestore(&dev_priv->irq_lock, flags); mutex_unlock(&dev_priv->dev->struct_mutex); @@ -1567,7 +1567,7 @@ static void ivybridge_parity_error_irq_handler(struct drm_device *dev, u32 iir) return; spin_lock(&dev_priv->irq_lock); - ilk_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev)); + gen5_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev)); spin_unlock(&dev_priv->irq_lock); iir &= GT_PARITY_ERROR(dev); @@ -1622,7 +1622,7 @@ static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) spin_lock(&dev_priv->irq_lock); dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events; - bdw_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events); + gen8_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events); spin_unlock(&dev_priv->irq_lock); queue_work(dev_priv->wq, &dev_priv->rps.work); @@ -1969,7 +1969,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) if (pm_iir & dev_priv->pm_rps_events) { spin_lock(&dev_priv->irq_lock); dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events; - snb_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events); + gen6_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events); spin_unlock(&dev_priv->irq_lock); queue_work(dev_priv->wq, &dev_priv->rps.work); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6093ebdeb7c..9d97a50cae4 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -683,12 +683,12 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev, enum transcoder pch_transcoder, bool enable); -void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); -void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); +void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); +void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask); +void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); +void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); +void gen8_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); +void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); void intel_runtime_pm_disable_interrupts(struct drm_device *dev); void intel_runtime_pm_restore_interrupts(struct drm_device *dev); int intel_get_crtc_scanline(struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6e03851a4fa..25ae4e6d3dd 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3474,7 +3474,7 @@ static void gen8_enable_rps_interrupts(struct drm_device *dev) spin_lock_irq(&dev_priv->irq_lock); WARN_ON(dev_priv->rps.pm_iir); - bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); + gen8_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events); spin_unlock_irq(&dev_priv->irq_lock); } @@ -3485,7 +3485,7 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev) spin_lock_irq(&dev_priv->irq_lock); WARN_ON(dev_priv->rps.pm_iir); - snb_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); + gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); I915_WRITE(GEN6_PMIIR, dev_priv->pm_rps_events); spin_unlock_irq(&dev_priv->irq_lock); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 599709e80a1..b3d8f766fa7 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1004,7 +1004,7 @@ gen5_ring_get_irq(struct intel_engine_cs *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (ring->irq_refcount++ == 0) - ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); + gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); spin_unlock_irqrestore(&dev_priv->irq_lock, flags); return true; @@ -1019,7 +1019,7 @@ gen5_ring_put_irq(struct intel_engine_cs *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (--ring->irq_refcount == 0) - ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); + gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); spin_unlock_irqrestore(&dev_priv->irq_lock, flags); } @@ -1212,7 +1212,7 @@ gen6_ring_get_irq(struct intel_engine_cs *ring) GT_PARITY_ERROR(dev))); else I915_WRITE_IMR(ring, ~ring->irq_enable_mask); - ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask); + gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -1232,7 +1232,7 @@ gen6_ring_put_irq(struct intel_engine_cs *ring) I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); else I915_WRITE_IMR(ring, ~0); - ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask); + gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); } @@ -1250,7 +1250,7 @@ hsw_vebox_get_irq(struct intel_engine_cs *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (ring->irq_refcount++ == 0) { I915_WRITE_IMR(ring, ~ring->irq_enable_mask); - snb_enable_pm_irq(dev_priv, ring->irq_enable_mask); + gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -1270,7 +1270,7 @@ hsw_vebox_put_irq(struct intel_engine_cs *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (--ring->irq_refcount == 0) { I915_WRITE_IMR(ring, ~0); - snb_disable_pm_irq(dev_priv, ring->irq_enable_mask); + gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); } -- cgit v1.2.3-70-g09d2 From d49bdb0e1054d022cc6f88fcecf9c79bae66eab0 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 4 Jul 2014 11:50:31 -0300 Subject: drm/i915: extract and improve gen8_irq_power_well_post_enable Move it from hsw_power_well_post_enable() (intel_pm.c) to i915_irq.c so we can reuse the nice IRQ macros we have there. The main difference is that now we're going to check if the IIR register is non-zero when we try to re-enable the interrupts. Signed-off-by: Paulo Zanoni Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 12 ++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 18 ++---------------- 3 files changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6f19420cc1b..e2e9bb8f4fe 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3478,6 +3478,18 @@ static void gen8_irq_reset(struct drm_device *dev) ibx_irq_reset(dev); } +void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_B, dev_priv->de_irq_mask[PIPE_B], + ~dev_priv->de_irq_mask[PIPE_B]); + GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_C, dev_priv->de_irq_mask[PIPE_C], + ~dev_priv->de_irq_mask[PIPE_C]); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); +} + static void cherryview_irq_preinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9d97a50cae4..bf415df1138 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -693,6 +693,7 @@ void intel_runtime_pm_disable_interrupts(struct drm_device *dev); void intel_runtime_pm_restore_interrupts(struct drm_device *dev); int intel_get_crtc_scanline(struct intel_crtc *crtc); void i9xx_check_fifo_underruns(struct drm_device *dev); +void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv); /* intel_crt.c */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 25ae4e6d3dd..d23ba37e6ab 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5998,7 +5998,6 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv, static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; - unsigned long irqflags; /* * After we re-enable the power well, if we touch VGA register 0x3d5 @@ -6014,21 +6013,8 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); - if (IS_BROADWELL(dev)) { - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B), - dev_priv->de_irq_mask[PIPE_B]); - I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B), - ~dev_priv->de_irq_mask[PIPE_B] | - GEN8_PIPE_VBLANK); - I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C), - dev_priv->de_irq_mask[PIPE_C]); - I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C), - ~dev_priv->de_irq_mask[PIPE_C] | - GEN8_PIPE_VBLANK); - POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C)); - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); - } + if (IS_BROADWELL(dev)) + gen8_irq_power_well_post_enable(dev_priv); } static void hsw_set_power_well(struct drm_i915_private *dev_priv, -- cgit v1.2.3-70-g09d2 From 9df7575f1c751a333b1989d1c7e2b9fc884d9105 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 20 Jun 2014 09:29:20 -0700 Subject: drm/i915: add helper for checking whether IRQs are enabled Now that we use the runtime IRQ enable/disable functions in our suspend path, we can simply check the pm._irqs_disabled flag everywhere. So rename it to catch the users, and add an inline for it to make the checks clear everywhere. Signed-off-by: Jesse Barnes Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 16 ++++++++-------- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 10 +++++++++- drivers/gpu/drm/i915/intel_pm.c | 6 +++--- 7 files changed, 24 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index fc39610fe12..7e72800c5d1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1996,7 +1996,7 @@ static int i915_pc8_status(struct seq_file *m, void *unused) seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->mm.busy)); seq_printf(m, "IRQs disabled: %s\n", - yesno(dev_priv->pm.irqs_disabled)); + yesno(!intel_irqs_enabled(dev_priv))); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7f4f2b74592..8b781f8ad3a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1339,7 +1339,7 @@ struct ilk_wm_values { */ struct i915_runtime_pm { bool suspended; - bool irqs_disabled; + bool _irqs_disabled; }; enum intel_pipe_crc_source { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ef047bce008..ed0b5fc4b6b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1161,7 +1161,7 @@ static int __wait_seqno(struct intel_engine_cs *ring, u32 seqno, unsigned long timeout_expire; int ret; - WARN(dev_priv->pm.irqs_disabled, "IRQs disabled\n"); + WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled"); if (i915_seqno_passed(ring->get_seqno(ring, true), seqno)) return 0; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3ae33e7e9d0..6774f88479e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -136,7 +136,7 @@ ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask) { assert_spin_locked(&dev_priv->irq_lock); - if (WARN_ON(dev_priv->pm.irqs_disabled)) + if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; if ((dev_priv->irq_mask & mask) != 0) { @@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask) { assert_spin_locked(&dev_priv->irq_lock); - if (dev_priv->pm.irqs_disabled) + if (!intel_irqs_enabled(dev_priv)) return; if ((dev_priv->irq_mask & mask) != mask) { @@ -173,7 +173,7 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv, { assert_spin_locked(&dev_priv->irq_lock); - if (WARN_ON(dev_priv->pm.irqs_disabled)) + if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; dev_priv->gt_irq_mask &= ~interrupt_mask; @@ -206,7 +206,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv, assert_spin_locked(&dev_priv->irq_lock); - if (WARN_ON(dev_priv->pm.irqs_disabled)) + if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; new_val = dev_priv->pm_irq_mask; @@ -264,7 +264,7 @@ static void bdw_update_pm_irq(struct drm_i915_private *dev_priv, assert_spin_locked(&dev_priv->irq_lock); - if (WARN_ON(dev_priv->pm.irqs_disabled)) + if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; new_val = dev_priv->pm_irq_mask; @@ -420,7 +420,7 @@ static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, assert_spin_locked(&dev_priv->irq_lock); - if (WARN_ON(dev_priv->pm.irqs_disabled)) + if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; I915_WRITE(SDEIMR, sdeimr); @@ -4774,7 +4774,7 @@ void intel_runtime_pm_disable_interrupts(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; dev->driver->irq_uninstall(dev); - dev_priv->pm.irqs_disabled = true; + dev_priv->pm._irqs_disabled = true; } /* Restore interrupts so we can recover from runtime PM. */ @@ -4782,7 +4782,7 @@ void intel_runtime_pm_restore_interrupts(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - dev_priv->pm.irqs_disabled = false; + dev_priv->pm._irqs_disabled = false; dev->driver->irq_preinstall(dev); dev->driver->irq_postinstall(dev); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 06566d6c328..1cdd1c16d98 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7341,7 +7341,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) * gen-specific and since we only disable LCPLL after we fully disable * the interrupts, the check below should be enough. */ - WARN(!dev_priv->pm.irqs_disabled, "IRQs enabled\n"); + WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n"); } static uint32_t hsw_read_dcomp(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 bf415df1138..8fc68c78322 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -691,11 +691,19 @@ void gen8_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); void intel_runtime_pm_disable_interrupts(struct drm_device *dev); void intel_runtime_pm_restore_interrupts(struct drm_device *dev); +static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv) +{ + /* + * We only use drm_irq_uninstall() at unload and VT switch, so + * this is the only thing we need to check. + */ + return !dev_priv->pm._irqs_disabled; +} + int intel_get_crtc_scanline(struct intel_crtc *crtc); void i9xx_check_fifo_underruns(struct drm_device *dev); void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv); - /* intel_crt.c */ void intel_crt_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d23ba37e6ab..3f88f29a98c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4976,7 +4976,7 @@ void intel_suspend_gt_powersave(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; /* Interrupts should be disabled already to avoid re-arming. */ - WARN_ON(dev->irq_enabled && !dev_priv->pm.irqs_disabled); + WARN_ON(intel_irqs_enabled(dev_priv)); flush_delayed_work(&dev_priv->rps.delayed_resume_work); @@ -4991,7 +4991,7 @@ void intel_disable_gt_powersave(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; /* Interrupts should be disabled already to avoid re-arming. */ - WARN_ON(dev->irq_enabled && !dev_priv->pm.irqs_disabled); + WARN_ON(intel_irqs_enabled(dev_priv)); if (IS_IRONLAKE_M(dev)) { ironlake_disable_drps(dev); @@ -7069,5 +7069,5 @@ void intel_pm_setup(struct drm_device *dev) intel_gen6_powersave_work); dev_priv->pm.suspended = false; - dev_priv->pm.irqs_disabled = false; + dev_priv->pm._irqs_disabled = false; } -- cgit v1.2.3-70-g09d2 From 8dfd1f044c157c7ec329d9bdecb74972393aa612 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 Aug 2014 11:15:56 +0200 Subject: drm/i915: Tune done rc6 enabling output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Power users spot this and then get adventurous and try to adjust module driver options. Nothing good ever came out of that, so hide it better. Reviewed-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3f88f29a98c..f81a8f433a5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3420,10 +3420,10 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode) else mode = 0; } - DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", - (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", - (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", - (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); + DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", + (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", + (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", + (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); } static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6) @@ -3447,8 +3447,8 @@ static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6) mask = INTEL_RC6_ENABLE; if ((enable_rc6 & mask) != enable_rc6) - DRM_INFO("Adjusting RC6 mask to %d (requested %d, valid %d)\n", - enable_rc6 & mask, enable_rc6, mask); + DRM_DEBUG_KMS("Adjusting RC6 mask to %d (requested %d, valid %d)\n", + enable_rc6 & mask, enable_rc6, mask); return enable_rc6 & mask; } -- cgit v1.2.3-70-g09d2 From df662a28c2c099a8ea1aa7cb4334d9df8aba6f95 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 Aug 2014 11:17:25 +0200 Subject: drm/i915: Tune down MCH_SSKPD values warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Users often can't do anything about this since their vendors stopped providing BIOS updates. Also we seem to be able to hack around it with increased latency values, and thus far the only reports have been for screens with really high resolutions. So tune it down to a level where only developers can see it. Also drop some of the end-user fluff. Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f81a8f433a5..72948a05312 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5230,11 +5230,9 @@ static void gen6_check_mch_setup(struct drm_device *dev) uint32_t tmp; tmp = I915_READ(MCH_SSKPD); - if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL) { - DRM_INFO("Wrong MCH_SSKPD value: 0x%08x\n", tmp); - DRM_INFO("This can cause pipe underruns and display issues.\n"); - DRM_INFO("Please upgrade your BIOS to fix this.\n"); - } + if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL) + DRM_DEBUG_KMS("Wrong MCH_SSKPD value: 0x%08x This can cause underruns.\n", + tmp); } static void gen6_init_clock_gating(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 22c5aee39906e19d51b6db9cfbfce1b9f6ecb65a Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 28 Feb 2014 06:50:06 +0800 Subject: drm/i915: Fix drain latency precision multipler for VLV Reviewed-by: Paulo Zanoni Signed-off-by: Zhenyu Wang Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 50 ++++++++++++++++++++--------------------- drivers/gpu/drm/i915/intel_pm.c | 12 +++++----- 2 files changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fe5c27630e9..e4d7607da2c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3863,47 +3863,47 @@ enum punit_power_well { /* drain latency register values*/ #define DRAIN_LATENCY_PRECISION_32 32 -#define DRAIN_LATENCY_PRECISION_16 16 +#define DRAIN_LATENCY_PRECISION_64 64 #define VLV_DDL1 (VLV_DISPLAY_BASE + 0x70050) -#define DDL_CURSORA_PRECISION_32 (1<<31) -#define DDL_CURSORA_PRECISION_16 (0<<31) +#define DDL_CURSORA_PRECISION_64 (1<<31) +#define DDL_CURSORA_PRECISION_32 (0<<31) #define DDL_CURSORA_SHIFT 24 -#define DDL_SPRITEB_PRECISION_32 (1<<23) -#define DDL_SPRITEB_PRECISION_16 (0<<23) +#define DDL_SPRITEB_PRECISION_64 (1<<23) +#define DDL_SPRITEB_PRECISION_32 (0<<23) #define DDL_SPRITEB_SHIFT 16 -#define DDL_SPRITEA_PRECISION_32 (1<<15) -#define DDL_SPRITEA_PRECISION_16 (0<<15) +#define DDL_SPRITEA_PRECISION_64 (1<<15) +#define DDL_SPRITEA_PRECISION_32 (0<<15) #define DDL_SPRITEA_SHIFT 8 -#define DDL_PLANEA_PRECISION_32 (1<<7) -#define DDL_PLANEA_PRECISION_16 (0<<7) +#define DDL_PLANEA_PRECISION_64 (1<<7) +#define DDL_PLANEA_PRECISION_32 (0<<7) #define DDL_PLANEA_SHIFT 0 #define VLV_DDL2 (VLV_DISPLAY_BASE + 0x70054) -#define DDL_CURSORB_PRECISION_32 (1<<31) -#define DDL_CURSORB_PRECISION_16 (0<<31) +#define DDL_CURSORB_PRECISION_64 (1<<31) +#define DDL_CURSORB_PRECISION_32 (0<<31) #define DDL_CURSORB_SHIFT 24 -#define DDL_SPRITED_PRECISION_32 (1<<23) -#define DDL_SPRITED_PRECISION_16 (0<<23) +#define DDL_SPRITED_PRECISION_64 (1<<23) +#define DDL_SPRITED_PRECISION_32 (0<<23) #define DDL_SPRITED_SHIFT 16 -#define DDL_SPRITEC_PRECISION_32 (1<<15) -#define DDL_SPRITEC_PRECISION_16 (0<<15) +#define DDL_SPRITEC_PRECISION_64 (1<<15) +#define DDL_SPRITEC_PRECISION_32 (0<<15) #define DDL_SPRITEC_SHIFT 8 -#define DDL_PLANEB_PRECISION_32 (1<<7) -#define DDL_PLANEB_PRECISION_16 (0<<7) +#define DDL_PLANEB_PRECISION_64 (1<<7) +#define DDL_PLANEB_PRECISION_32 (0<<7) #define DDL_PLANEB_SHIFT 0 #define VLV_DDL3 (VLV_DISPLAY_BASE + 0x70058) -#define DDL_CURSORC_PRECISION_32 (1<<31) -#define DDL_CURSORC_PRECISION_16 (0<<31) +#define DDL_CURSORC_PRECISION_64 (1<<31) +#define DDL_CURSORC_PRECISION_32 (0<<31) #define DDL_CURSORC_SHIFT 24 -#define DDL_SPRITEF_PRECISION_32 (1<<23) -#define DDL_SPRITEF_PRECISION_16 (0<<23) +#define DDL_SPRITEF_PRECISION_64 (1<<23) +#define DDL_SPRITEF_PRECISION_32 (0<<23) #define DDL_SPRITEF_SHIFT 16 -#define DDL_SPRITEE_PRECISION_32 (1<<15) -#define DDL_SPRITEE_PRECISION_16 (0<<15) +#define DDL_SPRITEE_PRECISION_64 (1<<15) +#define DDL_SPRITEE_PRECISION_32 (0<<15) #define DDL_SPRITEE_SHIFT 8 -#define DDL_PLANEC_PRECISION_32 (1<<7) -#define DDL_PLANEC_PRECISION_16 (0<<7) +#define DDL_PLANEC_PRECISION_64 (1<<7) +#define DDL_PLANEC_PRECISION_32 (0<<7) #define DDL_PLANEC_SHIFT 0 /* FIFO watermark sizes etc */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 72948a05312..91edd47e9bc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1288,13 +1288,13 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, entries = (clock / 1000) * pixel_size; *plane_prec_mult = (entries > 256) ? - DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16; + DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32; *plane_dl = (64 * (*plane_prec_mult) * 4) / ((clock / 1000) * pixel_size); entries = (clock / 1000) * 4; /* BPP is always 4 for cursor */ *cursor_prec_mult = (entries > 256) ? - DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16; + DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32; *cursor_dl = (64 * (*cursor_prec_mult) * 4) / ((clock / 1000) * 4); return true; @@ -1320,9 +1320,9 @@ static void vlv_update_drain_latency(struct drm_device *dev) if (vlv_compute_drain_latency(dev, 0, &plane_prec_mult, &planea_dl, &cursor_prec_mult, &cursora_dl)) { cursora_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ? - DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_16; + DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_64; planea_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ? - DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_16; + DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_64; I915_WRITE(VLV_DDL1, cursora_prec | (cursora_dl << DDL_CURSORA_SHIFT) | @@ -1333,9 +1333,9 @@ static void vlv_update_drain_latency(struct drm_device *dev) if (vlv_compute_drain_latency(dev, 1, &plane_prec_mult, &planeb_dl, &cursor_prec_mult, &cursorb_dl)) { cursorb_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ? - DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_16; + DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_64; planeb_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ? - DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_16; + DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_64; I915_WRITE(VLV_DDL2, cursorb_prec | (cursorb_dl << DDL_CURSORB_SHIFT) | -- cgit v1.2.3-70-g09d2 From 69bbeb4ae7b05c094b593b5df4f7a68f713589be Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 28 Jun 2014 00:40:34 +0300 Subject: drm/i915: Fix threshold for choosing 32 vs. 64 precisions for VLV DDL values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DDL registers can hold 7bit numbers. Make the most of those seven bits by adjusting the threshold where we switch between the 64 vs. 32 precision multipliers. Also we compute 'entries' to make the decision about precision, and then we recompute the same value to calculate the actual drain latency. Just use the already calculate 'entries' there. Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 91edd47e9bc..615e341682c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1287,15 +1287,14 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */ entries = (clock / 1000) * pixel_size; - *plane_prec_mult = (entries > 256) ? + *plane_prec_mult = (entries > 128) ? DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32; - *plane_dl = (64 * (*plane_prec_mult) * 4) / ((clock / 1000) * - pixel_size); + *plane_dl = (64 * (*plane_prec_mult) * 4) / entries; entries = (clock / 1000) * 4; /* BPP is always 4 for cursor */ - *cursor_prec_mult = (entries > 256) ? + *cursor_prec_mult = (entries > 128) ? DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32; - *cursor_dl = (64 * (*cursor_prec_mult) * 4) / ((clock / 1000) * 4); + *cursor_dl = (64 * (*cursor_prec_mult) * 4) / entries; return true; } -- cgit v1.2.3-70-g09d2 From 4811ff4f2388727a161ea49c2b0ddca95e44c7f9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 28 Jun 2014 02:04:07 +0300 Subject: drm/i915: Add chv_power_wells[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add chv_power_wells[] so we can start to build up the power well support for chv. Just the "always on" well there initialy. Signed-off-by: Ville Syrjälä Tested-by: Rafael Barbalho Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 615e341682c..7dbd7892b96 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6574,6 +6574,15 @@ static struct i915_power_well vlv_power_wells[] = { }, }; +static struct i915_power_well chv_power_wells[] = { + { + .name = "always-on", + .always_on = 1, + .domains = VLV_ALWAYS_ON_POWER_DOMAINS, + .ops = &i9xx_always_on_power_well_ops, + }, +}; + static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv, enum punit_power_well power_well_id) { @@ -6610,6 +6619,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) } else if (IS_BROADWELL(dev_priv->dev)) { set_power_wells(power_domains, bdw_power_wells); hsw_pwr = power_domains; + } else if (IS_CHERRYVIEW(dev_priv->dev)) { + set_power_wells(power_domains, chv_power_wells); } else if (IS_VALLEYVIEW(dev_priv->dev)) { set_power_wells(power_domains, vlv_power_wells); } else { -- cgit v1.2.3-70-g09d2 From 5d6f7ea752228788eddce0b9e268fa1f0eabdd7f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 28 Jun 2014 02:04:08 +0300 Subject: drm/i915: Add chv cmnlane power wells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHV has two display PHYs so there are also two cmnlane power wells. Add the approriate code to power the wells up/down. Like on VLV we do the cmnreset assert/deassert and the DPLL refclock enabling at approriate times. This code actually works on my bsw. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 89 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e4d7607da2c..c3338ca4ab1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -514,6 +514,7 @@ enum punit_power_well { PUNIT_POWER_WELL_DPIO_TX_C_LANES_23 = 9, PUNIT_POWER_WELL_DPIO_RX0 = 10, PUNIT_POWER_WELL_DPIO_RX1 = 11, + PUNIT_POWER_WELL_DPIO_CMN_D = 12, PUNIT_POWER_WELL_NUM, }; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7dbd7892b96..8a78015dd51 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6254,6 +6254,64 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, vlv_set_power_well(dev_priv, power_well, false); } +static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + enum dpio_phy phy; + + WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC && + power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D); + + /* + * Enable the CRI clock source so we can get at the + * display and the reference clock for VGA + * hotplug / manual detection. + */ + if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) { + phy = DPIO_PHY0; + I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | + DPLL_REFA_CLK_ENABLE_VLV); + I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) | + DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV); + } else { + phy = DPIO_PHY1; + I915_WRITE(DPLL(PIPE_C), I915_READ(DPLL(PIPE_C)) | + DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV); + } + udelay(1); /* >10ns for cmnreset, >0ns for sidereset */ + vlv_set_power_well(dev_priv, power_well, true); + + /* Poll for phypwrgood signal */ + if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1)) + DRM_ERROR("Display PHY %d is not power up\n", phy); + + I915_WRITE(DISPLAY_PHY_CONTROL, + PHY_COM_LANE_RESET_DEASSERT(phy, I915_READ(DISPLAY_PHY_CONTROL))); +} + +static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + enum dpio_phy phy; + + WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC && + power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D); + + if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) { + phy = DPIO_PHY0; + assert_pll_disabled(dev_priv, PIPE_A); + assert_pll_disabled(dev_priv, PIPE_B); + } else { + phy = DPIO_PHY1; + assert_pll_disabled(dev_priv, PIPE_C); + } + + I915_WRITE(DISPLAY_PHY_CONTROL, + PHY_COM_LANE_RESET_ASSERT(phy, I915_READ(DISPLAY_PHY_CONTROL))); + + vlv_set_power_well(dev_priv, power_well, false); +} + static void check_power_well_state(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -6445,6 +6503,18 @@ EXPORT_SYMBOL_GPL(i915_get_cdclk_freq); BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ BIT(POWER_DOMAIN_INIT)) +#define CHV_DPIO_CMN_BC_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ + BIT(POWER_DOMAIN_INIT)) + +#define CHV_DPIO_CMN_D_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ + BIT(POWER_DOMAIN_INIT)) + static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { .sync_hw = i9xx_always_on_power_well_noop, .enable = i9xx_always_on_power_well_noop, @@ -6452,6 +6522,13 @@ static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { .is_enabled = i9xx_always_on_power_well_enabled, }; +static const struct i915_power_well_ops chv_dpio_cmn_power_well_ops = { + .sync_hw = vlv_power_well_sync_hw, + .enable = chv_dpio_cmn_power_well_enable, + .disable = chv_dpio_cmn_power_well_disable, + .is_enabled = vlv_power_well_enabled, +}; + static struct i915_power_well i9xx_always_on_power_well[] = { { .name = "always-on", @@ -6581,6 +6658,18 @@ static struct i915_power_well chv_power_wells[] = { .domains = VLV_ALWAYS_ON_POWER_DOMAINS, .ops = &i9xx_always_on_power_well_ops, }, + { + .name = "dpio-common-bc", + .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS, + .data = PUNIT_POWER_WELL_DPIO_CMN_BC, + .ops = &chv_dpio_cmn_power_well_ops, + }, + { + .name = "dpio-common-d", + .domains = CHV_DPIO_CMN_D_POWER_DOMAINS, + .data = PUNIT_POWER_WELL_DPIO_CMN_D, + .ops = &chv_dpio_cmn_power_well_ops, + }, }; static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv, -- cgit v1.2.3-70-g09d2 From f07057d13c62c5b925725c6e03a0c4d1c0244bef Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 28 Jun 2014 02:04:10 +0300 Subject: drm/i915: Add disp2d power well for chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not sure if it's still there since chv has per-pipe power wells. At least with current Punit this doesn't work. Also the display irq handling would need to be adjusted for pipe C. So leave the code iffed out for now. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8a78015dd51..dc8719f29d0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6658,6 +6658,14 @@ static struct i915_power_well chv_power_wells[] = { .domains = VLV_ALWAYS_ON_POWER_DOMAINS, .ops = &i9xx_always_on_power_well_ops, }, +#if 0 + { + .name = "display", + .domains = VLV_DISPLAY_POWER_DOMAINS, + .data = PUNIT_POWER_WELL_DISP2D, + .ops = &vlv_display_power_well_ops, + }, +#endif { .name = "dpio-common-bc", .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS, -- cgit v1.2.3-70-g09d2 From 26972b0a80091ccece1cbd9422772ae625a612f6 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 28 Jun 2014 02:04:11 +0300 Subject: drm/i915: Add per-pipe power wells for chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHV has a power well for each pipe. Add the code to deal with them. The Punit in current hardware doesn't seem ready for this yet, so leave it iffed out. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 12 ++++ drivers/gpu/drm/i915/intel_pm.c | 126 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c3338ca4ab1..9d54aee6f8c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -501,6 +501,18 @@ #define DSPFREQSTAT_MASK (0x3 << DSPFREQSTAT_SHIFT) #define DSPFREQGUAR_SHIFT 14 #define DSPFREQGUAR_MASK (0x3 << DSPFREQGUAR_SHIFT) +#define _DP_SSC(val, pipe) ((val) << (2 * (pipe))) +#define DP_SSC_MASK(pipe) _DP_SSC(0x3, (pipe)) +#define DP_SSC_PWR_ON(pipe) _DP_SSC(0x0, (pipe)) +#define DP_SSC_CLK_GATE(pipe) _DP_SSC(0x1, (pipe)) +#define DP_SSC_RESET(pipe) _DP_SSC(0x2, (pipe)) +#define DP_SSC_PWR_GATE(pipe) _DP_SSC(0x3, (pipe)) +#define _DP_SSS(val, pipe) ((val) << (2 * (pipe) + 16)) +#define DP_SSS_MASK(pipe) _DP_SSS(0x3, (pipe)) +#define DP_SSS_PWR_ON(pipe) _DP_SSS(0x0, (pipe)) +#define DP_SSS_CLK_GATE(pipe) _DP_SSS(0x1, (pipe)) +#define DP_SSS_RESET(pipe) _DP_SSS(0x2, (pipe)) +#define DP_SSS_PWR_GATE(pipe) _DP_SSS(0x3, (pipe)) /* See the PUNIT HAS v0.8 for the below bits */ enum punit_power_well { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index dc8719f29d0..95b3ca5964e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6312,6 +6312,95 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, vlv_set_power_well(dev_priv, power_well, false); } +static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + enum pipe pipe = power_well->data; + bool enabled; + u32 state, ctrl; + + mutex_lock(&dev_priv->rps.hw_lock); + + state = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe); + /* + * We only ever set the power-on and power-gate states, anything + * else is unexpected. + */ + WARN_ON(state != DP_SSS_PWR_ON(pipe) && state != DP_SSS_PWR_GATE(pipe)); + enabled = state == DP_SSS_PWR_ON(pipe); + + /* + * A transient state at this point would mean some unexpected party + * is poking at the power controls too. + */ + ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSC_MASK(pipe); + WARN_ON(ctrl << 16 != state); + + mutex_unlock(&dev_priv->rps.hw_lock); + + return enabled; +} + +static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well, + bool enable) +{ + enum pipe pipe = power_well->data; + u32 state; + u32 ctrl; + + state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe); + + mutex_lock(&dev_priv->rps.hw_lock); + +#define COND \ + ((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe)) == state) + + if (COND) + goto out; + + ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); + ctrl &= ~DP_SSC_MASK(pipe); + ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe); + vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, ctrl); + + if (wait_for(COND, 100)) + DRM_ERROR("timout setting power well state %08x (%08x)\n", + state, + vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ)); + +#undef COND + +out: + mutex_unlock(&dev_priv->rps.hw_lock); +} + +static void chv_pipe_power_well_sync_hw(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + chv_set_pipe_power_well(dev_priv, power_well, power_well->count > 0); +} + +static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + WARN_ON_ONCE(power_well->data != PIPE_A && + power_well->data != PIPE_B && + power_well->data != PIPE_C); + + chv_set_pipe_power_well(dev_priv, power_well, true); +} + +static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + WARN_ON_ONCE(power_well->data != PIPE_A && + power_well->data != PIPE_B && + power_well->data != PIPE_C); + + chv_set_pipe_power_well(dev_priv, power_well, false); +} + static void check_power_well_state(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { @@ -6503,6 +6592,18 @@ EXPORT_SYMBOL_GPL(i915_get_cdclk_freq); BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ BIT(POWER_DOMAIN_INIT)) +#define CHV_PIPE_A_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PIPE_A) | \ + BIT(POWER_DOMAIN_INIT)) + +#define CHV_PIPE_B_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PIPE_B) | \ + BIT(POWER_DOMAIN_INIT)) + +#define CHV_PIPE_C_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PIPE_C) | \ + BIT(POWER_DOMAIN_INIT)) + #define CHV_DPIO_CMN_BC_POWER_DOMAINS ( \ BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \ BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \ @@ -6522,6 +6623,13 @@ static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { .is_enabled = i9xx_always_on_power_well_enabled, }; +static const struct i915_power_well_ops chv_pipe_power_well_ops = { + .sync_hw = chv_pipe_power_well_sync_hw, + .enable = chv_pipe_power_well_enable, + .disable = chv_pipe_power_well_disable, + .is_enabled = chv_pipe_power_well_enabled, +}; + static const struct i915_power_well_ops chv_dpio_cmn_power_well_ops = { .sync_hw = vlv_power_well_sync_hw, .enable = chv_dpio_cmn_power_well_enable, @@ -6665,6 +6773,24 @@ static struct i915_power_well chv_power_wells[] = { .data = PUNIT_POWER_WELL_DISP2D, .ops = &vlv_display_power_well_ops, }, + { + .name = "pipe-a", + .domains = CHV_PIPE_A_POWER_DOMAINS, + .data = PIPE_A, + .ops = &chv_pipe_power_well_ops, + }, + { + .name = "pipe-b", + .domains = CHV_PIPE_B_POWER_DOMAINS, + .data = PIPE_B, + .ops = &chv_pipe_power_well_ops, + }, + { + .name = "pipe-c", + .domains = CHV_PIPE_C_POWER_DOMAINS, + .data = PIPE_C, + .ops = &chv_pipe_power_well_ops, + }, #endif { .name = "dpio-common-bc", -- cgit v1.2.3-70-g09d2 From 8258356537871cf579868002552a0ed1762b0487 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 28 Jun 2014 02:04:12 +0300 Subject: drm/i915: Add chv port B and C TX wells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the TX wells for ports B and C just like on VLV. Again Punit doesn't seem ready (or the wells don't even exist anymore) so leave it iffed out. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 95b3ca5964e..59157635d41 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6804,6 +6804,36 @@ static struct i915_power_well chv_power_wells[] = { .data = PUNIT_POWER_WELL_DPIO_CMN_D, .ops = &chv_dpio_cmn_power_well_ops, }, +#if 0 + { + .name = "dpio-tx-b-01", + .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS | + VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS, + .ops = &vlv_dpio_power_well_ops, + .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01, + }, + { + .name = "dpio-tx-b-23", + .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS | + VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS, + .ops = &vlv_dpio_power_well_ops, + .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23, + }, + { + .name = "dpio-tx-c-01", + .domains = VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS | + VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS, + .ops = &vlv_dpio_power_well_ops, + .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01, + }, + { + .name = "dpio-tx-c-23", + .domains = VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS | + VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS, + .ops = &vlv_dpio_power_well_ops, + .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23, + }, +#endif }; static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv, -- cgit v1.2.3-70-g09d2 From 2ce147f36dc5a1f3b49abd8ce3164ad0f04ec863 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 28 Jun 2014 02:04:13 +0300 Subject: drm/i915: Add chv port D TX wells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the TX wells for port D. The Punit subsystem numbers are a total guess at this time. Also I'm not sure these even exist. Certainly the Punit in current hardware doesn't deal with these. Signed-off-by: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_pm.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9d54aee6f8c..e01a1a0b961 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -527,6 +527,10 @@ enum punit_power_well { PUNIT_POWER_WELL_DPIO_RX0 = 10, PUNIT_POWER_WELL_DPIO_RX1 = 11, PUNIT_POWER_WELL_DPIO_CMN_D = 12, + /* FIXME: guesswork below */ + PUNIT_POWER_WELL_DPIO_TX_D_LANES_01 = 13, + PUNIT_POWER_WELL_DPIO_TX_D_LANES_23 = 14, + PUNIT_POWER_WELL_DPIO_RX2 = 15, PUNIT_POWER_WELL_NUM, }; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 59157635d41..f4a1837c231 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6616,6 +6616,15 @@ EXPORT_SYMBOL_GPL(i915_get_cdclk_freq); BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ BIT(POWER_DOMAIN_INIT)) +#define CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \ + BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ + BIT(POWER_DOMAIN_INIT)) + +#define CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \ + BIT(POWER_DOMAIN_INIT)) + static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { .sync_hw = i9xx_always_on_power_well_noop, .enable = i9xx_always_on_power_well_noop, @@ -6833,6 +6842,20 @@ static struct i915_power_well chv_power_wells[] = { .ops = &vlv_dpio_power_well_ops, .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23, }, + { + .name = "dpio-tx-d-01", + .domains = CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS | + CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS, + .ops = &vlv_dpio_power_well_ops, + .data = PUNIT_POWER_WELL_DPIO_TX_D_LANES_01, + }, + { + .name = "dpio-tx-d-23", + .domains = CHV_DPIO_TX_D_LANES_01_POWER_DOMAINS | + CHV_DPIO_TX_D_LANES_23_POWER_DOMAINS, + .ops = &vlv_dpio_power_well_ops, + .data = PUNIT_POWER_WELL_DPIO_TX_D_LANES_23, + }, #endif }; -- cgit v1.2.3-70-g09d2 From a5043453aa2412ece984373294529d177324c901 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 28 Jun 2014 02:04:18 +0300 Subject: drm/i915: Split a few long debug prints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split some WM debug prints to multiple lines. This shouldn't hurt grappability since the important part is at the start and the rest is just repeated stuff for each pipe. Signed-off-by: Ville Syrjälä Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f4a1837c231..a318cd5ad8e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1387,7 +1387,8 @@ static void valleyview_update_wm(struct drm_crtc *crtc) plane_sr = cursor_sr = 0; } - DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", + DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, " + "B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", planea_wm, cursora_wm, planeb_wm, cursorb_wm, plane_sr, cursor_sr); @@ -1443,7 +1444,8 @@ static void g4x_update_wm(struct drm_crtc *crtc) plane_sr = cursor_sr = 0; } - DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", + DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, " + "B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", planea_wm, cursora_wm, planeb_wm, cursorb_wm, plane_sr, cursor_sr); -- cgit v1.2.3-70-g09d2 From da46f936bb0396f6a0fb87c2786f541e9f19a73c Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 1 Aug 2014 02:04:45 -0700 Subject: drm/i915: Introduce FBC False Color for debug purposes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this bit enabled, HW changes the color when compressing frames for debug purposes. ALthough the simple way to enable a single bit is over intel_reg_write, this value is overwriten on next update_fbc so depending on the workload it is not possible to set this bit with intel-gpu-tools. So this patch introduces a persistent way to enable false color over debugfs. v2: Use DEFINE_SIMPLE_ATTRIBUTE as Daniel suggested v3: (Ville) only do false color for IVB+ since according to spec bit is MBZ before IVB. v4: We don't have FBC on valleyview nor on cherryview (Ben) v5: s/!HAS_PCH_SPLIT/!HAS_FBC (Ville) Cc: Ville Syrjälä Reviewed-by: Ben Widawsky Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 42 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 3 +++ 4 files changed, 48 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9e737b771c4..aea1a819c77 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1433,6 +1433,47 @@ static int i915_fbc_status(struct seq_file *m, void *unused) return 0; } +static int i915_fbc_fc_get(void *data, u64 *val) +{ + struct drm_device *dev = data; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev)) + return -ENODEV; + + drm_modeset_lock_all(dev); + *val = dev_priv->fbc.false_color; + drm_modeset_unlock_all(dev); + + return 0; +} + +static int i915_fbc_fc_set(void *data, u64 val) +{ + struct drm_device *dev = data; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 reg; + + if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev)) + return -ENODEV; + + drm_modeset_lock_all(dev); + + reg = I915_READ(ILK_DPFC_CONTROL); + dev_priv->fbc.false_color = val; + + I915_WRITE(ILK_DPFC_CONTROL, val ? + (reg | FBC_CTL_FALSE_COLOR) : + (reg & ~FBC_CTL_FALSE_COLOR)); + + drm_modeset_unlock_all(dev); + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(i915_fbc_fc_fops, + i915_fbc_fc_get, i915_fbc_fc_set, + "%llu\n"); + static int i915_ips_status(struct seq_file *m, void *unused) { struct drm_info_node *node = m->private; @@ -3957,6 +3998,7 @@ static const struct i915_debugfs_files { {"i915_pri_wm_latency", &i915_pri_wm_latency_fops}, {"i915_spr_wm_latency", &i915_spr_wm_latency_fops}, {"i915_cur_wm_latency", &i915_cur_wm_latency_fops}, + {"i915_fbc_false_color", &i915_fbc_fc_fops}, }; void intel_display_crc_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c3beb08813c..ce30bb3ed56 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -637,6 +637,8 @@ struct i915_fbc { struct drm_mm_node compressed_fb; struct drm_mm_node *compressed_llb; + bool false_color; + struct intel_fbc_work { struct delayed_work work; struct drm_crtc *crtc; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 35553aa0a82..ca37febbc2a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1540,6 +1540,7 @@ enum punit_power_well { /* Framebuffer compression for Ironlake */ #define ILK_DPFC_CB_BASE 0x43200 #define ILK_DPFC_CONTROL 0x43208 +#define FBC_CTL_FALSE_COLOR (1<<10) /* The bit 28-8 is reserved */ #define DPFC_RESERVED (0x1FFFFF00) #define ILK_DPFC_RECOMP_CTL 0x4320c diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a318cd5ad8e..ab80df2909e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -309,6 +309,9 @@ static void gen7_enable_fbc(struct drm_crtc *crtc) dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; + if (dev_priv->fbc.false_color) + dpfc_ctl |= FBC_CTL_FALSE_COLOR; + I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); if (IS_IVYBRIDGE(dev)) { -- cgit v1.2.3-70-g09d2 From 0a56067469bde6662ce7c89a3d290171f878bac4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 11 Jun 2014 16:51:18 +0300 Subject: drm/i915: Fill out the FWx watermark register defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add defines for all the watermark registers on modernish gmch platforms. VLV has increased the number of bits available for certain watermaks so expand the masks appropriately. Also vlv and chv have added some extra FW registers. Not sure what happened on chv because a new register called FW9 is now at the offset where FW7 was on vlv, while FW7 and FW8 (another new register) have been moved off somewhere else. Oh well, well just need two defines for FW7 then. v2: Fix DSPHOWM1 offset (Paulo) Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 138 +++++++++++++++++++++++++++++++++++----- drivers/gpu/drm/i915/intel_pm.c | 11 ++-- 2 files changed, 130 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5ebac620bbc..a87eb18b4c9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3865,28 +3865,136 @@ enum punit_power_well { #define DSPARB_BEND_SHIFT 9 /* on 855 */ #define DSPARB_AEND_SHIFT 0 +/* pnv/gen4/g4x/vlv/chv */ #define DSPFW1 (dev_priv->info.display_mmio_offset + 0x70034) -#define DSPFW_SR_SHIFT 23 -#define DSPFW_SR_MASK (0x1ff<<23) -#define DSPFW_CURSORB_SHIFT 16 -#define DSPFW_CURSORB_MASK (0x3f<<16) -#define DSPFW_PLANEB_SHIFT 8 -#define DSPFW_PLANEB_MASK (0x7f<<8) -#define DSPFW_PLANEA_MASK (0x7f) +#define DSPFW_SR_SHIFT 23 +#define DSPFW_SR_MASK (0x1ff<<23) +#define DSPFW_CURSORB_SHIFT 16 +#define DSPFW_CURSORB_MASK (0x3f<<16) +#define DSPFW_PLANEB_SHIFT 8 +#define DSPFW_PLANEB_MASK (0x7f<<8) +#define DSPFW_PLANEB_MASK_VLV (0xff<<8) /* vlv/chv */ +#define DSPFW_PLANEA_SHIFT 0 +#define DSPFW_PLANEA_MASK (0x7f<<0) +#define DSPFW_PLANEA_MASK_VLV (0xff<<0) /* vlv/chv */ #define DSPFW2 (dev_priv->info.display_mmio_offset + 0x70038) -#define DSPFW_CURSORA_MASK 0x00003f00 -#define DSPFW_CURSORA_SHIFT 8 -#define DSPFW_PLANEC_MASK (0x7f) +#define DSPFW_FBC_SR_EN (1<<31) /* g4x */ +#define DSPFW_FBC_SR_SHIFT 28 +#define DSPFW_FBC_SR_MASK (0x7<<28) /* g4x */ +#define DSPFW_FBC_HPLL_SR_SHIFT 24 +#define DSPFW_FBC_HPLL_SR_MASK (0xf<<24) /* g4x */ +#define DSPFW_SPRITEB_SHIFT (16) +#define DSPFW_SPRITEB_MASK (0x7f<<16) /* g4x */ +#define DSPFW_SPRITEB_MASK_VLV (0xff<<16) /* vlv/chv */ +#define DSPFW_CURSORA_SHIFT 8 +#define DSPFW_CURSORA_MASK (0x3f<<8) +#define DSPFW_PLANEC_SHIFT_OLD 0 +#define DSPFW_PLANEC_MASK_OLD (0x7f<<0) /* pre-gen4 sprite C */ +#define DSPFW_SPRITEA_SHIFT 0 +#define DSPFW_SPRITEA_MASK (0x7f<<0) /* g4x */ +#define DSPFW_SPRITEA_MASK_VLV (0xff<<0) /* vlv/chv */ #define DSPFW3 (dev_priv->info.display_mmio_offset + 0x7003c) -#define DSPFW_HPLL_SR_EN (1<<31) -#define DSPFW_CURSOR_SR_SHIFT 24 +#define DSPFW_HPLL_SR_EN (1<<31) #define PINEVIEW_SELF_REFRESH_EN (1<<30) +#define DSPFW_CURSOR_SR_SHIFT 24 #define DSPFW_CURSOR_SR_MASK (0x3f<<24) #define DSPFW_HPLL_CURSOR_SHIFT 16 #define DSPFW_HPLL_CURSOR_MASK (0x3f<<16) -#define DSPFW_HPLL_SR_MASK (0x1ff) -#define DSPFW4 (dev_priv->info.display_mmio_offset + 0x70070) -#define DSPFW7 (dev_priv->info.display_mmio_offset + 0x7007c) +#define DSPFW_HPLL_SR_SHIFT 0 +#define DSPFW_HPLL_SR_MASK (0x1ff<<0) + +/* vlv/chv */ +#define DSPFW4 (VLV_DISPLAY_BASE + 0x70070) +#define DSPFW_SPRITEB_WM1_SHIFT 16 +#define DSPFW_SPRITEB_WM1_MASK (0xff<<16) +#define DSPFW_CURSORA_WM1_SHIFT 8 +#define DSPFW_CURSORA_WM1_MASK (0x3f<<8) +#define DSPFW_SPRITEA_WM1_SHIFT 0 +#define DSPFW_SPRITEA_WM1_MASK (0xff<<0) +#define DSPFW5 (VLV_DISPLAY_BASE + 0x70074) +#define DSPFW_PLANEB_WM1_SHIFT 24 +#define DSPFW_PLANEB_WM1_MASK (0xff<<24) +#define DSPFW_PLANEA_WM1_SHIFT 16 +#define DSPFW_PLANEA_WM1_MASK (0xff<<16) +#define DSPFW_CURSORB_WM1_SHIFT 8 +#define DSPFW_CURSORB_WM1_MASK (0x3f<<8) +#define DSPFW_CURSOR_SR_WM1_SHIFT 0 +#define DSPFW_CURSOR_SR_WM1_MASK (0x3f<<0) +#define DSPFW6 (VLV_DISPLAY_BASE + 0x70078) +#define DSPFW_SR_WM1_SHIFT 0 +#define DSPFW_SR_WM1_MASK (0x1ff<<0) +#define DSPFW7 (VLV_DISPLAY_BASE + 0x7007c) +#define DSPFW7_CHV (VLV_DISPLAY_BASE + 0x700b4) /* wtf #1? */ +#define DSPFW_SPRITED_WM1_SHIFT 24 +#define DSPFW_SPRITED_WM1_MASK (0xff<<24) +#define DSPFW_SPRITED_SHIFT 16 +#define DSPFW_SPRITED_MASK (0xff<<16) +#define DSPFW_SPRITEC_WM1_SHIFT 8 +#define DSPFW_SPRITEC_WM1_MASK (0xff<<8) +#define DSPFW_SPRITEC_SHIFT 0 +#define DSPFW_SPRITEC_MASK (0xff<<0) +#define DSPFW8_CHV (VLV_DISPLAY_BASE + 0x700b8) +#define DSPFW_SPRITEF_WM1_SHIFT 24 +#define DSPFW_SPRITEF_WM1_MASK (0xff<<24) +#define DSPFW_SPRITEF_SHIFT 16 +#define DSPFW_SPRITEF_MASK (0xff<<16) +#define DSPFW_SPRITEE_WM1_SHIFT 8 +#define DSPFW_SPRITEE_WM1_MASK (0xff<<8) +#define DSPFW_SPRITEE_SHIFT 0 +#define DSPFW_SPRITEE_MASK (0xff<<0) +#define DSPFW9_CHV (VLV_DISPLAY_BASE + 0x7007c) /* wtf #2? */ +#define DSPFW_PLANEC_WM1_SHIFT 24 +#define DSPFW_PLANEC_WM1_MASK (0xff<<24) +#define DSPFW_PLANEC_SHIFT 16 +#define DSPFW_PLANEC_MASK (0xff<<16) +#define DSPFW_CURSORC_WM1_SHIFT 8 +#define DSPFW_CURSORC_WM1_MASK (0x3f<<16) +#define DSPFW_CURSORC_SHIFT 0 +#define DSPFW_CURSORC_MASK (0x3f<<0) + +/* vlv/chv high order bits */ +#define DSPHOWM (VLV_DISPLAY_BASE + 0x70064) +#define DSPFW_SR_HI_SHIFT 24 +#define DSPFW_SR_HI_MASK (1<<24) +#define DSPFW_SPRITEF_HI_SHIFT 23 +#define DSPFW_SPRITEF_HI_MASK (1<<23) +#define DSPFW_SPRITEE_HI_SHIFT 22 +#define DSPFW_SPRITEE_HI_MASK (1<<22) +#define DSPFW_PLANEC_HI_SHIFT 21 +#define DSPFW_PLANEC_HI_MASK (1<<21) +#define DSPFW_SPRITED_HI_SHIFT 20 +#define DSPFW_SPRITED_HI_MASK (1<<20) +#define DSPFW_SPRITEC_HI_SHIFT 16 +#define DSPFW_SPRITEC_HI_MASK (1<<16) +#define DSPFW_PLANEB_HI_SHIFT 12 +#define DSPFW_PLANEB_HI_MASK (1<<12) +#define DSPFW_SPRITEB_HI_SHIFT 8 +#define DSPFW_SPRITEB_HI_MASK (1<<8) +#define DSPFW_SPRITEA_HI_SHIFT 4 +#define DSPFW_SPRITEA_HI_MASK (1<<4) +#define DSPFW_PLANEA_HI_SHIFT 0 +#define DSPFW_PLANEA_HI_MASK (1<<0) +#define DSPHOWM1 (VLV_DISPLAY_BASE + 0x70068) +#define DSPFW_SR_WM1_HI_SHIFT 24 +#define DSPFW_SR_WM1_HI_MASK (1<<24) +#define DSPFW_SPRITEF_WM1_HI_SHIFT 23 +#define DSPFW_SPRITEF_WM1_HI_MASK (1<<23) +#define DSPFW_SPRITEE_WM1_HI_SHIFT 22 +#define DSPFW_SPRITEE_WM1_HI_MASK (1<<22) +#define DSPFW_PLANEC_WM1_HI_SHIFT 21 +#define DSPFW_PLANEC_WM1_HI_MASK (1<<21) +#define DSPFW_SPRITED_WM1_HI_SHIFT 20 +#define DSPFW_SPRITED_WM1_HI_MASK (1<<20) +#define DSPFW_SPRITEC_WM1_HI_SHIFT 16 +#define DSPFW_SPRITEC_WM1_HI_MASK (1<<16) +#define DSPFW_PLANEB_WM1_HI_SHIFT 12 +#define DSPFW_PLANEB_WM1_HI_MASK (1<<12) +#define DSPFW_SPRITEB_WM1_HI_SHIFT 8 +#define DSPFW_SPRITEB_WM1_HI_MASK (1<<8) +#define DSPFW_SPRITEA_WM1_HI_SHIFT 4 +#define DSPFW_SPRITEA_WM1_HI_MASK (1<<4) +#define DSPFW_PLANEA_WM1_HI_SHIFT 0 +#define DSPFW_PLANEA_WM1_HI_MASK (1<<0) /* drain latency register values*/ #define DRAIN_LATENCY_PRECISION_32 32 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ab80df2909e..0f9164d854d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1400,7 +1400,7 @@ static void valleyview_update_wm(struct drm_crtc *crtc) (plane_sr << DSPFW_SR_SHIFT) | (cursorb_wm << DSPFW_CURSORB_SHIFT) | (planeb_wm << DSPFW_PLANEB_SHIFT) | - planea_wm); + (planea_wm << DSPFW_PLANEA_SHIFT)); I915_WRITE(DSPFW2, (I915_READ(DSPFW2) & ~DSPFW_CURSORA_MASK) | (cursora_wm << DSPFW_CURSORA_SHIFT)); @@ -1457,7 +1457,7 @@ static void g4x_update_wm(struct drm_crtc *crtc) (plane_sr << DSPFW_SR_SHIFT) | (cursorb_wm << DSPFW_CURSORB_SHIFT) | (planeb_wm << DSPFW_PLANEB_SHIFT) | - planea_wm); + (planea_wm << DSPFW_PLANEA_SHIFT)); I915_WRITE(DSPFW2, (I915_READ(DSPFW2) & ~DSPFW_CURSORA_MASK) | (cursora_wm << DSPFW_CURSORA_SHIFT)); @@ -1531,8 +1531,11 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) /* 965 has limitations... */ I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | - (8 << 16) | (8 << 8) | (8 << 0)); - I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); + (8 << DSPFW_CURSORB_SHIFT) | + (8 << DSPFW_PLANEB_SHIFT) | + (8 << DSPFW_PLANEA_SHIFT)); + I915_WRITE(DSPFW2, (8 << DSPFW_CURSORA_SHIFT) | + (8 << DSPFW_PLANEC_SHIFT_OLD)); /* update cursor SR watermark */ I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); -- cgit v1.2.3-70-g09d2 From 1abc4dc7e2ca7886b6b06bcf2ff1451702c83f9b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 26 Jun 2014 17:02:37 +0300 Subject: drm/i915: Parametrize VLV_DDL registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VLV/CHV DDL registers are uniform, and neatly enough the register offsets are sane so we can easily unify them to a single set of defines and just pass the pipe as the parameter to compute the register offset. Note that we now fill out the drain latency for pipe C on CHV which we didn't do before. The rest of the pipe C watermarks are still untouched but that will be remedied later by adding a proper cherryview_update_wm() function. v2: Add a note about CHV pipe C changes (Paulo) Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 54 ++++++++++------------------------------- drivers/gpu/drm/i915/intel_pm.c | 52 ++++++++++++++++++--------------------- 2 files changed, 36 insertions(+), 70 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a87eb18b4c9..fbdb08f4cd7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3999,47 +3999,19 @@ enum punit_power_well { /* drain latency register values*/ #define DRAIN_LATENCY_PRECISION_32 32 #define DRAIN_LATENCY_PRECISION_64 64 -#define VLV_DDL1 (VLV_DISPLAY_BASE + 0x70050) -#define DDL_CURSORA_PRECISION_64 (1<<31) -#define DDL_CURSORA_PRECISION_32 (0<<31) -#define DDL_CURSORA_SHIFT 24 -#define DDL_SPRITEB_PRECISION_64 (1<<23) -#define DDL_SPRITEB_PRECISION_32 (0<<23) -#define DDL_SPRITEB_SHIFT 16 -#define DDL_SPRITEA_PRECISION_64 (1<<15) -#define DDL_SPRITEA_PRECISION_32 (0<<15) -#define DDL_SPRITEA_SHIFT 8 -#define DDL_PLANEA_PRECISION_64 (1<<7) -#define DDL_PLANEA_PRECISION_32 (0<<7) -#define DDL_PLANEA_SHIFT 0 - -#define VLV_DDL2 (VLV_DISPLAY_BASE + 0x70054) -#define DDL_CURSORB_PRECISION_64 (1<<31) -#define DDL_CURSORB_PRECISION_32 (0<<31) -#define DDL_CURSORB_SHIFT 24 -#define DDL_SPRITED_PRECISION_64 (1<<23) -#define DDL_SPRITED_PRECISION_32 (0<<23) -#define DDL_SPRITED_SHIFT 16 -#define DDL_SPRITEC_PRECISION_64 (1<<15) -#define DDL_SPRITEC_PRECISION_32 (0<<15) -#define DDL_SPRITEC_SHIFT 8 -#define DDL_PLANEB_PRECISION_64 (1<<7) -#define DDL_PLANEB_PRECISION_32 (0<<7) -#define DDL_PLANEB_SHIFT 0 - -#define VLV_DDL3 (VLV_DISPLAY_BASE + 0x70058) -#define DDL_CURSORC_PRECISION_64 (1<<31) -#define DDL_CURSORC_PRECISION_32 (0<<31) -#define DDL_CURSORC_SHIFT 24 -#define DDL_SPRITEF_PRECISION_64 (1<<23) -#define DDL_SPRITEF_PRECISION_32 (0<<23) -#define DDL_SPRITEF_SHIFT 16 -#define DDL_SPRITEE_PRECISION_64 (1<<15) -#define DDL_SPRITEE_PRECISION_32 (0<<15) -#define DDL_SPRITEE_SHIFT 8 -#define DDL_PLANEC_PRECISION_64 (1<<7) -#define DDL_PLANEC_PRECISION_32 (0<<7) -#define DDL_PLANEC_SHIFT 0 +#define VLV_DDL(pipe) (VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe)) +#define DDL_CURSOR_PRECISION_64 (1<<31) +#define DDL_CURSOR_PRECISION_32 (0<<31) +#define DDL_CURSOR_SHIFT 24 +#define DDL_SPRITE1_PRECISION_64 (1<<23) +#define DDL_SPRITE1_PRECISION_32 (0<<23) +#define DDL_SPRITE1_SHIFT 16 +#define DDL_SPRITE0_PRECISION_64 (1<<15) +#define DDL_SPRITE0_PRECISION_32 (0<<15) +#define DDL_SPRITE0_SHIFT 8 +#define DDL_PLANE_PRECISION_64 (1<<7) +#define DDL_PLANE_PRECISION_32 (0<<7) +#define DDL_PLANE_SHIFT 0 /* FIFO watermark sizes etc */ #define G4X_FIFO_LINE_SIZE 64 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0f9164d854d..2573c696755 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1313,35 +1313,29 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, static void vlv_update_drain_latency(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - int planea_prec, planea_dl, planeb_prec, planeb_dl; - int cursora_prec, cursora_dl, cursorb_prec, cursorb_dl; - int plane_prec_mult, cursor_prec_mult; /* Precision multiplier is - either 16 or 32 */ - - /* For plane A, Cursor A */ - if (vlv_compute_drain_latency(dev, 0, &plane_prec_mult, &planea_dl, - &cursor_prec_mult, &cursora_dl)) { - cursora_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ? - DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_64; - planea_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ? - DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_64; - - I915_WRITE(VLV_DDL1, cursora_prec | - (cursora_dl << DDL_CURSORA_SHIFT) | - planea_prec | planea_dl); - } - - /* For plane B, Cursor B */ - if (vlv_compute_drain_latency(dev, 1, &plane_prec_mult, &planeb_dl, - &cursor_prec_mult, &cursorb_dl)) { - cursorb_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ? - DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_64; - planeb_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ? - DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_64; - - I915_WRITE(VLV_DDL2, cursorb_prec | - (cursorb_dl << DDL_CURSORB_SHIFT) | - planeb_prec | planeb_dl); + enum pipe pipe; + + for_each_pipe(pipe) { + int plane_prec, plane_dl; + int cursor_prec, cursor_dl; + int plane_prec_mult, cursor_prec_mult; + + if (!vlv_compute_drain_latency(dev, pipe, &plane_prec_mult, &plane_dl, + &cursor_prec_mult, &cursor_dl)) + continue; + + /* + * FIXME CHV spec still lists 16 and 32 as the precision + * values. Need to figure out if spec is outdated or what. + */ + cursor_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_64) ? + DDL_CURSOR_PRECISION_64 : DDL_CURSOR_PRECISION_32; + plane_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_64) ? + DDL_PLANE_PRECISION_64 : DDL_PLANE_PRECISION_32; + + I915_WRITE(VLV_DDL(pipe), cursor_prec | + (cursor_dl << DDL_CURSOR_SHIFT) | + plane_prec | (plane_dl << DDL_PLANE_SHIFT)); } } -- cgit v1.2.3-70-g09d2 From 41aad816d7061f6cc3d92f39fc655f034bbfb1c0 Mon Sep 17 00:00:00 2001 From: Gajanan Bhat Date: Wed, 16 Jul 2014 18:24:03 +0530 Subject: drm/i915: Update DDL only for current CRTC Instead of looping through all CRTCs, update DDL for current CRTC for which watermark is being updated. CHV is confirmed to have precision of 32/64 which is same as VLV. Reviewed-by: Imre Deak Signed-off-by: Gajanan Bhat Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2573c696755..0feeae845f1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1310,24 +1310,17 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, * latency value. */ -static void vlv_update_drain_latency(struct drm_device *dev) +static void vlv_update_drain_latency(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe; - - for_each_pipe(pipe) { - int plane_prec, plane_dl; - int cursor_prec, cursor_dl; - int plane_prec_mult, cursor_prec_mult; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + int plane_prec, plane_dl; + int cursor_prec, cursor_dl; + int plane_prec_mult, cursor_prec_mult; - if (!vlv_compute_drain_latency(dev, pipe, &plane_prec_mult, &plane_dl, - &cursor_prec_mult, &cursor_dl)) - continue; - - /* - * FIXME CHV spec still lists 16 and 32 as the precision - * values. Need to figure out if spec is outdated or what. - */ + if (vlv_compute_drain_latency(dev, pipe, &plane_prec_mult, &plane_dl, + &cursor_prec_mult, &cursor_dl)) { cursor_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_64) ? DDL_CURSOR_PRECISION_64 : DDL_CURSOR_PRECISION_32; plane_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_64) ? @@ -1352,7 +1345,7 @@ static void valleyview_update_wm(struct drm_crtc *crtc) unsigned int enabled = 0; bool cxsr_enabled; - vlv_update_drain_latency(dev); + vlv_update_drain_latency(crtc); if (g4x_compute_wm0(dev, PIPE_A, &valleyview_wm_info, latency_ns, -- cgit v1.2.3-70-g09d2 From 3c2777fd2faa5d1c1d5867baa086f2fd8b05479e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 26 Jun 2014 17:03:06 +0300 Subject: drm/i915: Add cherryview_update_wm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHV has a third pipe so we need to compute the watermarks for its planes. Add cherryview_update_wm() to do just that. v2: Rebase on top of Imre's cxsr changes v3: Pass crtc to vlv_update_drain_latency() Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 81 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0feeae845f1..da43e30ad60 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1399,6 +1399,85 @@ static void valleyview_update_wm(struct drm_crtc *crtc) intel_set_memory_cxsr(dev_priv, true); } +static void cherryview_update_wm(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + static const int sr_latency_ns = 12000; + struct drm_i915_private *dev_priv = dev->dev_private; + int planea_wm, planeb_wm, planec_wm; + int cursora_wm, cursorb_wm, cursorc_wm; + int plane_sr, cursor_sr; + int ignore_plane_sr, ignore_cursor_sr; + unsigned int enabled = 0; + bool cxsr_enabled; + + vlv_update_drain_latency(crtc); + + if (g4x_compute_wm0(dev, PIPE_A, + &valleyview_wm_info, latency_ns, + &valleyview_cursor_wm_info, latency_ns, + &planea_wm, &cursora_wm)) + enabled |= 1 << PIPE_A; + + if (g4x_compute_wm0(dev, PIPE_B, + &valleyview_wm_info, latency_ns, + &valleyview_cursor_wm_info, latency_ns, + &planeb_wm, &cursorb_wm)) + enabled |= 1 << PIPE_B; + + if (g4x_compute_wm0(dev, PIPE_C, + &valleyview_wm_info, latency_ns, + &valleyview_cursor_wm_info, latency_ns, + &planec_wm, &cursorc_wm)) + enabled |= 1 << PIPE_C; + + if (single_plane_enabled(enabled) && + g4x_compute_srwm(dev, ffs(enabled) - 1, + sr_latency_ns, + &valleyview_wm_info, + &valleyview_cursor_wm_info, + &plane_sr, &ignore_cursor_sr) && + g4x_compute_srwm(dev, ffs(enabled) - 1, + 2*sr_latency_ns, + &valleyview_wm_info, + &valleyview_cursor_wm_info, + &ignore_plane_sr, &cursor_sr)) { + cxsr_enabled = true; + } else { + cxsr_enabled = false; + intel_set_memory_cxsr(dev_priv, false); + plane_sr = cursor_sr = 0; + } + + DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, " + "B: plane=%d, cursor=%d, C: plane=%d, cursor=%d, " + "SR: plane=%d, cursor=%d\n", + planea_wm, cursora_wm, + planeb_wm, cursorb_wm, + planec_wm, cursorc_wm, + plane_sr, cursor_sr); + + I915_WRITE(DSPFW1, + (plane_sr << DSPFW_SR_SHIFT) | + (cursorb_wm << DSPFW_CURSORB_SHIFT) | + (planeb_wm << DSPFW_PLANEB_SHIFT) | + (planea_wm << DSPFW_PLANEA_SHIFT)); + I915_WRITE(DSPFW2, + (I915_READ(DSPFW2) & ~DSPFW_CURSORA_MASK) | + (cursora_wm << DSPFW_CURSORA_SHIFT)); + I915_WRITE(DSPFW3, + (I915_READ(DSPFW3) & ~DSPFW_CURSOR_SR_MASK) | + (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); + I915_WRITE(DSPFW9_CHV, + (I915_READ(DSPFW9_CHV) & ~(DSPFW_PLANEC_MASK | + DSPFW_CURSORC_MASK)) | + (planec_wm << DSPFW_PLANEC_SHIFT) | + (cursorc_wm << DSPFW_CURSORC_SHIFT)); + + if (cxsr_enabled) + intel_set_memory_cxsr(dev_priv, true); +} + static void g4x_update_wm(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -7119,7 +7198,7 @@ void intel_init_pm(struct drm_device *dev) else if (INTEL_INFO(dev)->gen == 8) dev_priv->display.init_clock_gating = gen8_init_clock_gating; } else if (IS_CHERRYVIEW(dev)) { - dev_priv->display.update_wm = valleyview_update_wm; + dev_priv->display.update_wm = cherryview_update_wm; dev_priv->display.init_clock_gating = cherryview_init_clock_gating; } else if (IS_VALLEYVIEW(dev)) { -- cgit v1.2.3-70-g09d2 From 3dd7b97458e8aa2d8985b46622d226fa635071e7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 27 Jun 2014 19:49:57 +0300 Subject: drm/i915: Hack to tie both common lanes together on chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It looks like frobbing the cmnreset line on pne PHY disturbs the other PHY on chv. The result is a black screen. On HDMI it's just a flash of black, but DP usually falls over and can't get back up. As a workaround set up the power domains so that both common lane wells power up and down together. I also tried leaving the cmnreset deasserted even the if the power well goes down but that didn't seem acceptable to the PHY. Reviewed-by: Rafael Barbalho Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index da43e30ad60..aaae2281596 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6877,13 +6877,23 @@ static struct i915_power_well chv_power_wells[] = { #endif { .name = "dpio-common-bc", - .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS, + /* + * XXX: cmnreset for one PHY seems to disturb the other. + * As a workaround keep both powered on at the same + * time for now. + */ + .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | CHV_DPIO_CMN_D_POWER_DOMAINS, .data = PUNIT_POWER_WELL_DPIO_CMN_BC, .ops = &chv_dpio_cmn_power_well_ops, }, { .name = "dpio-common-d", - .domains = CHV_DPIO_CMN_D_POWER_DOMAINS, + /* + * XXX: cmnreset for one PHY seems to disturb the other. + * As a workaround keep both powered on at the same + * time for now. + */ + .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | CHV_DPIO_CMN_D_POWER_DOMAINS, .data = PUNIT_POWER_WELL_DPIO_CMN_D, .ops = &chv_dpio_cmn_power_well_ops, }, -- cgit v1.2.3-70-g09d2 From efd814b73cfcf4ed1cb561561d8df6daccb3ceb6 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 27 Jun 2014 19:52:13 +0300 Subject: drm/i915: Polish the chv cmnlane resrt macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the semi-funky cmnlane assert/deassert macros with something a bit more conventional. Also protect the macro arguments properly (also for PHY_POWERGOOD()). Reviewed-by: Rafael Barbalho Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 7 ++----- drivers/gpu/drm/i915/intel_pm.c | 8 ++++---- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fbdb08f4cd7..468ef09d698 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1697,12 +1697,9 @@ enum punit_power_well { #define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240) #define DPLL_PORTD_READY_MASK (0xf) #define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100) -#define PHY_COM_LANE_RESET_DEASSERT(phy, val) \ - ((phy == DPIO_PHY0) ? (val | 1) : (val | 2)) -#define PHY_COM_LANE_RESET_ASSERT(phy, val) \ - ((phy == DPIO_PHY0) ? (val & ~1) : (val & ~2)) +#define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy)) #define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104) -#define PHY_POWERGOOD(phy) ((phy == DPIO_PHY0) ? (1<<31) : (1<<30)) +#define PHY_POWERGOOD(phy) (((phy) == DPIO_PHY0) ? (1<<31) : (1<<30)) /* * The i830 generation, in LVDS mode, defines P1 as the bit number set within diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index aaae2281596..42bb329b2d0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6359,8 +6359,8 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1)) DRM_ERROR("Display PHY %d is not power up\n", phy); - I915_WRITE(DISPLAY_PHY_CONTROL, - PHY_COM_LANE_RESET_DEASSERT(phy, I915_READ(DISPLAY_PHY_CONTROL))); + I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) | + PHY_COM_LANE_RESET_DEASSERT(phy)); } static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, @@ -6380,8 +6380,8 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, assert_pll_disabled(dev_priv, PIPE_C); } - I915_WRITE(DISPLAY_PHY_CONTROL, - PHY_COM_LANE_RESET_ASSERT(phy, I915_READ(DISPLAY_PHY_CONTROL))); + I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) & + ~PHY_COM_LANE_RESET_DEASSERT(phy)); vlv_set_power_well(dev_priv, power_well, false); } -- cgit v1.2.3-70-g09d2 From 0948c2651413d56c90d7ee9c99d75bef82d4c351 Mon Sep 17 00:00:00 2001 From: Gajanan Bhat Date: Thu, 7 Aug 2014 01:58:24 +0530 Subject: drm/i915: Generalize drain latency computation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modify drain latency computation to use it for any plane. Same function can be used for primary, cursor and sprite planes. v2: Adressed review comments by Imre and Ville. - Moved clock round up in separate patch - Added WARN check for clock and pixel size - Simplified bit masking - Use cursor_base instead of reg read v3: Changed to bitwise shorthand operator for plane_dl assignment. Signed-off-by: Gajanan Bhat Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 87 +++++++++++++++++++++++------------------ 2 files changed, 51 insertions(+), 37 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 468ef09d698..d0cff563056 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4009,6 +4009,7 @@ enum punit_power_well { #define DDL_PLANE_PRECISION_64 (1<<7) #define DDL_PLANE_PRECISION_32 (0<<7) #define DDL_PLANE_SHIFT 0 +#define DRAIN_LATENCY_MASK 0x7f /* FIFO watermark sizes etc */ #define G4X_FIFO_LINE_SIZE 64 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 42bb329b2d0..de27439636e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1271,33 +1271,24 @@ static bool g4x_compute_srwm(struct drm_device *dev, display, cursor); } -static bool vlv_compute_drain_latency(struct drm_device *dev, - int plane, - int *plane_prec_mult, - int *plane_dl, - int *cursor_prec_mult, - int *cursor_dl) +static bool vlv_compute_drain_latency(struct drm_crtc *crtc, + int pixel_size, + int *prec_mult, + int *drain_latency) { - struct drm_crtc *crtc; - int clock, pixel_size; int entries; + int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; - crtc = intel_get_crtc_for_plane(dev, plane); - if (!intel_crtc_active(crtc)) + if (WARN(clock == 0, "Pixel clock is zero!\n")) return false; - clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; - pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */ + if (WARN(pixel_size == 0, "Pixel size is zero!\n")) + return false; entries = (clock / 1000) * pixel_size; - *plane_prec_mult = (entries > 128) ? - DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32; - *plane_dl = (64 * (*plane_prec_mult) * 4) / entries; - - entries = (clock / 1000) * 4; /* BPP is always 4 for cursor */ - *cursor_prec_mult = (entries > 128) ? - DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32; - *cursor_dl = (64 * (*cursor_prec_mult) * 4) / entries; + *prec_mult = (entries > 128) ? DRAIN_LATENCY_PRECISION_64 : + DRAIN_LATENCY_PRECISION_32; + *drain_latency = (64 * (*prec_mult) * 4) / entries; return true; } @@ -1312,24 +1303,46 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, static void vlv_update_drain_latency(struct drm_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe = to_intel_crtc(crtc)->pipe; - int plane_prec, plane_dl; - int cursor_prec, cursor_dl; - int plane_prec_mult, cursor_prec_mult; - - if (vlv_compute_drain_latency(dev, pipe, &plane_prec_mult, &plane_dl, - &cursor_prec_mult, &cursor_dl)) { - cursor_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_64) ? - DDL_CURSOR_PRECISION_64 : DDL_CURSOR_PRECISION_32; - plane_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_64) ? - DDL_PLANE_PRECISION_64 : DDL_PLANE_PRECISION_32; - - I915_WRITE(VLV_DDL(pipe), cursor_prec | - (cursor_dl << DDL_CURSOR_SHIFT) | - plane_prec | (plane_dl << DDL_PLANE_SHIFT)); + struct drm_i915_private *dev_priv = crtc->dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pixel_size; + int drain_latency; + enum pipe pipe = intel_crtc->pipe; + int plane_prec, prec_mult, plane_dl; + + plane_dl = I915_READ(VLV_DDL(pipe)) & ~(DDL_PLANE_PRECISION_64 | + DRAIN_LATENCY_MASK | DDL_CURSOR_PRECISION_64 | + (DRAIN_LATENCY_MASK << DDL_CURSOR_SHIFT)); + + if (!intel_crtc_active(crtc)) { + I915_WRITE(VLV_DDL(pipe), plane_dl); + return; + } + + /* Primary plane Drain Latency */ + pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */ + if (vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, &drain_latency)) { + plane_prec = (prec_mult == DRAIN_LATENCY_PRECISION_64) ? + DDL_PLANE_PRECISION_64 : + DDL_PLANE_PRECISION_32; + plane_dl |= plane_prec | drain_latency; } + + /* Cursor Drain Latency + * BPP is always 4 for cursor + */ + pixel_size = 4; + + /* Program cursor DL only if it is enabled */ + if (intel_crtc->cursor_base && + vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, &drain_latency)) { + plane_prec = (prec_mult == DRAIN_LATENCY_PRECISION_64) ? + DDL_CURSOR_PRECISION_64 : + DDL_CURSOR_PRECISION_32; + plane_dl |= plane_prec | (drain_latency << DDL_CURSOR_SHIFT); + } + + I915_WRITE(VLV_DDL(pipe), plane_dl); } #define single_plane_enabled(mask) is_power_of_2(mask) -- cgit v1.2.3-70-g09d2 From a398e9c79eea74ba2f3f24ac08902661682f008c Mon Sep 17 00:00:00 2001 From: Gajanan Bhat Date: Tue, 5 Aug 2014 23:15:54 +0530 Subject: drm/i915: Round-up clock and limit drain latency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round up clock computation and limit drain latency to maximum of 0x7F. Signed-off-by: Gajanan Bhat Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index de27439636e..19bd7212f4a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1285,11 +1285,14 @@ static bool vlv_compute_drain_latency(struct drm_crtc *crtc, if (WARN(pixel_size == 0, "Pixel size is zero!\n")) return false; - entries = (clock / 1000) * pixel_size; + entries = DIV_ROUND_UP(clock, 1000) * pixel_size; *prec_mult = (entries > 128) ? DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32; *drain_latency = (64 * (*prec_mult) * 4) / entries; + if (*drain_latency > DRAIN_LATENCY_MASK) + *drain_latency = DRAIN_LATENCY_MASK; + return true; } -- cgit v1.2.3-70-g09d2 From 01e184cc85d4516cab0ecea7c2c43a2dd3ad432b Mon Sep 17 00:00:00 2001 From: Gajanan Bhat Date: Thu, 7 Aug 2014 17:03:30 +0530 Subject: drm/i915: Add sprite watermark programming for VLV and CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Program DDL register as part of sprite watermark programming for CHV and VLV. v2: Rename DRAIN_LATENCY_MAX by DRAIN_LATENCY_MASK v3: Addressed review comments by Ville - Changed Sprite DDL definitions to more generic to avoid multiple if-else - Changed bit masking to customary form - Changed to bitwise shorthand operator for sprite_dl assignment Signed-off-by: Gajanan Bhat Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 9 +++------ drivers/gpu/drm/i915/intel_pm.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d0cff563056..7a6cc69cdc2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4000,12 +4000,9 @@ enum punit_power_well { #define DDL_CURSOR_PRECISION_64 (1<<31) #define DDL_CURSOR_PRECISION_32 (0<<31) #define DDL_CURSOR_SHIFT 24 -#define DDL_SPRITE1_PRECISION_64 (1<<23) -#define DDL_SPRITE1_PRECISION_32 (0<<23) -#define DDL_SPRITE1_SHIFT 16 -#define DDL_SPRITE0_PRECISION_64 (1<<15) -#define DDL_SPRITE0_PRECISION_32 (0<<15) -#define DDL_SPRITE0_SHIFT 8 +#define DDL_SPRITE_PRECISION_64(sprite) (1<<(15+8*(sprite))) +#define DDL_SPRITE_PRECISION_32(sprite) (0<<(15+8*(sprite))) +#define DDL_SPRITE_SHIFT(sprite) (8+8*(sprite)) #define DDL_PLANE_PRECISION_64 (1<<7) #define DDL_PLANE_PRECISION_32 (0<<7) #define DDL_PLANE_SHIFT 0 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 19bd7212f4a..41de760bf1d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1494,6 +1494,37 @@ static void cherryview_update_wm(struct drm_crtc *crtc) intel_set_memory_cxsr(dev_priv, true); } +static void valleyview_update_sprite_wm(struct drm_plane *plane, + struct drm_crtc *crtc, + uint32_t sprite_width, + uint32_t sprite_height, + int pixel_size, + bool enabled, bool scaled) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int pipe = to_intel_plane(plane)->pipe; + int sprite = to_intel_plane(plane)->plane; + int drain_latency; + int plane_prec; + int sprite_dl; + int prec_mult; + + sprite_dl = I915_READ(VLV_DDL(pipe)) & ~(DDL_SPRITE_PRECISION_64(sprite) | + (DRAIN_LATENCY_MASK << DDL_SPRITE_SHIFT(sprite))); + + if (enabled && vlv_compute_drain_latency(crtc, pixel_size, &prec_mult, + &drain_latency)) { + plane_prec = (prec_mult == DRAIN_LATENCY_PRECISION_64) ? + DDL_SPRITE_PRECISION_64(sprite) : + DDL_SPRITE_PRECISION_32(sprite); + sprite_dl |= plane_prec | + (drain_latency << DDL_SPRITE_SHIFT(sprite)); + } + + I915_WRITE(VLV_DDL(pipe), sprite_dl); +} + static void g4x_update_wm(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -7225,10 +7256,12 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.init_clock_gating = gen8_init_clock_gating; } else if (IS_CHERRYVIEW(dev)) { dev_priv->display.update_wm = cherryview_update_wm; + dev_priv->display.update_sprite_wm = valleyview_update_sprite_wm; dev_priv->display.init_clock_gating = cherryview_init_clock_gating; } else if (IS_VALLEYVIEW(dev)) { dev_priv->display.update_wm = valleyview_update_wm; + dev_priv->display.update_sprite_wm = valleyview_update_sprite_wm; dev_priv->display.init_clock_gating = valleyview_init_clock_gating; } else if (IS_PINEVIEW(dev)) { -- cgit v1.2.3-70-g09d2 From 1bee20175f27b46427f10290fdd4a79334d41a60 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Sat, 9 Aug 2014 23:00:58 +0100 Subject: drm/i915: Remove set but unused 'gt_perf_status' Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 41de760bf1d..12f4e143328 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3719,7 +3719,6 @@ static void gen6_enable_rps(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; u32 rp_state_cap; - u32 gt_perf_status; u32 rc6vids, pcu_mbox = 0, rc6_mask = 0; u32 gtfifodbg; int rc6_mode; @@ -3744,7 +3743,6 @@ static void gen6_enable_rps(struct drm_device *dev) gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); - gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); parse_rp_state_cap(dev_priv, rp_state_cap); -- cgit v1.2.3-70-g09d2 From 48404c1e53d4e15d7e3e77cd2c8f3f22973ef38e Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Fri, 22 Aug 2014 14:06:04 +0530 Subject: drm/i915: Add 180 degree primary plane rotation support Primary planes support 180 degree rotation. Expose the feature through rotation drm property. v2: Calculating linear/tiled offsets based on pipe source width and height. Added 180 degree rotation support in ironlake_update_plane. v3: Checking if CRTC is active before issueing update_plane. Added wait for vblank to make sure we dont overtake page flips. Disabling FBC since it does not work with rotated planes. v4: Updated rotation checks for pending flips, fbc disable. Creating rotation property only for Gen4 onwards. Property resetting as part of lastclose. v5: Resetting property in i915_driver_lastclose properly for planes and crtcs. Fixed linear offset calculation that was off by 1 w.r.t width in i9xx_update_plane and ironlake_update_plane. Removed tab based indentation and unnecessary braces in intel_crtc_set_property and intel_update_fbc. FBC and flip related checks should be done only for valid crtcs. v6: Minor nits in FBC disable checks for comments in intel_crtc_set_property and positioning the disable code in intel_update_fbc. v7: In case rotation property on inactive crtc is updated, we return successfully printing debug log as crtc is inactive and only property change is preserved. v8: update_plane is changed to update_primary_plane, crtc->fb is changed to crtc->primary->fb and return value of update_primary_plane is ignored. v9: added rotation property to primary plane instead of crtc. Removing reset of rotation property from lastclose. rotation_property is moved to drm_mode_config, so drm layer will take care of resetting. Adding updation of fbc when rotation is set to 0. Allowing rotation only if value is different than old one. v10: Calling intel_primary_plane_setplane instead of update_primary_plane in set_property(Daniel). v11: Using same set_property function for both primary and sprite, Adding primary plane specific code in the same function (Matt). v12: Removing disabling/ enabling of fbc from set_property because it is done from intel_pipe_set_base. Other formatting v13: we need to call disable_fbc before changing the rotation to 180, disable_fbc from intel_pipe_set_base gets called very late, that will be used to re-enable fbc if rotation is set to 0 (Ville). Testcase: igt/kms_rotation_crc Signed-off-by: Uma Shankar Signed-off-by: Sagar Kamble Signed-off-by: Sonika Jindal [danvet: Add FIXME to explain why we need the open-coded update_fbc hunk to disable fbc when rotated 180 degree. And make checkpatch happier.] Acked-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 75 ++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_drv.h | 3 ++ drivers/gpu/drm/i915/intel_pm.c | 6 +++ drivers/gpu/drm/i915/intel_sprite.c | 8 ++-- 5 files changed, 85 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 203062e9345..142ac523f97 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4214,6 +4214,7 @@ enum punit_power_well { #define DISPPLANE_NO_LINE_DOUBLE 0 #define DISPPLANE_STEREO_POLARITY_FIRST 0 #define DISPPLANE_STEREO_POLARITY_SECOND (1<<18) +#define DISPPLANE_ROTATE_180 (1<<15) #define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* Ironlake */ #define DISPPLANE_TILED (1<<10) #define _DSPAADDR 0x70184 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f072b75d606..ae218e083dc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2378,6 +2378,9 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, unsigned long linear_offset; u32 dspcntr; u32 reg = DSPCNTR(plane); + int pixel_size; + + pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); if (!intel_crtc->primary_enabled) { I915_WRITE(reg, 0); @@ -2444,8 +2447,6 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, if (IS_G4X(dev)) dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; - I915_WRITE(reg, dspcntr); - linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); if (INTEL_INFO(dev)->gen >= 4) { @@ -2458,6 +2459,21 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, intel_crtc->dspaddr_offset = linear_offset; } + if (to_intel_plane(crtc->primary)->rotation == BIT(DRM_ROTATE_180)) { + dspcntr |= DISPPLANE_ROTATE_180; + + x += (intel_crtc->config.pipe_src_w - 1); + y += (intel_crtc->config.pipe_src_h - 1); + + /* Finding the last pixel of the last line of the display + data and adding to linear_offset*/ + linear_offset += + (intel_crtc->config.pipe_src_h - 1) * fb->pitches[0] + + (intel_crtc->config.pipe_src_w - 1) * pixel_size; + } + + I915_WRITE(reg, dspcntr); + DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", i915_gem_obj_ggtt_offset(obj), linear_offset, x, y, fb->pitches[0]); @@ -2484,6 +2500,9 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc, unsigned long linear_offset; u32 dspcntr; u32 reg = DSPCNTR(plane); + int pixel_size; + + pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); if (!intel_crtc->primary_enabled) { I915_WRITE(reg, 0); @@ -2532,14 +2551,28 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc, if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; - I915_WRITE(reg, dspcntr); - linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); intel_crtc->dspaddr_offset = intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, fb->bits_per_pixel / 8, fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; + if (to_intel_plane(crtc->primary)->rotation == BIT(DRM_ROTATE_180)) { + dspcntr |= DISPPLANE_ROTATE_180; + + if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { + x += (intel_crtc->config.pipe_src_w - 1); + y += (intel_crtc->config.pipe_src_h - 1); + + /* Finding the last pixel of the last line of the display + data and adding to linear_offset*/ + linear_offset += + (intel_crtc->config.pipe_src_h - 1) * fb->pitches[0] + + (intel_crtc->config.pipe_src_w - 1) * pixel_size; + } + } + + I915_WRITE(reg, dspcntr); DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", i915_gem_obj_ggtt_offset(obj), linear_offset, x, y, @@ -11562,6 +11595,7 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_w, uint32_t src_h) { struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); @@ -11674,6 +11708,24 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, mutex_unlock(&dev->struct_mutex); } else { + if (intel_crtc && intel_crtc->active && + intel_crtc->primary_enabled) { + /* + * FBC does not work on some platforms for rotated + * planes, so disable it when rotation is not 0 and + * update it when rotation is set back to 0. + * + * FIXME: This is redundant with the fbc update done in + * the primary plane enable function except that that + * one is done too late. We eventually need to unify + * this. + */ + if (INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && + dev_priv->fbc.plane == intel_crtc->plane && + intel_plane->rotation != BIT(DRM_ROTATE_0)) { + intel_disable_fbc(dev); + } + } ret = intel_pipe_set_base(crtc, src.x1, src.y1, fb); if (ret) return ret; @@ -11707,6 +11759,7 @@ static const struct drm_plane_funcs intel_primary_plane_funcs = { .update_plane = intel_primary_plane_setplane, .disable_plane = intel_primary_plane_disable, .destroy = intel_plane_destroy, + .set_property = intel_plane_set_property }; static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, @@ -11724,6 +11777,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, primary->max_downscale = 1; primary->pipe = pipe; primary->plane = pipe; + primary->rotation = BIT(DRM_ROTATE_0); if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) primary->plane = !pipe; @@ -11739,6 +11793,19 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, &intel_primary_plane_funcs, intel_primary_formats, num_formats, DRM_PLANE_TYPE_PRIMARY); + + if (INTEL_INFO(dev)->gen >= 4) { + if (!dev->mode_config.rotation_property) + dev->mode_config.rotation_property = + drm_mode_create_rotation_property(dev, + BIT(DRM_ROTATE_0) | + BIT(DRM_ROTATE_180)); + if (dev->mode_config.rotation_property) + drm_object_attach_property(&primary->base.base, + dev->mode_config.rotation_property, + primary->rotation); + } + return &primary->base; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d683a209024..2466b2bc909 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1093,6 +1093,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); void intel_flush_primary_plane(struct drm_i915_private *dev_priv, enum plane plane); +int intel_plane_set_property(struct drm_plane *plane, + struct drm_property *prop, + uint64_t val); int intel_plane_restore(struct drm_plane *plane); void intel_plane_disable(struct drm_plane *plane); int intel_sprite_set_colorkey(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c8f744c418f..1ab3e117644 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -581,6 +581,12 @@ void intel_update_fbc(struct drm_device *dev) DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n"); goto out_disable; } + if (INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && + to_intel_plane(crtc->primary)->rotation != BIT(DRM_ROTATE_0)) { + if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE)) + DRM_DEBUG_KMS("Rotation unsupported, disabling\n"); + goto out_disable; + } /* If the kernel debugger is active, always disable compression */ if (in_dbg_master()) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 0bdb00b7c59..fd5f27182a0 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1218,9 +1218,9 @@ out_unlock: return ret; } -static int intel_plane_set_property(struct drm_plane *plane, - struct drm_property *prop, - uint64_t val) +int intel_plane_set_property(struct drm_plane *plane, + struct drm_property *prop, + uint64_t val) { struct drm_device *dev = plane->dev; struct intel_plane *intel_plane = to_intel_plane(plane); @@ -1249,7 +1249,7 @@ int intel_plane_restore(struct drm_plane *plane) if (!plane->crtc || !plane->fb) return 0; - return intel_update_plane(plane, plane->crtc, plane->fb, + return plane->funcs->update_plane(plane, plane->crtc, plane->fb, intel_plane->crtc_x, intel_plane->crtc_y, intel_plane->crtc_w, intel_plane->crtc_h, intel_plane->src_x, intel_plane->src_y, -- cgit v1.2.3-70-g09d2 From 055e393fa3ade8cb91d8229f1c76ca9a7b23b8b3 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Mon, 18 Aug 2014 13:49:10 +0100 Subject: drm/i915: Use dev_priv as first argument of for_each_pipe() Chris has decided that enough is enough. It's time to fixup dev Vs dev_priv. This is a modest contribution to the crusade. v2: Still use INTEL_INFO(), for the (mythical!) case we want to hardcode the info struct with defines (Chris) Rename the macro argument from 'dev' to 'dev_priv' (Jani) v3: Use names unlikely to be used as macro arguments (Chris) Suggested-by: Chris Wilson Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 10 +++--- drivers/gpu/drm/i915/i915_dma.c | 4 +-- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_irq.c | 65 ++++++++++++++++++------------------ drivers/gpu/drm/i915/intel_display.c | 16 +++++---- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_panel.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 17 +++++----- 8 files changed, 60 insertions(+), 59 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b2c4cf8a246..8246cfea9ab 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -662,7 +662,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) I915_READ(VLV_IIR_RW)); seq_printf(m, "Display IMR:\t%08x\n", I915_READ(VLV_IMR)); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) seq_printf(m, "Pipe %c stat:\t%08x\n", pipe_name(pipe), I915_READ(PIPESTAT(pipe))); @@ -702,7 +702,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) i, I915_READ(GEN8_GT_IER(i))); } - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) { seq_printf(m, "Pipe %c power disabled\n", @@ -749,7 +749,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) I915_READ(VLV_IIR_RW)); seq_printf(m, "Display IMR:\t%08x\n", I915_READ(VLV_IMR)); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) seq_printf(m, "Pipe %c stat:\t%08x\n", pipe_name(pipe), I915_READ(PIPESTAT(pipe))); @@ -785,7 +785,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) I915_READ(IIR)); seq_printf(m, "Interrupt mask: %08x\n", I915_READ(IMR)); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) seq_printf(m, "Pipe %c stat: %08x\n", pipe_name(pipe), I915_READ(PIPESTAT(pipe))); @@ -4188,7 +4188,7 @@ void intel_display_crc_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe; - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; pipe_crc->opened = false; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 3f676f904f7..f19dbff0e73 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1528,10 +1528,10 @@ static void intel_device_info_runtime_init(struct drm_device *dev) info = (struct intel_device_info *)&dev_priv->info; if (IS_VALLEYVIEW(dev)) - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) info->num_sprites[pipe] = 2; else - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) info->num_sprites[pipe] = 1; if (i915.disable_display) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9c3677e4448..de334d78e07 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -163,7 +163,8 @@ enum hpd_pin { I915_GEM_DOMAIN_INSTRUCTION | \ I915_GEM_DOMAIN_VERTEX) -#define for_each_pipe(p) for ((p) = 0; (p) < INTEL_INFO(dev)->num_pipes; (p)++) +#define for_each_pipe(__dev_priv, __p) \ + for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++) #define for_each_sprite(p, s) for ((s) = 0; (s) < INTEL_INFO(dev)->num_sprites[(p)]; (s)++) #define for_each_crtc(dev, crtc) \ diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8b158f02bd0..8883a48c08b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -238,7 +238,7 @@ static bool ivb_can_enable_err_int(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); if (crtc->cpu_fifo_underrun_disabled) @@ -296,7 +296,7 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); if (crtc->pch_fifo_underrun_disabled) @@ -2020,7 +2020,7 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) int pipe; spin_lock(&dev_priv->irq_lock); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int reg; u32 mask, iir_bit = 0; @@ -2065,7 +2065,7 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir) } spin_unlock(&dev_priv->irq_lock); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) intel_pipe_handle_vblank(dev, pipe); @@ -2234,7 +2234,7 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) DRM_ERROR("PCH poison interrupt\n"); if (pch_iir & SDE_FDI_MASK) - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", pipe_name(pipe), I915_READ(FDI_RX_IIR(pipe))); @@ -2265,7 +2265,7 @@ static void ivb_err_int_handler(struct drm_device *dev) if (err_int & ERR_INT_POISON) DRM_ERROR("Poison interrupt\n"); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) { if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) @@ -2342,7 +2342,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) DRM_DEBUG_DRIVER("Audio CP change interrupt\n"); if (pch_iir & SDE_FDI_MASK_CPT) - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", pipe_name(pipe), I915_READ(FDI_RX_IIR(pipe))); @@ -2365,7 +2365,7 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) if (de_iir & DE_POISON) DRM_ERROR("Poison interrupt\n"); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (de_iir & DE_PIPE_VBLANK(pipe)) intel_pipe_handle_vblank(dev, pipe); @@ -2415,7 +2415,7 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) if (de_iir & DE_GSE_IVB) intel_opregion_asle_intr(dev); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (de_iir & (DE_PIPE_VBLANK_IVB(pipe))) intel_pipe_handle_vblank(dev, pipe); @@ -2562,7 +2562,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) DRM_ERROR("The master control interrupt lied (DE PORT)!\n"); } - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { uint32_t pipe_iir; if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe))) @@ -2781,7 +2781,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev) if (eir & I915_ERROR_MEMORY_REFRESH) { pr_err("memory refresh error:\n"); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) pr_err("pipe %c stat: 0x%08x\n", pipe_name(pipe), I915_READ(PIPESTAT(pipe))); /* pipestat has already been acked */ @@ -3459,7 +3459,7 @@ static void valleyview_irq_preinstall(struct drm_device *dev) I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); I915_WRITE(VLV_IIR, 0xffffffff); I915_WRITE(VLV_IMR, 0xffffffff); @@ -3485,7 +3485,7 @@ static void gen8_irq_reset(struct drm_device *dev) gen8_gt_irq_reset(dev_priv); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) if (intel_display_power_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); @@ -3528,7 +3528,7 @@ static void cherryview_irq_preinstall(struct drm_device *dev) I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); I915_WRITE(VLV_IMR, 0xffffffff); @@ -3825,7 +3825,6 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) { - struct drm_device *dev = dev_priv->dev; uint32_t de_pipe_masked = GEN8_PIPE_PRIMARY_FLIP_DONE | GEN8_PIPE_CDCLK_CRC_DONE | GEN8_DE_PIPE_IRQ_FAULT_ERRORS; @@ -3836,7 +3835,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked; dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked; - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) if (intel_display_power_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, @@ -3881,12 +3880,12 @@ static int cherryview_irq_postinstall(struct drm_device *dev) */ dev_priv->irq_mask = ~enable_mask; - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) i915_enable_pipestat(dev_priv, pipe, pipestat_enable); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); @@ -3923,7 +3922,7 @@ static void valleyview_irq_uninstall(struct drm_device *dev) I915_WRITE(VLV_MASTER_IER, 0); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); I915_WRITE(HWSTAM, 0xffffffff); @@ -3985,7 +3984,7 @@ do { \ I915_WRITE(PORT_HOTPLUG_EN, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0xffff); I915_WRITE(VLV_IMR, 0xffffffff); @@ -4009,7 +4008,7 @@ static void i8xx_irq_preinstall(struct drm_device * dev) struct drm_i915_private *dev_priv = dev->dev_private; int pipe; - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE16(IMR, 0xffff); I915_WRITE16(IER, 0x0); @@ -4109,7 +4108,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) "Command parser error, iir 0x%08x", iir); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); @@ -4129,7 +4128,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) if (iir & I915_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[RCS]); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int plane = pipe; if (HAS_FBC(dev)) plane = !plane; @@ -4157,7 +4156,7 @@ static void i8xx_irq_uninstall(struct drm_device * dev) struct drm_i915_private *dev_priv = dev->dev_private; int pipe; - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { /* Clear enable bits; then clear status bits */ I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe))); @@ -4178,7 +4177,7 @@ static void i915_irq_preinstall(struct drm_device * dev) } I915_WRITE16(HWSTAM, 0xeffe); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); @@ -4293,7 +4292,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) "Command parser error, iir 0x%08x", iir); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); @@ -4319,7 +4318,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) if (iir & I915_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[RCS]); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int plane = pipe; if (HAS_FBC(dev)) plane = !plane; @@ -4377,7 +4376,7 @@ static void i915_irq_uninstall(struct drm_device * dev) } I915_WRITE16(HWSTAM, 0xffff); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { /* Clear enable bits; then clear status bits */ I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe))); @@ -4397,7 +4396,7 @@ static void i965_irq_preinstall(struct drm_device * dev) I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xeffe); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); @@ -4522,7 +4521,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) "Command parser error, iir 0x%08x", iir); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { int reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); @@ -4553,7 +4552,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) if (iir & I915_BSD_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[VCS]); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS && i915_handle_vblank(dev, pipe, pipe, iir)) flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe); @@ -4610,12 +4609,12 @@ static void i965_irq_uninstall(struct drm_device * dev) I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xffffffff); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)) & 0x8000ffff); I915_WRITE(IIR, I915_READ(IIR)); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4933bb8504a..daac35e3841 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1301,7 +1301,7 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv, } /* Need to check both planes against the pipe */ - for_each_pipe(i) { + for_each_pipe(dev_priv, i) { reg = DSPCNTR(i); val = I915_READ(reg); cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> @@ -8993,12 +8993,13 @@ static void intel_mark_fb_busy(struct drm_device *dev, unsigned frontbuffer_bits, struct intel_engine_cs *ring) { + struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe; if (!i915.powersave) return; - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (!(frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(pipe))) continue; @@ -12752,7 +12753,7 @@ void intel_modeset_init(struct drm_device *dev) INTEL_INFO(dev)->num_pipes, INTEL_INFO(dev)->num_pipes > 1 ? "s" : ""); - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { intel_crtc_init(dev, pipe); for_each_sprite(pipe, sprite) { ret = intel_plane_init(dev, pipe, sprite); @@ -13159,7 +13160,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, intel_sanitize_encoder(encoder); } - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); intel_sanitize_crtc(crtc); intel_dump_pipe_config(crtc, &crtc->config, "[setup_hw_state]"); @@ -13187,7 +13188,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, * We need to use raw interfaces for restoring state to avoid * checking (bogus) intermediate states. */ - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; @@ -13408,7 +13409,7 @@ intel_display_capture_error_state(struct drm_device *dev) if (IS_HASWELL(dev) || IS_BROADWELL(dev)) error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); - for_each_pipe(i) { + for_each_pipe(dev_priv, i) { error->pipe[i].power_domain_on = intel_display_power_enabled_unlocked(dev_priv, POWER_DOMAIN_PIPE(i)); @@ -13472,6 +13473,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, struct drm_device *dev, struct intel_display_error_state *error) { + struct drm_i915_private *dev_priv = dev->dev_private; int i; if (!error) @@ -13481,7 +13483,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, if (IS_HASWELL(dev) || IS_BROADWELL(dev)) err_printf(m, "PWR_WELL_CTL2: %08x\n", error->power_well_driver); - for_each_pipe(i) { + for_each_pipe(dev_priv, i) { err_printf(m, "Pipe [%d]:\n", i); err_printf(m, " Power: %s\n", error->pipe[i].power_domain_on ? "on" : "off"); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1642d3019c0..6b359cf11df 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1598,7 +1598,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, return true; } - for_each_pipe(i) { + for_each_pipe(dev_priv, i) { trans_dp = I915_READ(TRANS_DP_CTL(i)); if ((trans_dp & TRANS_DP_PORT_SEL_MASK) == trans_sel) { *pipe = i; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 764f9283e57..fd6f1f89865 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1230,7 +1230,7 @@ static int vlv_setup_backlight(struct intel_connector *connector) enum pipe pipe; u32 ctl, ctl2, val; - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); /* Skip if the modulation freq is already set */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1ab3e117644..b1b3a6b892c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2654,7 +2654,7 @@ static struct intel_pipe_wm *ilk_find_best_result(struct drm_device *dev, #define WM_DIRTY_FBC (1 << 24) #define WM_DIRTY_DDB (1 << 25) -static unsigned int ilk_compute_wm_dirty(struct drm_device *dev, +static unsigned int ilk_compute_wm_dirty(struct drm_i915_private *dev_priv, const struct ilk_wm_values *old, const struct ilk_wm_values *new) { @@ -2662,7 +2662,7 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev, enum pipe pipe; int wm_lp; - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { if (old->wm_linetime[pipe] != new->wm_linetime[pipe]) { dirty |= WM_DIRTY_LINETIME(pipe); /* Must disable LP1+ watermarks too */ @@ -2748,7 +2748,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, unsigned int dirty; uint32_t val; - dirty = ilk_compute_wm_dirty(dev, previous, results); + dirty = ilk_compute_wm_dirty(dev_priv, previous, results); if (!dirty) return; @@ -5213,7 +5213,7 @@ static void g4x_disable_trickle_feed(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int pipe; - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { I915_WRITE(DSPCNTR(pipe), I915_READ(DSPCNTR(pipe)) | DISPPLANE_TRICKLE_FEED_DISABLE); @@ -5328,7 +5328,7 @@ static void cpt_init_clock_gating(struct drm_device *dev) /* The below fixes the weird display corruption, a few pixels shifted * downward, on (only) LVDS of some HP laptops with IVY. */ - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { val = I915_READ(TRANS_CHICKEN2(pipe)); val |= TRANS_CHICKEN2_TIMING_OVERRIDE; val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED; @@ -5340,7 +5340,7 @@ static void cpt_init_clock_gating(struct drm_device *dev) I915_WRITE(TRANS_CHICKEN2(pipe), val); } /* WADP0ClockGatingDisable */ - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { I915_WRITE(TRANS_CHICKEN1(pipe), TRANS_CHICKEN1_DP0UNIT_GC_DISABLE); } @@ -5560,7 +5560,7 @@ static void gen8_init_clock_gating(struct drm_device *dev) I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD); /* WaPsrDPRSUnmaskVBlankInSRD:bdw */ - for_each_pipe(pipe) { + for_each_pipe(dev_priv, pipe) { I915_WRITE(CHICKEN_PIPESL_1(pipe), I915_READ(CHICKEN_PIPESL_1(pipe)) | BDW_DPRS_MASK_VBLANK_SRD); @@ -6363,12 +6363,11 @@ static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - struct drm_device *dev = dev_priv->dev; enum pipe pipe; WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC); - for_each_pipe(pipe) + for_each_pipe(dev_priv, pipe) assert_pll_disabled(dev_priv, pipe); /* Assert common reset */ -- cgit v1.2.3-70-g09d2 From 98a2e5f94275b6aafb12a3650937f6c54222cdc2 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Mon, 18 Aug 2014 10:35:27 -0700 Subject: drm/i915: Bring UP Power Wells before disabling RC6. We need do forcewake before Disabling RC6, This is what the BIOS expects while going into suspend. v2: updated commit message. (Daniel) Cc: Paulo Zanoni Signed-off-by: Deepak S Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b1b3a6b892c..a381c9997a2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3533,8 +3533,14 @@ static void valleyview_disable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + /* we're doing forcewake before Disabling RC6, + * This what the BIOS expects when going into suspend */ + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); + I915_WRITE(GEN6_RC_CONTROL, 0); + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); + gen6_disable_rps_interrupts(dev); } -- cgit v1.2.3-70-g09d2 From 89d6b2b81fdfa57666188d63dc970f8f14efed71 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 21 Aug 2014 17:09:36 -0300 Subject: drm/i915: call lpt_init_clock_gating on BDW too Because BDW has WPT, which is equivalent to LPT. This is just like the CPT/PPT case. Signed-off-by: Paulo Zanoni Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a381c9997a2..88944607b3a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5607,6 +5607,8 @@ static void gen8_init_clock_gating(struct drm_device *dev) /* Wa4x4STCOptimizationDisable:bdw */ I915_WRITE(CACHE_MODE_1, _MASKED_BIT_ENABLE(GEN8_4x4_STC_OPTIMIZATION_DISABLE)); + + lpt_init_clock_gating(dev); } static void haswell_init_clock_gating(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 47c2bd97cf367f712433eece065df276a64d3e66 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 21 Aug 2014 17:09:37 -0300 Subject: drm/i915: rename gen8_init_clock_gating to broadwell_init_clock_gating Because CHV uses cherryview_init_clock_gating instead of gen8_init_clock_gating. Signed-off-by: Paulo Zanoni Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 88944607b3a..2253f878adf 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5514,7 +5514,7 @@ static void lpt_suspend_hw(struct drm_device *dev) } } -static void gen8_init_clock_gating(struct drm_device *dev) +static void broadwell_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe; @@ -7262,7 +7262,7 @@ void intel_init_pm(struct drm_device *dev) else if (IS_HASWELL(dev)) dev_priv->display.init_clock_gating = haswell_init_clock_gating; else if (INTEL_INFO(dev)->gen == 8) - dev_priv->display.init_clock_gating = gen8_init_clock_gating; + dev_priv->display.init_clock_gating = broadwell_init_clock_gating; } else if (IS_CHERRYVIEW(dev)) { dev_priv->display.update_wm = cherryview_update_wm; dev_priv->display.update_sprite_wm = valleyview_update_sprite_wm; -- cgit v1.2.3-70-g09d2 From c5ad011d7d256ecbe173324029e992817194d2b0 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 4 Aug 2014 03:51:38 -0700 Subject: drm/i915: FBC flush nuke for BDW According to spec FBC on BDW and HSW are identical without any gaps. So let's copy the nuke and let FBC really start compressing stuff. Without this patch we can verify with false color that nothing is being compressed. With the nuke in place and false color it is possible to see false color debugs. Unfortunatelly on some rings like BCS on BDW we have to avoid Bits 22:18 on LRIs due to a high risk of hung. So, when using Blt ring for frontbuffer rend cache would never been cleaned and FBC would stop compressing buffer. One alternative is to cache clean on software frontbuffer tracking. v2: Fix rebase conflict. v3: Do not clean cache on BCS ring. Instead use sw frontbuffer tracking. Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_display.c | 3 +++ drivers/gpu/drm/i915/intel_pm.c | 10 ++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 9 ++++++++- 4 files changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5957db463e2..f13f30d6517 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2772,6 +2772,7 @@ extern void intel_modeset_setup_hw_state(struct drm_device *dev, extern void i915_redisable_vga(struct drm_device *dev); extern void i915_redisable_vga_power_on(struct drm_device *dev); extern bool intel_fbc_enabled(struct drm_device *dev); +extern void gen8_fbc_sw_flush(struct drm_device *dev, u32 value); extern void intel_disable_fbc(struct drm_device *dev); extern bool ironlake_set_drps(struct drm_device *dev, u8 val); extern void intel_init_pch_refclk(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 794aa5e611e..cbd15916372 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9082,6 +9082,9 @@ void intel_frontbuffer_flush(struct drm_device *dev, intel_mark_fb_busy(dev, frontbuffer_bits, NULL); intel_edp_psr_flush(dev, frontbuffer_bits); + + if (IS_GEN8(dev)) + gen8_fbc_sw_flush(dev, FBC_REND_CACHE_CLEAN); } /** diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2253f878adf..b9edfd426a1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -345,6 +345,16 @@ bool intel_fbc_enabled(struct drm_device *dev) return dev_priv->display.fbc_enabled(dev); } +void gen8_fbc_sw_flush(struct drm_device *dev, u32 value) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!IS_GEN8(dev)) + return; + + I915_WRITE(MSG_FBC_REND_STATE, value); +} + static void intel_fbc_work_fn(struct work_struct *__work) { struct intel_fbc_work *work = diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 4fb1ec95ec0..de7654623ac 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -444,7 +444,14 @@ gen8_render_ring_flush(struct intel_engine_cs *ring, return ret; } - return gen8_emit_pipe_control(ring, flags, scratch_addr); + ret = gen8_emit_pipe_control(ring, flags, scratch_addr); + if (ret) + return ret; + + if (!invalidate_domains && flush_domains) + return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); + + return 0; } static void ring_write_tail(struct intel_engine_cs *ring, -- cgit v1.2.3-70-g09d2 From 86d7f23842f1bce3ab5e8c8d0c676112bbc4c99b Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Tue, 26 Aug 2014 14:44:50 +0100 Subject: drm/i915/bdw: Apply workarounds in render ring init function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For BDW workarounds are currently initialized in init_clock_gating() but they are lost during reset, suspend/resume etc; this patch moves the WAs that are part of register state context to render ring init fn otherwise default context ends up with incorrect values as they don't get initialized until init_clock_gating fn. v2: Add workarounds to golden render state This method has its own issues, first of all this is different for each gen and it is generated using a tool so adding new workaround and mainitaining them across gens is not a straightforward process. v3: Use LRIs to emit these workarounds (Ville) Instead of modifying the golden render state the same LRIs are emitted from within the driver. v4: Use abstract name when exporting gen specific routines (Chris) For: VIZ-4092 Signed-off-by: Arun Siluvery Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 6 +++ drivers/gpu/drm/i915/intel_pm.c | 48 -------------------- drivers/gpu/drm/i915/intel_ringbuffer.c | 79 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 4 files changed, 87 insertions(+), 48 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 62ee178b1ed..a5221d8f158 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -628,6 +628,12 @@ done: ring->last_context = to; if (uninitialized) { + if (ring->init_context) { + ret = ring->init_context(ring); + if (ret) + DRM_ERROR("ring init context: %d\n", ret); + } + ret = i915_gem_render_state_init(ring); if (ret) DRM_ERROR("init render state: %d\n", ret); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b9edfd426a1..71802385968 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5536,37 +5536,12 @@ static void broadwell_init_clock_gating(struct drm_device *dev) /* FIXME(BDW): Check all the w/a, some might only apply to * pre-production hw. */ - /* WaDisablePartialInstShootdown:bdw */ - I915_WRITE(GEN8_ROW_CHICKEN, - _MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE)); - - /* WaDisableThreadStallDopClockGating:bdw */ - /* FIXME: Unclear whether we really need this on production bdw. */ - I915_WRITE(GEN8_ROW_CHICKEN, - _MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE)); - /* - * This GEN8_CENTROID_PIXEL_OPT_DIS W/A is only needed for - * pre-production hardware - */ - I915_WRITE(HALF_SLICE_CHICKEN3, - _MASKED_BIT_ENABLE(GEN8_CENTROID_PIXEL_OPT_DIS)); - I915_WRITE(HALF_SLICE_CHICKEN3, - _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE)); I915_WRITE(_3D_CHICKEN3, _MASKED_BIT_ENABLE(_3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2))); - I915_WRITE(COMMON_SLICE_CHICKEN2, - _MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE)); - - I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, - _MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE)); - - /* WaDisableDopClockGating:bdw May not be needed for production */ - I915_WRITE(GEN7_ROW_CHICKEN2, - _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); /* WaSwitchSolVfFArbitrationPriority:bdw */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); @@ -5582,31 +5557,12 @@ static void broadwell_init_clock_gating(struct drm_device *dev) BDW_DPRS_MASK_VBLANK_SRD); } - /* Use Force Non-Coherent whenever executing a 3D context. This is a - * workaround for for a possible hang in the unlikely event a TLB - * invalidation occurs during a PSD flush. - */ - I915_WRITE(HDC_CHICKEN0, - I915_READ(HDC_CHICKEN0) | - _MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT)); - /* WaVSRefCountFullforceMissDisable:bdw */ /* WaDSRefCountFullforceMissDisable:bdw */ I915_WRITE(GEN7_FF_THREAD_MODE, I915_READ(GEN7_FF_THREAD_MODE) & ~(GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME)); - /* - * BSpec recommends 8x4 when MSAA is used, - * however in practice 16x4 seems fastest. - * - * Note that PS/WM thread counts depend on the WIZ hashing - * disable bit, which we don't touch here, but it's good - * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). - */ - I915_WRITE(GEN7_GT_MODE, - GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4); - I915_WRITE(GEN6_RC_SLEEP_PSMI_CONTROL, _MASKED_BIT_ENABLE(GEN8_RC_SEMA_IDLE_MSG_DISABLE)); @@ -5614,10 +5570,6 @@ static void broadwell_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | GEN8_SDEUNIT_CLOCK_GATE_DISABLE); - /* Wa4x4STCOptimizationDisable:bdw */ - I915_WRITE(CACHE_MODE_1, - _MASKED_BIT_ENABLE(GEN8_4x4_STC_OPTIMIZATION_DISABLE)); - lpt_init_clock_gating(dev); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index de7654623ac..1d5bfdb4fe9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -657,6 +657,84 @@ err: return ret; } +static inline void intel_ring_emit_wa(struct intel_engine_cs *ring, + u32 addr, u32 value) +{ + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit(ring, addr); + intel_ring_emit(ring, value); +} + +static int gen8_init_workarounds(struct intel_engine_cs *ring) +{ + int ret; + + /* + * workarounds applied in this fn are part of register state context, + * they need to be re-initialized followed by gpu reset, suspend/resume, + * module reload. + */ + + /* + * update the number of dwords required based on the + * actual number of workarounds applied + */ + ret = intel_ring_begin(ring, 24); + if (ret) + return ret; + + /* WaDisablePartialInstShootdown:bdw */ + /* WaDisableThreadStallDopClockGating:bdw */ + /* FIXME: Unclear whether we really need this on production bdw. */ + intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN, + _MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE + | STALL_DOP_GATING_DISABLE)); + + /* WaDisableDopClockGating:bdw May not be needed for production */ + intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2, + _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); + + /* + * This GEN8_CENTROID_PIXEL_OPT_DIS W/A is only needed for + * pre-production hardware + */ + intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3, + _MASKED_BIT_ENABLE(GEN8_CENTROID_PIXEL_OPT_DIS + | GEN8_SAMPLER_POWER_BYPASS_DIS)); + + intel_ring_emit_wa(ring, GEN7_HALF_SLICE_CHICKEN1, + _MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE)); + + intel_ring_emit_wa(ring, COMMON_SLICE_CHICKEN2, + _MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE)); + + /* Use Force Non-Coherent whenever executing a 3D context. This is a + * workaround for for a possible hang in the unlikely event a TLB + * invalidation occurs during a PSD flush. + */ + intel_ring_emit_wa(ring, HDC_CHICKEN0, + _MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT)); + + /* Wa4x4STCOptimizationDisable:bdw */ + intel_ring_emit_wa(ring, CACHE_MODE_1, + _MASKED_BIT_ENABLE(GEN8_4x4_STC_OPTIMIZATION_DISABLE)); + + /* + * BSpec recommends 8x4 when MSAA is used, + * however in practice 16x4 seems fastest. + * + * Note that PS/WM thread counts depend on the WIZ hashing + * disable bit, which we don't touch here, but it's good + * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). + */ + intel_ring_emit_wa(ring, GEN7_GT_MODE, + GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4); + + intel_ring_advance(ring); + + return 0; +} + static int init_render_ring(struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; @@ -2143,6 +2221,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) dev_priv->semaphore_obj = obj; } } + ring->init_context = gen8_init_workarounds; ring->add_request = gen6_add_request; ring->flush = gen8_render_ring_flush; ring->irq_get = gen8_ring_get_irq; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 9cbf7b0ebc9..96479c89f4b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -148,6 +148,8 @@ struct intel_engine_cs { int (*init)(struct intel_engine_cs *ring); + int (*init_context)(struct intel_engine_cs *ring); + void (*write_tail)(struct intel_engine_cs *ring, u32 value); int __must_check (*flush)(struct intel_engine_cs *ring, -- cgit v1.2.3-70-g09d2 From 2bb25c17bbe032eecaffa401dbc21809a3f8e44a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Aug 2014 14:42:44 +0300 Subject: drm/i915: Populate mem_freq in init_gt_powerwave() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit init_clock_gating() is too late to read out the mem_freq. We already want to print out the GPU MHz numbers before it's called. Move the mem_freq setup to init_gt_powersave(). v2: Also kill the CHV_CZ_CLOCK_FREQ_MODE_* defines Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 6 --- drivers/gpu/drm/i915/intel_pm.c | 90 ++++++++++++++++++++--------------------- 2 files changed, 43 insertions(+), 53 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 559c7f870cf..04461141a3e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5650,12 +5650,6 @@ enum punit_power_well { GEN6_PM_RP_DOWN_THRESHOLD | \ GEN6_PM_RP_DOWN_TIMEOUT) -#define CHV_CZ_CLOCK_FREQ_MODE_200 200 -#define CHV_CZ_CLOCK_FREQ_MODE_267 267 -#define CHV_CZ_CLOCK_FREQ_MODE_320 320 -#define CHV_CZ_CLOCK_FREQ_MODE_333 333 -#define CHV_CZ_CLOCK_FREQ_MODE_400 400 - #define GEN7_GT_SCRATCH_BASE 0x4F100 #define GEN7_GT_SCRATCH_REG_NUM 8 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 71802385968..a5c1a6cf5b5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4106,11 +4106,27 @@ static void valleyview_cleanup_pctx(struct drm_device *dev) static void valleyview_init_gt_powersave(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; valleyview_setup_pctx(dev); mutex_lock(&dev_priv->rps.hw_lock); + val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); + switch ((val >> 6) & 3) { + case 0: + case 1: + dev_priv->mem_freq = 800; + break; + case 2: + dev_priv->mem_freq = 1066; + break; + case 3: + dev_priv->mem_freq = 1333; + break; + } + DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); + dev_priv->rps.max_freq = valleyview_rps_max_freq(dev_priv); dev_priv->rps.rp0_freq = dev_priv->rps.max_freq; DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n", @@ -4145,11 +4161,38 @@ static void valleyview_init_gt_powersave(struct drm_device *dev) static void cherryview_init_gt_powersave(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; cherryview_setup_pctx(dev); mutex_lock(&dev_priv->rps.hw_lock); + val = vlv_punit_read(dev_priv, CCK_FUSE_REG); + switch ((val >> 2) & 0x7) { + case 0: + case 1: + dev_priv->rps.cz_freq = 200; + dev_priv->mem_freq = 1600; + break; + case 2: + dev_priv->rps.cz_freq = 267; + dev_priv->mem_freq = 1600; + break; + case 3: + dev_priv->rps.cz_freq = 333; + dev_priv->mem_freq = 2000; + break; + case 4: + dev_priv->rps.cz_freq = 320; + dev_priv->mem_freq = 1600; + break; + case 5: + dev_priv->rps.cz_freq = 400; + dev_priv->mem_freq = 1600; + break; + } + DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); + dev_priv->rps.max_freq = cherryview_rps_max_freq(dev_priv); dev_priv->rps.rp0_freq = dev_priv->rps.max_freq; DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n", @@ -5726,24 +5769,6 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) static void valleyview_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 val; - - mutex_lock(&dev_priv->rps.hw_lock); - val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); - mutex_unlock(&dev_priv->rps.hw_lock); - switch ((val >> 6) & 3) { - case 0: - case 1: - dev_priv->mem_freq = 800; - break; - case 2: - dev_priv->mem_freq = 1066; - break; - case 3: - dev_priv->mem_freq = 1333; - break; - } - DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE); @@ -5819,35 +5844,6 @@ static void valleyview_init_clock_gating(struct drm_device *dev) static void cherryview_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 val; - - mutex_lock(&dev_priv->rps.hw_lock); - val = vlv_punit_read(dev_priv, CCK_FUSE_REG); - mutex_unlock(&dev_priv->rps.hw_lock); - switch ((val >> 2) & 0x7) { - case 0: - case 1: - dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_200; - dev_priv->mem_freq = 1600; - break; - case 2: - dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_267; - dev_priv->mem_freq = 1600; - break; - case 3: - dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_333; - dev_priv->mem_freq = 2000; - break; - case 4: - dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_320; - dev_priv->mem_freq = 1600; - break; - case 5: - dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_400; - dev_priv->mem_freq = 1600; - break; - } - DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE); -- cgit v1.2.3-70-g09d2 From c76bb61a71083b2d90504cc6d0dda2047c5d63ca Mon Sep 17 00:00:00 2001 From: Daisy Sun Date: Mon, 11 Aug 2014 11:08:38 -0700 Subject: drm/i915/bdw: BDW Software Turbo BDW supports GT C0 residency reporting in constant time unit. Driver calculates GT utilization based on C0 residency and adjusts RP frequency up/down accordingly. For offscreen workload specificly, set frequency to RP0. Offscreen task is not restricted by frame rate, it can be executed as soon as possible. Transcoding and serilized workload between CPU and GPU both need high GT performance, RP0 is a good option in this case. RC6 will kick in to compensate power consumption when GT is not active. v2: Rebase on recent drm-intel-nightly v3: Add flip timerout monitor, when no flip is deteced within 100ms, set frequency to RP0. Signed-off-by: Daisy Sun [torourke: rebased on latest and resolved conflict] Signed-off-by: Tom O'Rourke Acked-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 22 ++++ drivers/gpu/drm/i915/i915_irq.c | 21 ++++ drivers/gpu/drm/i915/i915_reg.h | 4 + drivers/gpu/drm/i915/intel_display.c | 3 + drivers/gpu/drm/i915/intel_pm.c | 230 +++++++++++++++++++++++++++++------ 5 files changed, 241 insertions(+), 39 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 95820652e15..05c3c60c8f2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -936,6 +936,23 @@ struct intel_rps_ei { u32 media_c0; }; +struct intel_rps_bdw_cal { + u32 it_threshold_pct; /* interrupt, in percentage */ + u32 eval_interval; /* evaluation interval, in us */ + u32 last_ts; + u32 last_c0; + bool is_up; +}; + +struct intel_rps_bdw_turbo { + struct intel_rps_bdw_cal up; + struct intel_rps_bdw_cal down; + struct timer_list flip_timer; + u32 timeout; + atomic_t flip_received; + struct work_struct work_max_freq; +}; + struct intel_gen6_power_mgmt { /* work and pm_iir are protected by dev_priv->irq_lock */ struct work_struct work; @@ -969,6 +986,9 @@ struct intel_gen6_power_mgmt { bool enabled; struct delayed_work delayed_resume_work; + bool is_bdw_sw_turbo; /* Switch of BDW software turbo */ + struct intel_rps_bdw_turbo sw_turbo; /* Calculate RP interrupt timing */ + /* manual wa residency calculations */ struct intel_rps_ei up_ei, down_ei; @@ -2791,6 +2811,8 @@ extern void intel_disable_fbc(struct drm_device *dev); extern bool ironlake_set_drps(struct drm_device *dev, u8 val); extern void intel_init_pch_refclk(struct drm_device *dev); extern void gen6_set_rps(struct drm_device *dev, u8 val); +extern void bdw_software_turbo(struct drm_device *dev); +extern void gen8_flip_interrupt(struct drm_device *dev); extern void valleyview_set_rps(struct drm_device *dev, u8 val); extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c1186e1ba48..efc79605f79 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1979,6 +1979,27 @@ static void i9xx_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe) res1, res2); } +void gen8_flip_interrupt(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!dev_priv->rps.is_bdw_sw_turbo) + return; + + if(atomic_read(&dev_priv->rps.sw_turbo.flip_received)) { + mod_timer(&dev_priv->rps.sw_turbo.flip_timer, + usecs_to_jiffies(dev_priv->rps.sw_turbo.timeout) + jiffies); + } + else { + dev_priv->rps.sw_turbo.flip_timer.expires = + usecs_to_jiffies(dev_priv->rps.sw_turbo.timeout) + jiffies; + add_timer(&dev_priv->rps.sw_turbo.flip_timer); + atomic_set(&dev_priv->rps.sw_turbo.flip_received, true); + } + + bdw_software_turbo(dev); +} + /* The RPS events need forcewake, so we add them to a work queue and mask their * IMR bits until the work is done. Other interrupts can be processed without * the work queue. */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 04461141a3e..20673cc450c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5562,6 +5562,10 @@ enum punit_power_well { #define GEN8_UCGCTL6 0x9430 #define GEN8_SDEUNIT_CLOCK_GATE_DISABLE (1<<14) +#define TIMESTAMP_CTR 0x44070 +#define FREQ_1_28_US(us) (((us) * 100) >> 7) +#define MCHBAR_PCU_C0 (MCHBAR_MIRROR_BASE_SNB + 0x5960) + #define GEN6_GFXPAUSE 0xA000 #define GEN6_RPNSWREQ 0xA008 #define GEN6_TURBO_DISABLE (1<<31) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 127eb0ae851..e572ffa16a6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9757,6 +9757,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, unsigned long flags; int ret; + //trigger software GT busyness calculation + gen8_flip_interrupt(dev); + /* * drm_mode_page_flip_ioctl() should already catch this, but double * check to be safe. In the future we may enable pageflipping from diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a5c1a6cf5b5..72791a787f8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2258,7 +2258,6 @@ int ilk_wm_max_level(const struct drm_device *dev) else return 2; } - static void intel_print_wm_latency(struct drm_device *dev, const char *name, const uint16_t wm[5]) @@ -3227,6 +3226,9 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) { int new_power; + if (dev_priv->rps.is_bdw_sw_turbo) + return; + new_power = dev_priv->rps.power; switch (dev_priv->rps.power) { case LOW_POWER: @@ -3434,8 +3436,11 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); else if (IS_VALLEYVIEW(dev)) vlv_set_rps_idle(dev_priv); - else + else if (!dev_priv->rps.is_bdw_sw_turbo + || atomic_read(&dev_priv->rps.sw_turbo.flip_received)){ gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); + } + dev_priv->rps.last_adj = 0; } mutex_unlock(&dev_priv->rps.hw_lock); @@ -3449,8 +3454,11 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv) if (dev_priv->rps.enabled) { if (IS_VALLEYVIEW(dev)) valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit); - else + else if (!dev_priv->rps.is_bdw_sw_turbo + || atomic_read(&dev_priv->rps.sw_turbo.flip_received)){ gen6_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit); + } + dev_priv->rps.last_adj = 0; } mutex_unlock(&dev_priv->rps.hw_lock); @@ -3481,21 +3489,26 @@ void valleyview_set_rps(struct drm_device *dev, u8 val) static void gen8_disable_rps_interrupts(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + if (IS_BROADWELL(dev) && dev_priv->rps.is_bdw_sw_turbo){ + if (atomic_read(&dev_priv->rps.sw_turbo.flip_received)) + del_timer(&dev_priv->rps.sw_turbo.flip_timer); + dev_priv-> rps.is_bdw_sw_turbo = false; + } else { + I915_WRITE(GEN6_PMINTRMSK, ~GEN8_PMINTR_REDIRECT_TO_NON_DISP); + I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) & + ~dev_priv->pm_rps_events); + /* Complete PM interrupt masking here doesn't race with the rps work + * item again unmasking PM interrupts because that is using a different + * register (GEN8_GT_IMR(2)) to mask PM interrupts. The only risk is in + * leaving stale bits in GEN8_GT_IIR(2) and GEN8_GT_IMR(2) which + * gen8_enable_rps will clean up. */ - I915_WRITE(GEN6_PMINTRMSK, ~GEN8_PMINTR_REDIRECT_TO_NON_DISP); - I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) & - ~dev_priv->pm_rps_events); - /* Complete PM interrupt masking here doesn't race with the rps work - * item again unmasking PM interrupts because that is using a different - * register (GEN8_GT_IMR(2)) to mask PM interrupts. The only risk is in - * leaving stale bits in GEN8_GT_IIR(2) and GEN8_GT_IMR(2) which - * gen8_enable_rps will clean up. */ - - spin_lock_irq(&dev_priv->irq_lock); - dev_priv->rps.pm_iir = 0; - spin_unlock_irq(&dev_priv->irq_lock); + spin_lock_irq(&dev_priv->irq_lock); + dev_priv->rps.pm_iir = 0; + spin_unlock_irq(&dev_priv->irq_lock); - I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events); + I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events); + } } static void gen6_disable_rps_interrupts(struct drm_device *dev) @@ -3653,13 +3666,111 @@ static void parse_rp_state_cap(struct drm_i915_private *dev_priv, u32 rp_state_c dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq; } +static void bdw_sw_calculate_freq(struct drm_device *dev, + struct intel_rps_bdw_cal *c, u32 *cur_time, u32 *c0) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u64 busy = 0; + u32 busyness_pct = 0; + u32 elapsed_time = 0; + u16 new_freq = 0; + + if (!c || !cur_time || !c0) + return; + + if (0 == c->last_c0) + goto out; + + /* Check Evaluation interval */ + elapsed_time = *cur_time - c->last_ts; + if (elapsed_time < c->eval_interval) + return; + + mutex_lock(&dev_priv->rps.hw_lock); + + /* + * c0 unit in 32*1.28 usec, elapsed_time unit in 1 usec. + * Whole busyness_pct calculation should be + * busy = ((u64)(*c0 - c->last_c0) << 5 << 7) / 100; + * busyness_pct = (u32)(busy * 100 / elapsed_time); + * The final formula is to simplify CPU calculation + */ + busy = (u64)(*c0 - c->last_c0) << 12; + do_div(busy, elapsed_time); + busyness_pct = (u32)busy; + + if (c->is_up && busyness_pct >= c->it_threshold_pct) + new_freq = (u16)dev_priv->rps.cur_freq + 3; + if (!c->is_up && busyness_pct <= c->it_threshold_pct) + new_freq = (u16)dev_priv->rps.cur_freq - 1; + + /* Adjust to new frequency busyness and compare with threshold */ + if (0 != new_freq) { + if (new_freq > dev_priv->rps.max_freq_softlimit) + new_freq = dev_priv->rps.max_freq_softlimit; + else if (new_freq < dev_priv->rps.min_freq_softlimit) + new_freq = dev_priv->rps.min_freq_softlimit; + + gen6_set_rps(dev, new_freq); + } + + mutex_unlock(&dev_priv->rps.hw_lock); + +out: + c->last_c0 = *c0; + c->last_ts = *cur_time; +} + +static void gen8_set_frequency_RP0(struct work_struct *work) +{ + struct intel_rps_bdw_turbo *p_bdw_turbo = + container_of(work, struct intel_rps_bdw_turbo, work_max_freq); + struct intel_gen6_power_mgmt *p_power_mgmt = + container_of(p_bdw_turbo, struct intel_gen6_power_mgmt, sw_turbo); + struct drm_i915_private *dev_priv = + container_of(p_power_mgmt, struct drm_i915_private, rps); + + mutex_lock(&dev_priv->rps.hw_lock); + gen6_set_rps(dev_priv->dev, dev_priv->rps.rp0_freq); + mutex_unlock(&dev_priv->rps.hw_lock); +} + +static void flip_active_timeout_handler(unsigned long var) +{ + struct drm_i915_private *dev_priv = (struct drm_i915_private *) var; + + del_timer(&dev_priv->rps.sw_turbo.flip_timer); + atomic_set(&dev_priv->rps.sw_turbo.flip_received, false); + + queue_work(dev_priv->wq, &dev_priv->rps.sw_turbo.work_max_freq); +} + +void bdw_software_turbo(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + u32 current_time = I915_READ(TIMESTAMP_CTR); /* unit in usec */ + u32 current_c0 = I915_READ(MCHBAR_PCU_C0); /* unit in 32*1.28 usec */ + + bdw_sw_calculate_freq(dev, &dev_priv->rps.sw_turbo.up, + ¤t_time, ¤t_c0); + bdw_sw_calculate_freq(dev, &dev_priv->rps.sw_turbo.down, + ¤t_time, ¤t_c0); +} + static void gen8_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; uint32_t rc6_mask = 0, rp_state_cap; + uint32_t threshold_up_pct, threshold_down_pct; + uint32_t ei_up, ei_down; /* up and down evaluation interval */ + u32 rp_ctl_flag; int unused; + /* Use software Turbo for BDW */ + dev_priv->rps.is_bdw_sw_turbo = IS_BROADWELL(dev); + /* 1a: Software RC state - RC0 */ I915_WRITE(GEN6_RC_STATE, 0); @@ -3703,35 +3814,74 @@ static void gen8_enable_rps(struct drm_device *dev) HSW_FREQUENCY(dev_priv->rps.rp1_freq)); I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(dev_priv->rps.rp1_freq)); - /* NB: Docs say 1s, and 1000000 - which aren't equivalent */ - I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */ + ei_up = 84480; /* 84.48ms */ + ei_down = 448000; + threshold_up_pct = 90; /* x percent busy */ + threshold_down_pct = 70; + + if (dev_priv->rps.is_bdw_sw_turbo) { + dev_priv->rps.sw_turbo.up.it_threshold_pct = threshold_up_pct; + dev_priv->rps.sw_turbo.up.eval_interval = ei_up; + dev_priv->rps.sw_turbo.up.is_up = true; + dev_priv->rps.sw_turbo.up.last_ts = 0; + dev_priv->rps.sw_turbo.up.last_c0 = 0; + + dev_priv->rps.sw_turbo.down.it_threshold_pct = threshold_down_pct; + dev_priv->rps.sw_turbo.down.eval_interval = ei_down; + dev_priv->rps.sw_turbo.down.is_up = false; + dev_priv->rps.sw_turbo.down.last_ts = 0; + dev_priv->rps.sw_turbo.down.last_c0 = 0; + + /* Start the timer to track if flip comes*/ + dev_priv->rps.sw_turbo.timeout = 200*1000; /* in us */ + + init_timer(&dev_priv->rps.sw_turbo.flip_timer); + dev_priv->rps.sw_turbo.flip_timer.function = flip_active_timeout_handler; + dev_priv->rps.sw_turbo.flip_timer.data = (unsigned long) dev_priv; + dev_priv->rps.sw_turbo.flip_timer.expires = + usecs_to_jiffies(dev_priv->rps.sw_turbo.timeout) + jiffies; + add_timer(&dev_priv->rps.sw_turbo.flip_timer); + INIT_WORK(&dev_priv->rps.sw_turbo.work_max_freq, gen8_set_frequency_RP0); + + atomic_set(&dev_priv->rps.sw_turbo.flip_received, true); + } else { + /* NB: Docs say 1s, and 1000000 - which aren't equivalent + * 1 second timeout*/ + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, FREQ_1_28_US(1000000)); - /* Docs recommend 900MHz, and 300 MHz respectively */ - I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, - dev_priv->rps.max_freq_softlimit << 24 | - dev_priv->rps.min_freq_softlimit << 16); + /* Docs recommend 900MHz, and 300 MHz respectively */ + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + dev_priv->rps.max_freq_softlimit << 24 | + dev_priv->rps.min_freq_softlimit << 16); - I915_WRITE(GEN6_RP_UP_THRESHOLD, 7600000 / 128); /* 76ms busyness per EI, 90% */ - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 31300000 / 128); /* 313ms busyness per EI, 70%*/ - I915_WRITE(GEN6_RP_UP_EI, 66000); /* 84.48ms, XXX: random? */ - I915_WRITE(GEN6_RP_DOWN_EI, 350000); /* 448ms, XXX: random? */ + I915_WRITE(GEN6_RP_UP_THRESHOLD, + FREQ_1_28_US(ei_up * threshold_up_pct / 100)); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, + FREQ_1_28_US(ei_down * threshold_down_pct / 100)); + I915_WRITE(GEN6_RP_UP_EI, + FREQ_1_28_US(ei_up)); + I915_WRITE(GEN6_RP_DOWN_EI, + FREQ_1_28_US(ei_down)); - I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + } /* 5: Enable RPS */ - I915_WRITE(GEN6_RP_CONTROL, - GEN6_RP_MEDIA_TURBO | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_ENABLE | - GEN6_RP_UP_BUSY_AVG | - GEN6_RP_DOWN_IDLE_AVG); - - /* 6: Ring frequency + overclocking (our driver does this later */ - + rp_ctl_flag = GEN6_RP_MEDIA_TURBO | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_AVG; + if (!dev_priv->rps.is_bdw_sw_turbo) + rp_ctl_flag |= GEN6_RP_ENABLE; + + I915_WRITE(GEN6_RP_CONTROL, rp_ctl_flag); + + /* 6: Ring frequency + overclocking + * (our driver does this later */ gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8); - - gen8_enable_rps_interrupts(dev); + if (!dev_priv->rps.is_bdw_sw_turbo) + gen8_enable_rps_interrupts(dev); gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } @@ -5199,6 +5349,8 @@ static void intel_gen6_powersave_work(struct work_struct *work) rps.delayed_resume_work.work); struct drm_device *dev = dev_priv->dev; + dev_priv->rps.is_bdw_sw_turbo = false; + mutex_lock(&dev_priv->rps.hw_lock); if (IS_CHERRYVIEW(dev)) { -- cgit v1.2.3-70-g09d2 From 1c14762d0cc3eecfdc5060bd634d124d32bd9d44 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Aug 2014 14:42:43 +0300 Subject: drm/i915: Warn about odd rps values on CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHV wants even rps opcodes so print a warning of the min/max/rpe/rp1 values are odd, and warn if an odd value slips through to valleyview_set_rps() and truncate it to an even value. Also add a comment to chv_freq_opcode() to make sure no one changes the code without considering this requirement. Signed-off-by: Ville Syrjälä Reviewed-by: Deepak S [danvet: Help git along in applying the patch, somehow it silently ended up in the vlv init_gt_powersave function.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 72791a787f8..6bf533100da 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3477,6 +3477,10 @@ void valleyview_set_rps(struct drm_device *dev, u8 val) dev_priv->rps.cur_freq, vlv_gpu_freq(dev_priv, val), val); + if (WARN_ONCE(IS_CHERRYVIEW(dev) && (val & 1), + "Odd GPU freq value\n")) + val &= ~1; + if (val != dev_priv->rps.cur_freq) vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val); @@ -4364,6 +4368,12 @@ static void cherryview_init_gt_powersave(struct drm_device *dev) vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq), dev_priv->rps.min_freq); + WARN_ONCE((dev_priv->rps.max_freq | + dev_priv->rps.efficient_freq | + dev_priv->rps.rp1_freq | + dev_priv->rps.min_freq) & 1, + "Odd GPU freq values\n"); + /* Preserve min/max settings in case of re-init */ if (dev_priv->rps.max_freq_softlimit == 0) dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq; @@ -7566,6 +7576,7 @@ static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val) return -1; } + /* CHV needs even values */ opcode = (DIV_ROUND_CLOSEST((val * 2 * mul), dev_priv->rps.cz_freq) * 2); return opcode; -- cgit v1.2.3-70-g09d2 From 00e1e623e62cd8452e28633182b91ddcbb70cc7c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Aug 2014 17:33:12 +0300 Subject: drm/i915: Init some CHV workarounds via LRIs in ring->init_context() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow the BDW example and apply the workarounds touching registers which are saved in the context image through LRIs in the new ring->init_context() hook. This makes Mesa much happier and eg. glxgears doesn't hang after the first frame. Cc: Arun Siluvery Signed-off-by: Ville Syrjälä [danvet: Add missing wa table initialization to avoid a functional conflict with Arun's wa table debugfs support.] Reviewed-by: "Barbalho, Rafael" Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 14 ---------- drivers/gpu/drm/i915/intel_ringbuffer.c | 46 +++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6bf533100da..376cc2c8751 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6011,14 +6011,6 @@ static void cherryview_init_clock_gating(struct drm_device *dev) I915_WRITE(MI_ARB_VLV, MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE); - /* WaDisablePartialInstShootdown:chv */ - I915_WRITE(GEN8_ROW_CHICKEN, - _MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE)); - - /* WaDisableThreadStallDopClockGating:chv */ - I915_WRITE(GEN8_ROW_CHICKEN, - _MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE)); - /* WaVSRefCountFullforceMissDisable:chv */ /* WaDSRefCountFullforceMissDisable:chv */ I915_WRITE(GEN7_FF_THREAD_MODE, @@ -6037,10 +6029,6 @@ static void cherryview_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | GEN8_SDEUNIT_CLOCK_GATE_DISABLE); - /* WaDisableSamplerPowerBypass:chv (pre-production hw) */ - I915_WRITE(HALF_SLICE_CHICKEN3, - _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); - /* WaDisableGunitClockGating:chv (pre-production hw) */ I915_WRITE(VLV_GUNIT_CLOCK_GATE, I915_READ(VLV_GUNIT_CLOCK_GATE) | GINT_DIS); @@ -6050,8 +6038,6 @@ static void cherryview_init_clock_gating(struct drm_device *dev) _MASKED_BIT_ENABLE(GEN8_FF_DOP_CLOCK_GATE_DISABLE)); /* WaDisableDopClockGating:chv (pre-production hw) */ - I915_WRITE(GEN7_ROW_CHICKEN2, - _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); I915_WRITE(GEN6_UCGCTL1, I915_READ(GEN6_UCGCTL1) | GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 14b517d61b4..12135ef3606 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -681,7 +681,7 @@ static inline void intel_ring_emit_wa(struct intel_engine_cs *ring, return; } -static int gen8_init_workarounds(struct intel_engine_cs *ring) +static int bdw_init_workarounds(struct intel_engine_cs *ring) { int ret; struct drm_device *dev = ring->dev; @@ -758,6 +758,45 @@ static int gen8_init_workarounds(struct intel_engine_cs *ring) return 0; } +static int chv_init_workarounds(struct intel_engine_cs *ring) +{ + int ret; + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + /* + * workarounds applied in this fn are part of register state context, + * they need to be re-initialized followed by gpu reset, suspend/resume, + * module reload. + */ + dev_priv->num_wa_regs = 0; + memset(dev_priv->intel_wa_regs, 0, sizeof(dev_priv->intel_wa_regs)); + + ret = intel_ring_begin(ring, 12); + if (ret) + return ret; + + /* WaDisablePartialInstShootdown:chv */ + intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN, + _MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE)); + + /* WaDisableThreadStallDopClockGating:chv */ + intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN, + _MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE)); + + /* WaDisableDopClockGating:chv (pre-production hw) */ + intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2, + _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); + + /* WaDisableSamplerPowerBypass:chv (pre-production hw) */ + intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3, + _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); + + intel_ring_advance(ring); + + return 0; +} + static int init_render_ring(struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; @@ -2244,7 +2283,10 @@ int intel_init_render_ring_buffer(struct drm_device *dev) dev_priv->semaphore_obj = obj; } } - ring->init_context = gen8_init_workarounds; + if (IS_CHERRYVIEW(dev)) + ring->init_context = chv_init_workarounds; + else + ring->init_context = bdw_init_workarounds; ring->add_request = gen6_add_request; ring->flush = gen8_render_ring_flush; ring->irq_get = gen8_ring_get_irq; -- cgit v1.2.3-70-g09d2 From 9d53910580512207186729c94b39cca9a9778c13 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 15 Aug 2014 01:21:53 +0300 Subject: drm/i915: Fix gen2 planes B and C max watermark value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The max watermark value for gen2 planes B and C is 0x1f, instead of the 0x3f that plane A uses. Also check against the max even if the pipe is disabled since the FIFO size exceeds the plane B and C max watermark value. Signed-off-by: Ville Syrjälä Tested-by: Thomas Richter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 376cc2c8751..38b61e4d17a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1001,13 +1001,20 @@ static const struct intel_watermark_params i915_wm_info = { .guard_size = 2, .cacheline_size = I915_FIFO_LINE_SIZE, }; -static const struct intel_watermark_params i830_wm_info = { +static const struct intel_watermark_params i830_a_wm_info = { .fifo_size = I855GM_FIFO_SIZE, .max_wm = I915_MAX_WM, .default_wm = 1, .guard_size = 2, .cacheline_size = I830_FIFO_LINE_SIZE, }; +static const struct intel_watermark_params i830_bc_wm_info = { + .fifo_size = I855GM_FIFO_SIZE, + .max_wm = I915_MAX_WM/2, + .default_wm = 1, + .guard_size = 2, + .cacheline_size = I830_FIFO_LINE_SIZE, +}; static const struct intel_watermark_params i845_wm_info = { .fifo_size = I830_FIFO_SIZE, .max_wm = I915_MAX_WM, @@ -1689,7 +1696,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) else if (!IS_GEN2(dev)) wm_info = &i915_wm_info; else - wm_info = &i830_wm_info; + wm_info = &i830_a_wm_info; fifo_size = dev_priv->display.get_fifo_size(dev, 0); crtc = intel_get_crtc_for_plane(dev, 0); @@ -1704,8 +1711,14 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) wm_info, fifo_size, cpp, latency_ns); enabled = crtc; - } else + } else { planea_wm = fifo_size - wm_info->guard_size; + if (planea_wm > (long)wm_info->max_wm) + planea_wm = wm_info->max_wm; + } + + if (IS_GEN2(dev)) + wm_info = &i830_bc_wm_info; fifo_size = dev_priv->display.get_fifo_size(dev, 1); crtc = intel_get_crtc_for_plane(dev, 1); @@ -1723,8 +1736,11 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) enabled = crtc; else enabled = NULL; - } else + } else { planeb_wm = fifo_size - wm_info->guard_size; + if (planeb_wm > (long)wm_info->max_wm) + planeb_wm = wm_info->max_wm; + } DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); -- cgit v1.2.3-70-g09d2 From 1038392b4dd02a46006d38f33aab71486d477ced Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 15 Aug 2014 01:21:54 +0300 Subject: drm/i915: Disable trickle feed for gen2/3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My 830 is unhappy with trickle feed enabled. The symptom is that the image on the screen shifts a bit to right occasionally. The BIOS initially disables trickle feed, but it gets reset during suspend, so we need to re-disable it ourselves. Juse disable it always. Also disable it for all other gen2/3 platforms since we disable it for all more recent platforms as well (until HSW that is). At least my 855 doesn't seem to mind us doing this. I don't have gen3 hardware to test that. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_pm.c | 10 ++++++++++ 2 files changed, 14 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 20673cc450c..b7b2e63c14d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1272,6 +1272,10 @@ enum punit_power_well { #define INSTPM_TLB_INVALIDATE (1<<9) #define INSTPM_SYNC_FLUSH (1<<5) #define ACTHD 0x020c8 +#define MEM_MODE 0x020cc +#define MEM_DISPLAY_B_TRICKLE_FEED_DISABLE (1<<3) /* 830 only */ +#define MEM_DISPLAY_A_TRICKLE_FEED_DISABLE (1<<2) /* 830/845 only */ +#define MEM_DISPLAY_TRICKLE_FEED_DISABLE (1<<2) /* 85x only */ #define FW_BLC 0x020d8 #define FW_BLC2 0x020dc #define FW_BLC_SELF 0x020e0 /* 915+ only */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 38b61e4d17a..8541feb893f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6138,6 +6138,9 @@ static void gen3_init_clock_gating(struct drm_device *dev) /* On GEN3 we really need to make sure the ARB C3 LP bit is set */ I915_WRITE(MI_ARB_STATE, _MASKED_BIT_ENABLE(MI_ARB_C3_LP_WRITE_ENABLE)); + + I915_WRITE(MI_ARB_STATE, + _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE)); } static void i85x_init_clock_gating(struct drm_device *dev) @@ -6149,6 +6152,9 @@ static void i85x_init_clock_gating(struct drm_device *dev) /* interrupts should cause a wake up from C3 */ I915_WRITE(MI_STATE, _MASKED_BIT_ENABLE(MI_AGPBUSY_INT_EN) | _MASKED_BIT_DISABLE(MI_AGPBUSY_830_MODE)); + + I915_WRITE(MEM_MODE, + _MASKED_BIT_ENABLE(MEM_DISPLAY_TRICKLE_FEED_DISABLE)); } static void i830_init_clock_gating(struct drm_device *dev) @@ -6156,6 +6162,10 @@ static void i830_init_clock_gating(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); + + I915_WRITE(MEM_MODE, + _MASKED_BIT_ENABLE(MEM_DISPLAY_A_TRICKLE_FEED_DISABLE) | + _MASKED_BIT_ENABLE(MEM_DISPLAY_B_TRICKLE_FEED_DISABLE)); } void intel_init_clock_gating(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 5aef600321caee7f950842b87f878780f693ca3a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 3 Sep 2014 11:56:07 +0100 Subject: drm/i915: Rename global latency_ns variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We use the variable name latency_ns in both the local lowlevel wm calculation routines and at the global level. Rename the global value to reduce shadow warnings and future confusion. Signed-off-by: Chris Wilson Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8541feb893f..49af81f6b4a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -872,7 +872,7 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) * A value of 5us seems to be a good balance; safe for very low end * platforms but not overly aggressive on lower latency configs. */ -static const int latency_ns = 5000; +static const int pessimal_latency_ns = 5000; static int i9xx_get_fifo_size(struct drm_device *dev, int plane) { @@ -1387,14 +1387,14 @@ static void valleyview_update_wm(struct drm_crtc *crtc) vlv_update_drain_latency(crtc); if (g4x_compute_wm0(dev, PIPE_A, - &valleyview_wm_info, latency_ns, - &valleyview_cursor_wm_info, latency_ns, + &valleyview_wm_info, pessimal_latency_ns, + &valleyview_cursor_wm_info, pessimal_latency_ns, &planea_wm, &cursora_wm)) enabled |= 1 << PIPE_A; if (g4x_compute_wm0(dev, PIPE_B, - &valleyview_wm_info, latency_ns, - &valleyview_cursor_wm_info, latency_ns, + &valleyview_wm_info, pessimal_latency_ns, + &valleyview_cursor_wm_info, pessimal_latency_ns, &planeb_wm, &cursorb_wm)) enabled |= 1 << PIPE_B; @@ -1453,20 +1453,20 @@ static void cherryview_update_wm(struct drm_crtc *crtc) vlv_update_drain_latency(crtc); if (g4x_compute_wm0(dev, PIPE_A, - &valleyview_wm_info, latency_ns, - &valleyview_cursor_wm_info, latency_ns, + &valleyview_wm_info, pessimal_latency_ns, + &valleyview_cursor_wm_info, pessimal_latency_ns, &planea_wm, &cursora_wm)) enabled |= 1 << PIPE_A; if (g4x_compute_wm0(dev, PIPE_B, - &valleyview_wm_info, latency_ns, - &valleyview_cursor_wm_info, latency_ns, + &valleyview_wm_info, pessimal_latency_ns, + &valleyview_cursor_wm_info, pessimal_latency_ns, &planeb_wm, &cursorb_wm)) enabled |= 1 << PIPE_B; if (g4x_compute_wm0(dev, PIPE_C, - &valleyview_wm_info, latency_ns, - &valleyview_cursor_wm_info, latency_ns, + &valleyview_wm_info, pessimal_latency_ns, + &valleyview_cursor_wm_info, pessimal_latency_ns, &planec_wm, &cursorc_wm)) enabled |= 1 << PIPE_C; @@ -1559,14 +1559,14 @@ static void g4x_update_wm(struct drm_crtc *crtc) bool cxsr_enabled; if (g4x_compute_wm0(dev, PIPE_A, - &g4x_wm_info, latency_ns, - &g4x_cursor_wm_info, latency_ns, + &g4x_wm_info, pessimal_latency_ns, + &g4x_cursor_wm_info, pessimal_latency_ns, &planea_wm, &cursora_wm)) enabled |= 1 << PIPE_A; if (g4x_compute_wm0(dev, PIPE_B, - &g4x_wm_info, latency_ns, - &g4x_cursor_wm_info, latency_ns, + &g4x_wm_info, pessimal_latency_ns, + &g4x_cursor_wm_info, pessimal_latency_ns, &planeb_wm, &cursorb_wm)) enabled |= 1 << PIPE_B; @@ -1709,7 +1709,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, wm_info, fifo_size, cpp, - latency_ns); + pessimal_latency_ns); enabled = crtc; } else { planea_wm = fifo_size - wm_info->guard_size; @@ -1731,7 +1731,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; planeb_wm = intel_calculate_wm(adjusted_mode->crtc_clock, wm_info, fifo_size, cpp, - latency_ns); + pessimal_latency_ns); if (enabled == NULL) enabled = crtc; else @@ -1827,7 +1827,7 @@ static void i845_update_wm(struct drm_crtc *unused_crtc) planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, &i845_wm_info, dev_priv->display.get_fifo_size(dev, 0), - 4, latency_ns); + 4, pessimal_latency_ns); fwater_lo = I915_READ(FW_BLC) & ~0xfff; fwater_lo |= (3<<8) | planea_wm; -- cgit v1.2.3-70-g09d2 From 773538e86081d146e0020435d614f4b96996c1f9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 4 Sep 2014 14:54:56 +0300 Subject: drm/i915: Reset power sequencer pipe tracking when disp2d is off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The power sequencer loses its state when the disp2d power well is down. Clear the dev_priv->pps_pipe tracking so that the power sequencer state gets reinitialized the next time it's needed. v2: Fix the pps_mutex vs. power_domain mutex deadlock by taking power domain reference first v3: Rename from edp_pps_(un)lock() to just pps_(un)lock() for the future, update due to backlight code changes Reviewed-by: Imre Deak Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 161 +++++++++++++++++++++++++-------------- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 2 + 3 files changed, 107 insertions(+), 57 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ef6a0a5088f..83d2f76cf3e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -290,6 +290,38 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, struct intel_dp *intel_dp, struct edp_power_seq *out); +static void pps_lock(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &intel_dig_port->base; + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_display_power_domain power_domain; + + /* + * See vlv_power_sequencer_reset() why we need + * a power domain reference here. + */ + power_domain = intel_display_port_power_domain(encoder); + intel_display_power_get(dev_priv, power_domain); + + mutex_lock(&dev_priv->pps_mutex); +} + +static void pps_unlock(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &intel_dig_port->base; + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_display_power_domain power_domain; + + mutex_unlock(&dev_priv->pps_mutex); + + power_domain = intel_display_port_power_domain(encoder); + intel_display_power_put(dev_priv, power_domain); +} + static enum pipe vlv_power_sequencer_pipe(struct intel_dp *intel_dp) { @@ -391,6 +423,35 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) &power_seq); } +void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + struct intel_encoder *encoder; + + if (WARN_ON(!IS_VALLEYVIEW(dev))) + return; + + /* + * We can't grab pps_mutex here due to deadlock with power_domain + * mutex when power_domain functions are called while holding pps_mutex. + * That also means that in order to use pps_pipe the code needs to + * hold both a power domain reference and pps_mutex, and the power domain + * reference get/put must be done while _not_ holding pps_mutex. + * pps_{lock,unlock}() do these steps in the correct order, so one + * should use them always. + */ + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { + struct intel_dp *intel_dp; + + if (encoder->type != INTEL_OUTPUT_EDP) + continue; + + intel_dp = enc_to_intel_dp(&encoder->base); + intel_dp->pps_pipe = INVALID_PIPE; + } +} + static u32 _pp_ctrl_reg(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); @@ -426,7 +487,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code, if (!is_edp(intel_dp) || code != SYS_RESTART) return 0; - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); if (IS_VALLEYVIEW(dev)) { enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); @@ -442,7 +503,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code, msleep(intel_dp->panel_power_cycle_delay); } - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); return 0; } @@ -461,15 +522,10 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct intel_encoder *intel_encoder = &intel_dig_port->base; - enum intel_display_power_domain power_domain; lockdep_assert_held(&dev_priv->pps_mutex); - power_domain = intel_display_port_power_domain(intel_encoder); - return intel_display_power_enabled(dev_priv, power_domain) && - (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0; + return I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD; } static void @@ -617,7 +673,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, bool has_aux_irq = HAS_AUX_IRQ(dev); bool vdd; - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); /* * We will be called with VDD already enabled for dpcd/edid/oui reads. @@ -734,7 +790,7 @@ out: if (vdd) edp_panel_vdd_off(intel_dp, false); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); return ret; } @@ -1315,16 +1371,14 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) void intel_edp_panel_vdd_on(struct intel_dp *intel_dp) { - struct drm_i915_private *dev_priv = - intel_dp_to_dev(intel_dp)->dev_private; bool vdd; if (!is_edp(intel_dp)) return; - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); vdd = edp_panel_vdd_on(intel_dp); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); WARN(!vdd, "eDP VDD already requested on\n"); } @@ -1373,13 +1427,11 @@ static void edp_panel_vdd_work(struct work_struct *__work) { struct intel_dp *intel_dp = container_of(to_delayed_work(__work), struct intel_dp, panel_vdd_work); - struct drm_i915_private *dev_priv = - intel_dp_to_dev(intel_dp)->dev_private; - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); if (!intel_dp->want_panel_vdd) edp_panel_vdd_off_sync(intel_dp); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp) @@ -1417,15 +1469,12 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) { - struct drm_i915_private *dev_priv = - intel_dp_to_dev(intel_dp)->dev_private; - if (!is_edp(intel_dp)) return; - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); edp_panel_vdd_off(intel_dp, sync); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } void intel_edp_panel_on(struct intel_dp *intel_dp) @@ -1440,7 +1489,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp) DRM_DEBUG_KMS("Turn eDP power on\n"); - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); if (edp_have_panel_power(intel_dp)) { DRM_DEBUG_KMS("eDP power already on\n"); @@ -1475,7 +1524,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp) } out: - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } void intel_edp_panel_off(struct intel_dp *intel_dp) @@ -1493,7 +1542,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp) DRM_DEBUG_KMS("Turn eDP power off\n"); - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); @@ -1517,7 +1566,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp) power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_put(dev_priv, power_domain); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } /* Enable backlight in the panel power control. */ @@ -1537,7 +1586,7 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp) */ wait_backlight_on(intel_dp); - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); pp = ironlake_get_pp_control(intel_dp); pp |= EDP_BLC_ENABLE; @@ -1547,7 +1596,7 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp) I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } /* Enable backlight PWM and backlight PP control. */ @@ -1573,7 +1622,7 @@ static void _intel_edp_backlight_off(struct intel_dp *intel_dp) if (!is_edp(intel_dp)) return; - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); pp = ironlake_get_pp_control(intel_dp); pp &= ~EDP_BLC_ENABLE; @@ -1583,7 +1632,7 @@ static void _intel_edp_backlight_off(struct intel_dp *intel_dp) I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); intel_dp->last_backlight_off = jiffies; edp_wait_backlight_off(intel_dp); @@ -1608,13 +1657,12 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp) static void intel_edp_backlight_power(struct intel_connector *connector, bool enable) { - struct drm_i915_private *dev_priv = connector->base.dev->dev_private; struct intel_dp *intel_dp = intel_attached_dp(&connector->base); bool is_enabled; - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE; - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); if (is_enabled == enable) return; @@ -2339,18 +2387,19 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { struct intel_dp *intel_dp; + enum port port; if (encoder->type != INTEL_OUTPUT_EDP) continue; intel_dp = enc_to_intel_dp(&encoder->base); + port = dp_to_dig_port(intel_dp)->port; if (intel_dp->pps_pipe != pipe) continue; DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n", - pipe_name(pipe), - port_name(dp_to_dig_port(intel_dp)->port)); + pipe_name(pipe), port_name(port)); /* make sure vdd is off before we steal it */ edp_panel_vdd_off_sync(intel_dp); @@ -2426,9 +2475,9 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) mutex_unlock(&dev_priv->dpio_lock); if (is_edp(intel_dp)) { - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); vlv_init_panel_power_sequencer(intel_dp); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } intel_enable_dp(encoder); @@ -2517,9 +2566,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) mutex_unlock(&dev_priv->dpio_lock); if (is_edp(intel_dp)) { - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); vlv_init_panel_power_sequencer(intel_dp); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } intel_enable_dp(encoder); @@ -4258,17 +4307,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) { struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); struct intel_dp *intel_dp = &intel_dig_port->dp; - struct drm_device *dev = intel_dp_to_dev(intel_dp); - struct drm_i915_private *dev_priv = dev->dev_private; drm_dp_aux_unregister(&intel_dp->aux); intel_dp_mst_encoder_cleanup(intel_dig_port); drm_encoder_cleanup(encoder); if (is_edp(intel_dp)) { cancel_delayed_work_sync(&intel_dp->panel_vdd_work); - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); edp_panel_vdd_off_sync(intel_dp); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); + if (intel_dp->edp_notifier.notifier_call) { unregister_reboot_notifier(&intel_dp->edp_notifier); intel_dp->edp_notifier.notifier_call = NULL; @@ -4280,15 +4328,13 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); - struct drm_device *dev = intel_dp_to_dev(intel_dp); - struct drm_i915_private *dev_priv = dev->dev_private; if (!is_edp(intel_dp)) return; - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); edp_panel_vdd_off_sync(intel_dp); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } static void intel_dp_encoder_reset(struct drm_encoder *encoder) @@ -4767,9 +4813,10 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder) if (intel_encoder->type != INTEL_OUTPUT_EDP) return; - mutex_lock(&dev_priv->pps_mutex); - intel_dp = enc_to_intel_dp(&intel_encoder->base); + + pps_lock(intel_dp); + if (!edp_have_panel_vdd(intel_dp)) goto out; /* @@ -4784,7 +4831,7 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder) edp_panel_vdd_schedule_off(intel_dp); out: - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } static bool intel_edp_init_connector(struct intel_dp *intel_dp, @@ -4826,9 +4873,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } /* We now know it's not a ghost, init power sequence regs. */ - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); mutex_lock(&dev->mode_config.mutex); edid = drm_get_edid(connector, &intel_dp->aux.ddc); @@ -4963,7 +5010,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, } if (is_edp(intel_dp)) { - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); if (IS_VALLEYVIEW(dev)) { vlv_initial_power_sequencer_setup(intel_dp); } else { @@ -4971,8 +5018,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); } + pps_unlock(intel_dp); } - mutex_unlock(&dev_priv->pps_mutex); intel_dp_aux_init(intel_dp, intel_connector); @@ -4988,9 +5035,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, drm_dp_aux_unregister(&intel_dp->aux); if (is_edp(intel_dp)) { cancel_delayed_work_sync(&intel_dp->panel_vdd_work); - mutex_lock(&dev_priv->pps_mutex); + pps_lock(intel_dp); edp_panel_vdd_off_sync(intel_dp); - mutex_unlock(&dev_priv->pps_mutex); + pps_unlock(intel_dp); } drm_connector_unregister(connector); drm_connector_cleanup(connector); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1278b2529d6..a505bf3ef33 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -946,6 +946,7 @@ void intel_dp_mst_suspend(struct drm_device *dev); void intel_dp_mst_resume(struct drm_device *dev); int intel_dp_max_link_bw(struct intel_dp *intel_dp); void intel_dp_hot_plug(struct intel_encoder *intel_encoder); +void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv); /* intel_dp_mst.c */ int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 49af81f6b4a..45f71e6dc54 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6468,6 +6468,8 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv, spin_unlock_irq(&dev_priv->irq_lock); vlv_set_power_well(dev_priv, power_well, false); + + vlv_power_sequencer_reset(dev_priv); } static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, -- cgit v1.2.3-70-g09d2 From d6feb1962d08890080cbce080a3d73e1035f0a3d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Sep 2014 21:54:13 +0300 Subject: drm/i915: Limit the watermark to at least 8 entries on gen2/3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 830 is very unhappy of the watermark value is too low (indicating a very high watermark in fact, ie. memory fetch will occur with an almost full FIFO). Limit the watermark value to at least 8 cache lines. That also matches the burst size we use on most platforms. BSpec seems to indicate we should limit the watermark to 'burst size + 1'. But on gen4 we already use a hardcoded 8 as the watermark value (as the spec says we should), so just use 8 as the limit on gen2/3 as well. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 45f71e6dc54..675e8a2ce98 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1070,6 +1070,17 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, wm_size = wm->max_wm; if (wm_size <= 0) wm_size = wm->default_wm; + + /* + * Bspec seems to indicate that the value shouldn't be lower than + * 'burst size + 1'. Certainly 830 is quite unhappy with low values. + * Lets go for 8 which is the burst size since certain platforms + * already use a hardcoded 8 (which is what the spec says should be + * done). + */ + if (wm_size <= 8) + wm_size = 8; + return wm_size; } -- cgit v1.2.3-70-g09d2 From 7526ed79b014cbd943cd48b8dda63e74391ddd48 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 29 Sep 2014 15:07:19 +0200 Subject: Revert "drm/i915/bdw: BDW Software Turbo" This reverts commit c76bb61a71083b2d90504cc6d0dda2047c5d63ca. It's apparently too broken so that Rodrigo submitted a patch to add a config option for it. Given that the design is also ... suboptimal and that I've only merged this to get lead engineers and managers off my back for one second let's just revert this. /me puts on combat gear again It was worth a shot ... References: http://mid.mail-archive.com/1411686380-1953-1-git-send-email-rodrigo.vivi@intel.com Cc: Jesse Barnes Cc: Daisy Sun Cc: Jesse Barnes Cc: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 22 ---- drivers/gpu/drm/i915/i915_irq.c | 21 ---- drivers/gpu/drm/i915/i915_reg.h | 4 - drivers/gpu/drm/i915/intel_display.c | 3 - drivers/gpu/drm/i915/intel_pm.c | 230 ++++++----------------------------- 5 files changed, 39 insertions(+), 241 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 17dfce0f4e6..32180ac9277 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -945,23 +945,6 @@ struct intel_rps_ei { u32 media_c0; }; -struct intel_rps_bdw_cal { - u32 it_threshold_pct; /* interrupt, in percentage */ - u32 eval_interval; /* evaluation interval, in us */ - u32 last_ts; - u32 last_c0; - bool is_up; -}; - -struct intel_rps_bdw_turbo { - struct intel_rps_bdw_cal up; - struct intel_rps_bdw_cal down; - struct timer_list flip_timer; - u32 timeout; - atomic_t flip_received; - struct work_struct work_max_freq; -}; - struct intel_gen6_power_mgmt { /* work and pm_iir are protected by dev_priv->irq_lock */ struct work_struct work; @@ -995,9 +978,6 @@ struct intel_gen6_power_mgmt { bool enabled; struct delayed_work delayed_resume_work; - bool is_bdw_sw_turbo; /* Switch of BDW software turbo */ - struct intel_rps_bdw_turbo sw_turbo; /* Calculate RP interrupt timing */ - /* manual wa residency calculations */ struct intel_rps_ei up_ei, down_ei; @@ -2828,8 +2808,6 @@ extern void intel_disable_fbc(struct drm_device *dev); extern bool ironlake_set_drps(struct drm_device *dev, u8 val); extern void intel_init_pch_refclk(struct drm_device *dev); extern void gen6_set_rps(struct drm_device *dev, u8 val); -extern void bdw_software_turbo(struct drm_device *dev); -extern void gen8_flip_interrupt(struct drm_device *dev); extern void valleyview_set_rps(struct drm_device *dev, u8 val); extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c96ddc95353..3201986bf25 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1979,27 +1979,6 @@ static void i9xx_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe) res1, res2); } -void gen8_flip_interrupt(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!dev_priv->rps.is_bdw_sw_turbo) - return; - - if(atomic_read(&dev_priv->rps.sw_turbo.flip_received)) { - mod_timer(&dev_priv->rps.sw_turbo.flip_timer, - usecs_to_jiffies(dev_priv->rps.sw_turbo.timeout) + jiffies); - } - else { - dev_priv->rps.sw_turbo.flip_timer.expires = - usecs_to_jiffies(dev_priv->rps.sw_turbo.timeout) + jiffies; - add_timer(&dev_priv->rps.sw_turbo.flip_timer); - atomic_set(&dev_priv->rps.sw_turbo.flip_received, true); - } - - bdw_software_turbo(dev); -} - /* The RPS events need forcewake, so we add them to a work queue and mask their * IMR bits until the work is done. Other interrupts can be processed without * the work queue. */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ad8179b40d1..e887d4c13ca 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5585,10 +5585,6 @@ enum punit_power_well { #define GEN8_UCGCTL6 0x9430 #define GEN8_SDEUNIT_CLOCK_GATE_DISABLE (1<<14) -#define TIMESTAMP_CTR 0x44070 -#define FREQ_1_28_US(us) (((us) * 100) >> 7) -#define MCHBAR_PCU_C0 (MCHBAR_MIRROR_BASE_SNB + 0x5960) - #define GEN6_GFXPAUSE 0xA000 #define GEN6_RPNSWREQ 0xA008 #define GEN6_TURBO_DISABLE (1<<31) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c5079f2c49f..2d4258038ef 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9926,9 +9926,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, unsigned long flags; int ret; - //trigger software GT busyness calculation - gen8_flip_interrupt(dev); - /* * drm_mode_page_flip_ioctl() should already catch this, but double * check to be safe. In the future we may enable pageflipping from diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 675e8a2ce98..45f2aa0b8fe 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2285,6 +2285,7 @@ int ilk_wm_max_level(const struct drm_device *dev) else return 2; } + static void intel_print_wm_latency(struct drm_device *dev, const char *name, const uint16_t wm[5]) @@ -3253,9 +3254,6 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) { int new_power; - if (dev_priv->rps.is_bdw_sw_turbo) - return; - new_power = dev_priv->rps.power; switch (dev_priv->rps.power) { case LOW_POWER: @@ -3463,11 +3461,8 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); else if (IS_VALLEYVIEW(dev)) vlv_set_rps_idle(dev_priv); - else if (!dev_priv->rps.is_bdw_sw_turbo - || atomic_read(&dev_priv->rps.sw_turbo.flip_received)){ + else gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); - } - dev_priv->rps.last_adj = 0; } mutex_unlock(&dev_priv->rps.hw_lock); @@ -3481,11 +3476,8 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv) if (dev_priv->rps.enabled) { if (IS_VALLEYVIEW(dev)) valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit); - else if (!dev_priv->rps.is_bdw_sw_turbo - || atomic_read(&dev_priv->rps.sw_turbo.flip_received)){ + else gen6_set_rps(dev_priv->dev, dev_priv->rps.max_freq_softlimit); - } - dev_priv->rps.last_adj = 0; } mutex_unlock(&dev_priv->rps.hw_lock); @@ -3520,26 +3512,21 @@ void valleyview_set_rps(struct drm_device *dev, u8 val) static void gen8_disable_rps_interrupts(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (IS_BROADWELL(dev) && dev_priv->rps.is_bdw_sw_turbo){ - if (atomic_read(&dev_priv->rps.sw_turbo.flip_received)) - del_timer(&dev_priv->rps.sw_turbo.flip_timer); - dev_priv-> rps.is_bdw_sw_turbo = false; - } else { - I915_WRITE(GEN6_PMINTRMSK, ~GEN8_PMINTR_REDIRECT_TO_NON_DISP); - I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) & - ~dev_priv->pm_rps_events); - /* Complete PM interrupt masking here doesn't race with the rps work - * item again unmasking PM interrupts because that is using a different - * register (GEN8_GT_IMR(2)) to mask PM interrupts. The only risk is in - * leaving stale bits in GEN8_GT_IIR(2) and GEN8_GT_IMR(2) which - * gen8_enable_rps will clean up. */ - spin_lock_irq(&dev_priv->irq_lock); - dev_priv->rps.pm_iir = 0; - spin_unlock_irq(&dev_priv->irq_lock); + I915_WRITE(GEN6_PMINTRMSK, ~GEN8_PMINTR_REDIRECT_TO_NON_DISP); + I915_WRITE(GEN8_GT_IER(2), I915_READ(GEN8_GT_IER(2)) & + ~dev_priv->pm_rps_events); + /* Complete PM interrupt masking here doesn't race with the rps work + * item again unmasking PM interrupts because that is using a different + * register (GEN8_GT_IMR(2)) to mask PM interrupts. The only risk is in + * leaving stale bits in GEN8_GT_IIR(2) and GEN8_GT_IMR(2) which + * gen8_enable_rps will clean up. */ - I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events); - } + spin_lock_irq(&dev_priv->irq_lock); + dev_priv->rps.pm_iir = 0; + spin_unlock_irq(&dev_priv->irq_lock); + + I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events); } static void gen6_disable_rps_interrupts(struct drm_device *dev) @@ -3697,111 +3684,13 @@ static void parse_rp_state_cap(struct drm_i915_private *dev_priv, u32 rp_state_c dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq; } -static void bdw_sw_calculate_freq(struct drm_device *dev, - struct intel_rps_bdw_cal *c, u32 *cur_time, u32 *c0) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u64 busy = 0; - u32 busyness_pct = 0; - u32 elapsed_time = 0; - u16 new_freq = 0; - - if (!c || !cur_time || !c0) - return; - - if (0 == c->last_c0) - goto out; - - /* Check Evaluation interval */ - elapsed_time = *cur_time - c->last_ts; - if (elapsed_time < c->eval_interval) - return; - - mutex_lock(&dev_priv->rps.hw_lock); - - /* - * c0 unit in 32*1.28 usec, elapsed_time unit in 1 usec. - * Whole busyness_pct calculation should be - * busy = ((u64)(*c0 - c->last_c0) << 5 << 7) / 100; - * busyness_pct = (u32)(busy * 100 / elapsed_time); - * The final formula is to simplify CPU calculation - */ - busy = (u64)(*c0 - c->last_c0) << 12; - do_div(busy, elapsed_time); - busyness_pct = (u32)busy; - - if (c->is_up && busyness_pct >= c->it_threshold_pct) - new_freq = (u16)dev_priv->rps.cur_freq + 3; - if (!c->is_up && busyness_pct <= c->it_threshold_pct) - new_freq = (u16)dev_priv->rps.cur_freq - 1; - - /* Adjust to new frequency busyness and compare with threshold */ - if (0 != new_freq) { - if (new_freq > dev_priv->rps.max_freq_softlimit) - new_freq = dev_priv->rps.max_freq_softlimit; - else if (new_freq < dev_priv->rps.min_freq_softlimit) - new_freq = dev_priv->rps.min_freq_softlimit; - - gen6_set_rps(dev, new_freq); - } - - mutex_unlock(&dev_priv->rps.hw_lock); - -out: - c->last_c0 = *c0; - c->last_ts = *cur_time; -} - -static void gen8_set_frequency_RP0(struct work_struct *work) -{ - struct intel_rps_bdw_turbo *p_bdw_turbo = - container_of(work, struct intel_rps_bdw_turbo, work_max_freq); - struct intel_gen6_power_mgmt *p_power_mgmt = - container_of(p_bdw_turbo, struct intel_gen6_power_mgmt, sw_turbo); - struct drm_i915_private *dev_priv = - container_of(p_power_mgmt, struct drm_i915_private, rps); - - mutex_lock(&dev_priv->rps.hw_lock); - gen6_set_rps(dev_priv->dev, dev_priv->rps.rp0_freq); - mutex_unlock(&dev_priv->rps.hw_lock); -} - -static void flip_active_timeout_handler(unsigned long var) -{ - struct drm_i915_private *dev_priv = (struct drm_i915_private *) var; - - del_timer(&dev_priv->rps.sw_turbo.flip_timer); - atomic_set(&dev_priv->rps.sw_turbo.flip_received, false); - - queue_work(dev_priv->wq, &dev_priv->rps.sw_turbo.work_max_freq); -} - -void bdw_software_turbo(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - u32 current_time = I915_READ(TIMESTAMP_CTR); /* unit in usec */ - u32 current_c0 = I915_READ(MCHBAR_PCU_C0); /* unit in 32*1.28 usec */ - - bdw_sw_calculate_freq(dev, &dev_priv->rps.sw_turbo.up, - ¤t_time, ¤t_c0); - bdw_sw_calculate_freq(dev, &dev_priv->rps.sw_turbo.down, - ¤t_time, ¤t_c0); -} - static void gen8_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; uint32_t rc6_mask = 0, rp_state_cap; - uint32_t threshold_up_pct, threshold_down_pct; - uint32_t ei_up, ei_down; /* up and down evaluation interval */ - u32 rp_ctl_flag; int unused; - /* Use software Turbo for BDW */ - dev_priv->rps.is_bdw_sw_turbo = IS_BROADWELL(dev); - /* 1a: Software RC state - RC0 */ I915_WRITE(GEN6_RC_STATE, 0); @@ -3845,74 +3734,35 @@ static void gen8_enable_rps(struct drm_device *dev) HSW_FREQUENCY(dev_priv->rps.rp1_freq)); I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(dev_priv->rps.rp1_freq)); - ei_up = 84480; /* 84.48ms */ - ei_down = 448000; - threshold_up_pct = 90; /* x percent busy */ - threshold_down_pct = 70; - - if (dev_priv->rps.is_bdw_sw_turbo) { - dev_priv->rps.sw_turbo.up.it_threshold_pct = threshold_up_pct; - dev_priv->rps.sw_turbo.up.eval_interval = ei_up; - dev_priv->rps.sw_turbo.up.is_up = true; - dev_priv->rps.sw_turbo.up.last_ts = 0; - dev_priv->rps.sw_turbo.up.last_c0 = 0; - - dev_priv->rps.sw_turbo.down.it_threshold_pct = threshold_down_pct; - dev_priv->rps.sw_turbo.down.eval_interval = ei_down; - dev_priv->rps.sw_turbo.down.is_up = false; - dev_priv->rps.sw_turbo.down.last_ts = 0; - dev_priv->rps.sw_turbo.down.last_c0 = 0; - - /* Start the timer to track if flip comes*/ - dev_priv->rps.sw_turbo.timeout = 200*1000; /* in us */ - - init_timer(&dev_priv->rps.sw_turbo.flip_timer); - dev_priv->rps.sw_turbo.flip_timer.function = flip_active_timeout_handler; - dev_priv->rps.sw_turbo.flip_timer.data = (unsigned long) dev_priv; - dev_priv->rps.sw_turbo.flip_timer.expires = - usecs_to_jiffies(dev_priv->rps.sw_turbo.timeout) + jiffies; - add_timer(&dev_priv->rps.sw_turbo.flip_timer); - INIT_WORK(&dev_priv->rps.sw_turbo.work_max_freq, gen8_set_frequency_RP0); - - atomic_set(&dev_priv->rps.sw_turbo.flip_received, true); - } else { - /* NB: Docs say 1s, and 1000000 - which aren't equivalent - * 1 second timeout*/ - I915_WRITE(GEN6_RP_DOWN_TIMEOUT, FREQ_1_28_US(1000000)); + /* NB: Docs say 1s, and 1000000 - which aren't equivalent */ + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */ - /* Docs recommend 900MHz, and 300 MHz respectively */ - I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, - dev_priv->rps.max_freq_softlimit << 24 | - dev_priv->rps.min_freq_softlimit << 16); + /* Docs recommend 900MHz, and 300 MHz respectively */ + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + dev_priv->rps.max_freq_softlimit << 24 | + dev_priv->rps.min_freq_softlimit << 16); - I915_WRITE(GEN6_RP_UP_THRESHOLD, - FREQ_1_28_US(ei_up * threshold_up_pct / 100)); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, - FREQ_1_28_US(ei_down * threshold_down_pct / 100)); - I915_WRITE(GEN6_RP_UP_EI, - FREQ_1_28_US(ei_up)); - I915_WRITE(GEN6_RP_DOWN_EI, - FREQ_1_28_US(ei_down)); + I915_WRITE(GEN6_RP_UP_THRESHOLD, 7600000 / 128); /* 76ms busyness per EI, 90% */ + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 31300000 / 128); /* 313ms busyness per EI, 70%*/ + I915_WRITE(GEN6_RP_UP_EI, 66000); /* 84.48ms, XXX: random? */ + I915_WRITE(GEN6_RP_DOWN_EI, 350000); /* 448ms, XXX: random? */ - I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); - } + I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); /* 5: Enable RPS */ - rp_ctl_flag = GEN6_RP_MEDIA_TURBO | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_UP_BUSY_AVG | - GEN6_RP_DOWN_IDLE_AVG; - if (!dev_priv->rps.is_bdw_sw_turbo) - rp_ctl_flag |= GEN6_RP_ENABLE; - - I915_WRITE(GEN6_RP_CONTROL, rp_ctl_flag); - - /* 6: Ring frequency + overclocking - * (our driver does this later */ + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_TURBO | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_AVG); + + /* 6: Ring frequency + overclocking (our driver does this later */ + gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8); - if (!dev_priv->rps.is_bdw_sw_turbo) - gen8_enable_rps_interrupts(dev); + + gen8_enable_rps_interrupts(dev); gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL); } @@ -5386,8 +5236,6 @@ static void intel_gen6_powersave_work(struct work_struct *work) rps.delayed_resume_work.work); struct drm_device *dev = dev_priv->dev; - dev_priv->rps.is_bdw_sw_turbo = false; - mutex_lock(&dev_priv->rps.hw_lock); if (IS_CHERRYVIEW(dev)) { -- cgit v1.2.3-70-g09d2 From 67956867aa07c59d6d83628bbc9ee4bd9799a1e1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 2 Sep 2014 15:12:17 +0300 Subject: drm/i915: Don't spam dmesg with rps messages on vlv/chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the GPU frequency isn't going to change don't spam dmesg with debug messages about it. Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 45f2aa0b8fe..c27b6140bfd 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3491,17 +3491,18 @@ void valleyview_set_rps(struct drm_device *dev, u8 val) WARN_ON(val > dev_priv->rps.max_freq_softlimit); WARN_ON(val < dev_priv->rps.min_freq_softlimit); - DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n", - vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq), - dev_priv->rps.cur_freq, - vlv_gpu_freq(dev_priv, val), val); - if (WARN_ONCE(IS_CHERRYVIEW(dev) && (val & 1), "Odd GPU freq value\n")) val &= ~1; - if (val != dev_priv->rps.cur_freq) + if (val != dev_priv->rps.cur_freq) { + DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n", + vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq), + dev_priv->rps.cur_freq, + vlv_gpu_freq(dev_priv, val), val); + vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val); + } I915_WRITE(GEN6_PMINTRMSK, gen6_rps_pm_mask(dev_priv, val)); -- cgit v1.2.3-70-g09d2