intel_pm.c revision 296548
1277487Skib/* 2277487Skib * Copyright �� 2012 Intel Corporation 3277487Skib * 4277487Skib * Permission is hereby granted, free of charge, to any person obtaining a 5277487Skib * copy of this software and associated documentation files (the "Software"), 6277487Skib * to deal in the Software without restriction, including without limitation 7277487Skib * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8277487Skib * and/or sell copies of the Software, and to permit persons to whom the 9277487Skib * Software is furnished to do so, subject to the following conditions: 10277487Skib * 11277487Skib * The above copyright notice and this permission notice (including the next 12277487Skib * paragraph) shall be included in all copies or substantial portions of the 13277487Skib * Software. 14277487Skib * 15277487Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16277487Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17277487Skib * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18277487Skib * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19277487Skib * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20277487Skib * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21277487Skib * IN THE SOFTWARE. 22277487Skib * 23277487Skib * Authors: 24277487Skib * Eugeni Dodonov <eugeni.dodonov@intel.com> 25277487Skib * 26277487Skib */ 27277487Skib 28277487Skib#include <sys/cdefs.h> 29277487Skib__FBSDID("$FreeBSD: head/sys/dev/drm2/i915/intel_pm.c 296548 2016-03-08 20:33:02Z dumbbell $"); 30277487Skib 31277487Skib#include <dev/drm2/drmP.h> 32277487Skib#include <dev/drm2/i915/i915_drv.h> 33277487Skib#include <dev/drm2/i915/intel_drv.h> 34277487Skib#include <sys/kdb.h> 35277487Skib 36296548Sdumbbell#define FORCEWAKE_ACK_TIMEOUT_MS 2 37277487Skib 38277487Skib/* FBC, or Frame Buffer Compression, is a technique employed to compress the 39277487Skib * framebuffer contents in-memory, aiming at reducing the required bandwidth 40277487Skib * during in-memory transfers and, therefore, reduce the power packet. 41277487Skib * 42277487Skib * The benefits of FBC are mostly visible with solid backgrounds and 43277487Skib * variation-less patterns. 44277487Skib * 45277487Skib * FBC-related functionality can be enabled by the means of the 46277487Skib * i915.i915_enable_fbc parameter 47277487Skib */ 48277487Skib 49296548Sdumbbellstatic bool intel_crtc_active(struct drm_crtc *crtc) 50296548Sdumbbell{ 51296548Sdumbbell /* Be paranoid as we can arrive here with only partial 52296548Sdumbbell * state retrieved from the hardware during setup. 53296548Sdumbbell */ 54296548Sdumbbell return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; 55296548Sdumbbell} 56296548Sdumbbell 57277487Skibstatic void i8xx_disable_fbc(struct drm_device *dev) 58277487Skib{ 59277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 60277487Skib u32 fbc_ctl; 61277487Skib 62277487Skib /* Disable compression */ 63277487Skib fbc_ctl = I915_READ(FBC_CONTROL); 64277487Skib if ((fbc_ctl & FBC_CTL_EN) == 0) 65277487Skib return; 66277487Skib 67277487Skib fbc_ctl &= ~FBC_CTL_EN; 68277487Skib I915_WRITE(FBC_CONTROL, fbc_ctl); 69277487Skib 70277487Skib /* Wait for compressing bit to clear */ 71277487Skib if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) { 72277487Skib DRM_DEBUG_KMS("FBC idle timed out\n"); 73277487Skib return; 74277487Skib } 75277487Skib 76277487Skib DRM_DEBUG_KMS("disabled FBC\n"); 77277487Skib} 78277487Skib 79277487Skibstatic void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 80277487Skib{ 81277487Skib struct drm_device *dev = crtc->dev; 82277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 83277487Skib struct drm_framebuffer *fb = crtc->fb; 84277487Skib struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 85277487Skib struct drm_i915_gem_object *obj = intel_fb->obj; 86277487Skib struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 87277487Skib int cfb_pitch; 88277487Skib int plane, i; 89277487Skib u32 fbc_ctl, fbc_ctl2; 90277487Skib 91277487Skib cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE; 92277487Skib if (fb->pitches[0] < cfb_pitch) 93277487Skib cfb_pitch = fb->pitches[0]; 94277487Skib 95277487Skib /* FBC_CTL wants 64B units */ 96277487Skib cfb_pitch = (cfb_pitch / 64) - 1; 97277487Skib plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB; 98277487Skib 99277487Skib /* Clear old tags */ 100277487Skib for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) 101277487Skib I915_WRITE(FBC_TAG + (i * 4), 0); 102277487Skib 103277487Skib /* Set it up... */ 104277487Skib fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; 105277487Skib fbc_ctl2 |= plane; 106277487Skib I915_WRITE(FBC_CONTROL2, fbc_ctl2); 107277487Skib I915_WRITE(FBC_FENCE_OFF, crtc->y); 108277487Skib 109277487Skib /* enable it... */ 110277487Skib fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; 111277487Skib if (IS_I945GM(dev)) 112277487Skib fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ 113277487Skib fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; 114277487Skib fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; 115277487Skib fbc_ctl |= obj->fence_reg; 116277487Skib I915_WRITE(FBC_CONTROL, fbc_ctl); 117277487Skib 118277487Skib DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ", 119277487Skib cfb_pitch, crtc->y, intel_crtc->plane); 120277487Skib} 121277487Skib 122277487Skibstatic bool i8xx_fbc_enabled(struct drm_device *dev) 123277487Skib{ 124277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 125277487Skib 126277487Skib return I915_READ(FBC_CONTROL) & FBC_CTL_EN; 127277487Skib} 128277487Skib 129277487Skibstatic void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 130277487Skib{ 131277487Skib struct drm_device *dev = crtc->dev; 132277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 133277487Skib struct drm_framebuffer *fb = crtc->fb; 134277487Skib struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 135277487Skib struct drm_i915_gem_object *obj = intel_fb->obj; 136277487Skib struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 137277487Skib int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; 138277487Skib unsigned long stall_watermark = 200; 139277487Skib u32 dpfc_ctl; 140277487Skib 141277487Skib dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; 142277487Skib dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; 143277487Skib I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY); 144277487Skib 145277487Skib I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | 146277487Skib (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | 147277487Skib (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); 148277487Skib I915_WRITE(DPFC_FENCE_YOFF, crtc->y); 149277487Skib 150277487Skib /* enable it... */ 151277487Skib I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN); 152277487Skib 153277487Skib DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); 154277487Skib} 155277487Skib 156277487Skibstatic void g4x_disable_fbc(struct drm_device *dev) 157277487Skib{ 158277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 159277487Skib u32 dpfc_ctl; 160277487Skib 161277487Skib /* Disable compression */ 162277487Skib dpfc_ctl = I915_READ(DPFC_CONTROL); 163277487Skib if (dpfc_ctl & DPFC_CTL_EN) { 164277487Skib dpfc_ctl &= ~DPFC_CTL_EN; 165277487Skib I915_WRITE(DPFC_CONTROL, dpfc_ctl); 166277487Skib 167277487Skib DRM_DEBUG_KMS("disabled FBC\n"); 168277487Skib } 169277487Skib} 170277487Skib 171277487Skibstatic bool g4x_fbc_enabled(struct drm_device *dev) 172277487Skib{ 173277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 174277487Skib 175277487Skib return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; 176277487Skib} 177277487Skib 178277487Skibstatic void sandybridge_blit_fbc_update(struct drm_device *dev) 179277487Skib{ 180277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 181277487Skib u32 blt_ecoskpd; 182277487Skib 183277487Skib /* Make sure blitter notifies FBC of writes */ 184277487Skib gen6_gt_force_wake_get(dev_priv); 185277487Skib blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); 186277487Skib blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << 187277487Skib GEN6_BLITTER_LOCK_SHIFT; 188277487Skib I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); 189277487Skib blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY; 190277487Skib I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); 191277487Skib blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY << 192277487Skib GEN6_BLITTER_LOCK_SHIFT); 193277487Skib I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); 194277487Skib POSTING_READ(GEN6_BLITTER_ECOSKPD); 195277487Skib gen6_gt_force_wake_put(dev_priv); 196277487Skib} 197277487Skib 198277487Skibstatic void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 199277487Skib{ 200277487Skib struct drm_device *dev = crtc->dev; 201277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 202277487Skib struct drm_framebuffer *fb = crtc->fb; 203277487Skib struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); 204277487Skib struct drm_i915_gem_object *obj = intel_fb->obj; 205277487Skib struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 206277487Skib int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; 207277487Skib unsigned long stall_watermark = 200; 208277487Skib u32 dpfc_ctl; 209277487Skib 210277487Skib dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); 211277487Skib dpfc_ctl &= DPFC_RESERVED; 212277487Skib dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); 213277487Skib /* Set persistent mode for front-buffer rendering, ala X. */ 214277487Skib dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE; 215277487Skib dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg); 216277487Skib I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY); 217277487Skib 218277487Skib I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | 219277487Skib (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | 220277487Skib (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); 221277487Skib I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); 222277487Skib I915_WRITE(ILK_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID); 223277487Skib /* enable it... */ 224277487Skib I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); 225277487Skib 226277487Skib if (IS_GEN6(dev)) { 227277487Skib I915_WRITE(SNB_DPFC_CTL_SA, 228277487Skib SNB_CPU_FENCE_ENABLE | obj->fence_reg); 229277487Skib I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); 230277487Skib sandybridge_blit_fbc_update(dev); 231277487Skib } 232277487Skib 233277487Skib DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); 234277487Skib} 235277487Skib 236277487Skibstatic void ironlake_disable_fbc(struct drm_device *dev) 237277487Skib{ 238277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 239277487Skib u32 dpfc_ctl; 240277487Skib 241277487Skib /* Disable compression */ 242277487Skib dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); 243277487Skib if (dpfc_ctl & DPFC_CTL_EN) { 244277487Skib dpfc_ctl &= ~DPFC_CTL_EN; 245277487Skib I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); 246277487Skib 247277487Skib DRM_DEBUG_KMS("disabled FBC\n"); 248277487Skib } 249277487Skib} 250277487Skib 251277487Skibstatic bool ironlake_fbc_enabled(struct drm_device *dev) 252277487Skib{ 253277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 254277487Skib 255277487Skib return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN; 256277487Skib} 257277487Skib 258277487Skibbool intel_fbc_enabled(struct drm_device *dev) 259277487Skib{ 260277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 261277487Skib 262277487Skib if (!dev_priv->display.fbc_enabled) 263277487Skib return false; 264277487Skib 265277487Skib return dev_priv->display.fbc_enabled(dev); 266277487Skib} 267277487Skib 268277487Skibstatic void intel_fbc_work_fn(void *arg, int pending) 269277487Skib{ 270277487Skib struct intel_fbc_work *work = arg; 271277487Skib struct drm_device *dev = work->crtc->dev; 272277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 273277487Skib 274277487Skib DRM_LOCK(dev); 275277487Skib if (work == dev_priv->fbc_work) { 276277487Skib /* Double check that we haven't switched fb without cancelling 277277487Skib * the prior work. 278277487Skib */ 279277487Skib if (work->crtc->fb == work->fb) { 280277487Skib dev_priv->display.enable_fbc(work->crtc, 281277487Skib work->interval); 282277487Skib 283277487Skib dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane; 284277487Skib dev_priv->cfb_fb = work->crtc->fb->base.id; 285277487Skib dev_priv->cfb_y = work->crtc->y; 286277487Skib } 287277487Skib 288277487Skib dev_priv->fbc_work = NULL; 289277487Skib } 290277487Skib DRM_UNLOCK(dev); 291277487Skib 292277487Skib free(work, DRM_MEM_KMS); 293277487Skib} 294277487Skib 295277487Skibstatic void intel_cancel_fbc_work(struct drm_i915_private *dev_priv) 296277487Skib{ 297277487Skib if (dev_priv->fbc_work == NULL) 298277487Skib return; 299277487Skib 300277487Skib DRM_DEBUG_KMS("cancelling pending FBC enable\n"); 301277487Skib 302277487Skib /* Synchronisation is provided by struct_mutex and checking of 303277487Skib * dev_priv->fbc_work, so we can perform the cancellation 304277487Skib * entirely asynchronously. 305277487Skib */ 306296548Sdumbbell if (taskqueue_cancel_timeout(dev_priv->wq, &dev_priv->fbc_work->work, 307296548Sdumbbell NULL) == 0) 308277487Skib /* tasklet was killed before being run, clean up */ 309277487Skib free(dev_priv->fbc_work, DRM_MEM_KMS); 310277487Skib 311277487Skib /* Mark the work as no longer wanted so that if it does 312277487Skib * wake-up (because the work was already running and waiting 313277487Skib * for our mutex), it will discover that is no longer 314277487Skib * necessary to run. 315277487Skib */ 316277487Skib dev_priv->fbc_work = NULL; 317277487Skib} 318277487Skib 319277487Skibvoid intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 320277487Skib{ 321277487Skib struct intel_fbc_work *work; 322277487Skib struct drm_device *dev = crtc->dev; 323277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 324277487Skib 325277487Skib if (!dev_priv->display.enable_fbc) 326277487Skib return; 327277487Skib 328277487Skib intel_cancel_fbc_work(dev_priv); 329277487Skib 330296548Sdumbbell work = malloc(sizeof *work, DRM_MEM_KMS, M_WAITOK | M_ZERO); 331296548Sdumbbell if (work == NULL) { 332296548Sdumbbell dev_priv->display.enable_fbc(crtc, interval); 333296548Sdumbbell return; 334296548Sdumbbell } 335277487Skib 336277487Skib work->crtc = crtc; 337277487Skib work->fb = crtc->fb; 338277487Skib work->interval = interval; 339296548Sdumbbell TIMEOUT_TASK_INIT(dev_priv->wq, &work->work, 0, intel_fbc_work_fn, 340277487Skib work); 341277487Skib 342277487Skib dev_priv->fbc_work = work; 343277487Skib 344277487Skib DRM_DEBUG_KMS("scheduling delayed FBC enable\n"); 345277487Skib 346277487Skib /* Delay the actual enabling to let pageflipping cease and the 347277487Skib * display to settle before starting the compression. Note that 348277487Skib * this delay also serves a second purpose: it allows for a 349277487Skib * vblank to pass after disabling the FBC before we attempt 350277487Skib * to modify the control registers. 351277487Skib * 352277487Skib * A more complicated solution would involve tracking vblanks 353277487Skib * following the termination of the page-flipping sequence 354277487Skib * and indeed performing the enable as a co-routine and not 355277487Skib * waiting synchronously upon the vblank. 356277487Skib */ 357296548Sdumbbell taskqueue_enqueue_timeout(dev_priv->wq, &work->work, 358277487Skib msecs_to_jiffies(50)); 359277487Skib} 360277487Skib 361277487Skibvoid intel_disable_fbc(struct drm_device *dev) 362277487Skib{ 363277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 364277487Skib 365277487Skib intel_cancel_fbc_work(dev_priv); 366277487Skib 367277487Skib if (!dev_priv->display.disable_fbc) 368277487Skib return; 369277487Skib 370277487Skib dev_priv->display.disable_fbc(dev); 371277487Skib dev_priv->cfb_plane = -1; 372277487Skib} 373277487Skib 374277487Skib/** 375277487Skib * intel_update_fbc - enable/disable FBC as needed 376277487Skib * @dev: the drm_device 377277487Skib * 378277487Skib * Set up the framebuffer compression hardware at mode set time. We 379277487Skib * enable it if possible: 380277487Skib * - plane A only (on pre-965) 381277487Skib * - no pixel mulitply/line duplication 382277487Skib * - no alpha buffer discard 383277487Skib * - no dual wide 384277487Skib * - framebuffer <= 2048 in width, 1536 in height 385277487Skib * 386277487Skib * We can't assume that any compression will take place (worst case), 387277487Skib * so the compressed buffer has to be the same size as the uncompressed 388277487Skib * one. It also must reside (along with the line length buffer) in 389277487Skib * stolen memory. 390277487Skib * 391277487Skib * We need to enable/disable FBC on a global basis. 392277487Skib */ 393277487Skibvoid intel_update_fbc(struct drm_device *dev) 394277487Skib{ 395277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 396277487Skib struct drm_crtc *crtc = NULL, *tmp_crtc; 397277487Skib struct intel_crtc *intel_crtc; 398277487Skib struct drm_framebuffer *fb; 399277487Skib struct intel_framebuffer *intel_fb; 400277487Skib struct drm_i915_gem_object *obj; 401277487Skib int enable_fbc; 402277487Skib 403277487Skib if (!i915_powersave) 404277487Skib return; 405277487Skib 406277487Skib if (!I915_HAS_FBC(dev)) 407277487Skib return; 408277487Skib 409277487Skib /* 410277487Skib * If FBC is already on, we just have to verify that we can 411277487Skib * keep it that way... 412277487Skib * Need to disable if: 413277487Skib * - more than one pipe is active 414277487Skib * - changing FBC params (stride, fence, mode) 415277487Skib * - new fb is too large to fit in compressed buffer 416277487Skib * - going to an unsupported config (interlace, pixel multiply, etc.) 417277487Skib */ 418277487Skib list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { 419296548Sdumbbell if (intel_crtc_active(tmp_crtc) && 420296548Sdumbbell !to_intel_crtc(tmp_crtc)->primary_disabled) { 421277487Skib if (crtc) { 422277487Skib DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); 423277487Skib dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; 424277487Skib goto out_disable; 425277487Skib } 426277487Skib crtc = tmp_crtc; 427277487Skib } 428277487Skib } 429277487Skib 430277487Skib if (!crtc || crtc->fb == NULL) { 431277487Skib DRM_DEBUG_KMS("no output, disabling\n"); 432277487Skib dev_priv->no_fbc_reason = FBC_NO_OUTPUT; 433277487Skib goto out_disable; 434277487Skib } 435277487Skib 436277487Skib intel_crtc = to_intel_crtc(crtc); 437277487Skib fb = crtc->fb; 438277487Skib intel_fb = to_intel_framebuffer(fb); 439277487Skib obj = intel_fb->obj; 440277487Skib 441277487Skib enable_fbc = i915_enable_fbc; 442277487Skib if (enable_fbc < 0) { 443277487Skib DRM_DEBUG_KMS("fbc set to per-chip default\n"); 444277487Skib enable_fbc = 1; 445277487Skib if (INTEL_INFO(dev)->gen <= 6) 446277487Skib enable_fbc = 0; 447277487Skib } 448277487Skib if (!enable_fbc) { 449277487Skib DRM_DEBUG_KMS("fbc disabled per module param\n"); 450277487Skib dev_priv->no_fbc_reason = FBC_MODULE_PARAM; 451277487Skib goto out_disable; 452277487Skib } 453277487Skib if (intel_fb->obj->base.size > dev_priv->cfb_size) { 454277487Skib DRM_DEBUG_KMS("framebuffer too large, disabling " 455277487Skib "compression\n"); 456277487Skib dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; 457277487Skib goto out_disable; 458277487Skib } 459277487Skib if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || 460277487Skib (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { 461277487Skib DRM_DEBUG_KMS("mode incompatible with compression, " 462277487Skib "disabling\n"); 463277487Skib dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE; 464277487Skib goto out_disable; 465277487Skib } 466277487Skib if ((crtc->mode.hdisplay > 2048) || 467277487Skib (crtc->mode.vdisplay > 1536)) { 468277487Skib DRM_DEBUG_KMS("mode too large for compression, disabling\n"); 469277487Skib dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE; 470277487Skib goto out_disable; 471277487Skib } 472277487Skib if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) { 473277487Skib DRM_DEBUG_KMS("plane not 0, disabling compression\n"); 474277487Skib dev_priv->no_fbc_reason = FBC_BAD_PLANE; 475277487Skib goto out_disable; 476277487Skib } 477277487Skib 478277487Skib /* The use of a CPU fence is mandatory in order to detect writes 479277487Skib * by the CPU to the scanout and trigger updates to the FBC. 480277487Skib */ 481277487Skib if (obj->tiling_mode != I915_TILING_X || 482277487Skib obj->fence_reg == I915_FENCE_REG_NONE) { 483277487Skib DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n"); 484277487Skib dev_priv->no_fbc_reason = FBC_NOT_TILED; 485277487Skib goto out_disable; 486277487Skib } 487277487Skib 488277487Skib /* If the kernel debugger is active, always disable compression */ 489277487Skib if (kdb_active) 490277487Skib goto out_disable; 491277487Skib 492277487Skib /* If the scanout has not changed, don't modify the FBC settings. 493277487Skib * Note that we make the fundamental assumption that the fb->obj 494277487Skib * cannot be unpinned (and have its GTT offset and fence revoked) 495277487Skib * without first being decoupled from the scanout and FBC disabled. 496277487Skib */ 497277487Skib if (dev_priv->cfb_plane == intel_crtc->plane && 498277487Skib dev_priv->cfb_fb == fb->base.id && 499277487Skib dev_priv->cfb_y == crtc->y) 500277487Skib return; 501277487Skib 502277487Skib if (intel_fbc_enabled(dev)) { 503277487Skib /* We update FBC along two paths, after changing fb/crtc 504277487Skib * configuration (modeswitching) and after page-flipping 505277487Skib * finishes. For the latter, we know that not only did 506277487Skib * we disable the FBC at the start of the page-flip 507277487Skib * sequence, but also more than one vblank has passed. 508277487Skib * 509277487Skib * For the former case of modeswitching, it is possible 510277487Skib * to switch between two FBC valid configurations 511277487Skib * instantaneously so we do need to disable the FBC 512277487Skib * before we can modify its control registers. We also 513277487Skib * have to wait for the next vblank for that to take 514277487Skib * effect. However, since we delay enabling FBC we can 515277487Skib * assume that a vblank has passed since disabling and 516277487Skib * that we can safely alter the registers in the deferred 517277487Skib * callback. 518277487Skib * 519277487Skib * In the scenario that we go from a valid to invalid 520277487Skib * and then back to valid FBC configuration we have 521277487Skib * no strict enforcement that a vblank occurred since 522277487Skib * disabling the FBC. However, along all current pipe 523277487Skib * disabling paths we do need to wait for a vblank at 524277487Skib * some point. And we wait before enabling FBC anyway. 525277487Skib */ 526277487Skib DRM_DEBUG_KMS("disabling active FBC for update\n"); 527277487Skib intel_disable_fbc(dev); 528277487Skib } 529277487Skib 530277487Skib intel_enable_fbc(crtc, 500); 531277487Skib return; 532277487Skib 533277487Skibout_disable: 534277487Skib /* Multiple disables should be harmless */ 535277487Skib if (intel_fbc_enabled(dev)) { 536277487Skib DRM_DEBUG_KMS("unsupported config, disabling FBC\n"); 537277487Skib intel_disable_fbc(dev); 538277487Skib } 539277487Skib} 540277487Skib 541277487Skibstatic void i915_pineview_get_mem_freq(struct drm_device *dev) 542277487Skib{ 543277487Skib drm_i915_private_t *dev_priv = dev->dev_private; 544277487Skib u32 tmp; 545277487Skib 546277487Skib tmp = I915_READ(CLKCFG); 547277487Skib 548277487Skib switch (tmp & CLKCFG_FSB_MASK) { 549277487Skib case CLKCFG_FSB_533: 550277487Skib dev_priv->fsb_freq = 533; /* 133*4 */ 551277487Skib break; 552277487Skib case CLKCFG_FSB_800: 553277487Skib dev_priv->fsb_freq = 800; /* 200*4 */ 554277487Skib break; 555277487Skib case CLKCFG_FSB_667: 556277487Skib dev_priv->fsb_freq = 667; /* 167*4 */ 557277487Skib break; 558277487Skib case CLKCFG_FSB_400: 559277487Skib dev_priv->fsb_freq = 400; /* 100*4 */ 560277487Skib break; 561277487Skib } 562277487Skib 563277487Skib switch (tmp & CLKCFG_MEM_MASK) { 564277487Skib case CLKCFG_MEM_533: 565277487Skib dev_priv->mem_freq = 533; 566277487Skib break; 567277487Skib case CLKCFG_MEM_667: 568277487Skib dev_priv->mem_freq = 667; 569277487Skib break; 570277487Skib case CLKCFG_MEM_800: 571277487Skib dev_priv->mem_freq = 800; 572277487Skib break; 573277487Skib } 574277487Skib 575277487Skib /* detect pineview DDR3 setting */ 576277487Skib tmp = I915_READ(CSHRDDR3CTL); 577277487Skib dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0; 578277487Skib} 579277487Skib 580277487Skibstatic void i915_ironlake_get_mem_freq(struct drm_device *dev) 581277487Skib{ 582277487Skib drm_i915_private_t *dev_priv = dev->dev_private; 583277487Skib u16 ddrpll, csipll; 584277487Skib 585277487Skib ddrpll = I915_READ16(DDRMPLL1); 586277487Skib csipll = I915_READ16(CSIPLL0); 587277487Skib 588277487Skib switch (ddrpll & 0xff) { 589277487Skib case 0xc: 590277487Skib dev_priv->mem_freq = 800; 591277487Skib break; 592277487Skib case 0x10: 593277487Skib dev_priv->mem_freq = 1066; 594277487Skib break; 595277487Skib case 0x14: 596277487Skib dev_priv->mem_freq = 1333; 597277487Skib break; 598277487Skib case 0x18: 599277487Skib dev_priv->mem_freq = 1600; 600277487Skib break; 601277487Skib default: 602290228Sdumbbell DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n", 603277487Skib ddrpll & 0xff); 604277487Skib dev_priv->mem_freq = 0; 605277487Skib break; 606277487Skib } 607277487Skib 608296548Sdumbbell dev_priv->ips.r_t = dev_priv->mem_freq; 609277487Skib 610277487Skib switch (csipll & 0x3ff) { 611277487Skib case 0x00c: 612277487Skib dev_priv->fsb_freq = 3200; 613277487Skib break; 614277487Skib case 0x00e: 615277487Skib dev_priv->fsb_freq = 3733; 616277487Skib break; 617277487Skib case 0x010: 618277487Skib dev_priv->fsb_freq = 4266; 619277487Skib break; 620277487Skib case 0x012: 621277487Skib dev_priv->fsb_freq = 4800; 622277487Skib break; 623277487Skib case 0x014: 624277487Skib dev_priv->fsb_freq = 5333; 625277487Skib break; 626277487Skib case 0x016: 627277487Skib dev_priv->fsb_freq = 5866; 628277487Skib break; 629277487Skib case 0x018: 630277487Skib dev_priv->fsb_freq = 6400; 631277487Skib break; 632277487Skib default: 633290228Sdumbbell DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n", 634277487Skib csipll & 0x3ff); 635277487Skib dev_priv->fsb_freq = 0; 636277487Skib break; 637277487Skib } 638277487Skib 639277487Skib if (dev_priv->fsb_freq == 3200) { 640296548Sdumbbell dev_priv->ips.c_m = 0; 641277487Skib } else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) { 642296548Sdumbbell dev_priv->ips.c_m = 1; 643277487Skib } else { 644296548Sdumbbell dev_priv->ips.c_m = 2; 645277487Skib } 646277487Skib} 647277487Skib 648277487Skibstatic const struct cxsr_latency cxsr_latency_table[] = { 649277487Skib {1, 0, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */ 650277487Skib {1, 0, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */ 651277487Skib {1, 0, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */ 652277487Skib {1, 1, 800, 667, 6420, 36420, 6873, 36873}, /* DDR3-667 SC */ 653277487Skib {1, 1, 800, 800, 5902, 35902, 6318, 36318}, /* DDR3-800 SC */ 654277487Skib 655277487Skib {1, 0, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */ 656277487Skib {1, 0, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */ 657277487Skib {1, 0, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */ 658277487Skib {1, 1, 667, 667, 6438, 36438, 6911, 36911}, /* DDR3-667 SC */ 659277487Skib {1, 1, 667, 800, 5941, 35941, 6377, 36377}, /* DDR3-800 SC */ 660277487Skib 661277487Skib {1, 0, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */ 662277487Skib {1, 0, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */ 663277487Skib {1, 0, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */ 664277487Skib {1, 1, 400, 667, 6509, 36509, 7062, 37062}, /* DDR3-667 SC */ 665277487Skib {1, 1, 400, 800, 5985, 35985, 6501, 36501}, /* DDR3-800 SC */ 666277487Skib 667277487Skib {0, 0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */ 668277487Skib {0, 0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */ 669277487Skib {0, 0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */ 670277487Skib {0, 1, 800, 667, 6476, 36476, 6955, 36955}, /* DDR3-667 SC */ 671277487Skib {0, 1, 800, 800, 5958, 35958, 6400, 36400}, /* DDR3-800 SC */ 672277487Skib 673277487Skib {0, 0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */ 674277487Skib {0, 0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */ 675277487Skib {0, 0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */ 676277487Skib {0, 1, 667, 667, 6494, 36494, 6993, 36993}, /* DDR3-667 SC */ 677277487Skib {0, 1, 667, 800, 5998, 35998, 6460, 36460}, /* DDR3-800 SC */ 678277487Skib 679277487Skib {0, 0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */ 680277487Skib {0, 0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */ 681277487Skib {0, 0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */ 682277487Skib {0, 1, 400, 667, 6566, 36566, 7145, 37145}, /* DDR3-667 SC */ 683277487Skib {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */ 684277487Skib}; 685277487Skib 686277487Skibstatic const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, 687277487Skib int is_ddr3, 688277487Skib int fsb, 689277487Skib int mem) 690277487Skib{ 691277487Skib const struct cxsr_latency *latency; 692277487Skib int i; 693277487Skib 694277487Skib if (fsb == 0 || mem == 0) 695277487Skib return NULL; 696277487Skib 697296548Sdumbbell for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { 698277487Skib latency = &cxsr_latency_table[i]; 699277487Skib if (is_desktop == latency->is_desktop && 700277487Skib is_ddr3 == latency->is_ddr3 && 701277487Skib fsb == latency->fsb_freq && mem == latency->mem_freq) 702277487Skib return latency; 703277487Skib } 704277487Skib 705277487Skib DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); 706277487Skib 707277487Skib return NULL; 708277487Skib} 709277487Skib 710277487Skibstatic void pineview_disable_cxsr(struct drm_device *dev) 711277487Skib{ 712277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 713277487Skib 714277487Skib /* deactivate cxsr */ 715277487Skib I915_WRITE(DSPFW3, I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN); 716277487Skib} 717277487Skib 718277487Skib/* 719277487Skib * Latency for FIFO fetches is dependent on several factors: 720277487Skib * - memory configuration (speed, channels) 721277487Skib * - chipset 722277487Skib * - current MCH state 723277487Skib * It can be fairly high in some situations, so here we assume a fairly 724277487Skib * pessimal value. It's a tradeoff between extra memory fetches (if we 725277487Skib * set this value too high, the FIFO will fetch frequently to stay full) 726277487Skib * and power consumption (set it too low to save power and we might see 727277487Skib * FIFO underruns and display "flicker"). 728277487Skib * 729277487Skib * A value of 5us seems to be a good balance; safe for very low end 730277487Skib * platforms but not overly aggressive on lower latency configs. 731277487Skib */ 732277487Skibstatic const int latency_ns = 5000; 733277487Skib 734277487Skibstatic int i9xx_get_fifo_size(struct drm_device *dev, int plane) 735277487Skib{ 736277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 737277487Skib uint32_t dsparb = I915_READ(DSPARB); 738277487Skib int size; 739277487Skib 740277487Skib size = dsparb & 0x7f; 741277487Skib if (plane) 742277487Skib size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size; 743277487Skib 744277487Skib DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, 745277487Skib plane ? "B" : "A", size); 746277487Skib 747277487Skib return size; 748277487Skib} 749277487Skib 750277487Skibstatic int i85x_get_fifo_size(struct drm_device *dev, int plane) 751277487Skib{ 752277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 753277487Skib uint32_t dsparb = I915_READ(DSPARB); 754277487Skib int size; 755277487Skib 756277487Skib size = dsparb & 0x1ff; 757277487Skib if (plane) 758277487Skib size = ((dsparb >> DSPARB_BEND_SHIFT) & 0x1ff) - size; 759277487Skib size >>= 1; /* Convert to cachelines */ 760277487Skib 761277487Skib DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, 762277487Skib plane ? "B" : "A", size); 763277487Skib 764277487Skib return size; 765277487Skib} 766277487Skib 767277487Skibstatic int i845_get_fifo_size(struct drm_device *dev, int plane) 768277487Skib{ 769277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 770277487Skib uint32_t dsparb = I915_READ(DSPARB); 771277487Skib int size; 772277487Skib 773277487Skib size = dsparb & 0x7f; 774277487Skib size >>= 2; /* Convert to cachelines */ 775277487Skib 776277487Skib DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, 777277487Skib plane ? "B" : "A", 778277487Skib size); 779277487Skib 780277487Skib return size; 781277487Skib} 782277487Skib 783277487Skibstatic int i830_get_fifo_size(struct drm_device *dev, int plane) 784277487Skib{ 785277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 786277487Skib uint32_t dsparb = I915_READ(DSPARB); 787277487Skib int size; 788277487Skib 789277487Skib size = dsparb & 0x7f; 790277487Skib size >>= 1; /* Convert to cachelines */ 791277487Skib 792277487Skib DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, 793277487Skib plane ? "B" : "A", size); 794277487Skib 795277487Skib return size; 796277487Skib} 797277487Skib 798277487Skib/* Pineview has different values for various configs */ 799277487Skibstatic const struct intel_watermark_params pineview_display_wm = { 800277487Skib PINEVIEW_DISPLAY_FIFO, 801277487Skib PINEVIEW_MAX_WM, 802277487Skib PINEVIEW_DFT_WM, 803277487Skib PINEVIEW_GUARD_WM, 804277487Skib PINEVIEW_FIFO_LINE_SIZE 805277487Skib}; 806277487Skibstatic const struct intel_watermark_params pineview_display_hplloff_wm = { 807277487Skib PINEVIEW_DISPLAY_FIFO, 808277487Skib PINEVIEW_MAX_WM, 809277487Skib PINEVIEW_DFT_HPLLOFF_WM, 810277487Skib PINEVIEW_GUARD_WM, 811277487Skib PINEVIEW_FIFO_LINE_SIZE 812277487Skib}; 813277487Skibstatic const struct intel_watermark_params pineview_cursor_wm = { 814277487Skib PINEVIEW_CURSOR_FIFO, 815277487Skib PINEVIEW_CURSOR_MAX_WM, 816277487Skib PINEVIEW_CURSOR_DFT_WM, 817277487Skib PINEVIEW_CURSOR_GUARD_WM, 818277487Skib PINEVIEW_FIFO_LINE_SIZE, 819277487Skib}; 820277487Skibstatic const struct intel_watermark_params pineview_cursor_hplloff_wm = { 821277487Skib PINEVIEW_CURSOR_FIFO, 822277487Skib PINEVIEW_CURSOR_MAX_WM, 823277487Skib PINEVIEW_CURSOR_DFT_WM, 824277487Skib PINEVIEW_CURSOR_GUARD_WM, 825277487Skib PINEVIEW_FIFO_LINE_SIZE 826277487Skib}; 827277487Skibstatic const struct intel_watermark_params g4x_wm_info = { 828277487Skib G4X_FIFO_SIZE, 829277487Skib G4X_MAX_WM, 830277487Skib G4X_MAX_WM, 831277487Skib 2, 832277487Skib G4X_FIFO_LINE_SIZE, 833277487Skib}; 834277487Skibstatic const struct intel_watermark_params g4x_cursor_wm_info = { 835277487Skib I965_CURSOR_FIFO, 836277487Skib I965_CURSOR_MAX_WM, 837277487Skib I965_CURSOR_DFT_WM, 838277487Skib 2, 839277487Skib G4X_FIFO_LINE_SIZE, 840277487Skib}; 841277487Skibstatic const struct intel_watermark_params valleyview_wm_info = { 842277487Skib VALLEYVIEW_FIFO_SIZE, 843277487Skib VALLEYVIEW_MAX_WM, 844277487Skib VALLEYVIEW_MAX_WM, 845277487Skib 2, 846277487Skib G4X_FIFO_LINE_SIZE, 847277487Skib}; 848277487Skibstatic const struct intel_watermark_params valleyview_cursor_wm_info = { 849277487Skib I965_CURSOR_FIFO, 850277487Skib VALLEYVIEW_CURSOR_MAX_WM, 851277487Skib I965_CURSOR_DFT_WM, 852277487Skib 2, 853277487Skib G4X_FIFO_LINE_SIZE, 854277487Skib}; 855277487Skibstatic const struct intel_watermark_params i965_cursor_wm_info = { 856277487Skib I965_CURSOR_FIFO, 857277487Skib I965_CURSOR_MAX_WM, 858277487Skib I965_CURSOR_DFT_WM, 859277487Skib 2, 860277487Skib I915_FIFO_LINE_SIZE, 861277487Skib}; 862277487Skibstatic const struct intel_watermark_params i945_wm_info = { 863277487Skib I945_FIFO_SIZE, 864277487Skib I915_MAX_WM, 865277487Skib 1, 866277487Skib 2, 867277487Skib I915_FIFO_LINE_SIZE 868277487Skib}; 869277487Skibstatic const struct intel_watermark_params i915_wm_info = { 870277487Skib I915_FIFO_SIZE, 871277487Skib I915_MAX_WM, 872277487Skib 1, 873277487Skib 2, 874277487Skib I915_FIFO_LINE_SIZE 875277487Skib}; 876277487Skibstatic const struct intel_watermark_params i855_wm_info = { 877277487Skib I855GM_FIFO_SIZE, 878277487Skib I915_MAX_WM, 879277487Skib 1, 880277487Skib 2, 881277487Skib I830_FIFO_LINE_SIZE 882277487Skib}; 883277487Skibstatic const struct intel_watermark_params i830_wm_info = { 884277487Skib I830_FIFO_SIZE, 885277487Skib I915_MAX_WM, 886277487Skib 1, 887277487Skib 2, 888277487Skib I830_FIFO_LINE_SIZE 889277487Skib}; 890277487Skib 891277487Skibstatic const struct intel_watermark_params ironlake_display_wm_info = { 892277487Skib ILK_DISPLAY_FIFO, 893277487Skib ILK_DISPLAY_MAXWM, 894277487Skib ILK_DISPLAY_DFTWM, 895277487Skib 2, 896277487Skib ILK_FIFO_LINE_SIZE 897277487Skib}; 898277487Skibstatic const struct intel_watermark_params ironlake_cursor_wm_info = { 899277487Skib ILK_CURSOR_FIFO, 900277487Skib ILK_CURSOR_MAXWM, 901277487Skib ILK_CURSOR_DFTWM, 902277487Skib 2, 903277487Skib ILK_FIFO_LINE_SIZE 904277487Skib}; 905277487Skibstatic const struct intel_watermark_params ironlake_display_srwm_info = { 906277487Skib ILK_DISPLAY_SR_FIFO, 907277487Skib ILK_DISPLAY_MAX_SRWM, 908277487Skib ILK_DISPLAY_DFT_SRWM, 909277487Skib 2, 910277487Skib ILK_FIFO_LINE_SIZE 911277487Skib}; 912277487Skibstatic const struct intel_watermark_params ironlake_cursor_srwm_info = { 913277487Skib ILK_CURSOR_SR_FIFO, 914277487Skib ILK_CURSOR_MAX_SRWM, 915277487Skib ILK_CURSOR_DFT_SRWM, 916277487Skib 2, 917277487Skib ILK_FIFO_LINE_SIZE 918277487Skib}; 919277487Skib 920277487Skibstatic const struct intel_watermark_params sandybridge_display_wm_info = { 921277487Skib SNB_DISPLAY_FIFO, 922277487Skib SNB_DISPLAY_MAXWM, 923277487Skib SNB_DISPLAY_DFTWM, 924277487Skib 2, 925277487Skib SNB_FIFO_LINE_SIZE 926277487Skib}; 927277487Skibstatic const struct intel_watermark_params sandybridge_cursor_wm_info = { 928277487Skib SNB_CURSOR_FIFO, 929277487Skib SNB_CURSOR_MAXWM, 930277487Skib SNB_CURSOR_DFTWM, 931277487Skib 2, 932277487Skib SNB_FIFO_LINE_SIZE 933277487Skib}; 934277487Skibstatic const struct intel_watermark_params sandybridge_display_srwm_info = { 935277487Skib SNB_DISPLAY_SR_FIFO, 936277487Skib SNB_DISPLAY_MAX_SRWM, 937277487Skib SNB_DISPLAY_DFT_SRWM, 938277487Skib 2, 939277487Skib SNB_FIFO_LINE_SIZE 940277487Skib}; 941277487Skibstatic const struct intel_watermark_params sandybridge_cursor_srwm_info = { 942277487Skib SNB_CURSOR_SR_FIFO, 943277487Skib SNB_CURSOR_MAX_SRWM, 944277487Skib SNB_CURSOR_DFT_SRWM, 945277487Skib 2, 946277487Skib SNB_FIFO_LINE_SIZE 947277487Skib}; 948277487Skib 949277487Skib 950277487Skib/** 951277487Skib * intel_calculate_wm - calculate watermark level 952277487Skib * @clock_in_khz: pixel clock 953277487Skib * @wm: chip FIFO params 954277487Skib * @pixel_size: display pixel size 955277487Skib * @latency_ns: memory latency for the platform 956277487Skib * 957277487Skib * Calculate the watermark level (the level at which the display plane will 958277487Skib * start fetching from memory again). Each chip has a different display 959277487Skib * FIFO size and allocation, so the caller needs to figure that out and pass 960277487Skib * in the correct intel_watermark_params structure. 961277487Skib * 962277487Skib * As the pixel clock runs, the FIFO will be drained at a rate that depends 963277487Skib * on the pixel size. When it reaches the watermark level, it'll start 964277487Skib * fetching FIFO line sized based chunks from memory until the FIFO fills 965277487Skib * past the watermark point. If the FIFO drains completely, a FIFO underrun 966277487Skib * will occur, and a display engine hang could result. 967277487Skib */ 968277487Skibstatic unsigned long intel_calculate_wm(unsigned long clock_in_khz, 969277487Skib const struct intel_watermark_params *wm, 970277487Skib int fifo_size, 971277487Skib int pixel_size, 972277487Skib unsigned long latency_ns) 973277487Skib{ 974277487Skib long entries_required, wm_size; 975277487Skib 976277487Skib /* 977277487Skib * Note: we need to make sure we don't overflow for various clock & 978277487Skib * latency values. 979277487Skib * clocks go from a few thousand to several hundred thousand. 980277487Skib * latency is usually a few thousand 981277487Skib */ 982277487Skib entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) / 983277487Skib 1000; 984277487Skib entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size); 985277487Skib 986277487Skib DRM_DEBUG_KMS("FIFO entries required for mode: %ld\n", entries_required); 987277487Skib 988277487Skib wm_size = fifo_size - (entries_required + wm->guard_size); 989277487Skib 990277487Skib DRM_DEBUG_KMS("FIFO watermark level: %ld\n", wm_size); 991277487Skib 992277487Skib /* Don't promote wm_size to unsigned... */ 993277487Skib if (wm_size > (long)wm->max_wm) 994277487Skib wm_size = wm->max_wm; 995277487Skib if (wm_size <= 0) 996277487Skib wm_size = wm->default_wm; 997277487Skib return wm_size; 998277487Skib} 999277487Skib 1000277487Skibstatic struct drm_crtc *single_enabled_crtc(struct drm_device *dev) 1001277487Skib{ 1002277487Skib struct drm_crtc *crtc, *enabled = NULL; 1003277487Skib 1004277487Skib list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 1005296548Sdumbbell if (intel_crtc_active(crtc)) { 1006277487Skib if (enabled) 1007277487Skib return NULL; 1008277487Skib enabled = crtc; 1009277487Skib } 1010277487Skib } 1011277487Skib 1012277487Skib return enabled; 1013277487Skib} 1014277487Skib 1015277487Skibstatic void pineview_update_wm(struct drm_device *dev) 1016277487Skib{ 1017277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1018277487Skib struct drm_crtc *crtc; 1019277487Skib const struct cxsr_latency *latency; 1020277487Skib u32 reg; 1021277487Skib unsigned long wm; 1022277487Skib 1023277487Skib latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, 1024277487Skib dev_priv->fsb_freq, dev_priv->mem_freq); 1025277487Skib if (!latency) { 1026277487Skib DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); 1027277487Skib pineview_disable_cxsr(dev); 1028277487Skib return; 1029277487Skib } 1030277487Skib 1031277487Skib crtc = single_enabled_crtc(dev); 1032277487Skib if (crtc) { 1033277487Skib int clock = crtc->mode.clock; 1034277487Skib int pixel_size = crtc->fb->bits_per_pixel / 8; 1035277487Skib 1036277487Skib /* Display SR */ 1037277487Skib wm = intel_calculate_wm(clock, &pineview_display_wm, 1038277487Skib pineview_display_wm.fifo_size, 1039277487Skib pixel_size, latency->display_sr); 1040277487Skib reg = I915_READ(DSPFW1); 1041277487Skib reg &= ~DSPFW_SR_MASK; 1042277487Skib reg |= wm << DSPFW_SR_SHIFT; 1043277487Skib I915_WRITE(DSPFW1, reg); 1044277487Skib DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg); 1045277487Skib 1046277487Skib /* cursor SR */ 1047277487Skib wm = intel_calculate_wm(clock, &pineview_cursor_wm, 1048277487Skib pineview_display_wm.fifo_size, 1049277487Skib pixel_size, latency->cursor_sr); 1050277487Skib reg = I915_READ(DSPFW3); 1051277487Skib reg &= ~DSPFW_CURSOR_SR_MASK; 1052277487Skib reg |= (wm & 0x3f) << DSPFW_CURSOR_SR_SHIFT; 1053277487Skib I915_WRITE(DSPFW3, reg); 1054277487Skib 1055277487Skib /* Display HPLL off SR */ 1056277487Skib wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm, 1057277487Skib pineview_display_hplloff_wm.fifo_size, 1058277487Skib pixel_size, latency->display_hpll_disable); 1059277487Skib reg = I915_READ(DSPFW3); 1060277487Skib reg &= ~DSPFW_HPLL_SR_MASK; 1061277487Skib reg |= wm & DSPFW_HPLL_SR_MASK; 1062277487Skib I915_WRITE(DSPFW3, reg); 1063277487Skib 1064277487Skib /* cursor HPLL off SR */ 1065277487Skib wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm, 1066277487Skib pineview_display_hplloff_wm.fifo_size, 1067277487Skib pixel_size, latency->cursor_hpll_disable); 1068277487Skib reg = I915_READ(DSPFW3); 1069277487Skib reg &= ~DSPFW_HPLL_CURSOR_MASK; 1070277487Skib reg |= (wm & 0x3f) << DSPFW_HPLL_CURSOR_SHIFT; 1071277487Skib I915_WRITE(DSPFW3, reg); 1072277487Skib DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg); 1073277487Skib 1074277487Skib /* activate cxsr */ 1075277487Skib I915_WRITE(DSPFW3, 1076277487Skib I915_READ(DSPFW3) | PINEVIEW_SELF_REFRESH_EN); 1077277487Skib DRM_DEBUG_KMS("Self-refresh is enabled\n"); 1078277487Skib } else { 1079277487Skib pineview_disable_cxsr(dev); 1080277487Skib DRM_DEBUG_KMS("Self-refresh is disabled\n"); 1081277487Skib } 1082277487Skib} 1083277487Skib 1084277487Skibstatic bool g4x_compute_wm0(struct drm_device *dev, 1085277487Skib int plane, 1086277487Skib const struct intel_watermark_params *display, 1087277487Skib int display_latency_ns, 1088277487Skib const struct intel_watermark_params *cursor, 1089277487Skib int cursor_latency_ns, 1090277487Skib int *plane_wm, 1091277487Skib int *cursor_wm) 1092277487Skib{ 1093277487Skib struct drm_crtc *crtc; 1094277487Skib int htotal, hdisplay, clock, pixel_size; 1095277487Skib int line_time_us, line_count; 1096277487Skib int entries, tlb_miss; 1097277487Skib 1098277487Skib crtc = intel_get_crtc_for_plane(dev, plane); 1099296548Sdumbbell if (!intel_crtc_active(crtc)) { 1100277487Skib *cursor_wm = cursor->guard_size; 1101277487Skib *plane_wm = display->guard_size; 1102277487Skib return false; 1103277487Skib } 1104277487Skib 1105277487Skib htotal = crtc->mode.htotal; 1106277487Skib hdisplay = crtc->mode.hdisplay; 1107277487Skib clock = crtc->mode.clock; 1108277487Skib pixel_size = crtc->fb->bits_per_pixel / 8; 1109277487Skib 1110277487Skib /* Use the small buffer method to calculate plane watermark */ 1111277487Skib entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; 1112277487Skib tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8; 1113277487Skib if (tlb_miss > 0) 1114277487Skib entries += tlb_miss; 1115277487Skib entries = DIV_ROUND_UP(entries, display->cacheline_size); 1116277487Skib *plane_wm = entries + display->guard_size; 1117277487Skib if (*plane_wm > (int)display->max_wm) 1118277487Skib *plane_wm = display->max_wm; 1119277487Skib 1120277487Skib /* Use the large buffer method to calculate cursor watermark */ 1121277487Skib line_time_us = ((htotal * 1000) / clock); 1122277487Skib line_count = (cursor_latency_ns / line_time_us + 1000) / 1000; 1123277487Skib entries = line_count * 64 * pixel_size; 1124277487Skib tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8; 1125277487Skib if (tlb_miss > 0) 1126277487Skib entries += tlb_miss; 1127277487Skib entries = DIV_ROUND_UP(entries, cursor->cacheline_size); 1128277487Skib *cursor_wm = entries + cursor->guard_size; 1129277487Skib if (*cursor_wm > (int)cursor->max_wm) 1130277487Skib *cursor_wm = (int)cursor->max_wm; 1131277487Skib 1132277487Skib return true; 1133277487Skib} 1134277487Skib 1135277487Skib/* 1136277487Skib * Check the wm result. 1137277487Skib * 1138277487Skib * If any calculated watermark values is larger than the maximum value that 1139277487Skib * can be programmed into the associated watermark register, that watermark 1140277487Skib * must be disabled. 1141277487Skib */ 1142277487Skibstatic bool g4x_check_srwm(struct drm_device *dev, 1143277487Skib int display_wm, int cursor_wm, 1144277487Skib const struct intel_watermark_params *display, 1145277487Skib const struct intel_watermark_params *cursor) 1146277487Skib{ 1147277487Skib DRM_DEBUG_KMS("SR watermark: display plane %d, cursor %d\n", 1148277487Skib display_wm, cursor_wm); 1149277487Skib 1150277487Skib if (display_wm > display->max_wm) { 1151277487Skib DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n", 1152277487Skib display_wm, display->max_wm); 1153277487Skib return false; 1154277487Skib } 1155277487Skib 1156277487Skib if (cursor_wm > cursor->max_wm) { 1157277487Skib DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n", 1158277487Skib cursor_wm, cursor->max_wm); 1159277487Skib return false; 1160277487Skib } 1161277487Skib 1162277487Skib if (!(display_wm || cursor_wm)) { 1163277487Skib DRM_DEBUG_KMS("SR latency is 0, disabling\n"); 1164277487Skib return false; 1165277487Skib } 1166277487Skib 1167277487Skib return true; 1168277487Skib} 1169277487Skib 1170277487Skibstatic bool g4x_compute_srwm(struct drm_device *dev, 1171277487Skib int plane, 1172277487Skib int latency_ns, 1173277487Skib const struct intel_watermark_params *display, 1174277487Skib const struct intel_watermark_params *cursor, 1175277487Skib int *display_wm, int *cursor_wm) 1176277487Skib{ 1177277487Skib struct drm_crtc *crtc; 1178277487Skib int hdisplay, htotal, pixel_size, clock; 1179277487Skib unsigned long line_time_us; 1180277487Skib int line_count, line_size; 1181277487Skib int small, large; 1182277487Skib int entries; 1183277487Skib 1184277487Skib if (!latency_ns) { 1185277487Skib *display_wm = *cursor_wm = 0; 1186277487Skib return false; 1187277487Skib } 1188277487Skib 1189277487Skib crtc = intel_get_crtc_for_plane(dev, plane); 1190277487Skib hdisplay = crtc->mode.hdisplay; 1191277487Skib htotal = crtc->mode.htotal; 1192277487Skib clock = crtc->mode.clock; 1193277487Skib pixel_size = crtc->fb->bits_per_pixel / 8; 1194277487Skib 1195277487Skib line_time_us = (htotal * 1000) / clock; 1196277487Skib line_count = (latency_ns / line_time_us + 1000) / 1000; 1197277487Skib line_size = hdisplay * pixel_size; 1198277487Skib 1199277487Skib /* Use the minimum of the small and large buffer method for primary */ 1200277487Skib small = ((clock * pixel_size / 1000) * latency_ns) / 1000; 1201277487Skib large = line_count * line_size; 1202277487Skib 1203277487Skib entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); 1204277487Skib *display_wm = entries + display->guard_size; 1205277487Skib 1206277487Skib /* calculate the self-refresh watermark for display cursor */ 1207277487Skib entries = line_count * pixel_size * 64; 1208277487Skib entries = DIV_ROUND_UP(entries, cursor->cacheline_size); 1209277487Skib *cursor_wm = entries + cursor->guard_size; 1210277487Skib 1211277487Skib return g4x_check_srwm(dev, 1212277487Skib *display_wm, *cursor_wm, 1213277487Skib display, cursor); 1214277487Skib} 1215277487Skib 1216277487Skibstatic bool vlv_compute_drain_latency(struct drm_device *dev, 1217277487Skib int plane, 1218277487Skib int *plane_prec_mult, 1219277487Skib int *plane_dl, 1220277487Skib int *cursor_prec_mult, 1221277487Skib int *cursor_dl) 1222277487Skib{ 1223277487Skib struct drm_crtc *crtc; 1224277487Skib int clock, pixel_size; 1225277487Skib int entries; 1226277487Skib 1227277487Skib crtc = intel_get_crtc_for_plane(dev, plane); 1228296548Sdumbbell if (!intel_crtc_active(crtc)) 1229277487Skib return false; 1230277487Skib 1231277487Skib clock = crtc->mode.clock; /* VESA DOT Clock */ 1232277487Skib pixel_size = crtc->fb->bits_per_pixel / 8; /* BPP */ 1233277487Skib 1234277487Skib entries = (clock / 1000) * pixel_size; 1235277487Skib *plane_prec_mult = (entries > 256) ? 1236277487Skib DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16; 1237277487Skib *plane_dl = (64 * (*plane_prec_mult) * 4) / ((clock / 1000) * 1238277487Skib pixel_size); 1239277487Skib 1240277487Skib entries = (clock / 1000) * 4; /* BPP is always 4 for cursor */ 1241277487Skib *cursor_prec_mult = (entries > 256) ? 1242277487Skib DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16; 1243277487Skib *cursor_dl = (64 * (*cursor_prec_mult) * 4) / ((clock / 1000) * 4); 1244277487Skib 1245277487Skib return true; 1246277487Skib} 1247277487Skib 1248277487Skib/* 1249277487Skib * Update drain latency registers of memory arbiter 1250277487Skib * 1251277487Skib * Valleyview SoC has a new memory arbiter and needs drain latency registers 1252277487Skib * to be programmed. Each plane has a drain latency multiplier and a drain 1253277487Skib * latency value. 1254277487Skib */ 1255277487Skib 1256277487Skibstatic void vlv_update_drain_latency(struct drm_device *dev) 1257277487Skib{ 1258277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1259277487Skib int planea_prec, planea_dl, planeb_prec, planeb_dl; 1260277487Skib int cursora_prec, cursora_dl, cursorb_prec, cursorb_dl; 1261277487Skib int plane_prec_mult, cursor_prec_mult; /* Precision multiplier is 1262277487Skib either 16 or 32 */ 1263277487Skib 1264277487Skib /* For plane A, Cursor A */ 1265277487Skib if (vlv_compute_drain_latency(dev, 0, &plane_prec_mult, &planea_dl, 1266277487Skib &cursor_prec_mult, &cursora_dl)) { 1267277487Skib cursora_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ? 1268277487Skib DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_16; 1269277487Skib planea_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ? 1270277487Skib DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_16; 1271277487Skib 1272277487Skib I915_WRITE(VLV_DDL1, cursora_prec | 1273277487Skib (cursora_dl << DDL_CURSORA_SHIFT) | 1274277487Skib planea_prec | planea_dl); 1275277487Skib } 1276277487Skib 1277277487Skib /* For plane B, Cursor B */ 1278277487Skib if (vlv_compute_drain_latency(dev, 1, &plane_prec_mult, &planeb_dl, 1279277487Skib &cursor_prec_mult, &cursorb_dl)) { 1280277487Skib cursorb_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ? 1281277487Skib DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_16; 1282277487Skib planeb_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ? 1283277487Skib DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_16; 1284277487Skib 1285277487Skib I915_WRITE(VLV_DDL2, cursorb_prec | 1286277487Skib (cursorb_dl << DDL_CURSORB_SHIFT) | 1287277487Skib planeb_prec | planeb_dl); 1288277487Skib } 1289277487Skib} 1290277487Skib 1291277487Skib#define single_plane_enabled(mask) ((mask) != 0 && powerof2(mask)) 1292277487Skib 1293277487Skibstatic void valleyview_update_wm(struct drm_device *dev) 1294277487Skib{ 1295277487Skib static const int sr_latency_ns = 12000; 1296277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1297277487Skib int planea_wm, planeb_wm, cursora_wm, cursorb_wm; 1298277487Skib int plane_sr, cursor_sr; 1299296548Sdumbbell int ignore_plane_sr, ignore_cursor_sr; 1300277487Skib unsigned int enabled = 0; 1301277487Skib 1302277487Skib vlv_update_drain_latency(dev); 1303277487Skib 1304277487Skib if (g4x_compute_wm0(dev, 0, 1305277487Skib &valleyview_wm_info, latency_ns, 1306277487Skib &valleyview_cursor_wm_info, latency_ns, 1307277487Skib &planea_wm, &cursora_wm)) 1308277487Skib enabled |= 1; 1309277487Skib 1310277487Skib if (g4x_compute_wm0(dev, 1, 1311277487Skib &valleyview_wm_info, latency_ns, 1312277487Skib &valleyview_cursor_wm_info, latency_ns, 1313277487Skib &planeb_wm, &cursorb_wm)) 1314277487Skib enabled |= 2; 1315277487Skib 1316277487Skib if (single_plane_enabled(enabled) && 1317277487Skib g4x_compute_srwm(dev, ffs(enabled) - 1, 1318277487Skib sr_latency_ns, 1319277487Skib &valleyview_wm_info, 1320277487Skib &valleyview_cursor_wm_info, 1321296548Sdumbbell &plane_sr, &ignore_cursor_sr) && 1322296548Sdumbbell g4x_compute_srwm(dev, ffs(enabled) - 1, 1323296548Sdumbbell 2*sr_latency_ns, 1324296548Sdumbbell &valleyview_wm_info, 1325296548Sdumbbell &valleyview_cursor_wm_info, 1326296548Sdumbbell &ignore_plane_sr, &cursor_sr)) { 1327277487Skib I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN); 1328296548Sdumbbell } else { 1329277487Skib I915_WRITE(FW_BLC_SELF_VLV, 1330277487Skib I915_READ(FW_BLC_SELF_VLV) & ~FW_CSPWRDWNEN); 1331296548Sdumbbell plane_sr = cursor_sr = 0; 1332296548Sdumbbell } 1333277487Skib 1334277487Skib DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", 1335277487Skib planea_wm, cursora_wm, 1336277487Skib planeb_wm, cursorb_wm, 1337277487Skib plane_sr, cursor_sr); 1338277487Skib 1339277487Skib I915_WRITE(DSPFW1, 1340277487Skib (plane_sr << DSPFW_SR_SHIFT) | 1341277487Skib (cursorb_wm << DSPFW_CURSORB_SHIFT) | 1342277487Skib (planeb_wm << DSPFW_PLANEB_SHIFT) | 1343277487Skib planea_wm); 1344277487Skib I915_WRITE(DSPFW2, 1345296548Sdumbbell (I915_READ(DSPFW2) & ~DSPFW_CURSORA_MASK) | 1346277487Skib (cursora_wm << DSPFW_CURSORA_SHIFT)); 1347277487Skib I915_WRITE(DSPFW3, 1348296548Sdumbbell (I915_READ(DSPFW3) & ~DSPFW_CURSOR_SR_MASK) | 1349296548Sdumbbell (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); 1350277487Skib} 1351277487Skib 1352277487Skibstatic void g4x_update_wm(struct drm_device *dev) 1353277487Skib{ 1354277487Skib static const int sr_latency_ns = 12000; 1355277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1356277487Skib int planea_wm, planeb_wm, cursora_wm, cursorb_wm; 1357277487Skib int plane_sr, cursor_sr; 1358277487Skib unsigned int enabled = 0; 1359277487Skib 1360277487Skib if (g4x_compute_wm0(dev, 0, 1361277487Skib &g4x_wm_info, latency_ns, 1362277487Skib &g4x_cursor_wm_info, latency_ns, 1363277487Skib &planea_wm, &cursora_wm)) 1364277487Skib enabled |= 1; 1365277487Skib 1366277487Skib if (g4x_compute_wm0(dev, 1, 1367277487Skib &g4x_wm_info, latency_ns, 1368277487Skib &g4x_cursor_wm_info, latency_ns, 1369277487Skib &planeb_wm, &cursorb_wm)) 1370277487Skib enabled |= 2; 1371277487Skib 1372277487Skib if (single_plane_enabled(enabled) && 1373277487Skib g4x_compute_srwm(dev, ffs(enabled) - 1, 1374277487Skib sr_latency_ns, 1375277487Skib &g4x_wm_info, 1376277487Skib &g4x_cursor_wm_info, 1377296548Sdumbbell &plane_sr, &cursor_sr)) { 1378277487Skib I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); 1379296548Sdumbbell } else { 1380277487Skib I915_WRITE(FW_BLC_SELF, 1381277487Skib I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN); 1382296548Sdumbbell plane_sr = cursor_sr = 0; 1383296548Sdumbbell } 1384277487Skib 1385277487Skib DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", 1386277487Skib planea_wm, cursora_wm, 1387277487Skib planeb_wm, cursorb_wm, 1388277487Skib plane_sr, cursor_sr); 1389277487Skib 1390277487Skib I915_WRITE(DSPFW1, 1391277487Skib (plane_sr << DSPFW_SR_SHIFT) | 1392277487Skib (cursorb_wm << DSPFW_CURSORB_SHIFT) | 1393277487Skib (planeb_wm << DSPFW_PLANEB_SHIFT) | 1394277487Skib planea_wm); 1395277487Skib I915_WRITE(DSPFW2, 1396296548Sdumbbell (I915_READ(DSPFW2) & ~DSPFW_CURSORA_MASK) | 1397277487Skib (cursora_wm << DSPFW_CURSORA_SHIFT)); 1398277487Skib /* HPLL off in SR has some issues on G4x... disable it */ 1399277487Skib I915_WRITE(DSPFW3, 1400296548Sdumbbell (I915_READ(DSPFW3) & ~(DSPFW_HPLL_SR_EN | DSPFW_CURSOR_SR_MASK)) | 1401277487Skib (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); 1402277487Skib} 1403277487Skib 1404277487Skibstatic void i965_update_wm(struct drm_device *dev) 1405277487Skib{ 1406277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1407277487Skib struct drm_crtc *crtc; 1408277487Skib int srwm = 1; 1409277487Skib int cursor_sr = 16; 1410277487Skib 1411277487Skib /* Calc sr entries for one plane configs */ 1412277487Skib crtc = single_enabled_crtc(dev); 1413277487Skib if (crtc) { 1414277487Skib /* self-refresh has much higher latency */ 1415277487Skib static const int sr_latency_ns = 12000; 1416277487Skib int clock = crtc->mode.clock; 1417277487Skib int htotal = crtc->mode.htotal; 1418277487Skib int hdisplay = crtc->mode.hdisplay; 1419277487Skib int pixel_size = crtc->fb->bits_per_pixel / 8; 1420277487Skib unsigned long line_time_us; 1421277487Skib int entries; 1422277487Skib 1423277487Skib line_time_us = ((htotal * 1000) / clock); 1424277487Skib 1425277487Skib /* Use ns/us then divide to preserve precision */ 1426277487Skib entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * 1427277487Skib pixel_size * hdisplay; 1428277487Skib entries = DIV_ROUND_UP(entries, I915_FIFO_LINE_SIZE); 1429277487Skib srwm = I965_FIFO_SIZE - entries; 1430277487Skib if (srwm < 0) 1431277487Skib srwm = 1; 1432277487Skib srwm &= 0x1ff; 1433277487Skib DRM_DEBUG_KMS("self-refresh entries: %d, wm: %d\n", 1434277487Skib entries, srwm); 1435277487Skib 1436277487Skib entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * 1437277487Skib pixel_size * 64; 1438277487Skib entries = DIV_ROUND_UP(entries, 1439277487Skib i965_cursor_wm_info.cacheline_size); 1440277487Skib cursor_sr = i965_cursor_wm_info.fifo_size - 1441277487Skib (entries + i965_cursor_wm_info.guard_size); 1442277487Skib 1443277487Skib if (cursor_sr > i965_cursor_wm_info.max_wm) 1444277487Skib cursor_sr = i965_cursor_wm_info.max_wm; 1445277487Skib 1446277487Skib DRM_DEBUG_KMS("self-refresh watermark: display plane %d " 1447277487Skib "cursor %d\n", srwm, cursor_sr); 1448277487Skib 1449277487Skib if (IS_CRESTLINE(dev)) 1450277487Skib I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); 1451277487Skib } else { 1452277487Skib /* Turn off self refresh if both pipes are enabled */ 1453277487Skib if (IS_CRESTLINE(dev)) 1454277487Skib I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) 1455277487Skib & ~FW_BLC_SELF_EN); 1456277487Skib } 1457277487Skib 1458277487Skib DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n", 1459277487Skib srwm); 1460277487Skib 1461277487Skib /* 965 has limitations... */ 1462277487Skib I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | 1463277487Skib (8 << 16) | (8 << 8) | (8 << 0)); 1464277487Skib I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); 1465277487Skib /* update cursor SR watermark */ 1466277487Skib I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); 1467277487Skib} 1468277487Skib 1469277487Skibstatic void i9xx_update_wm(struct drm_device *dev) 1470277487Skib{ 1471277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1472277487Skib const struct intel_watermark_params *wm_info; 1473277487Skib uint32_t fwater_lo; 1474277487Skib uint32_t fwater_hi; 1475277487Skib int cwm, srwm = 1; 1476277487Skib int fifo_size; 1477277487Skib int planea_wm, planeb_wm; 1478277487Skib struct drm_crtc *crtc, *enabled = NULL; 1479277487Skib 1480277487Skib if (IS_I945GM(dev)) 1481277487Skib wm_info = &i945_wm_info; 1482277487Skib else if (!IS_GEN2(dev)) 1483277487Skib wm_info = &i915_wm_info; 1484277487Skib else 1485277487Skib wm_info = &i855_wm_info; 1486277487Skib 1487277487Skib fifo_size = dev_priv->display.get_fifo_size(dev, 0); 1488277487Skib crtc = intel_get_crtc_for_plane(dev, 0); 1489296548Sdumbbell if (intel_crtc_active(crtc)) { 1490296548Sdumbbell int cpp = crtc->fb->bits_per_pixel / 8; 1491296548Sdumbbell if (IS_GEN2(dev)) 1492296548Sdumbbell cpp = 4; 1493296548Sdumbbell 1494277487Skib planea_wm = intel_calculate_wm(crtc->mode.clock, 1495296548Sdumbbell wm_info, fifo_size, cpp, 1496277487Skib latency_ns); 1497277487Skib enabled = crtc; 1498277487Skib } else 1499277487Skib planea_wm = fifo_size - wm_info->guard_size; 1500277487Skib 1501277487Skib fifo_size = dev_priv->display.get_fifo_size(dev, 1); 1502277487Skib crtc = intel_get_crtc_for_plane(dev, 1); 1503296548Sdumbbell if (intel_crtc_active(crtc)) { 1504296548Sdumbbell int cpp = crtc->fb->bits_per_pixel / 8; 1505296548Sdumbbell if (IS_GEN2(dev)) 1506296548Sdumbbell cpp = 4; 1507296548Sdumbbell 1508277487Skib planeb_wm = intel_calculate_wm(crtc->mode.clock, 1509296548Sdumbbell wm_info, fifo_size, cpp, 1510277487Skib latency_ns); 1511277487Skib if (enabled == NULL) 1512277487Skib enabled = crtc; 1513277487Skib else 1514277487Skib enabled = NULL; 1515277487Skib } else 1516277487Skib planeb_wm = fifo_size - wm_info->guard_size; 1517277487Skib 1518277487Skib DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); 1519277487Skib 1520277487Skib /* 1521277487Skib * Overlay gets an aggressive default since video jitter is bad. 1522277487Skib */ 1523277487Skib cwm = 2; 1524277487Skib 1525277487Skib /* Play safe and disable self-refresh before adjusting watermarks. */ 1526277487Skib if (IS_I945G(dev) || IS_I945GM(dev)) 1527277487Skib I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0); 1528277487Skib else if (IS_I915GM(dev)) 1529277487Skib I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN); 1530277487Skib 1531277487Skib /* Calc sr entries for one plane configs */ 1532277487Skib if (HAS_FW_BLC(dev) && enabled) { 1533277487Skib /* self-refresh has much higher latency */ 1534277487Skib static const int sr_latency_ns = 6000; 1535277487Skib int clock = enabled->mode.clock; 1536277487Skib int htotal = enabled->mode.htotal; 1537277487Skib int hdisplay = enabled->mode.hdisplay; 1538277487Skib int pixel_size = enabled->fb->bits_per_pixel / 8; 1539277487Skib unsigned long line_time_us; 1540277487Skib int entries; 1541277487Skib 1542277487Skib line_time_us = (htotal * 1000) / clock; 1543277487Skib 1544277487Skib /* Use ns/us then divide to preserve precision */ 1545277487Skib entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * 1546277487Skib pixel_size * hdisplay; 1547277487Skib entries = DIV_ROUND_UP(entries, wm_info->cacheline_size); 1548277487Skib DRM_DEBUG_KMS("self-refresh entries: %d\n", entries); 1549277487Skib srwm = wm_info->fifo_size - entries; 1550277487Skib if (srwm < 0) 1551277487Skib srwm = 1; 1552277487Skib 1553277487Skib if (IS_I945G(dev) || IS_I945GM(dev)) 1554277487Skib I915_WRITE(FW_BLC_SELF, 1555277487Skib FW_BLC_SELF_FIFO_MASK | (srwm & 0xff)); 1556277487Skib else if (IS_I915GM(dev)) 1557277487Skib I915_WRITE(FW_BLC_SELF, srwm & 0x3f); 1558277487Skib } 1559277487Skib 1560277487Skib DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", 1561277487Skib planea_wm, planeb_wm, cwm, srwm); 1562277487Skib 1563277487Skib fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f); 1564277487Skib fwater_hi = (cwm & 0x1f); 1565277487Skib 1566277487Skib /* Set request length to 8 cachelines per fetch */ 1567277487Skib fwater_lo = fwater_lo | (1 << 24) | (1 << 8); 1568277487Skib fwater_hi = fwater_hi | (1 << 8); 1569277487Skib 1570277487Skib I915_WRITE(FW_BLC, fwater_lo); 1571277487Skib I915_WRITE(FW_BLC2, fwater_hi); 1572277487Skib 1573277487Skib if (HAS_FW_BLC(dev)) { 1574277487Skib if (enabled) { 1575277487Skib if (IS_I945G(dev) || IS_I945GM(dev)) 1576277487Skib I915_WRITE(FW_BLC_SELF, 1577277487Skib FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN); 1578277487Skib else if (IS_I915GM(dev)) 1579277487Skib I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN); 1580277487Skib DRM_DEBUG_KMS("memory self refresh enabled\n"); 1581277487Skib } else 1582277487Skib DRM_DEBUG_KMS("memory self refresh disabled\n"); 1583277487Skib } 1584277487Skib} 1585277487Skib 1586277487Skibstatic void i830_update_wm(struct drm_device *dev) 1587277487Skib{ 1588277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1589277487Skib struct drm_crtc *crtc; 1590277487Skib uint32_t fwater_lo; 1591277487Skib int planea_wm; 1592277487Skib 1593277487Skib crtc = single_enabled_crtc(dev); 1594277487Skib if (crtc == NULL) 1595277487Skib return; 1596277487Skib 1597277487Skib planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info, 1598277487Skib dev_priv->display.get_fifo_size(dev, 0), 1599296548Sdumbbell 4, latency_ns); 1600277487Skib fwater_lo = I915_READ(FW_BLC) & ~0xfff; 1601277487Skib fwater_lo |= (3<<8) | planea_wm; 1602277487Skib 1603277487Skib DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm); 1604277487Skib 1605277487Skib I915_WRITE(FW_BLC, fwater_lo); 1606277487Skib} 1607277487Skib 1608277487Skib#define ILK_LP0_PLANE_LATENCY 700 1609277487Skib#define ILK_LP0_CURSOR_LATENCY 1300 1610277487Skib 1611277487Skib/* 1612277487Skib * Check the wm result. 1613277487Skib * 1614277487Skib * If any calculated watermark values is larger than the maximum value that 1615277487Skib * can be programmed into the associated watermark register, that watermark 1616277487Skib * must be disabled. 1617277487Skib */ 1618277487Skibstatic bool ironlake_check_srwm(struct drm_device *dev, int level, 1619277487Skib int fbc_wm, int display_wm, int cursor_wm, 1620277487Skib const struct intel_watermark_params *display, 1621277487Skib const struct intel_watermark_params *cursor) 1622277487Skib{ 1623277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1624277487Skib 1625277487Skib DRM_DEBUG_KMS("watermark %d: display plane %d, fbc lines %d," 1626277487Skib " cursor %d\n", level, display_wm, fbc_wm, cursor_wm); 1627277487Skib 1628277487Skib if (fbc_wm > SNB_FBC_MAX_SRWM) { 1629277487Skib DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n", 1630277487Skib fbc_wm, SNB_FBC_MAX_SRWM, level); 1631277487Skib 1632277487Skib /* fbc has it's own way to disable FBC WM */ 1633277487Skib I915_WRITE(DISP_ARB_CTL, 1634277487Skib I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS); 1635277487Skib return false; 1636277487Skib } 1637277487Skib 1638277487Skib if (display_wm > display->max_wm) { 1639277487Skib DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n", 1640277487Skib display_wm, SNB_DISPLAY_MAX_SRWM, level); 1641277487Skib return false; 1642277487Skib } 1643277487Skib 1644277487Skib if (cursor_wm > cursor->max_wm) { 1645277487Skib DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n", 1646277487Skib cursor_wm, SNB_CURSOR_MAX_SRWM, level); 1647277487Skib return false; 1648277487Skib } 1649277487Skib 1650277487Skib if (!(fbc_wm || display_wm || cursor_wm)) { 1651277487Skib DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level); 1652277487Skib return false; 1653277487Skib } 1654277487Skib 1655277487Skib return true; 1656277487Skib} 1657277487Skib 1658277487Skib/* 1659277487Skib * Compute watermark values of WM[1-3], 1660277487Skib */ 1661277487Skibstatic bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, 1662277487Skib int latency_ns, 1663277487Skib const struct intel_watermark_params *display, 1664277487Skib const struct intel_watermark_params *cursor, 1665277487Skib int *fbc_wm, int *display_wm, int *cursor_wm) 1666277487Skib{ 1667277487Skib struct drm_crtc *crtc; 1668277487Skib unsigned long line_time_us; 1669277487Skib int hdisplay, htotal, pixel_size, clock; 1670277487Skib int line_count, line_size; 1671277487Skib int small, large; 1672277487Skib int entries; 1673277487Skib 1674277487Skib if (!latency_ns) { 1675277487Skib *fbc_wm = *display_wm = *cursor_wm = 0; 1676277487Skib return false; 1677277487Skib } 1678277487Skib 1679277487Skib crtc = intel_get_crtc_for_plane(dev, plane); 1680277487Skib hdisplay = crtc->mode.hdisplay; 1681277487Skib htotal = crtc->mode.htotal; 1682277487Skib clock = crtc->mode.clock; 1683277487Skib pixel_size = crtc->fb->bits_per_pixel / 8; 1684277487Skib 1685277487Skib line_time_us = (htotal * 1000) / clock; 1686277487Skib line_count = (latency_ns / line_time_us + 1000) / 1000; 1687277487Skib line_size = hdisplay * pixel_size; 1688277487Skib 1689277487Skib /* Use the minimum of the small and large buffer method for primary */ 1690277487Skib small = ((clock * pixel_size / 1000) * latency_ns) / 1000; 1691277487Skib large = line_count * line_size; 1692277487Skib 1693277487Skib entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); 1694277487Skib *display_wm = entries + display->guard_size; 1695277487Skib 1696277487Skib /* 1697277487Skib * Spec says: 1698277487Skib * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2 1699277487Skib */ 1700277487Skib *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2; 1701277487Skib 1702277487Skib /* calculate the self-refresh watermark for display cursor */ 1703277487Skib entries = line_count * pixel_size * 64; 1704277487Skib entries = DIV_ROUND_UP(entries, cursor->cacheline_size); 1705277487Skib *cursor_wm = entries + cursor->guard_size; 1706277487Skib 1707277487Skib return ironlake_check_srwm(dev, level, 1708277487Skib *fbc_wm, *display_wm, *cursor_wm, 1709277487Skib display, cursor); 1710277487Skib} 1711277487Skib 1712277487Skibstatic void ironlake_update_wm(struct drm_device *dev) 1713277487Skib{ 1714277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1715277487Skib int fbc_wm, plane_wm, cursor_wm; 1716277487Skib unsigned int enabled; 1717277487Skib 1718277487Skib enabled = 0; 1719277487Skib if (g4x_compute_wm0(dev, 0, 1720277487Skib &ironlake_display_wm_info, 1721277487Skib ILK_LP0_PLANE_LATENCY, 1722277487Skib &ironlake_cursor_wm_info, 1723277487Skib ILK_LP0_CURSOR_LATENCY, 1724277487Skib &plane_wm, &cursor_wm)) { 1725277487Skib I915_WRITE(WM0_PIPEA_ILK, 1726277487Skib (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); 1727277487Skib DRM_DEBUG_KMS("FIFO watermarks For pipe A -" 1728277487Skib " plane %d, " "cursor: %d\n", 1729277487Skib plane_wm, cursor_wm); 1730277487Skib enabled |= 1; 1731277487Skib } 1732277487Skib 1733277487Skib if (g4x_compute_wm0(dev, 1, 1734277487Skib &ironlake_display_wm_info, 1735277487Skib ILK_LP0_PLANE_LATENCY, 1736277487Skib &ironlake_cursor_wm_info, 1737277487Skib ILK_LP0_CURSOR_LATENCY, 1738277487Skib &plane_wm, &cursor_wm)) { 1739277487Skib I915_WRITE(WM0_PIPEB_ILK, 1740277487Skib (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); 1741277487Skib DRM_DEBUG_KMS("FIFO watermarks For pipe B -" 1742277487Skib " plane %d, cursor: %d\n", 1743277487Skib plane_wm, cursor_wm); 1744277487Skib enabled |= 2; 1745277487Skib } 1746277487Skib 1747277487Skib /* 1748277487Skib * Calculate and update the self-refresh watermark only when one 1749277487Skib * display plane is used. 1750277487Skib */ 1751277487Skib I915_WRITE(WM3_LP_ILK, 0); 1752277487Skib I915_WRITE(WM2_LP_ILK, 0); 1753277487Skib I915_WRITE(WM1_LP_ILK, 0); 1754277487Skib 1755277487Skib if (!single_plane_enabled(enabled)) 1756277487Skib return; 1757277487Skib enabled = ffs(enabled) - 1; 1758277487Skib 1759277487Skib /* WM1 */ 1760277487Skib if (!ironlake_compute_srwm(dev, 1, enabled, 1761277487Skib ILK_READ_WM1_LATENCY() * 500, 1762277487Skib &ironlake_display_srwm_info, 1763277487Skib &ironlake_cursor_srwm_info, 1764277487Skib &fbc_wm, &plane_wm, &cursor_wm)) 1765277487Skib return; 1766277487Skib 1767277487Skib I915_WRITE(WM1_LP_ILK, 1768277487Skib WM1_LP_SR_EN | 1769277487Skib (ILK_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) | 1770277487Skib (fbc_wm << WM1_LP_FBC_SHIFT) | 1771277487Skib (plane_wm << WM1_LP_SR_SHIFT) | 1772277487Skib cursor_wm); 1773277487Skib 1774277487Skib /* WM2 */ 1775277487Skib if (!ironlake_compute_srwm(dev, 2, enabled, 1776277487Skib ILK_READ_WM2_LATENCY() * 500, 1777277487Skib &ironlake_display_srwm_info, 1778277487Skib &ironlake_cursor_srwm_info, 1779277487Skib &fbc_wm, &plane_wm, &cursor_wm)) 1780277487Skib return; 1781277487Skib 1782277487Skib I915_WRITE(WM2_LP_ILK, 1783277487Skib WM2_LP_EN | 1784277487Skib (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) | 1785277487Skib (fbc_wm << WM1_LP_FBC_SHIFT) | 1786277487Skib (plane_wm << WM1_LP_SR_SHIFT) | 1787277487Skib cursor_wm); 1788277487Skib 1789277487Skib /* 1790277487Skib * WM3 is unsupported on ILK, probably because we don't have latency 1791277487Skib * data for that power state 1792277487Skib */ 1793277487Skib} 1794277487Skib 1795277487Skibstatic void sandybridge_update_wm(struct drm_device *dev) 1796277487Skib{ 1797277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 1798277487Skib int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ 1799277487Skib u32 val; 1800277487Skib int fbc_wm, plane_wm, cursor_wm; 1801277487Skib unsigned int enabled; 1802277487Skib 1803277487Skib enabled = 0; 1804277487Skib if (g4x_compute_wm0(dev, 0, 1805277487Skib &sandybridge_display_wm_info, latency, 1806277487Skib &sandybridge_cursor_wm_info, latency, 1807277487Skib &plane_wm, &cursor_wm)) { 1808277487Skib val = I915_READ(WM0_PIPEA_ILK); 1809277487Skib val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); 1810277487Skib I915_WRITE(WM0_PIPEA_ILK, val | 1811277487Skib ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); 1812277487Skib DRM_DEBUG_KMS("FIFO watermarks For pipe A -" 1813277487Skib " plane %d, " "cursor: %d\n", 1814277487Skib plane_wm, cursor_wm); 1815277487Skib enabled |= 1; 1816277487Skib } 1817277487Skib 1818277487Skib if (g4x_compute_wm0(dev, 1, 1819277487Skib &sandybridge_display_wm_info, latency, 1820277487Skib &sandybridge_cursor_wm_info, latency, 1821277487Skib &plane_wm, &cursor_wm)) { 1822277487Skib val = I915_READ(WM0_PIPEB_ILK); 1823277487Skib val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); 1824277487Skib I915_WRITE(WM0_PIPEB_ILK, val | 1825277487Skib ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); 1826277487Skib DRM_DEBUG_KMS("FIFO watermarks For pipe B -" 1827277487Skib " plane %d, cursor: %d\n", 1828277487Skib plane_wm, cursor_wm); 1829277487Skib enabled |= 2; 1830277487Skib } 1831277487Skib 1832296548Sdumbbell /* 1833296548Sdumbbell * Calculate and update the self-refresh watermark only when one 1834296548Sdumbbell * display plane is used. 1835296548Sdumbbell * 1836296548Sdumbbell * SNB support 3 levels of watermark. 1837296548Sdumbbell * 1838296548Sdumbbell * WM1/WM2/WM2 watermarks have to be enabled in the ascending order, 1839296548Sdumbbell * and disabled in the descending order 1840296548Sdumbbell * 1841296548Sdumbbell */ 1842296548Sdumbbell I915_WRITE(WM3_LP_ILK, 0); 1843296548Sdumbbell I915_WRITE(WM2_LP_ILK, 0); 1844296548Sdumbbell I915_WRITE(WM1_LP_ILK, 0); 1845296548Sdumbbell 1846296548Sdumbbell if (!single_plane_enabled(enabled) || 1847296548Sdumbbell dev_priv->sprite_scaling_enabled) 1848296548Sdumbbell return; 1849296548Sdumbbell enabled = ffs(enabled) - 1; 1850296548Sdumbbell 1851296548Sdumbbell /* WM1 */ 1852296548Sdumbbell if (!ironlake_compute_srwm(dev, 1, enabled, 1853296548Sdumbbell SNB_READ_WM1_LATENCY() * 500, 1854296548Sdumbbell &sandybridge_display_srwm_info, 1855296548Sdumbbell &sandybridge_cursor_srwm_info, 1856296548Sdumbbell &fbc_wm, &plane_wm, &cursor_wm)) 1857296548Sdumbbell return; 1858296548Sdumbbell 1859296548Sdumbbell I915_WRITE(WM1_LP_ILK, 1860296548Sdumbbell WM1_LP_SR_EN | 1861296548Sdumbbell (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) | 1862296548Sdumbbell (fbc_wm << WM1_LP_FBC_SHIFT) | 1863296548Sdumbbell (plane_wm << WM1_LP_SR_SHIFT) | 1864296548Sdumbbell cursor_wm); 1865296548Sdumbbell 1866296548Sdumbbell /* WM2 */ 1867296548Sdumbbell if (!ironlake_compute_srwm(dev, 2, enabled, 1868296548Sdumbbell SNB_READ_WM2_LATENCY() * 500, 1869296548Sdumbbell &sandybridge_display_srwm_info, 1870296548Sdumbbell &sandybridge_cursor_srwm_info, 1871296548Sdumbbell &fbc_wm, &plane_wm, &cursor_wm)) 1872296548Sdumbbell return; 1873296548Sdumbbell 1874296548Sdumbbell I915_WRITE(WM2_LP_ILK, 1875296548Sdumbbell WM2_LP_EN | 1876296548Sdumbbell (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) | 1877296548Sdumbbell (fbc_wm << WM1_LP_FBC_SHIFT) | 1878296548Sdumbbell (plane_wm << WM1_LP_SR_SHIFT) | 1879296548Sdumbbell cursor_wm); 1880296548Sdumbbell 1881296548Sdumbbell /* WM3 */ 1882296548Sdumbbell if (!ironlake_compute_srwm(dev, 3, enabled, 1883296548Sdumbbell SNB_READ_WM3_LATENCY() * 500, 1884296548Sdumbbell &sandybridge_display_srwm_info, 1885296548Sdumbbell &sandybridge_cursor_srwm_info, 1886296548Sdumbbell &fbc_wm, &plane_wm, &cursor_wm)) 1887296548Sdumbbell return; 1888296548Sdumbbell 1889296548Sdumbbell I915_WRITE(WM3_LP_ILK, 1890296548Sdumbbell WM3_LP_EN | 1891296548Sdumbbell (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) | 1892296548Sdumbbell (fbc_wm << WM1_LP_FBC_SHIFT) | 1893296548Sdumbbell (plane_wm << WM1_LP_SR_SHIFT) | 1894296548Sdumbbell cursor_wm); 1895296548Sdumbbell} 1896296548Sdumbbell 1897296548Sdumbbellstatic void ivybridge_update_wm(struct drm_device *dev) 1898296548Sdumbbell{ 1899296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 1900296548Sdumbbell int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ 1901296548Sdumbbell u32 val; 1902296548Sdumbbell int fbc_wm, plane_wm, cursor_wm; 1903296548Sdumbbell int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm; 1904296548Sdumbbell unsigned int enabled; 1905296548Sdumbbell 1906296548Sdumbbell enabled = 0; 1907296548Sdumbbell if (g4x_compute_wm0(dev, 0, 1908277487Skib &sandybridge_display_wm_info, latency, 1909277487Skib &sandybridge_cursor_wm_info, latency, 1910277487Skib &plane_wm, &cursor_wm)) { 1911296548Sdumbbell val = I915_READ(WM0_PIPEA_ILK); 1912296548Sdumbbell val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); 1913296548Sdumbbell I915_WRITE(WM0_PIPEA_ILK, val | 1914296548Sdumbbell ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); 1915296548Sdumbbell DRM_DEBUG_KMS("FIFO watermarks For pipe A -" 1916296548Sdumbbell " plane %d, " "cursor: %d\n", 1917296548Sdumbbell plane_wm, cursor_wm); 1918296548Sdumbbell enabled |= 1; 1919296548Sdumbbell } 1920296548Sdumbbell 1921296548Sdumbbell if (g4x_compute_wm0(dev, 1, 1922296548Sdumbbell &sandybridge_display_wm_info, latency, 1923296548Sdumbbell &sandybridge_cursor_wm_info, latency, 1924296548Sdumbbell &plane_wm, &cursor_wm)) { 1925296548Sdumbbell val = I915_READ(WM0_PIPEB_ILK); 1926296548Sdumbbell val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); 1927296548Sdumbbell I915_WRITE(WM0_PIPEB_ILK, val | 1928296548Sdumbbell ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); 1929296548Sdumbbell DRM_DEBUG_KMS("FIFO watermarks For pipe B -" 1930296548Sdumbbell " plane %d, cursor: %d\n", 1931296548Sdumbbell plane_wm, cursor_wm); 1932296548Sdumbbell enabled |= 2; 1933296548Sdumbbell } 1934296548Sdumbbell 1935296548Sdumbbell if (g4x_compute_wm0(dev, 2, 1936296548Sdumbbell &sandybridge_display_wm_info, latency, 1937296548Sdumbbell &sandybridge_cursor_wm_info, latency, 1938296548Sdumbbell &plane_wm, &cursor_wm)) { 1939277487Skib val = I915_READ(WM0_PIPEC_IVB); 1940277487Skib val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); 1941277487Skib I915_WRITE(WM0_PIPEC_IVB, val | 1942277487Skib ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm)); 1943277487Skib DRM_DEBUG_KMS("FIFO watermarks For pipe C -" 1944277487Skib " plane %d, cursor: %d\n", 1945277487Skib plane_wm, cursor_wm); 1946277487Skib enabled |= 3; 1947277487Skib } 1948277487Skib 1949277487Skib /* 1950277487Skib * Calculate and update the self-refresh watermark only when one 1951277487Skib * display plane is used. 1952277487Skib * 1953277487Skib * SNB support 3 levels of watermark. 1954277487Skib * 1955277487Skib * WM1/WM2/WM2 watermarks have to be enabled in the ascending order, 1956277487Skib * and disabled in the descending order 1957277487Skib * 1958277487Skib */ 1959277487Skib I915_WRITE(WM3_LP_ILK, 0); 1960277487Skib I915_WRITE(WM2_LP_ILK, 0); 1961277487Skib I915_WRITE(WM1_LP_ILK, 0); 1962277487Skib 1963277487Skib if (!single_plane_enabled(enabled) || 1964277487Skib dev_priv->sprite_scaling_enabled) 1965277487Skib return; 1966277487Skib enabled = ffs(enabled) - 1; 1967277487Skib 1968277487Skib /* WM1 */ 1969277487Skib if (!ironlake_compute_srwm(dev, 1, enabled, 1970277487Skib SNB_READ_WM1_LATENCY() * 500, 1971277487Skib &sandybridge_display_srwm_info, 1972277487Skib &sandybridge_cursor_srwm_info, 1973277487Skib &fbc_wm, &plane_wm, &cursor_wm)) 1974277487Skib return; 1975277487Skib 1976277487Skib I915_WRITE(WM1_LP_ILK, 1977277487Skib WM1_LP_SR_EN | 1978277487Skib (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) | 1979277487Skib (fbc_wm << WM1_LP_FBC_SHIFT) | 1980277487Skib (plane_wm << WM1_LP_SR_SHIFT) | 1981277487Skib cursor_wm); 1982277487Skib 1983277487Skib /* WM2 */ 1984277487Skib if (!ironlake_compute_srwm(dev, 2, enabled, 1985277487Skib SNB_READ_WM2_LATENCY() * 500, 1986277487Skib &sandybridge_display_srwm_info, 1987277487Skib &sandybridge_cursor_srwm_info, 1988277487Skib &fbc_wm, &plane_wm, &cursor_wm)) 1989277487Skib return; 1990277487Skib 1991277487Skib I915_WRITE(WM2_LP_ILK, 1992277487Skib WM2_LP_EN | 1993277487Skib (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) | 1994277487Skib (fbc_wm << WM1_LP_FBC_SHIFT) | 1995277487Skib (plane_wm << WM1_LP_SR_SHIFT) | 1996277487Skib cursor_wm); 1997277487Skib 1998296548Sdumbbell /* WM3, note we have to correct the cursor latency */ 1999277487Skib if (!ironlake_compute_srwm(dev, 3, enabled, 2000277487Skib SNB_READ_WM3_LATENCY() * 500, 2001277487Skib &sandybridge_display_srwm_info, 2002277487Skib &sandybridge_cursor_srwm_info, 2003296548Sdumbbell &fbc_wm, &plane_wm, &ignore_cursor_wm) || 2004296548Sdumbbell !ironlake_compute_srwm(dev, 3, enabled, 2005296548Sdumbbell 2 * SNB_READ_WM3_LATENCY() * 500, 2006296548Sdumbbell &sandybridge_display_srwm_info, 2007296548Sdumbbell &sandybridge_cursor_srwm_info, 2008296548Sdumbbell &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm)) 2009277487Skib return; 2010277487Skib 2011277487Skib I915_WRITE(WM3_LP_ILK, 2012277487Skib WM3_LP_EN | 2013277487Skib (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) | 2014277487Skib (fbc_wm << WM1_LP_FBC_SHIFT) | 2015277487Skib (plane_wm << WM1_LP_SR_SHIFT) | 2016277487Skib cursor_wm); 2017277487Skib} 2018277487Skib 2019277487Skibstatic void 2020277487Skibhaswell_update_linetime_wm(struct drm_device *dev, int pipe, 2021277487Skib struct drm_display_mode *mode) 2022277487Skib{ 2023277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2024277487Skib u32 temp; 2025277487Skib 2026277487Skib temp = I915_READ(PIPE_WM_LINETIME(pipe)); 2027277487Skib temp &= ~PIPE_WM_LINETIME_MASK; 2028277487Skib 2029277487Skib /* The WM are computed with base on how long it takes to fill a single 2030277487Skib * row at the given clock rate, multiplied by 8. 2031277487Skib * */ 2032277487Skib temp |= PIPE_WM_LINETIME_TIME( 2033277487Skib ((mode->crtc_hdisplay * 1000) / mode->clock) * 8); 2034277487Skib 2035277487Skib /* IPS watermarks are only used by pipe A, and are ignored by 2036277487Skib * pipes B and C. They are calculated similarly to the common 2037277487Skib * linetime values, except that we are using CD clock frequency 2038277487Skib * in MHz instead of pixel rate for the division. 2039277487Skib * 2040277487Skib * This is a placeholder for the IPS watermark calculation code. 2041277487Skib */ 2042277487Skib 2043277487Skib I915_WRITE(PIPE_WM_LINETIME(pipe), temp); 2044277487Skib} 2045277487Skib 2046277487Skibstatic bool 2047277487Skibsandybridge_compute_sprite_wm(struct drm_device *dev, int plane, 2048277487Skib uint32_t sprite_width, int pixel_size, 2049277487Skib const struct intel_watermark_params *display, 2050277487Skib int display_latency_ns, int *sprite_wm) 2051277487Skib{ 2052277487Skib struct drm_crtc *crtc; 2053277487Skib int clock; 2054277487Skib int entries, tlb_miss; 2055277487Skib 2056277487Skib crtc = intel_get_crtc_for_plane(dev, plane); 2057296548Sdumbbell if (!intel_crtc_active(crtc)) { 2058277487Skib *sprite_wm = display->guard_size; 2059277487Skib return false; 2060277487Skib } 2061277487Skib 2062277487Skib clock = crtc->mode.clock; 2063277487Skib 2064277487Skib /* Use the small buffer method to calculate the sprite watermark */ 2065277487Skib entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; 2066277487Skib tlb_miss = display->fifo_size*display->cacheline_size - 2067277487Skib sprite_width * 8; 2068277487Skib if (tlb_miss > 0) 2069277487Skib entries += tlb_miss; 2070277487Skib entries = DIV_ROUND_UP(entries, display->cacheline_size); 2071277487Skib *sprite_wm = entries + display->guard_size; 2072277487Skib if (*sprite_wm > (int)display->max_wm) 2073277487Skib *sprite_wm = display->max_wm; 2074277487Skib 2075277487Skib return true; 2076277487Skib} 2077277487Skib 2078277487Skibstatic bool 2079277487Skibsandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, 2080277487Skib uint32_t sprite_width, int pixel_size, 2081277487Skib const struct intel_watermark_params *display, 2082277487Skib int latency_ns, int *sprite_wm) 2083277487Skib{ 2084277487Skib struct drm_crtc *crtc; 2085277487Skib unsigned long line_time_us; 2086277487Skib int clock; 2087277487Skib int line_count, line_size; 2088277487Skib int small, large; 2089277487Skib int entries; 2090277487Skib 2091277487Skib if (!latency_ns) { 2092277487Skib *sprite_wm = 0; 2093277487Skib return false; 2094277487Skib } 2095277487Skib 2096277487Skib crtc = intel_get_crtc_for_plane(dev, plane); 2097277487Skib clock = crtc->mode.clock; 2098277487Skib if (!clock) { 2099277487Skib *sprite_wm = 0; 2100277487Skib return false; 2101277487Skib } 2102277487Skib 2103277487Skib line_time_us = (sprite_width * 1000) / clock; 2104277487Skib if (!line_time_us) { 2105277487Skib *sprite_wm = 0; 2106277487Skib return false; 2107277487Skib } 2108277487Skib 2109277487Skib line_count = (latency_ns / line_time_us + 1000) / 1000; 2110277487Skib line_size = sprite_width * pixel_size; 2111277487Skib 2112277487Skib /* Use the minimum of the small and large buffer method for primary */ 2113277487Skib small = ((clock * pixel_size / 1000) * latency_ns) / 1000; 2114277487Skib large = line_count * line_size; 2115277487Skib 2116277487Skib entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); 2117277487Skib *sprite_wm = entries + display->guard_size; 2118277487Skib 2119277487Skib return *sprite_wm > 0x3ff ? false : true; 2120277487Skib} 2121277487Skib 2122277487Skibstatic void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe, 2123277487Skib uint32_t sprite_width, int pixel_size) 2124277487Skib{ 2125277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2126277487Skib int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ 2127277487Skib u32 val; 2128277487Skib int sprite_wm, reg; 2129277487Skib int ret; 2130277487Skib 2131277487Skib switch (pipe) { 2132277487Skib case 0: 2133277487Skib reg = WM0_PIPEA_ILK; 2134277487Skib break; 2135277487Skib case 1: 2136277487Skib reg = WM0_PIPEB_ILK; 2137277487Skib break; 2138277487Skib case 2: 2139277487Skib reg = WM0_PIPEC_IVB; 2140277487Skib break; 2141277487Skib default: 2142277487Skib return; /* bad pipe */ 2143277487Skib } 2144277487Skib 2145277487Skib ret = sandybridge_compute_sprite_wm(dev, pipe, sprite_width, pixel_size, 2146277487Skib &sandybridge_display_wm_info, 2147277487Skib latency, &sprite_wm); 2148277487Skib if (!ret) { 2149277487Skib DRM_DEBUG_KMS("failed to compute sprite wm for pipe %d\n", 2150277487Skib pipe); 2151277487Skib return; 2152277487Skib } 2153277487Skib 2154277487Skib val = I915_READ(reg); 2155277487Skib val &= ~WM0_PIPE_SPRITE_MASK; 2156277487Skib I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT)); 2157277487Skib DRM_DEBUG_KMS("sprite watermarks For pipe %d - %d\n", pipe, sprite_wm); 2158277487Skib 2159277487Skib 2160277487Skib ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, 2161277487Skib pixel_size, 2162277487Skib &sandybridge_display_srwm_info, 2163277487Skib SNB_READ_WM1_LATENCY() * 500, 2164277487Skib &sprite_wm); 2165277487Skib if (!ret) { 2166277487Skib DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %d\n", 2167277487Skib pipe); 2168277487Skib return; 2169277487Skib } 2170277487Skib I915_WRITE(WM1S_LP_ILK, sprite_wm); 2171277487Skib 2172277487Skib /* Only IVB has two more LP watermarks for sprite */ 2173277487Skib if (!IS_IVYBRIDGE(dev)) 2174277487Skib return; 2175277487Skib 2176277487Skib ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, 2177277487Skib pixel_size, 2178277487Skib &sandybridge_display_srwm_info, 2179277487Skib SNB_READ_WM2_LATENCY() * 500, 2180277487Skib &sprite_wm); 2181277487Skib if (!ret) { 2182277487Skib DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %d\n", 2183277487Skib pipe); 2184277487Skib return; 2185277487Skib } 2186277487Skib I915_WRITE(WM2S_LP_IVB, sprite_wm); 2187277487Skib 2188277487Skib ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width, 2189277487Skib pixel_size, 2190277487Skib &sandybridge_display_srwm_info, 2191277487Skib SNB_READ_WM3_LATENCY() * 500, 2192277487Skib &sprite_wm); 2193277487Skib if (!ret) { 2194277487Skib DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %d\n", 2195277487Skib pipe); 2196277487Skib return; 2197277487Skib } 2198277487Skib I915_WRITE(WM3S_LP_IVB, sprite_wm); 2199277487Skib} 2200277487Skib 2201277487Skib/** 2202277487Skib * intel_update_watermarks - update FIFO watermark values based on current modes 2203277487Skib * 2204277487Skib * Calculate watermark values for the various WM regs based on current mode 2205277487Skib * and plane configuration. 2206277487Skib * 2207277487Skib * There are several cases to deal with here: 2208277487Skib * - normal (i.e. non-self-refresh) 2209277487Skib * - self-refresh (SR) mode 2210277487Skib * - lines are large relative to FIFO size (buffer can hold up to 2) 2211277487Skib * - lines are small relative to FIFO size (buffer can hold more than 2 2212277487Skib * lines), so need to account for TLB latency 2213277487Skib * 2214277487Skib * The normal calculation is: 2215277487Skib * watermark = dotclock * bytes per pixel * latency 2216277487Skib * where latency is platform & configuration dependent (we assume pessimal 2217277487Skib * values here). 2218277487Skib * 2219277487Skib * The SR calculation is: 2220277487Skib * watermark = (trunc(latency/line time)+1) * surface width * 2221277487Skib * bytes per pixel 2222277487Skib * where 2223277487Skib * line time = htotal / dotclock 2224277487Skib * surface width = hdisplay for normal plane and 64 for cursor 2225277487Skib * and latency is assumed to be high, as above. 2226277487Skib * 2227277487Skib * The final value programmed to the register should always be rounded up, 2228277487Skib * and include an extra 2 entries to account for clock crossings. 2229277487Skib * 2230277487Skib * We don't use the sprite, so we can ignore that. And on Crestline we have 2231277487Skib * to set the non-SR watermarks to 8. 2232277487Skib */ 2233277487Skibvoid intel_update_watermarks(struct drm_device *dev) 2234277487Skib{ 2235277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2236277487Skib 2237277487Skib if (dev_priv->display.update_wm) 2238277487Skib dev_priv->display.update_wm(dev); 2239277487Skib} 2240277487Skib 2241277487Skibvoid intel_update_linetime_watermarks(struct drm_device *dev, 2242277487Skib int pipe, struct drm_display_mode *mode) 2243277487Skib{ 2244277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2245277487Skib 2246277487Skib if (dev_priv->display.update_linetime_wm) 2247277487Skib dev_priv->display.update_linetime_wm(dev, pipe, mode); 2248277487Skib} 2249277487Skib 2250277487Skibvoid intel_update_sprite_watermarks(struct drm_device *dev, int pipe, 2251277487Skib uint32_t sprite_width, int pixel_size) 2252277487Skib{ 2253277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2254277487Skib 2255277487Skib if (dev_priv->display.update_sprite_wm) 2256277487Skib dev_priv->display.update_sprite_wm(dev, pipe, sprite_width, 2257277487Skib pixel_size); 2258277487Skib} 2259277487Skib 2260277487Skibstatic struct drm_i915_gem_object * 2261277487Skibintel_alloc_context_page(struct drm_device *dev) 2262277487Skib{ 2263277487Skib struct drm_i915_gem_object *ctx; 2264277487Skib int ret; 2265277487Skib 2266277487Skib DRM_LOCK_ASSERT(dev); 2267277487Skib 2268277487Skib ctx = i915_gem_alloc_object(dev, 4096); 2269277487Skib if (!ctx) { 2270277487Skib DRM_DEBUG("failed to alloc power context, RC6 disabled\n"); 2271277487Skib return NULL; 2272277487Skib } 2273277487Skib 2274296548Sdumbbell ret = i915_gem_object_pin(ctx, 4096, true, false); 2275277487Skib if (ret) { 2276277487Skib DRM_ERROR("failed to pin power context: %d\n", ret); 2277277487Skib goto err_unref; 2278277487Skib } 2279277487Skib 2280277487Skib ret = i915_gem_object_set_to_gtt_domain(ctx, 1); 2281277487Skib if (ret) { 2282277487Skib DRM_ERROR("failed to set-domain on power context: %d\n", ret); 2283277487Skib goto err_unpin; 2284277487Skib } 2285277487Skib 2286277487Skib return ctx; 2287277487Skib 2288277487Skiberr_unpin: 2289277487Skib i915_gem_object_unpin(ctx); 2290277487Skiberr_unref: 2291277487Skib drm_gem_object_unreference(&ctx->base); 2292277487Skib DRM_UNLOCK(dev); 2293277487Skib return NULL; 2294277487Skib} 2295277487Skib 2296296548Sdumbbell/** 2297296548Sdumbbell * Lock protecting IPS related data structures 2298296548Sdumbbell */ 2299296548Sdumbbellstruct mtx mchdev_lock; 2300296548SdumbbellMTX_SYSINIT(mchdev, &mchdev_lock, "mchdev", MTX_DEF); 2301296548Sdumbbell 2302296548Sdumbbell/* Global for IPS driver to get at the current i915 device. Protected by 2303296548Sdumbbell * mchdev_lock. */ 2304296548Sdumbbellstatic struct drm_i915_private *i915_mch_dev; 2305296548Sdumbbell 2306277487Skibbool ironlake_set_drps(struct drm_device *dev, u8 val) 2307277487Skib{ 2308277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2309277487Skib u16 rgvswctl; 2310277487Skib 2311296548Sdumbbell mtx_assert(&mchdev_lock, MA_OWNED); 2312296548Sdumbbell 2313277487Skib rgvswctl = I915_READ16(MEMSWCTL); 2314277487Skib if (rgvswctl & MEMCTL_CMD_STS) { 2315277487Skib DRM_DEBUG("gpu busy, RCS change rejected\n"); 2316277487Skib return false; /* still busy with another command */ 2317277487Skib } 2318277487Skib 2319277487Skib rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) | 2320277487Skib (val << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM; 2321277487Skib I915_WRITE16(MEMSWCTL, rgvswctl); 2322277487Skib POSTING_READ16(MEMSWCTL); 2323277487Skib 2324277487Skib rgvswctl |= MEMCTL_CMD_STS; 2325277487Skib I915_WRITE16(MEMSWCTL, rgvswctl); 2326277487Skib 2327277487Skib return true; 2328277487Skib} 2329277487Skib 2330296548Sdumbbellstatic void ironlake_enable_drps(struct drm_device *dev) 2331277487Skib{ 2332277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2333277487Skib u32 rgvmodectl = I915_READ(MEMMODECTL); 2334277487Skib u8 fmax, fmin, fstart, vstart; 2335277487Skib 2336296548Sdumbbell mtx_lock(&mchdev_lock); 2337296548Sdumbbell 2338277487Skib /* Enable temp reporting */ 2339277487Skib I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN); 2340277487Skib I915_WRITE16(TSC1, I915_READ(TSC1) | TSE); 2341277487Skib 2342277487Skib /* 100ms RC evaluation intervals */ 2343277487Skib I915_WRITE(RCUPEI, 100000); 2344277487Skib I915_WRITE(RCDNEI, 100000); 2345277487Skib 2346277487Skib /* Set max/min thresholds to 90ms and 80ms respectively */ 2347277487Skib I915_WRITE(RCBMAXAVG, 90000); 2348277487Skib I915_WRITE(RCBMINAVG, 80000); 2349277487Skib 2350277487Skib I915_WRITE(MEMIHYST, 1); 2351277487Skib 2352277487Skib /* Set up min, max, and cur for interrupt handling */ 2353277487Skib fmax = (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT; 2354277487Skib fmin = (rgvmodectl & MEMMODE_FMIN_MASK); 2355277487Skib fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> 2356277487Skib MEMMODE_FSTART_SHIFT; 2357277487Skib 2358277487Skib vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> 2359277487Skib PXVFREQ_PX_SHIFT; 2360277487Skib 2361296548Sdumbbell dev_priv->ips.fmax = fmax; /* IPS callback will increase this */ 2362296548Sdumbbell dev_priv->ips.fstart = fstart; 2363277487Skib 2364296548Sdumbbell dev_priv->ips.max_delay = fstart; 2365296548Sdumbbell dev_priv->ips.min_delay = fmin; 2366296548Sdumbbell dev_priv->ips.cur_delay = fstart; 2367277487Skib 2368277487Skib DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", 2369277487Skib fmax, fmin, fstart); 2370277487Skib 2371277487Skib I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN); 2372277487Skib 2373277487Skib /* 2374277487Skib * Interrupts will be enabled in ironlake_irq_postinstall 2375277487Skib */ 2376277487Skib 2377277487Skib I915_WRITE(VIDSTART, vstart); 2378277487Skib POSTING_READ(VIDSTART); 2379277487Skib 2380277487Skib rgvmodectl |= MEMMODE_SWMODE_EN; 2381277487Skib I915_WRITE(MEMMODECTL, rgvmodectl); 2382277487Skib 2383296548Sdumbbell if (wait_for_atomic((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10)) 2384277487Skib DRM_ERROR("stuck trying to change perf mode\n"); 2385296548Sdumbbell mdelay(1); 2386277487Skib 2387277487Skib ironlake_set_drps(dev, fstart); 2388277487Skib 2389296548Sdumbbell dev_priv->ips.last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) + 2390277487Skib I915_READ(0x112e0); 2391296548Sdumbbell dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies); 2392296548Sdumbbell dev_priv->ips.last_count2 = I915_READ(0x112f4); 2393296548Sdumbbell getrawmonotonic(&dev_priv->ips.last_time2); 2394296548Sdumbbell 2395296548Sdumbbell mtx_unlock(&mchdev_lock); 2396277487Skib} 2397277487Skib 2398296548Sdumbbellstatic void ironlake_disable_drps(struct drm_device *dev) 2399277487Skib{ 2400277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2401296548Sdumbbell u16 rgvswctl; 2402277487Skib 2403296548Sdumbbell mtx_lock(&mchdev_lock); 2404296548Sdumbbell 2405296548Sdumbbell rgvswctl = I915_READ16(MEMSWCTL); 2406296548Sdumbbell 2407277487Skib /* Ack interrupts, disable EFC interrupt */ 2408277487Skib I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN); 2409277487Skib I915_WRITE(MEMINTRSTS, MEMINT_EVAL_CHG); 2410277487Skib I915_WRITE(DEIER, I915_READ(DEIER) & ~DE_PCU_EVENT); 2411277487Skib I915_WRITE(DEIIR, DE_PCU_EVENT); 2412277487Skib I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT); 2413277487Skib 2414277487Skib /* Go back to the starting frequency */ 2415296548Sdumbbell ironlake_set_drps(dev, dev_priv->ips.fstart); 2416296548Sdumbbell mdelay(1); 2417277487Skib rgvswctl |= MEMCTL_CMD_STS; 2418277487Skib I915_WRITE(MEMSWCTL, rgvswctl); 2419296548Sdumbbell mdelay(1); 2420277487Skib 2421296548Sdumbbell mtx_unlock(&mchdev_lock); 2422277487Skib} 2423277487Skib 2424296548Sdumbbell/* There's a funny hw issue where the hw returns all 0 when reading from 2425296548Sdumbbell * GEN6_RP_INTERRUPT_LIMITS. Hence we always need to compute the desired value 2426296548Sdumbbell * ourselves, instead of doing a rmw cycle (which might result in us clearing 2427296548Sdumbbell * all limits and the gpu stuck at whatever frequency it is at atm). 2428296548Sdumbbell */ 2429296548Sdumbbellstatic u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val) 2430296548Sdumbbell{ 2431296548Sdumbbell u32 limits; 2432296548Sdumbbell 2433296548Sdumbbell limits = 0; 2434296548Sdumbbell 2435296548Sdumbbell if (*val >= dev_priv->rps.max_delay) 2436296548Sdumbbell *val = dev_priv->rps.max_delay; 2437296548Sdumbbell limits |= dev_priv->rps.max_delay << 24; 2438296548Sdumbbell 2439296548Sdumbbell /* Only set the down limit when we've reached the lowest level to avoid 2440296548Sdumbbell * getting more interrupts, otherwise leave this clear. This prevents a 2441296548Sdumbbell * race in the hw when coming out of rc6: There's a tiny window where 2442296548Sdumbbell * the hw runs at the minimal clock before selecting the desired 2443296548Sdumbbell * frequency, if the down threshold expires in that window we will not 2444296548Sdumbbell * receive a down interrupt. */ 2445296548Sdumbbell if (*val <= dev_priv->rps.min_delay) { 2446296548Sdumbbell *val = dev_priv->rps.min_delay; 2447296548Sdumbbell limits |= dev_priv->rps.min_delay << 16; 2448296548Sdumbbell } 2449296548Sdumbbell 2450296548Sdumbbell return limits; 2451296548Sdumbbell} 2452296548Sdumbbell 2453277487Skibvoid gen6_set_rps(struct drm_device *dev, u8 val) 2454277487Skib{ 2455277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2456296548Sdumbbell u32 limits = gen6_rps_limits(dev_priv, &val); 2457277487Skib 2458296548Sdumbbell sx_assert(&dev_priv->rps.hw_lock, SA_XLOCKED); 2459296548Sdumbbell WARN_ON(val > dev_priv->rps.max_delay); 2460296548Sdumbbell WARN_ON(val < dev_priv->rps.min_delay); 2461296548Sdumbbell 2462296548Sdumbbell if (val == dev_priv->rps.cur_delay) 2463296548Sdumbbell return; 2464296548Sdumbbell 2465296548Sdumbbell I915_WRITE(GEN6_RPNSWREQ, 2466296548Sdumbbell GEN6_FREQUENCY(val) | 2467296548Sdumbbell GEN6_OFFSET(0) | 2468296548Sdumbbell GEN6_AGGRESSIVE_TURBO); 2469296548Sdumbbell 2470296548Sdumbbell /* Make sure we continue to get interrupts 2471296548Sdumbbell * until we hit the minimum or maximum frequencies. 2472296548Sdumbbell */ 2473296548Sdumbbell I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); 2474296548Sdumbbell 2475296548Sdumbbell POSTING_READ(GEN6_RPNSWREQ); 2476296548Sdumbbell 2477296548Sdumbbell dev_priv->rps.cur_delay = val; 2478277487Skib} 2479277487Skib 2480296548Sdumbbellstatic void gen6_disable_rps(struct drm_device *dev) 2481277487Skib{ 2482277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2483277487Skib 2484296548Sdumbbell I915_WRITE(GEN6_RC_CONTROL, 0); 2485277487Skib I915_WRITE(GEN6_RPNSWREQ, 1 << 31); 2486277487Skib I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); 2487277487Skib I915_WRITE(GEN6_PMIER, 0); 2488277487Skib /* Complete PM interrupt masking here doesn't race with the rps work 2489277487Skib * item again unmasking PM interrupts because that is using a different 2490277487Skib * register (PMIMR) to mask PM interrupts. The only risk is in leaving 2491277487Skib * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */ 2492277487Skib 2493296548Sdumbbell mtx_lock(&dev_priv->rps.lock); 2494296548Sdumbbell dev_priv->rps.pm_iir = 0; 2495296548Sdumbbell mtx_unlock(&dev_priv->rps.lock); 2496277487Skib 2497277487Skib I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR)); 2498277487Skib} 2499277487Skib 2500277487Skibint intel_enable_rc6(const struct drm_device *dev) 2501277487Skib{ 2502296548Sdumbbell /* Respect the kernel parameter if it is set */ 2503277487Skib if (i915_enable_rc6 >= 0) 2504277487Skib return i915_enable_rc6; 2505277487Skib 2506296548Sdumbbell /* Disable RC6 on Ironlake */ 2507277487Skib if (INTEL_INFO(dev)->gen == 5) 2508277487Skib return 0; 2509277487Skib 2510296548Sdumbbell if (IS_HASWELL(dev)) { 2511296548Sdumbbell DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); 2512296548Sdumbbell return INTEL_RC6_ENABLE; 2513296548Sdumbbell } 2514277487Skib 2515296548Sdumbbell /* snb/ivb have more than one rc6 state. */ 2516277487Skib if (INTEL_INFO(dev)->gen == 6) { 2517277487Skib DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); 2518277487Skib return INTEL_RC6_ENABLE; 2519277487Skib } 2520296548Sdumbbell 2521277487Skib DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); 2522277487Skib return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); 2523277487Skib} 2524277487Skib 2525296548Sdumbbellstatic void gen6_enable_rps(struct drm_device *dev) 2526277487Skib{ 2527296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 2528277487Skib struct intel_ring_buffer *ring; 2529296548Sdumbbell u32 rp_state_cap; 2530296548Sdumbbell u32 gt_perf_status; 2531296548Sdumbbell u32 rc6vids, pcu_mbox, rc6_mask = 0; 2532277487Skib u32 gtfifodbg; 2533277487Skib int rc6_mode; 2534296548Sdumbbell int i, ret; 2535277487Skib 2536296548Sdumbbell sx_assert(&dev_priv->rps.hw_lock, SA_XLOCKED); 2537296548Sdumbbell 2538277487Skib /* Here begins a magic sequence of register writes to enable 2539277487Skib * auto-downclocking. 2540277487Skib * 2541277487Skib * Perhaps there might be some value in exposing these to 2542277487Skib * userspace... 2543277487Skib */ 2544277487Skib I915_WRITE(GEN6_RC_STATE, 0); 2545277487Skib 2546277487Skib /* Clear the DBG now so we don't confuse earlier errors */ 2547277487Skib if ((gtfifodbg = I915_READ(GTFIFODBG))) { 2548277487Skib DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg); 2549277487Skib I915_WRITE(GTFIFODBG, gtfifodbg); 2550277487Skib } 2551277487Skib 2552277487Skib gen6_gt_force_wake_get(dev_priv); 2553277487Skib 2554296548Sdumbbell rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); 2555296548Sdumbbell gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); 2556296548Sdumbbell 2557296548Sdumbbell /* In units of 100MHz */ 2558296548Sdumbbell dev_priv->rps.max_delay = rp_state_cap & 0xff; 2559296548Sdumbbell dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16; 2560296548Sdumbbell dev_priv->rps.cur_delay = 0; 2561296548Sdumbbell 2562277487Skib /* disable the counters and set deterministic thresholds */ 2563277487Skib I915_WRITE(GEN6_RC_CONTROL, 0); 2564277487Skib 2565277487Skib I915_WRITE(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16); 2566277487Skib I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30); 2567277487Skib I915_WRITE(GEN6_RC6pp_WAKE_RATE_LIMIT, 30); 2568277487Skib I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); 2569277487Skib I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); 2570277487Skib 2571277487Skib for_each_ring(ring, dev_priv, i) 2572277487Skib I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); 2573277487Skib 2574277487Skib I915_WRITE(GEN6_RC_SLEEP, 0); 2575277487Skib I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); 2576277487Skib I915_WRITE(GEN6_RC6_THRESHOLD, 50000); 2577296548Sdumbbell I915_WRITE(GEN6_RC6p_THRESHOLD, 150000); 2578277487Skib I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ 2579277487Skib 2580296548Sdumbbell /* Check if we are enabling RC6 */ 2581277487Skib rc6_mode = intel_enable_rc6(dev_priv->dev); 2582277487Skib if (rc6_mode & INTEL_RC6_ENABLE) 2583277487Skib rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; 2584277487Skib 2585296548Sdumbbell /* We don't use those on Haswell */ 2586296548Sdumbbell if (!IS_HASWELL(dev)) { 2587296548Sdumbbell if (rc6_mode & INTEL_RC6p_ENABLE) 2588296548Sdumbbell rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; 2589277487Skib 2590296548Sdumbbell if (rc6_mode & INTEL_RC6pp_ENABLE) 2591296548Sdumbbell rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; 2592296548Sdumbbell } 2593277487Skib 2594277487Skib DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", 2595296548Sdumbbell (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", 2596296548Sdumbbell (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", 2597296548Sdumbbell (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); 2598277487Skib 2599277487Skib I915_WRITE(GEN6_RC_CONTROL, 2600277487Skib rc6_mask | 2601277487Skib GEN6_RC_CTL_EI_MODE(1) | 2602277487Skib GEN6_RC_CTL_HW_ENABLE); 2603277487Skib 2604277487Skib I915_WRITE(GEN6_RPNSWREQ, 2605277487Skib GEN6_FREQUENCY(10) | 2606277487Skib GEN6_OFFSET(0) | 2607277487Skib GEN6_AGGRESSIVE_TURBO); 2608277487Skib I915_WRITE(GEN6_RC_VIDEO_FREQ, 2609277487Skib GEN6_FREQUENCY(12)); 2610277487Skib 2611277487Skib I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); 2612277487Skib I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, 2613296548Sdumbbell dev_priv->rps.max_delay << 24 | 2614296548Sdumbbell dev_priv->rps.min_delay << 16); 2615296548Sdumbbell 2616296548Sdumbbell I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); 2617296548Sdumbbell I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); 2618296548Sdumbbell I915_WRITE(GEN6_RP_UP_EI, 66000); 2619296548Sdumbbell I915_WRITE(GEN6_RP_DOWN_EI, 350000); 2620296548Sdumbbell 2621277487Skib I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); 2622277487Skib I915_WRITE(GEN6_RP_CONTROL, 2623277487Skib GEN6_RP_MEDIA_TURBO | 2624296548Sdumbbell GEN6_RP_MEDIA_HW_NORMAL_MODE | 2625277487Skib GEN6_RP_MEDIA_IS_GFX | 2626277487Skib GEN6_RP_ENABLE | 2627277487Skib GEN6_RP_UP_BUSY_AVG | 2628296548Sdumbbell (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT)); 2629277487Skib 2630296548Sdumbbell ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0); 2631296548Sdumbbell if (!ret) { 2632296548Sdumbbell pcu_mbox = 0; 2633296548Sdumbbell ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox); 2634296548Sdumbbell if (ret && pcu_mbox & (1<<31)) { /* OC supported */ 2635296548Sdumbbell dev_priv->rps.max_delay = pcu_mbox & 0xff; 2636296548Sdumbbell DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50); 2637296548Sdumbbell } 2638296548Sdumbbell } else { 2639296548Sdumbbell DRM_DEBUG_DRIVER("Failed to set the min frequency\n"); 2640277487Skib } 2641277487Skib 2642296548Sdumbbell gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); 2643277487Skib 2644277487Skib /* requires MSI enabled */ 2645296548Sdumbbell I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS); 2646296548Sdumbbell mtx_lock(&dev_priv->rps.lock); 2647296548Sdumbbell WARN_ON(dev_priv->rps.pm_iir != 0); 2648277487Skib I915_WRITE(GEN6_PMIMR, 0); 2649296548Sdumbbell mtx_unlock(&dev_priv->rps.lock); 2650277487Skib /* enable all PM interrupts */ 2651277487Skib I915_WRITE(GEN6_PMINTRMSK, 0); 2652277487Skib 2653296548Sdumbbell rc6vids = 0; 2654296548Sdumbbell ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); 2655296548Sdumbbell if (IS_GEN6(dev) && ret) { 2656296548Sdumbbell DRM_DEBUG_DRIVER("Couldn't check for BIOS workaround\n"); 2657296548Sdumbbell } else if (IS_GEN6(dev) && (GEN6_DECODE_RC6_VID(rc6vids & 0xff) < 450)) { 2658296548Sdumbbell DRM_DEBUG_DRIVER("You should update your BIOS. Correcting minimum rc6 voltage (%dmV->%dmV)\n", 2659296548Sdumbbell GEN6_DECODE_RC6_VID(rc6vids & 0xff), 450); 2660296548Sdumbbell rc6vids &= 0xffff00; 2661296548Sdumbbell rc6vids |= GEN6_ENCODE_RC6_VID(450); 2662296548Sdumbbell ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_RC6VIDS, rc6vids); 2663296548Sdumbbell if (ret) 2664296548Sdumbbell DRM_ERROR("Couldn't fix incorrect rc6 voltage\n"); 2665296548Sdumbbell } 2666296548Sdumbbell 2667277487Skib gen6_gt_force_wake_put(dev_priv); 2668277487Skib} 2669277487Skib 2670296548Sdumbbellstatic void gen6_update_ring_freq(struct drm_device *dev) 2671277487Skib{ 2672296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 2673277487Skib int min_freq = 15; 2674296548Sdumbbell int gpu_freq; 2675296548Sdumbbell unsigned int ia_freq, max_ia_freq; 2676277487Skib int scaling_factor = 180; 2677277487Skib 2678296548Sdumbbell sx_assert(&dev_priv->rps.hw_lock, SA_XLOCKED); 2679296548Sdumbbell 2680296548Sdumbbell#ifdef FREEBSD_WIP 2681277487Skib max_ia_freq = cpufreq_quick_get_max(0); 2682277487Skib /* 2683277487Skib * Default to measured freq if none found, PCU will ensure we don't go 2684277487Skib * over 2685277487Skib */ 2686277487Skib if (!max_ia_freq) 2687277487Skib max_ia_freq = tsc_khz; 2688296548Sdumbbell#else 2689296548Sdumbbell uint64_t tsc_freq; 2690296548Sdumbbell tsc_freq = atomic_load_acq_64(&tsc_freq); 2691296548Sdumbbell max_ia_freq = tsc_freq / 1000; 2692296548Sdumbbell#endif /* FREEBSD_WIP */ 2693277487Skib 2694277487Skib /* Convert from kHz to MHz */ 2695277487Skib max_ia_freq /= 1000; 2696277487Skib 2697277487Skib /* 2698277487Skib * For each potential GPU frequency, load a ring frequency we'd like 2699277487Skib * to use for memory access. We do this by specifying the IA frequency 2700277487Skib * the PCU should use as a reference to determine the ring frequency. 2701277487Skib */ 2702296548Sdumbbell for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay; 2703277487Skib gpu_freq--) { 2704296548Sdumbbell int diff = dev_priv->rps.max_delay - gpu_freq; 2705277487Skib 2706277487Skib /* 2707277487Skib * For GPU frequencies less than 750MHz, just use the lowest 2708277487Skib * ring freq. 2709277487Skib */ 2710277487Skib if (gpu_freq < min_freq) 2711277487Skib ia_freq = 800; 2712277487Skib else 2713277487Skib ia_freq = max_ia_freq - ((diff * scaling_factor) / 2); 2714296548Sdumbbell ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100); 2715296548Sdumbbell ia_freq <<= GEN6_PCODE_FREQ_IA_RATIO_SHIFT; 2716277487Skib 2717296548Sdumbbell sandybridge_pcode_write(dev_priv, 2718296548Sdumbbell GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 2719296548Sdumbbell ia_freq | gpu_freq); 2720277487Skib } 2721277487Skib} 2722277487Skib 2723296548Sdumbbellvoid ironlake_teardown_rc6(struct drm_device *dev) 2724277487Skib{ 2725277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2726277487Skib 2727296548Sdumbbell if (dev_priv->ips.renderctx) { 2728296548Sdumbbell i915_gem_object_unpin(dev_priv->ips.renderctx); 2729296548Sdumbbell drm_gem_object_unreference(&dev_priv->ips.renderctx->base); 2730296548Sdumbbell dev_priv->ips.renderctx = NULL; 2731277487Skib } 2732277487Skib 2733296548Sdumbbell if (dev_priv->ips.pwrctx) { 2734296548Sdumbbell i915_gem_object_unpin(dev_priv->ips.pwrctx); 2735296548Sdumbbell drm_gem_object_unreference(&dev_priv->ips.pwrctx->base); 2736296548Sdumbbell dev_priv->ips.pwrctx = NULL; 2737277487Skib } 2738277487Skib} 2739277487Skib 2740296548Sdumbbellstatic void ironlake_disable_rc6(struct drm_device *dev) 2741277487Skib{ 2742277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2743277487Skib 2744277487Skib if (I915_READ(PWRCTXA)) { 2745277487Skib /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ 2746277487Skib I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); 2747277487Skib wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), 2748277487Skib 50); 2749277487Skib 2750277487Skib I915_WRITE(PWRCTXA, 0); 2751277487Skib POSTING_READ(PWRCTXA); 2752277487Skib 2753277487Skib I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); 2754277487Skib POSTING_READ(RSTDBYCTL); 2755277487Skib } 2756277487Skib} 2757277487Skib 2758277487Skibstatic int ironlake_setup_rc6(struct drm_device *dev) 2759277487Skib{ 2760277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2761277487Skib 2762296548Sdumbbell if (dev_priv->ips.renderctx == NULL) 2763296548Sdumbbell dev_priv->ips.renderctx = intel_alloc_context_page(dev); 2764296548Sdumbbell if (!dev_priv->ips.renderctx) 2765277487Skib return -ENOMEM; 2766277487Skib 2767296548Sdumbbell if (dev_priv->ips.pwrctx == NULL) 2768296548Sdumbbell dev_priv->ips.pwrctx = intel_alloc_context_page(dev); 2769296548Sdumbbell if (!dev_priv->ips.pwrctx) { 2770277487Skib ironlake_teardown_rc6(dev); 2771277487Skib return -ENOMEM; 2772277487Skib } 2773277487Skib 2774277487Skib return 0; 2775277487Skib} 2776277487Skib 2777296548Sdumbbellstatic void ironlake_enable_rc6(struct drm_device *dev) 2778277487Skib{ 2779277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 2780296548Sdumbbell struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; 2781296548Sdumbbell bool was_interruptible; 2782277487Skib int ret; 2783277487Skib 2784277487Skib /* rc6 disabled by default due to repeated reports of hanging during 2785277487Skib * boot and resume. 2786277487Skib */ 2787277487Skib if (!intel_enable_rc6(dev)) 2788277487Skib return; 2789277487Skib 2790296548Sdumbbell DRM_LOCK_ASSERT(dev); 2791296548Sdumbbell 2792277487Skib ret = ironlake_setup_rc6(dev); 2793296548Sdumbbell if (ret) 2794277487Skib return; 2795277487Skib 2796296548Sdumbbell was_interruptible = dev_priv->mm.interruptible; 2797296548Sdumbbell dev_priv->mm.interruptible = false; 2798296548Sdumbbell 2799277487Skib /* 2800277487Skib * GPU can automatically power down the render unit if given a page 2801277487Skib * to save state. 2802277487Skib */ 2803277487Skib ret = intel_ring_begin(ring, 6); 2804277487Skib if (ret) { 2805277487Skib ironlake_teardown_rc6(dev); 2806296548Sdumbbell dev_priv->mm.interruptible = was_interruptible; 2807277487Skib return; 2808277487Skib } 2809277487Skib 2810277487Skib intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); 2811277487Skib intel_ring_emit(ring, MI_SET_CONTEXT); 2812296548Sdumbbell intel_ring_emit(ring, dev_priv->ips.renderctx->gtt_offset | 2813277487Skib MI_MM_SPACE_GTT | 2814277487Skib MI_SAVE_EXT_STATE_EN | 2815277487Skib MI_RESTORE_EXT_STATE_EN | 2816277487Skib MI_RESTORE_INHIBIT); 2817277487Skib intel_ring_emit(ring, MI_SUSPEND_FLUSH); 2818277487Skib intel_ring_emit(ring, MI_NOOP); 2819277487Skib intel_ring_emit(ring, MI_FLUSH); 2820277487Skib intel_ring_advance(ring); 2821277487Skib 2822277487Skib /* 2823277487Skib * Wait for the command parser to advance past MI_SET_CONTEXT. The HW 2824277487Skib * does an implicit flush, combined with MI_FLUSH above, it should be 2825277487Skib * safe to assume that renderctx is valid 2826277487Skib */ 2827296548Sdumbbell ret = intel_ring_idle(ring); 2828296548Sdumbbell dev_priv->mm.interruptible = was_interruptible; 2829277487Skib if (ret) { 2830277487Skib DRM_ERROR("failed to enable ironlake power power savings\n"); 2831277487Skib ironlake_teardown_rc6(dev); 2832277487Skib return; 2833277487Skib } 2834277487Skib 2835296548Sdumbbell I915_WRITE(PWRCTXA, dev_priv->ips.pwrctx->gtt_offset | PWRCTX_EN); 2836277487Skib I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); 2837277487Skib} 2838277487Skib 2839277487Skibstatic unsigned long intel_pxfreq(u32 vidfreq) 2840277487Skib{ 2841277487Skib unsigned long freq; 2842277487Skib int div = (vidfreq & 0x3f0000) >> 16; 2843277487Skib int post = (vidfreq & 0x3000) >> 12; 2844277487Skib int pre = (vidfreq & 0x7); 2845277487Skib 2846277487Skib if (!pre) 2847277487Skib return 0; 2848277487Skib 2849277487Skib freq = ((div * 133333) / ((1<<post) * pre)); 2850277487Skib 2851277487Skib return freq; 2852277487Skib} 2853277487Skib 2854277487Skibstatic const struct cparams { 2855277487Skib u16 i; 2856277487Skib u16 t; 2857277487Skib u16 m; 2858277487Skib u16 c; 2859277487Skib} cparams[] = { 2860277487Skib { 1, 1333, 301, 28664 }, 2861277487Skib { 1, 1066, 294, 24460 }, 2862277487Skib { 1, 800, 294, 25192 }, 2863277487Skib { 0, 1333, 276, 27605 }, 2864277487Skib { 0, 1066, 276, 27605 }, 2865277487Skib { 0, 800, 231, 23784 }, 2866277487Skib}; 2867277487Skib 2868296548Sdumbbellstatic unsigned long __i915_chipset_val(struct drm_i915_private *dev_priv) 2869277487Skib{ 2870277487Skib u64 total_count, diff, ret; 2871277487Skib u32 count1, count2, count3, m = 0, c = 0; 2872277487Skib unsigned long now = jiffies_to_msecs(jiffies), diff1; 2873277487Skib int i; 2874277487Skib 2875296548Sdumbbell mtx_assert(&mchdev_lock, MA_OWNED); 2876296548Sdumbbell 2877296548Sdumbbell diff1 = now - dev_priv->ips.last_time1; 2878296548Sdumbbell 2879296548Sdumbbell /* Prevent division-by-zero if we are asking too fast. 2880296548Sdumbbell * Also, we don't get interesting results if we are polling 2881296548Sdumbbell * faster than once in 10ms, so just return the saved value 2882296548Sdumbbell * in such cases. 2883277487Skib */ 2884277487Skib if (diff1 <= 10) 2885296548Sdumbbell return dev_priv->ips.chipset_power; 2886277487Skib 2887277487Skib count1 = I915_READ(DMIEC); 2888277487Skib count2 = I915_READ(DDREC); 2889277487Skib count3 = I915_READ(CSIEC); 2890277487Skib 2891277487Skib total_count = count1 + count2 + count3; 2892277487Skib 2893277487Skib /* FIXME: handle per-counter overflow */ 2894296548Sdumbbell if (total_count < dev_priv->ips.last_count1) { 2895296548Sdumbbell diff = ~0UL - dev_priv->ips.last_count1; 2896277487Skib diff += total_count; 2897277487Skib } else { 2898296548Sdumbbell diff = total_count - dev_priv->ips.last_count1; 2899277487Skib } 2900277487Skib 2901296548Sdumbbell for (i = 0; i < ARRAY_SIZE(cparams); i++) { 2902296548Sdumbbell if (cparams[i].i == dev_priv->ips.c_m && 2903296548Sdumbbell cparams[i].t == dev_priv->ips.r_t) { 2904277487Skib m = cparams[i].m; 2905277487Skib c = cparams[i].c; 2906277487Skib break; 2907277487Skib } 2908277487Skib } 2909277487Skib 2910296548Sdumbbell diff = div_u64(diff, diff1); 2911277487Skib ret = ((m * diff) + c); 2912296548Sdumbbell ret = div_u64(ret, 10); 2913277487Skib 2914296548Sdumbbell dev_priv->ips.last_count1 = total_count; 2915296548Sdumbbell dev_priv->ips.last_time1 = now; 2916277487Skib 2917296548Sdumbbell dev_priv->ips.chipset_power = ret; 2918296548Sdumbbell 2919290228Sdumbbell return ret; 2920277487Skib} 2921277487Skib 2922296548Sdumbbellunsigned long i915_chipset_val(struct drm_i915_private *dev_priv) 2923296548Sdumbbell{ 2924296548Sdumbbell unsigned long val; 2925296548Sdumbbell 2926296548Sdumbbell if (dev_priv->info->gen != 5) 2927296548Sdumbbell return 0; 2928296548Sdumbbell 2929296548Sdumbbell mtx_lock(&mchdev_lock); 2930296548Sdumbbell 2931296548Sdumbbell val = __i915_chipset_val(dev_priv); 2932296548Sdumbbell 2933296548Sdumbbell mtx_unlock(&mchdev_lock); 2934296548Sdumbbell 2935296548Sdumbbell return val; 2936296548Sdumbbell} 2937296548Sdumbbell 2938277487Skibunsigned long i915_mch_val(struct drm_i915_private *dev_priv) 2939277487Skib{ 2940277487Skib unsigned long m, x, b; 2941277487Skib u32 tsfs; 2942277487Skib 2943277487Skib tsfs = I915_READ(TSFS); 2944277487Skib 2945277487Skib m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT); 2946277487Skib x = I915_READ8(I915_TR1); 2947277487Skib 2948277487Skib b = tsfs & TSFS_INTR_MASK; 2949277487Skib 2950277487Skib return ((m * x) / 127) - b; 2951277487Skib} 2952277487Skib 2953277487Skibstatic u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid) 2954277487Skib{ 2955277487Skib static const struct v_table { 2956277487Skib u16 vd; /* in .1 mil */ 2957277487Skib u16 vm; /* in .1 mil */ 2958277487Skib } v_table[] = { 2959277487Skib { 0, 0, }, 2960277487Skib { 375, 0, }, 2961277487Skib { 500, 0, }, 2962277487Skib { 625, 0, }, 2963277487Skib { 750, 0, }, 2964277487Skib { 875, 0, }, 2965277487Skib { 1000, 0, }, 2966277487Skib { 1125, 0, }, 2967277487Skib { 4125, 3000, }, 2968277487Skib { 4125, 3000, }, 2969277487Skib { 4125, 3000, }, 2970277487Skib { 4125, 3000, }, 2971277487Skib { 4125, 3000, }, 2972277487Skib { 4125, 3000, }, 2973277487Skib { 4125, 3000, }, 2974277487Skib { 4125, 3000, }, 2975277487Skib { 4125, 3000, }, 2976277487Skib { 4125, 3000, }, 2977277487Skib { 4125, 3000, }, 2978277487Skib { 4125, 3000, }, 2979277487Skib { 4125, 3000, }, 2980277487Skib { 4125, 3000, }, 2981277487Skib { 4125, 3000, }, 2982277487Skib { 4125, 3000, }, 2983277487Skib { 4125, 3000, }, 2984277487Skib { 4125, 3000, }, 2985277487Skib { 4125, 3000, }, 2986277487Skib { 4125, 3000, }, 2987277487Skib { 4125, 3000, }, 2988277487Skib { 4125, 3000, }, 2989277487Skib { 4125, 3000, }, 2990277487Skib { 4125, 3000, }, 2991277487Skib { 4250, 3125, }, 2992277487Skib { 4375, 3250, }, 2993277487Skib { 4500, 3375, }, 2994277487Skib { 4625, 3500, }, 2995277487Skib { 4750, 3625, }, 2996277487Skib { 4875, 3750, }, 2997277487Skib { 5000, 3875, }, 2998277487Skib { 5125, 4000, }, 2999277487Skib { 5250, 4125, }, 3000277487Skib { 5375, 4250, }, 3001277487Skib { 5500, 4375, }, 3002277487Skib { 5625, 4500, }, 3003277487Skib { 5750, 4625, }, 3004277487Skib { 5875, 4750, }, 3005277487Skib { 6000, 4875, }, 3006277487Skib { 6125, 5000, }, 3007277487Skib { 6250, 5125, }, 3008277487Skib { 6375, 5250, }, 3009277487Skib { 6500, 5375, }, 3010277487Skib { 6625, 5500, }, 3011277487Skib { 6750, 5625, }, 3012277487Skib { 6875, 5750, }, 3013277487Skib { 7000, 5875, }, 3014277487Skib { 7125, 6000, }, 3015277487Skib { 7250, 6125, }, 3016277487Skib { 7375, 6250, }, 3017277487Skib { 7500, 6375, }, 3018277487Skib { 7625, 6500, }, 3019277487Skib { 7750, 6625, }, 3020277487Skib { 7875, 6750, }, 3021277487Skib { 8000, 6875, }, 3022277487Skib { 8125, 7000, }, 3023277487Skib { 8250, 7125, }, 3024277487Skib { 8375, 7250, }, 3025277487Skib { 8500, 7375, }, 3026277487Skib { 8625, 7500, }, 3027277487Skib { 8750, 7625, }, 3028277487Skib { 8875, 7750, }, 3029277487Skib { 9000, 7875, }, 3030277487Skib { 9125, 8000, }, 3031277487Skib { 9250, 8125, }, 3032277487Skib { 9375, 8250, }, 3033277487Skib { 9500, 8375, }, 3034277487Skib { 9625, 8500, }, 3035277487Skib { 9750, 8625, }, 3036277487Skib { 9875, 8750, }, 3037277487Skib { 10000, 8875, }, 3038277487Skib { 10125, 9000, }, 3039277487Skib { 10250, 9125, }, 3040277487Skib { 10375, 9250, }, 3041277487Skib { 10500, 9375, }, 3042277487Skib { 10625, 9500, }, 3043277487Skib { 10750, 9625, }, 3044277487Skib { 10875, 9750, }, 3045277487Skib { 11000, 9875, }, 3046277487Skib { 11125, 10000, }, 3047277487Skib { 11250, 10125, }, 3048277487Skib { 11375, 10250, }, 3049277487Skib { 11500, 10375, }, 3050277487Skib { 11625, 10500, }, 3051277487Skib { 11750, 10625, }, 3052277487Skib { 11875, 10750, }, 3053277487Skib { 12000, 10875, }, 3054277487Skib { 12125, 11000, }, 3055277487Skib { 12250, 11125, }, 3056277487Skib { 12375, 11250, }, 3057277487Skib { 12500, 11375, }, 3058277487Skib { 12625, 11500, }, 3059277487Skib { 12750, 11625, }, 3060277487Skib { 12875, 11750, }, 3061277487Skib { 13000, 11875, }, 3062277487Skib { 13125, 12000, }, 3063277487Skib { 13250, 12125, }, 3064277487Skib { 13375, 12250, }, 3065277487Skib { 13500, 12375, }, 3066277487Skib { 13625, 12500, }, 3067277487Skib { 13750, 12625, }, 3068277487Skib { 13875, 12750, }, 3069277487Skib { 14000, 12875, }, 3070277487Skib { 14125, 13000, }, 3071277487Skib { 14250, 13125, }, 3072277487Skib { 14375, 13250, }, 3073277487Skib { 14500, 13375, }, 3074277487Skib { 14625, 13500, }, 3075277487Skib { 14750, 13625, }, 3076277487Skib { 14875, 13750, }, 3077277487Skib { 15000, 13875, }, 3078277487Skib { 15125, 14000, }, 3079277487Skib { 15250, 14125, }, 3080277487Skib { 15375, 14250, }, 3081277487Skib { 15500, 14375, }, 3082277487Skib { 15625, 14500, }, 3083277487Skib { 15750, 14625, }, 3084277487Skib { 15875, 14750, }, 3085277487Skib { 16000, 14875, }, 3086277487Skib { 16125, 15000, }, 3087277487Skib }; 3088277487Skib if (dev_priv->info->is_mobile) 3089277487Skib return v_table[pxvid].vm; 3090277487Skib else 3091277487Skib return v_table[pxvid].vd; 3092277487Skib} 3093277487Skib 3094296548Sdumbbellstatic void __i915_update_gfx_val(struct drm_i915_private *dev_priv) 3095277487Skib{ 3096277487Skib struct timespec now, diff1; 3097277487Skib u64 diff; 3098277487Skib unsigned long diffms; 3099277487Skib u32 count; 3100277487Skib 3101296548Sdumbbell mtx_assert(&mchdev_lock, MA_OWNED); 3102277487Skib 3103277487Skib nanotime(&now); 3104277487Skib diff1 = now; 3105296548Sdumbbell timespecsub(&diff1, &dev_priv->ips.last_time2); 3106277487Skib 3107277487Skib /* Don't divide by 0 */ 3108277487Skib diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000; 3109277487Skib if (!diffms) 3110277487Skib return; 3111277487Skib 3112277487Skib count = I915_READ(GFXEC); 3113277487Skib 3114296548Sdumbbell if (count < dev_priv->ips.last_count2) { 3115296548Sdumbbell diff = ~0UL - dev_priv->ips.last_count2; 3116277487Skib diff += count; 3117277487Skib } else { 3118296548Sdumbbell diff = count - dev_priv->ips.last_count2; 3119277487Skib } 3120277487Skib 3121296548Sdumbbell dev_priv->ips.last_count2 = count; 3122296548Sdumbbell dev_priv->ips.last_time2 = now; 3123277487Skib 3124277487Skib /* More magic constants... */ 3125277487Skib diff = diff * 1181; 3126296548Sdumbbell diff = div_u64(diff, diffms * 10); 3127296548Sdumbbell dev_priv->ips.gfx_power = diff; 3128277487Skib} 3129277487Skib 3130296548Sdumbbellvoid i915_update_gfx_val(struct drm_i915_private *dev_priv) 3131277487Skib{ 3132296548Sdumbbell if (dev_priv->info->gen != 5) 3133296548Sdumbbell return; 3134296548Sdumbbell 3135296548Sdumbbell mtx_lock(&mchdev_lock); 3136296548Sdumbbell 3137296548Sdumbbell __i915_update_gfx_val(dev_priv); 3138296548Sdumbbell 3139296548Sdumbbell mtx_unlock(&mchdev_lock); 3140296548Sdumbbell} 3141296548Sdumbbell 3142296548Sdumbbellstatic unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv) 3143296548Sdumbbell{ 3144277487Skib unsigned long t, corr, state1, corr2, state2; 3145277487Skib u32 pxvid, ext_v; 3146277487Skib 3147296548Sdumbbell mtx_assert(&mchdev_lock, MA_OWNED); 3148296548Sdumbbell 3149296548Sdumbbell pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_delay * 4)); 3150277487Skib pxvid = (pxvid >> 24) & 0x7f; 3151277487Skib ext_v = pvid_to_extvid(dev_priv, pxvid); 3152277487Skib 3153277487Skib state1 = ext_v; 3154277487Skib 3155277487Skib t = i915_mch_val(dev_priv); 3156277487Skib 3157277487Skib /* Revel in the empirically derived constants */ 3158277487Skib 3159277487Skib /* Correction factor in 1/100000 units */ 3160277487Skib if (t > 80) 3161277487Skib corr = ((t * 2349) + 135940); 3162277487Skib else if (t >= 50) 3163277487Skib corr = ((t * 964) + 29317); 3164277487Skib else /* < 50 */ 3165277487Skib corr = ((t * 301) + 1004); 3166277487Skib 3167277487Skib corr = corr * ((150142 * state1) / 10000 - 78642); 3168277487Skib corr /= 100000; 3169296548Sdumbbell corr2 = (corr * dev_priv->ips.corr); 3170277487Skib 3171277487Skib state2 = (corr2 * state1) / 10000; 3172277487Skib state2 /= 100; /* convert to mW */ 3173277487Skib 3174296548Sdumbbell __i915_update_gfx_val(dev_priv); 3175277487Skib 3176296548Sdumbbell return dev_priv->ips.gfx_power + state2; 3177277487Skib} 3178277487Skib 3179296548Sdumbbellunsigned long i915_gfx_val(struct drm_i915_private *dev_priv) 3180296548Sdumbbell{ 3181296548Sdumbbell unsigned long val; 3182296548Sdumbbell 3183296548Sdumbbell if (dev_priv->info->gen != 5) 3184296548Sdumbbell return 0; 3185296548Sdumbbell 3186296548Sdumbbell mtx_lock(&mchdev_lock); 3187296548Sdumbbell 3188296548Sdumbbell val = __i915_gfx_val(dev_priv); 3189296548Sdumbbell 3190296548Sdumbbell mtx_unlock(&mchdev_lock); 3191296548Sdumbbell 3192296548Sdumbbell return val; 3193296548Sdumbbell} 3194296548Sdumbbell 3195277487Skib/** 3196277487Skib * i915_read_mch_val - return value for IPS use 3197277487Skib * 3198277487Skib * Calculate and return a value for the IPS driver to use when deciding whether 3199277487Skib * we have thermal and power headroom to increase CPU or GPU power budget. 3200277487Skib */ 3201277487Skibunsigned long i915_read_mch_val(void) 3202277487Skib{ 3203277487Skib struct drm_i915_private *dev_priv; 3204277487Skib unsigned long chipset_val, graphics_val, ret = 0; 3205277487Skib 3206277487Skib mtx_lock(&mchdev_lock); 3207277487Skib if (!i915_mch_dev) 3208277487Skib goto out_unlock; 3209277487Skib dev_priv = i915_mch_dev; 3210277487Skib 3211296548Sdumbbell chipset_val = __i915_chipset_val(dev_priv); 3212296548Sdumbbell graphics_val = __i915_gfx_val(dev_priv); 3213277487Skib 3214277487Skib ret = chipset_val + graphics_val; 3215277487Skib 3216277487Skibout_unlock: 3217277487Skib mtx_unlock(&mchdev_lock); 3218277487Skib 3219277487Skib return ret; 3220277487Skib} 3221296548SdumbbellEXPORT_SYMBOL_GPL(i915_read_mch_val); 3222277487Skib 3223277487Skib/** 3224277487Skib * i915_gpu_raise - raise GPU frequency limit 3225277487Skib * 3226277487Skib * Raise the limit; IPS indicates we have thermal headroom. 3227277487Skib */ 3228277487Skibbool i915_gpu_raise(void) 3229277487Skib{ 3230277487Skib struct drm_i915_private *dev_priv; 3231277487Skib bool ret = true; 3232277487Skib 3233277487Skib mtx_lock(&mchdev_lock); 3234277487Skib if (!i915_mch_dev) { 3235277487Skib ret = false; 3236277487Skib goto out_unlock; 3237277487Skib } 3238277487Skib dev_priv = i915_mch_dev; 3239277487Skib 3240296548Sdumbbell if (dev_priv->ips.max_delay > dev_priv->ips.fmax) 3241296548Sdumbbell dev_priv->ips.max_delay--; 3242277487Skib 3243277487Skibout_unlock: 3244277487Skib mtx_unlock(&mchdev_lock); 3245277487Skib 3246277487Skib return ret; 3247277487Skib} 3248296548SdumbbellEXPORT_SYMBOL_GPL(i915_gpu_raise); 3249277487Skib 3250277487Skib/** 3251277487Skib * i915_gpu_lower - lower GPU frequency limit 3252277487Skib * 3253277487Skib * IPS indicates we're close to a thermal limit, so throttle back the GPU 3254277487Skib * frequency maximum. 3255277487Skib */ 3256277487Skibbool i915_gpu_lower(void) 3257277487Skib{ 3258277487Skib struct drm_i915_private *dev_priv; 3259277487Skib bool ret = true; 3260277487Skib 3261277487Skib mtx_lock(&mchdev_lock); 3262277487Skib if (!i915_mch_dev) { 3263277487Skib ret = false; 3264277487Skib goto out_unlock; 3265277487Skib } 3266277487Skib dev_priv = i915_mch_dev; 3267277487Skib 3268296548Sdumbbell if (dev_priv->ips.max_delay < dev_priv->ips.min_delay) 3269296548Sdumbbell dev_priv->ips.max_delay++; 3270277487Skib 3271277487Skibout_unlock: 3272277487Skib mtx_unlock(&mchdev_lock); 3273277487Skib 3274277487Skib return ret; 3275277487Skib} 3276296548SdumbbellEXPORT_SYMBOL_GPL(i915_gpu_lower); 3277277487Skib 3278277487Skib/** 3279277487Skib * i915_gpu_busy - indicate GPU business to IPS 3280277487Skib * 3281277487Skib * Tell the IPS driver whether or not the GPU is busy. 3282277487Skib */ 3283277487Skibbool i915_gpu_busy(void) 3284277487Skib{ 3285277487Skib struct drm_i915_private *dev_priv; 3286296548Sdumbbell struct intel_ring_buffer *ring; 3287277487Skib bool ret = false; 3288296548Sdumbbell int i; 3289277487Skib 3290277487Skib mtx_lock(&mchdev_lock); 3291277487Skib if (!i915_mch_dev) 3292277487Skib goto out_unlock; 3293277487Skib dev_priv = i915_mch_dev; 3294277487Skib 3295296548Sdumbbell for_each_ring(ring, dev_priv, i) 3296296548Sdumbbell ret |= !list_empty(&ring->request_list); 3297277487Skib 3298277487Skibout_unlock: 3299277487Skib mtx_unlock(&mchdev_lock); 3300277487Skib 3301277487Skib return ret; 3302277487Skib} 3303296548SdumbbellEXPORT_SYMBOL_GPL(i915_gpu_busy); 3304277487Skib 3305277487Skib/** 3306277487Skib * i915_gpu_turbo_disable - disable graphics turbo 3307277487Skib * 3308277487Skib * Disable graphics turbo by resetting the max frequency and setting the 3309277487Skib * current frequency to the default. 3310277487Skib */ 3311277487Skibbool i915_gpu_turbo_disable(void) 3312277487Skib{ 3313277487Skib struct drm_i915_private *dev_priv; 3314277487Skib bool ret = true; 3315277487Skib 3316277487Skib mtx_lock(&mchdev_lock); 3317277487Skib if (!i915_mch_dev) { 3318277487Skib ret = false; 3319277487Skib goto out_unlock; 3320277487Skib } 3321277487Skib dev_priv = i915_mch_dev; 3322277487Skib 3323296548Sdumbbell dev_priv->ips.max_delay = dev_priv->ips.fstart; 3324277487Skib 3325296548Sdumbbell if (!ironlake_set_drps(dev_priv->dev, dev_priv->ips.fstart)) 3326277487Skib ret = false; 3327277487Skib 3328277487Skibout_unlock: 3329277487Skib mtx_unlock(&mchdev_lock); 3330277487Skib 3331277487Skib return ret; 3332277487Skib} 3333296548SdumbbellEXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); 3334277487Skib 3335296548Sdumbbell#ifdef FREEBSD_WIP 3336296548Sdumbbell/** 3337296548Sdumbbell * Tells the intel_ips driver that the i915 driver is now loaded, if 3338296548Sdumbbell * IPS got loaded first. 3339296548Sdumbbell * 3340296548Sdumbbell * This awkward dance is so that neither module has to depend on the 3341296548Sdumbbell * other in order for IPS to do the appropriate communication of 3342296548Sdumbbell * GPU turbo limits to i915. 3343296548Sdumbbell */ 3344296548Sdumbbellstatic void 3345296548Sdumbbellips_ping_for_i915_load(void) 3346296548Sdumbbell{ 3347296548Sdumbbell void (*link)(void); 3348296548Sdumbbell 3349296548Sdumbbell link = symbol_get(ips_link_to_i915_driver); 3350296548Sdumbbell if (link) { 3351296548Sdumbbell link(); 3352296548Sdumbbell symbol_put(ips_link_to_i915_driver); 3353296548Sdumbbell } 3354296548Sdumbbell} 3355296548Sdumbbell#endif /* FREEBSD_WIP */ 3356296548Sdumbbell 3357277487Skibvoid intel_gpu_ips_init(struct drm_i915_private *dev_priv) 3358277487Skib{ 3359296548Sdumbbell /* We only register the i915 ips part with intel-ips once everything is 3360296548Sdumbbell * set up, to avoid intel-ips sneaking in and reading bogus values. */ 3361277487Skib mtx_lock(&mchdev_lock); 3362277487Skib i915_mch_dev = dev_priv; 3363277487Skib mtx_unlock(&mchdev_lock); 3364277487Skib 3365296548Sdumbbell#ifdef FREEBSD_WIP 3366277487Skib ips_ping_for_i915_load(); 3367296548Sdumbbell#endif /* FREEBSD_WIP */ 3368277487Skib} 3369277487Skib 3370277487Skibvoid intel_gpu_ips_teardown(void) 3371277487Skib{ 3372277487Skib mtx_lock(&mchdev_lock); 3373277487Skib i915_mch_dev = NULL; 3374277487Skib mtx_unlock(&mchdev_lock); 3375277487Skib} 3376296548Sdumbbellstatic void intel_init_emon(struct drm_device *dev) 3377277487Skib{ 3378277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 3379277487Skib u32 lcfuse; 3380277487Skib u8 pxw[16]; 3381277487Skib int i; 3382277487Skib 3383277487Skib /* Disable to program */ 3384277487Skib I915_WRITE(ECR, 0); 3385277487Skib POSTING_READ(ECR); 3386277487Skib 3387277487Skib /* Program energy weights for various events */ 3388277487Skib I915_WRITE(SDEW, 0x15040d00); 3389277487Skib I915_WRITE(CSIEW0, 0x007f0000); 3390277487Skib I915_WRITE(CSIEW1, 0x1e220004); 3391277487Skib I915_WRITE(CSIEW2, 0x04000004); 3392277487Skib 3393277487Skib for (i = 0; i < 5; i++) 3394277487Skib I915_WRITE(PEW + (i * 4), 0); 3395277487Skib for (i = 0; i < 3; i++) 3396277487Skib I915_WRITE(DEW + (i * 4), 0); 3397277487Skib 3398277487Skib /* Program P-state weights to account for frequency power adjustment */ 3399277487Skib for (i = 0; i < 16; i++) { 3400277487Skib u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4)); 3401277487Skib unsigned long freq = intel_pxfreq(pxvidfreq); 3402277487Skib unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >> 3403277487Skib PXVFREQ_PX_SHIFT; 3404277487Skib unsigned long val; 3405277487Skib 3406277487Skib val = vid * vid; 3407277487Skib val *= (freq / 1000); 3408277487Skib val *= 255; 3409277487Skib val /= (127*127*900); 3410277487Skib if (val > 0xff) 3411277487Skib DRM_ERROR("bad pxval: %ld\n", val); 3412277487Skib pxw[i] = val; 3413277487Skib } 3414277487Skib /* Render standby states get 0 weight */ 3415277487Skib pxw[14] = 0; 3416277487Skib pxw[15] = 0; 3417277487Skib 3418277487Skib for (i = 0; i < 4; i++) { 3419277487Skib u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) | 3420277487Skib (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]); 3421277487Skib I915_WRITE(PXW + (i * 4), val); 3422277487Skib } 3423277487Skib 3424277487Skib /* Adjust magic regs to magic values (more experimental results) */ 3425277487Skib I915_WRITE(OGW0, 0); 3426277487Skib I915_WRITE(OGW1, 0); 3427277487Skib I915_WRITE(EG0, 0x00007f00); 3428277487Skib I915_WRITE(EG1, 0x0000000e); 3429277487Skib I915_WRITE(EG2, 0x000e0000); 3430277487Skib I915_WRITE(EG3, 0x68000300); 3431277487Skib I915_WRITE(EG4, 0x42000000); 3432277487Skib I915_WRITE(EG5, 0x00140031); 3433277487Skib I915_WRITE(EG6, 0); 3434277487Skib I915_WRITE(EG7, 0); 3435277487Skib 3436277487Skib for (i = 0; i < 8; i++) 3437277487Skib I915_WRITE(PXWL + (i * 4), 0); 3438277487Skib 3439277487Skib /* Enable PMON + select events */ 3440277487Skib I915_WRITE(ECR, 0x80000019); 3441277487Skib 3442277487Skib lcfuse = I915_READ(LCFUSE02); 3443277487Skib 3444296548Sdumbbell dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK); 3445277487Skib} 3446277487Skib 3447296548Sdumbbellvoid intel_disable_gt_powersave(struct drm_device *dev) 3448296548Sdumbbell{ 3449296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 3450296548Sdumbbell 3451296548Sdumbbell if (IS_IRONLAKE_M(dev)) { 3452296548Sdumbbell ironlake_disable_drps(dev); 3453296548Sdumbbell ironlake_disable_rc6(dev); 3454296548Sdumbbell } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) { 3455296548Sdumbbell taskqueue_cancel_timeout(dev_priv->wq, &dev_priv->rps.delayed_resume_work, NULL); 3456296548Sdumbbell sx_xlock(&dev_priv->rps.hw_lock); 3457296548Sdumbbell gen6_disable_rps(dev); 3458296548Sdumbbell sx_xunlock(&dev_priv->rps.hw_lock); 3459296548Sdumbbell } 3460296548Sdumbbell} 3461296548Sdumbbell 3462296548Sdumbbellstatic void intel_gen6_powersave_work(void *arg, int pending) 3463296548Sdumbbell{ 3464296548Sdumbbell struct drm_i915_private *dev_priv = arg; 3465296548Sdumbbell struct drm_device *dev = dev_priv->dev; 3466296548Sdumbbell 3467296548Sdumbbell sx_xlock(&dev_priv->rps.hw_lock); 3468296548Sdumbbell gen6_enable_rps(dev); 3469296548Sdumbbell gen6_update_ring_freq(dev); 3470296548Sdumbbell sx_xunlock(&dev_priv->rps.hw_lock); 3471296548Sdumbbell} 3472296548Sdumbbell 3473296548Sdumbbellvoid intel_enable_gt_powersave(struct drm_device *dev) 3474296548Sdumbbell{ 3475296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 3476296548Sdumbbell 3477296548Sdumbbell if (IS_IRONLAKE_M(dev)) { 3478296548Sdumbbell ironlake_enable_drps(dev); 3479296548Sdumbbell ironlake_enable_rc6(dev); 3480296548Sdumbbell intel_init_emon(dev); 3481296548Sdumbbell } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { 3482296548Sdumbbell /* 3483296548Sdumbbell * PCU communication is slow and this doesn't need to be 3484296548Sdumbbell * done at any specific time, so do this out of our fast path 3485296548Sdumbbell * to make resume and init faster. 3486296548Sdumbbell */ 3487296548Sdumbbell taskqueue_enqueue_timeout(dev_priv->wq, &dev_priv->rps.delayed_resume_work, 3488296548Sdumbbell round_jiffies_up_relative(HZ)); 3489296548Sdumbbell } 3490296548Sdumbbell} 3491296548Sdumbbell 3492290228Sdumbbellstatic void ibx_init_clock_gating(struct drm_device *dev) 3493290228Sdumbbell{ 3494290228Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 3495290228Sdumbbell 3496290228Sdumbbell /* 3497290228Sdumbbell * On Ibex Peak and Cougar Point, we need to disable clock 3498290228Sdumbbell * gating for the panel power sequencer or it will fail to 3499290228Sdumbbell * start up when no ports are active. 3500290228Sdumbbell */ 3501290228Sdumbbell I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); 3502290228Sdumbbell} 3503290228Sdumbbell 3504277487Skibstatic void ironlake_init_clock_gating(struct drm_device *dev) 3505277487Skib{ 3506277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 3507296548Sdumbbell uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; 3508277487Skib 3509277487Skib /* Required for FBC */ 3510296548Sdumbbell dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE | 3511296548Sdumbbell ILK_DPFCUNIT_CLOCK_GATE_DISABLE | 3512296548Sdumbbell ILK_DPFDUNIT_CLOCK_GATE_ENABLE; 3513277487Skib 3514277487Skib I915_WRITE(PCH_3DCGDIS0, 3515277487Skib MARIUNIT_CLOCK_GATE_DISABLE | 3516277487Skib SVSMUNIT_CLOCK_GATE_DISABLE); 3517277487Skib I915_WRITE(PCH_3DCGDIS1, 3518277487Skib VFMUNIT_CLOCK_GATE_DISABLE); 3519277487Skib 3520277487Skib /* 3521277487Skib * According to the spec the following bits should be set in 3522277487Skib * order to enable memory self-refresh 3523277487Skib * The bit 22/21 of 0x42004 3524277487Skib * The bit 5 of 0x42020 3525277487Skib * The bit 15 of 0x45000 3526277487Skib */ 3527277487Skib I915_WRITE(ILK_DISPLAY_CHICKEN2, 3528277487Skib (I915_READ(ILK_DISPLAY_CHICKEN2) | 3529277487Skib ILK_DPARB_GATE | ILK_VSDPFD_FULL)); 3530296548Sdumbbell dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE; 3531277487Skib I915_WRITE(DISP_ARB_CTL, 3532277487Skib (I915_READ(DISP_ARB_CTL) | 3533277487Skib DISP_FBC_WM_DIS)); 3534277487Skib I915_WRITE(WM3_LP_ILK, 0); 3535277487Skib I915_WRITE(WM2_LP_ILK, 0); 3536277487Skib I915_WRITE(WM1_LP_ILK, 0); 3537277487Skib 3538277487Skib /* 3539277487Skib * Based on the document from hardware guys the following bits 3540277487Skib * should be set unconditionally in order to enable FBC. 3541277487Skib * The bit 22 of 0x42000 3542277487Skib * The bit 22 of 0x42004 3543277487Skib * The bit 7,8,9 of 0x42020. 3544277487Skib */ 3545277487Skib if (IS_IRONLAKE_M(dev)) { 3546277487Skib I915_WRITE(ILK_DISPLAY_CHICKEN1, 3547277487Skib I915_READ(ILK_DISPLAY_CHICKEN1) | 3548277487Skib ILK_FBCQ_DIS); 3549277487Skib I915_WRITE(ILK_DISPLAY_CHICKEN2, 3550277487Skib I915_READ(ILK_DISPLAY_CHICKEN2) | 3551277487Skib ILK_DPARB_GATE); 3552277487Skib } 3553277487Skib 3554296548Sdumbbell I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate); 3555296548Sdumbbell 3556277487Skib I915_WRITE(ILK_DISPLAY_CHICKEN2, 3557277487Skib I915_READ(ILK_DISPLAY_CHICKEN2) | 3558277487Skib ILK_ELPIN_409_SELECT); 3559277487Skib I915_WRITE(_3D_CHICKEN2, 3560277487Skib _3D_CHICKEN2_WM_READ_PIPELINED << 16 | 3561277487Skib _3D_CHICKEN2_WM_READ_PIPELINED); 3562296548Sdumbbell 3563296548Sdumbbell /* WaDisableRenderCachePipelinedFlush */ 3564296548Sdumbbell I915_WRITE(CACHE_MODE_0, 3565296548Sdumbbell _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE)); 3566296548Sdumbbell 3567296548Sdumbbell ibx_init_clock_gating(dev); 3568277487Skib} 3569277487Skib 3570290228Sdumbbellstatic void cpt_init_clock_gating(struct drm_device *dev) 3571290228Sdumbbell{ 3572290228Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 3573290228Sdumbbell int pipe; 3574296548Sdumbbell uint32_t val; 3575290228Sdumbbell 3576290228Sdumbbell /* 3577290228Sdumbbell * On Ibex Peak and Cougar Point, we need to disable clock 3578290228Sdumbbell * gating for the panel power sequencer or it will fail to 3579290228Sdumbbell * start up when no ports are active. 3580290228Sdumbbell */ 3581290228Sdumbbell I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); 3582290228Sdumbbell I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) | 3583290228Sdumbbell DPLS_EDP_PPS_FIX_DIS); 3584296548Sdumbbell /* The below fixes the weird display corruption, a few pixels shifted 3585296548Sdumbbell * downward, on (only) LVDS of some HP laptops with IVY. 3586296548Sdumbbell */ 3587296548Sdumbbell for_each_pipe(pipe) { 3588296548Sdumbbell val = TRANS_CHICKEN2_TIMING_OVERRIDE; 3589296548Sdumbbell if (dev_priv->fdi_rx_polarity_inverted) 3590296548Sdumbbell val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED; 3591296548Sdumbbell I915_WRITE(TRANS_CHICKEN2(pipe), val); 3592296548Sdumbbell } 3593296548Sdumbbell /* WADP0ClockGatingDisable */ 3594296548Sdumbbell for_each_pipe(pipe) { 3595296548Sdumbbell I915_WRITE(TRANS_CHICKEN1(pipe), 3596296548Sdumbbell TRANS_CHICKEN1_DP0UNIT_GC_DISABLE); 3597296548Sdumbbell } 3598290228Sdumbbell} 3599290228Sdumbbell 3600277487Skibstatic void gen6_init_clock_gating(struct drm_device *dev) 3601277487Skib{ 3602277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 3603277487Skib int pipe; 3604296548Sdumbbell uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; 3605277487Skib 3606296548Sdumbbell I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate); 3607277487Skib 3608277487Skib I915_WRITE(ILK_DISPLAY_CHICKEN2, 3609277487Skib I915_READ(ILK_DISPLAY_CHICKEN2) | 3610277487Skib ILK_ELPIN_409_SELECT); 3611277487Skib 3612296548Sdumbbell /* WaDisableHiZPlanesWhenMSAAEnabled */ 3613296548Sdumbbell I915_WRITE(_3D_CHICKEN, 3614296548Sdumbbell _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB)); 3615296548Sdumbbell 3616296548Sdumbbell /* WaSetupGtModeTdRowDispatch */ 3617296548Sdumbbell if (IS_SNB_GT1(dev)) 3618296548Sdumbbell I915_WRITE(GEN6_GT_MODE, 3619296548Sdumbbell _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE)); 3620296548Sdumbbell 3621277487Skib I915_WRITE(WM3_LP_ILK, 0); 3622277487Skib I915_WRITE(WM2_LP_ILK, 0); 3623277487Skib I915_WRITE(WM1_LP_ILK, 0); 3624277487Skib 3625277487Skib I915_WRITE(CACHE_MODE_0, 3626277487Skib _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); 3627277487Skib 3628277487Skib I915_WRITE(GEN6_UCGCTL1, 3629277487Skib I915_READ(GEN6_UCGCTL1) | 3630277487Skib GEN6_BLBUNIT_CLOCK_GATE_DISABLE | 3631277487Skib GEN6_CSUNIT_CLOCK_GATE_DISABLE); 3632277487Skib 3633277487Skib /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock 3634277487Skib * gating disable must be set. Failure to set it results in 3635277487Skib * flickering pixels due to Z write ordering failures after 3636277487Skib * some amount of runtime in the Mesa "fire" demo, and Unigine 3637277487Skib * Sanctuary and Tropics, and apparently anything else with 3638277487Skib * alpha test or pixel discard. 3639277487Skib * 3640277487Skib * According to the spec, bit 11 (RCCUNIT) must also be set, 3641277487Skib * but we didn't debug actual testcases to find it out. 3642296548Sdumbbell * 3643296548Sdumbbell * Also apply WaDisableVDSUnitClockGating and 3644296548Sdumbbell * WaDisableRCPBUnitClockGating. 3645277487Skib */ 3646277487Skib I915_WRITE(GEN6_UCGCTL2, 3647296548Sdumbbell GEN7_VDSUNIT_CLOCK_GATE_DISABLE | 3648277487Skib GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | 3649277487Skib GEN6_RCCUNIT_CLOCK_GATE_DISABLE); 3650277487Skib 3651277487Skib /* Bspec says we need to always set all mask bits. */ 3652296548Sdumbbell I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) | 3653287171Sbapt _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL); 3654277487Skib 3655277487Skib /* 3656277487Skib * According to the spec the following bits should be 3657277487Skib * set in order to enable memory self-refresh and fbc: 3658277487Skib * The bit21 and bit22 of 0x42000 3659277487Skib * The bit21 and bit22 of 0x42004 3660277487Skib * The bit5 and bit7 of 0x42020 3661277487Skib * The bit14 of 0x70180 3662277487Skib * The bit14 of 0x71180 3663277487Skib */ 3664277487Skib I915_WRITE(ILK_DISPLAY_CHICKEN1, 3665277487Skib I915_READ(ILK_DISPLAY_CHICKEN1) | 3666277487Skib ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); 3667277487Skib I915_WRITE(ILK_DISPLAY_CHICKEN2, 3668277487Skib I915_READ(ILK_DISPLAY_CHICKEN2) | 3669277487Skib ILK_DPARB_GATE | ILK_VSDPFD_FULL); 3670296548Sdumbbell I915_WRITE(ILK_DSPCLK_GATE_D, 3671296548Sdumbbell I915_READ(ILK_DSPCLK_GATE_D) | 3672296548Sdumbbell ILK_DPARBUNIT_CLOCK_GATE_ENABLE | 3673296548Sdumbbell ILK_DPFDUNIT_CLOCK_GATE_ENABLE); 3674277487Skib 3675296548Sdumbbell /* WaMbcDriverBootEnable */ 3676296548Sdumbbell I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | 3677296548Sdumbbell GEN6_MBCTL_ENABLE_BOOT_FETCH); 3678296548Sdumbbell 3679277487Skib for_each_pipe(pipe) { 3680277487Skib I915_WRITE(DSPCNTR(pipe), 3681277487Skib I915_READ(DSPCNTR(pipe)) | 3682277487Skib DISPPLANE_TRICKLE_FEED_DISABLE); 3683277487Skib intel_flush_display_plane(dev_priv, pipe); 3684277487Skib } 3685296548Sdumbbell 3686296548Sdumbbell /* The default value should be 0x200 according to docs, but the two 3687296548Sdumbbell * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */ 3688296548Sdumbbell I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_DISABLE(0xffff)); 3689296548Sdumbbell I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_GT_MODE_HI)); 3690296548Sdumbbell 3691296548Sdumbbell cpt_init_clock_gating(dev); 3692277487Skib} 3693277487Skib 3694277487Skibstatic void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) 3695277487Skib{ 3696277487Skib uint32_t reg = I915_READ(GEN7_FF_THREAD_MODE); 3697277487Skib 3698277487Skib reg &= ~GEN7_FF_SCHED_MASK; 3699277487Skib reg |= GEN7_FF_TS_SCHED_HW; 3700277487Skib reg |= GEN7_FF_VS_SCHED_HW; 3701277487Skib reg |= GEN7_FF_DS_SCHED_HW; 3702277487Skib 3703277487Skib I915_WRITE(GEN7_FF_THREAD_MODE, reg); 3704277487Skib} 3705277487Skib 3706296548Sdumbbellstatic void lpt_init_clock_gating(struct drm_device *dev) 3707277487Skib{ 3708277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 3709296548Sdumbbell 3710296548Sdumbbell /* 3711296548Sdumbbell * TODO: this bit should only be enabled when really needed, then 3712296548Sdumbbell * disabled when not needed anymore in order to save power. 3713296548Sdumbbell */ 3714296548Sdumbbell if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) 3715296548Sdumbbell I915_WRITE(SOUTH_DSPCLK_GATE_D, 3716296548Sdumbbell I915_READ(SOUTH_DSPCLK_GATE_D) | 3717296548Sdumbbell PCH_LP_PARTITION_LEVEL_DISABLE); 3718296548Sdumbbell} 3719296548Sdumbbell 3720296548Sdumbbellstatic void haswell_init_clock_gating(struct drm_device *dev) 3721296548Sdumbbell{ 3722296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 3723277487Skib int pipe; 3724277487Skib 3725277487Skib I915_WRITE(WM3_LP_ILK, 0); 3726277487Skib I915_WRITE(WM2_LP_ILK, 0); 3727277487Skib I915_WRITE(WM1_LP_ILK, 0); 3728277487Skib 3729277487Skib /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. 3730277487Skib * This implements the WaDisableRCZUnitClockGating workaround. 3731277487Skib */ 3732277487Skib I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); 3733277487Skib 3734296548Sdumbbell /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ 3735296548Sdumbbell I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, 3736296548Sdumbbell GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); 3737277487Skib 3738296548Sdumbbell /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ 3739296548Sdumbbell I915_WRITE(GEN7_L3CNTLREG1, 3740296548Sdumbbell GEN7_WA_FOR_GEN7_L3_CONTROL); 3741296548Sdumbbell I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, 3742296548Sdumbbell GEN7_WA_L3_CHICKEN_MODE); 3743296548Sdumbbell 3744296548Sdumbbell /* This is required by WaCatErrorRejectionIssue */ 3745296548Sdumbbell I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, 3746296548Sdumbbell I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | 3747296548Sdumbbell GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); 3748296548Sdumbbell 3749296548Sdumbbell for_each_pipe(pipe) { 3750296548Sdumbbell I915_WRITE(DSPCNTR(pipe), 3751296548Sdumbbell I915_READ(DSPCNTR(pipe)) | 3752296548Sdumbbell DISPPLANE_TRICKLE_FEED_DISABLE); 3753296548Sdumbbell intel_flush_display_plane(dev_priv, pipe); 3754296548Sdumbbell } 3755296548Sdumbbell 3756296548Sdumbbell gen7_setup_fixed_func_scheduler(dev_priv); 3757296548Sdumbbell 3758296548Sdumbbell /* WaDisable4x2SubspanOptimization */ 3759296548Sdumbbell I915_WRITE(CACHE_MODE_1, 3760296548Sdumbbell _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); 3761296548Sdumbbell 3762296548Sdumbbell /* WaMbcDriverBootEnable */ 3763296548Sdumbbell I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | 3764296548Sdumbbell GEN6_MBCTL_ENABLE_BOOT_FETCH); 3765296548Sdumbbell 3766296548Sdumbbell /* XXX: This is a workaround for early silicon revisions and should be 3767296548Sdumbbell * removed later. 3768296548Sdumbbell */ 3769296548Sdumbbell I915_WRITE(WM_DBG, 3770296548Sdumbbell I915_READ(WM_DBG) | 3771296548Sdumbbell WM_DBG_DISALLOW_MULTIPLE_LP | 3772296548Sdumbbell WM_DBG_DISALLOW_SPRITE | 3773296548Sdumbbell WM_DBG_DISALLOW_MAXFIFO); 3774296548Sdumbbell 3775296548Sdumbbell lpt_init_clock_gating(dev); 3776296548Sdumbbell} 3777296548Sdumbbell 3778296548Sdumbbellstatic void ivybridge_init_clock_gating(struct drm_device *dev) 3779296548Sdumbbell{ 3780296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 3781296548Sdumbbell int pipe; 3782296548Sdumbbell uint32_t snpcr; 3783296548Sdumbbell 3784296548Sdumbbell I915_WRITE(WM3_LP_ILK, 0); 3785296548Sdumbbell I915_WRITE(WM2_LP_ILK, 0); 3786296548Sdumbbell I915_WRITE(WM1_LP_ILK, 0); 3787296548Sdumbbell 3788296548Sdumbbell I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); 3789296548Sdumbbell 3790296548Sdumbbell /* WaDisableEarlyCull */ 3791296548Sdumbbell I915_WRITE(_3D_CHICKEN3, 3792296548Sdumbbell _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL)); 3793296548Sdumbbell 3794296548Sdumbbell /* WaDisableBackToBackFlipFix */ 3795277487Skib I915_WRITE(IVB_CHICKEN3, 3796277487Skib CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | 3797277487Skib CHICKEN3_DGMG_DONE_FIX_DISABLE); 3798277487Skib 3799296548Sdumbbell /* WaDisablePSDDualDispatchEnable */ 3800296548Sdumbbell if (IS_IVB_GT1(dev)) 3801296548Sdumbbell I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, 3802296548Sdumbbell _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); 3803296548Sdumbbell else 3804296548Sdumbbell I915_WRITE(GEN7_HALF_SLICE_CHICKEN1_GT2, 3805296548Sdumbbell _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); 3806296548Sdumbbell 3807277487Skib /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ 3808277487Skib I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, 3809277487Skib GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); 3810277487Skib 3811277487Skib /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ 3812277487Skib I915_WRITE(GEN7_L3CNTLREG1, 3813277487Skib GEN7_WA_FOR_GEN7_L3_CONTROL); 3814277487Skib I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, 3815296548Sdumbbell GEN7_WA_L3_CHICKEN_MODE); 3816296548Sdumbbell if (IS_IVB_GT1(dev)) 3817296548Sdumbbell I915_WRITE(GEN7_ROW_CHICKEN2, 3818296548Sdumbbell _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); 3819296548Sdumbbell else 3820296548Sdumbbell I915_WRITE(GEN7_ROW_CHICKEN2_GT2, 3821296548Sdumbbell _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); 3822277487Skib 3823296548Sdumbbell 3824296548Sdumbbell /* WaForceL3Serialization */ 3825296548Sdumbbell I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) & 3826296548Sdumbbell ~L3SQ_URB_READ_CAM_MATCH_DISABLE); 3827296548Sdumbbell 3828296548Sdumbbell /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock 3829296548Sdumbbell * gating disable must be set. Failure to set it results in 3830296548Sdumbbell * flickering pixels due to Z write ordering failures after 3831296548Sdumbbell * some amount of runtime in the Mesa "fire" demo, and Unigine 3832296548Sdumbbell * Sanctuary and Tropics, and apparently anything else with 3833296548Sdumbbell * alpha test or pixel discard. 3834296548Sdumbbell * 3835296548Sdumbbell * According to the spec, bit 11 (RCCUNIT) must also be set, 3836296548Sdumbbell * but we didn't debug actual testcases to find it out. 3837296548Sdumbbell * 3838296548Sdumbbell * According to the spec, bit 13 (RCZUNIT) must be set on IVB. 3839296548Sdumbbell * This implements the WaDisableRCZUnitClockGating workaround. 3840296548Sdumbbell */ 3841296548Sdumbbell I915_WRITE(GEN6_UCGCTL2, 3842296548Sdumbbell GEN6_RCZUNIT_CLOCK_GATE_DISABLE | 3843296548Sdumbbell GEN6_RCCUNIT_CLOCK_GATE_DISABLE); 3844296548Sdumbbell 3845277487Skib /* This is required by WaCatErrorRejectionIssue */ 3846277487Skib I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, 3847277487Skib I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | 3848277487Skib GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); 3849277487Skib 3850277487Skib for_each_pipe(pipe) { 3851277487Skib I915_WRITE(DSPCNTR(pipe), 3852277487Skib I915_READ(DSPCNTR(pipe)) | 3853277487Skib DISPPLANE_TRICKLE_FEED_DISABLE); 3854277487Skib intel_flush_display_plane(dev_priv, pipe); 3855277487Skib } 3856277487Skib 3857296548Sdumbbell /* WaMbcDriverBootEnable */ 3858296548Sdumbbell I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | 3859296548Sdumbbell GEN6_MBCTL_ENABLE_BOOT_FETCH); 3860296548Sdumbbell 3861277487Skib gen7_setup_fixed_func_scheduler(dev_priv); 3862277487Skib 3863277487Skib /* WaDisable4x2SubspanOptimization */ 3864277487Skib I915_WRITE(CACHE_MODE_1, 3865277487Skib _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); 3866296548Sdumbbell 3867296548Sdumbbell snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); 3868296548Sdumbbell snpcr &= ~GEN6_MBC_SNPCR_MASK; 3869296548Sdumbbell snpcr |= GEN6_MBC_SNPCR_MED; 3870296548Sdumbbell I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); 3871296548Sdumbbell 3872296548Sdumbbell cpt_init_clock_gating(dev); 3873277487Skib} 3874277487Skib 3875277487Skibstatic void valleyview_init_clock_gating(struct drm_device *dev) 3876277487Skib{ 3877277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 3878277487Skib int pipe; 3879277487Skib 3880277487Skib I915_WRITE(WM3_LP_ILK, 0); 3881277487Skib I915_WRITE(WM2_LP_ILK, 0); 3882277487Skib I915_WRITE(WM1_LP_ILK, 0); 3883277487Skib 3884296548Sdumbbell I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); 3885277487Skib 3886296548Sdumbbell /* WaDisableEarlyCull */ 3887296548Sdumbbell I915_WRITE(_3D_CHICKEN3, 3888296548Sdumbbell _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL)); 3889277487Skib 3890296548Sdumbbell /* WaDisableBackToBackFlipFix */ 3891277487Skib I915_WRITE(IVB_CHICKEN3, 3892277487Skib CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | 3893277487Skib CHICKEN3_DGMG_DONE_FIX_DISABLE); 3894277487Skib 3895296548Sdumbbell I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, 3896296548Sdumbbell _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); 3897296548Sdumbbell 3898277487Skib /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ 3899277487Skib I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, 3900277487Skib GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); 3901277487Skib 3902277487Skib /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ 3903296548Sdumbbell I915_WRITE(GEN7_L3CNTLREG1, I915_READ(GEN7_L3CNTLREG1) | GEN7_L3AGDIS); 3904277487Skib I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE); 3905277487Skib 3906296548Sdumbbell /* WaForceL3Serialization */ 3907296548Sdumbbell I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) & 3908296548Sdumbbell ~L3SQ_URB_READ_CAM_MATCH_DISABLE); 3909296548Sdumbbell 3910296548Sdumbbell /* WaDisableDopClockGating */ 3911296548Sdumbbell I915_WRITE(GEN7_ROW_CHICKEN2, 3912296548Sdumbbell _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); 3913296548Sdumbbell 3914296548Sdumbbell /* WaForceL3Serialization */ 3915296548Sdumbbell I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) & 3916296548Sdumbbell ~L3SQ_URB_READ_CAM_MATCH_DISABLE); 3917296548Sdumbbell 3918277487Skib /* This is required by WaCatErrorRejectionIssue */ 3919277487Skib I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, 3920277487Skib I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | 3921277487Skib GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); 3922277487Skib 3923296548Sdumbbell /* WaMbcDriverBootEnable */ 3924296548Sdumbbell I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | 3925296548Sdumbbell GEN6_MBCTL_ENABLE_BOOT_FETCH); 3926296548Sdumbbell 3927296548Sdumbbell 3928296548Sdumbbell /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock 3929296548Sdumbbell * gating disable must be set. Failure to set it results in 3930296548Sdumbbell * flickering pixels due to Z write ordering failures after 3931296548Sdumbbell * some amount of runtime in the Mesa "fire" demo, and Unigine 3932296548Sdumbbell * Sanctuary and Tropics, and apparently anything else with 3933296548Sdumbbell * alpha test or pixel discard. 3934296548Sdumbbell * 3935296548Sdumbbell * According to the spec, bit 11 (RCCUNIT) must also be set, 3936296548Sdumbbell * but we didn't debug actual testcases to find it out. 3937296548Sdumbbell * 3938296548Sdumbbell * According to the spec, bit 13 (RCZUNIT) must be set on IVB. 3939296548Sdumbbell * This implements the WaDisableRCZUnitClockGating workaround. 3940296548Sdumbbell * 3941296548Sdumbbell * Also apply WaDisableVDSUnitClockGating and 3942296548Sdumbbell * WaDisableRCPBUnitClockGating. 3943296548Sdumbbell */ 3944296548Sdumbbell I915_WRITE(GEN6_UCGCTL2, 3945296548Sdumbbell GEN7_VDSUNIT_CLOCK_GATE_DISABLE | 3946296548Sdumbbell GEN7_TDLUNIT_CLOCK_GATE_DISABLE | 3947296548Sdumbbell GEN6_RCZUNIT_CLOCK_GATE_DISABLE | 3948296548Sdumbbell GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | 3949296548Sdumbbell GEN6_RCCUNIT_CLOCK_GATE_DISABLE); 3950296548Sdumbbell 3951296548Sdumbbell I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE); 3952296548Sdumbbell 3953277487Skib for_each_pipe(pipe) { 3954277487Skib I915_WRITE(DSPCNTR(pipe), 3955277487Skib I915_READ(DSPCNTR(pipe)) | 3956277487Skib DISPPLANE_TRICKLE_FEED_DISABLE); 3957277487Skib intel_flush_display_plane(dev_priv, pipe); 3958277487Skib } 3959277487Skib 3960277487Skib I915_WRITE(CACHE_MODE_1, 3961277487Skib _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); 3962296548Sdumbbell 3963296548Sdumbbell /* 3964296548Sdumbbell * On ValleyView, the GUnit needs to signal the GT 3965296548Sdumbbell * when flip and other events complete. So enable 3966296548Sdumbbell * all the GUnit->GT interrupts here 3967296548Sdumbbell */ 3968296548Sdumbbell I915_WRITE(VLV_DPFLIPSTAT, PIPEB_LINE_COMPARE_INT_EN | 3969296548Sdumbbell PIPEB_HLINE_INT_EN | PIPEB_VBLANK_INT_EN | 3970296548Sdumbbell SPRITED_FLIPDONE_INT_EN | SPRITEC_FLIPDONE_INT_EN | 3971296548Sdumbbell PLANEB_FLIPDONE_INT_EN | PIPEA_LINE_COMPARE_INT_EN | 3972296548Sdumbbell PIPEA_HLINE_INT_EN | PIPEA_VBLANK_INT_EN | 3973296548Sdumbbell SPRITEB_FLIPDONE_INT_EN | SPRITEA_FLIPDONE_INT_EN | 3974296548Sdumbbell PLANEA_FLIPDONE_INT_EN); 3975296548Sdumbbell 3976296548Sdumbbell /* 3977296548Sdumbbell * WaDisableVLVClockGating_VBIIssue 3978296548Sdumbbell * Disable clock gating on th GCFG unit to prevent a delay 3979296548Sdumbbell * in the reporting of vblank events. 3980296548Sdumbbell */ 3981296548Sdumbbell I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS); 3982277487Skib} 3983277487Skib 3984277487Skibstatic void g4x_init_clock_gating(struct drm_device *dev) 3985277487Skib{ 3986277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 3987277487Skib uint32_t dspclk_gate; 3988277487Skib 3989277487Skib I915_WRITE(RENCLK_GATE_D1, 0); 3990277487Skib I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | 3991277487Skib GS_UNIT_CLOCK_GATE_DISABLE | 3992277487Skib CL_UNIT_CLOCK_GATE_DISABLE); 3993277487Skib I915_WRITE(RAMCLK_GATE_D, 0); 3994277487Skib dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | 3995277487Skib OVRUNIT_CLOCK_GATE_DISABLE | 3996277487Skib OVCUNIT_CLOCK_GATE_DISABLE; 3997277487Skib if (IS_GM45(dev)) 3998277487Skib dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; 3999277487Skib I915_WRITE(DSPCLK_GATE_D, dspclk_gate); 4000296548Sdumbbell 4001296548Sdumbbell /* WaDisableRenderCachePipelinedFlush */ 4002296548Sdumbbell I915_WRITE(CACHE_MODE_0, 4003296548Sdumbbell _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE)); 4004277487Skib} 4005277487Skib 4006277487Skibstatic void crestline_init_clock_gating(struct drm_device *dev) 4007277487Skib{ 4008277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 4009277487Skib 4010277487Skib I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); 4011277487Skib I915_WRITE(RENCLK_GATE_D2, 0); 4012277487Skib I915_WRITE(DSPCLK_GATE_D, 0); 4013277487Skib I915_WRITE(RAMCLK_GATE_D, 0); 4014277487Skib I915_WRITE16(DEUC, 0); 4015277487Skib} 4016277487Skib 4017277487Skibstatic void broadwater_init_clock_gating(struct drm_device *dev) 4018277487Skib{ 4019277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 4020277487Skib 4021277487Skib I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | 4022277487Skib I965_RCC_CLOCK_GATE_DISABLE | 4023277487Skib I965_RCPB_CLOCK_GATE_DISABLE | 4024277487Skib I965_ISC_CLOCK_GATE_DISABLE | 4025277487Skib I965_FBC_CLOCK_GATE_DISABLE); 4026277487Skib I915_WRITE(RENCLK_GATE_D2, 0); 4027277487Skib} 4028277487Skib 4029277487Skibstatic void gen3_init_clock_gating(struct drm_device *dev) 4030277487Skib{ 4031277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 4032277487Skib u32 dstate = I915_READ(D_STATE); 4033277487Skib 4034277487Skib dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | 4035277487Skib DSTATE_DOT_CLOCK_GATING; 4036277487Skib I915_WRITE(D_STATE, dstate); 4037277487Skib 4038277487Skib if (IS_PINEVIEW(dev)) 4039277487Skib I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); 4040296548Sdumbbell 4041296548Sdumbbell /* IIR "flip pending" means done if this bit is set */ 4042296548Sdumbbell I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); 4043277487Skib} 4044277487Skib 4045277487Skibstatic void i85x_init_clock_gating(struct drm_device *dev) 4046277487Skib{ 4047277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 4048277487Skib 4049277487Skib I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); 4050277487Skib} 4051277487Skib 4052277487Skibstatic void i830_init_clock_gating(struct drm_device *dev) 4053277487Skib{ 4054277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 4055277487Skib 4056277487Skib I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); 4057277487Skib} 4058277487Skib 4059277487Skibvoid intel_init_clock_gating(struct drm_device *dev) 4060277487Skib{ 4061277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 4062277487Skib 4063277487Skib dev_priv->display.init_clock_gating(dev); 4064277487Skib} 4065277487Skib 4066277487Skib/* Starting with Haswell, we have different power wells for 4067277487Skib * different parts of the GPU. This attempts to enable them all. 4068277487Skib */ 4069296548Sdumbbellvoid intel_init_power_wells(struct drm_device *dev) 4070277487Skib{ 4071277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 4072277487Skib unsigned long power_wells[] = { 4073277487Skib HSW_PWR_WELL_CTL1, 4074277487Skib HSW_PWR_WELL_CTL2, 4075277487Skib HSW_PWR_WELL_CTL4 4076277487Skib }; 4077277487Skib int i; 4078277487Skib 4079277487Skib if (!IS_HASWELL(dev)) 4080277487Skib return; 4081277487Skib 4082277487Skib DRM_LOCK(dev); 4083277487Skib 4084296548Sdumbbell for (i = 0; i < ARRAY_SIZE(power_wells); i++) { 4085277487Skib int well = I915_READ(power_wells[i]); 4086277487Skib 4087277487Skib if ((well & HSW_PWR_WELL_STATE) == 0) { 4088277487Skib I915_WRITE(power_wells[i], well & HSW_PWR_WELL_ENABLE); 4089296548Sdumbbell if (wait_for((I915_READ(power_wells[i]) & HSW_PWR_WELL_STATE), 20)) 4090277487Skib DRM_ERROR("Error enabling power well %lx\n", power_wells[i]); 4091277487Skib } 4092277487Skib } 4093277487Skib 4094277487Skib DRM_UNLOCK(dev); 4095277487Skib} 4096277487Skib 4097277487Skib/* Set up chip specific power management-related functions */ 4098277487Skibvoid intel_init_pm(struct drm_device *dev) 4099277487Skib{ 4100277487Skib struct drm_i915_private *dev_priv = dev->dev_private; 4101277487Skib 4102277487Skib if (I915_HAS_FBC(dev)) { 4103277487Skib if (HAS_PCH_SPLIT(dev)) { 4104277487Skib dev_priv->display.fbc_enabled = ironlake_fbc_enabled; 4105277487Skib dev_priv->display.enable_fbc = ironlake_enable_fbc; 4106277487Skib dev_priv->display.disable_fbc = ironlake_disable_fbc; 4107277487Skib } else if (IS_GM45(dev)) { 4108277487Skib dev_priv->display.fbc_enabled = g4x_fbc_enabled; 4109277487Skib dev_priv->display.enable_fbc = g4x_enable_fbc; 4110277487Skib dev_priv->display.disable_fbc = g4x_disable_fbc; 4111277487Skib } else if (IS_CRESTLINE(dev)) { 4112277487Skib dev_priv->display.fbc_enabled = i8xx_fbc_enabled; 4113277487Skib dev_priv->display.enable_fbc = i8xx_enable_fbc; 4114277487Skib dev_priv->display.disable_fbc = i8xx_disable_fbc; 4115277487Skib } 4116277487Skib /* 855GM needs testing */ 4117277487Skib } 4118277487Skib 4119277487Skib /* For cxsr */ 4120277487Skib if (IS_PINEVIEW(dev)) 4121277487Skib i915_pineview_get_mem_freq(dev); 4122277487Skib else if (IS_GEN5(dev)) 4123277487Skib i915_ironlake_get_mem_freq(dev); 4124277487Skib 4125277487Skib /* For FIFO watermark updates */ 4126277487Skib if (HAS_PCH_SPLIT(dev)) { 4127277487Skib if (IS_GEN5(dev)) { 4128277487Skib if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK) 4129277487Skib dev_priv->display.update_wm = ironlake_update_wm; 4130277487Skib else { 4131277487Skib DRM_DEBUG_KMS("Failed to get proper latency. " 4132277487Skib "Disable CxSR\n"); 4133277487Skib dev_priv->display.update_wm = NULL; 4134277487Skib } 4135277487Skib dev_priv->display.init_clock_gating = ironlake_init_clock_gating; 4136277487Skib } else if (IS_GEN6(dev)) { 4137277487Skib if (SNB_READ_WM0_LATENCY()) { 4138277487Skib dev_priv->display.update_wm = sandybridge_update_wm; 4139277487Skib dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; 4140277487Skib } else { 4141277487Skib DRM_DEBUG_KMS("Failed to read display plane latency. " 4142277487Skib "Disable CxSR\n"); 4143277487Skib dev_priv->display.update_wm = NULL; 4144277487Skib } 4145277487Skib dev_priv->display.init_clock_gating = gen6_init_clock_gating; 4146277487Skib } else if (IS_IVYBRIDGE(dev)) { 4147277487Skib /* FIXME: detect B0+ stepping and use auto training */ 4148277487Skib if (SNB_READ_WM0_LATENCY()) { 4149296548Sdumbbell dev_priv->display.update_wm = ivybridge_update_wm; 4150277487Skib dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; 4151277487Skib } else { 4152277487Skib DRM_DEBUG_KMS("Failed to read display plane latency. " 4153277487Skib "Disable CxSR\n"); 4154277487Skib dev_priv->display.update_wm = NULL; 4155277487Skib } 4156277487Skib dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; 4157277487Skib } else if (IS_HASWELL(dev)) { 4158277487Skib if (SNB_READ_WM0_LATENCY()) { 4159277487Skib dev_priv->display.update_wm = sandybridge_update_wm; 4160277487Skib dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; 4161277487Skib dev_priv->display.update_linetime_wm = haswell_update_linetime_wm; 4162277487Skib } else { 4163277487Skib DRM_DEBUG_KMS("Failed to read display plane latency. " 4164277487Skib "Disable CxSR\n"); 4165277487Skib dev_priv->display.update_wm = NULL; 4166277487Skib } 4167296548Sdumbbell dev_priv->display.init_clock_gating = haswell_init_clock_gating; 4168277487Skib } else 4169277487Skib dev_priv->display.update_wm = NULL; 4170277487Skib } else if (IS_VALLEYVIEW(dev)) { 4171277487Skib dev_priv->display.update_wm = valleyview_update_wm; 4172277487Skib dev_priv->display.init_clock_gating = 4173277487Skib valleyview_init_clock_gating; 4174277487Skib } else if (IS_PINEVIEW(dev)) { 4175277487Skib if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), 4176277487Skib dev_priv->is_ddr3, 4177277487Skib dev_priv->fsb_freq, 4178277487Skib dev_priv->mem_freq)) { 4179277487Skib DRM_INFO("failed to find known CxSR latency " 4180277487Skib "(found ddr%s fsb freq %d, mem freq %d), " 4181277487Skib "disabling CxSR\n", 4182277487Skib (dev_priv->is_ddr3 == 1) ? "3" : "2", 4183277487Skib dev_priv->fsb_freq, dev_priv->mem_freq); 4184277487Skib /* Disable CxSR and never update its watermark again */ 4185277487Skib pineview_disable_cxsr(dev); 4186277487Skib dev_priv->display.update_wm = NULL; 4187277487Skib } else 4188277487Skib dev_priv->display.update_wm = pineview_update_wm; 4189277487Skib dev_priv->display.init_clock_gating = gen3_init_clock_gating; 4190277487Skib } else if (IS_G4X(dev)) { 4191277487Skib dev_priv->display.update_wm = g4x_update_wm; 4192277487Skib dev_priv->display.init_clock_gating = g4x_init_clock_gating; 4193277487Skib } else if (IS_GEN4(dev)) { 4194277487Skib dev_priv->display.update_wm = i965_update_wm; 4195277487Skib if (IS_CRESTLINE(dev)) 4196277487Skib dev_priv->display.init_clock_gating = crestline_init_clock_gating; 4197277487Skib else if (IS_BROADWATER(dev)) 4198277487Skib dev_priv->display.init_clock_gating = broadwater_init_clock_gating; 4199277487Skib } else if (IS_GEN3(dev)) { 4200277487Skib dev_priv->display.update_wm = i9xx_update_wm; 4201277487Skib dev_priv->display.get_fifo_size = i9xx_get_fifo_size; 4202277487Skib dev_priv->display.init_clock_gating = gen3_init_clock_gating; 4203277487Skib } else if (IS_I865G(dev)) { 4204277487Skib dev_priv->display.update_wm = i830_update_wm; 4205277487Skib dev_priv->display.init_clock_gating = i85x_init_clock_gating; 4206277487Skib dev_priv->display.get_fifo_size = i830_get_fifo_size; 4207277487Skib } else if (IS_I85X(dev)) { 4208277487Skib dev_priv->display.update_wm = i9xx_update_wm; 4209277487Skib dev_priv->display.get_fifo_size = i85x_get_fifo_size; 4210277487Skib dev_priv->display.init_clock_gating = i85x_init_clock_gating; 4211277487Skib } else { 4212277487Skib dev_priv->display.update_wm = i830_update_wm; 4213277487Skib dev_priv->display.init_clock_gating = i830_init_clock_gating; 4214277487Skib if (IS_845G(dev)) 4215277487Skib dev_priv->display.get_fifo_size = i845_get_fifo_size; 4216277487Skib else 4217277487Skib dev_priv->display.get_fifo_size = i830_get_fifo_size; 4218277487Skib } 4219296548Sdumbbell} 4220277487Skib 4221296548Sdumbbellstatic void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) 4222296548Sdumbbell{ 4223296548Sdumbbell u32 gt_thread_status_mask; 4224296548Sdumbbell 4225296548Sdumbbell if (IS_HASWELL(dev_priv->dev)) 4226296548Sdumbbell gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW; 4227296548Sdumbbell else 4228296548Sdumbbell gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK; 4229296548Sdumbbell 4230296548Sdumbbell /* w/a for a sporadic read returning 0 by waiting for the GT 4231296548Sdumbbell * thread to wake up. 4232277487Skib */ 4233296548Sdumbbell if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500)) 4234296548Sdumbbell DRM_ERROR("GT thread status wait timed out\n"); 4235277487Skib} 4236277487Skib 4237296548Sdumbbellstatic void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv) 4238296548Sdumbbell{ 4239296548Sdumbbell I915_WRITE_NOTRACE(FORCEWAKE, 0); 4240296548Sdumbbell POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ 4241296548Sdumbbell} 4242296548Sdumbbell 4243296548Sdumbbellstatic void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) 4244296548Sdumbbell{ 4245296548Sdumbbell u32 forcewake_ack; 4246296548Sdumbbell 4247296548Sdumbbell if (IS_HASWELL(dev_priv->dev)) 4248296548Sdumbbell forcewake_ack = FORCEWAKE_ACK_HSW; 4249296548Sdumbbell else 4250296548Sdumbbell forcewake_ack = FORCEWAKE_ACK; 4251296548Sdumbbell 4252296548Sdumbbell if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 4253296548Sdumbbell FORCEWAKE_ACK_TIMEOUT_MS)) 4254296548Sdumbbell DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); 4255296548Sdumbbell 4256296548Sdumbbell I915_WRITE_NOTRACE(FORCEWAKE, FORCEWAKE_KERNEL); 4257296548Sdumbbell POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ 4258296548Sdumbbell 4259296548Sdumbbell if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), 4260296548Sdumbbell FORCEWAKE_ACK_TIMEOUT_MS)) 4261296548Sdumbbell DRM_ERROR("Timed out waiting for forcewake to ack request.\n"); 4262296548Sdumbbell 4263296548Sdumbbell __gen6_gt_wait_for_thread_c0(dev_priv); 4264296548Sdumbbell} 4265296548Sdumbbell 4266296548Sdumbbellstatic void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) 4267296548Sdumbbell{ 4268296548Sdumbbell I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); 4269296548Sdumbbell /* something from same cacheline, but !FORCEWAKE_MT */ 4270296548Sdumbbell POSTING_READ(ECOBUS); 4271296548Sdumbbell} 4272296548Sdumbbell 4273296548Sdumbbellstatic void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) 4274296548Sdumbbell{ 4275296548Sdumbbell u32 forcewake_ack; 4276296548Sdumbbell 4277296548Sdumbbell if (IS_HASWELL(dev_priv->dev)) 4278296548Sdumbbell forcewake_ack = FORCEWAKE_ACK_HSW; 4279296548Sdumbbell else 4280296548Sdumbbell forcewake_ack = FORCEWAKE_MT_ACK; 4281296548Sdumbbell 4282296548Sdumbbell if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 4283296548Sdumbbell FORCEWAKE_ACK_TIMEOUT_MS)) 4284296548Sdumbbell DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); 4285296548Sdumbbell 4286296548Sdumbbell I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); 4287296548Sdumbbell /* something from same cacheline, but !FORCEWAKE_MT */ 4288296548Sdumbbell POSTING_READ(ECOBUS); 4289296548Sdumbbell 4290296548Sdumbbell if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), 4291296548Sdumbbell FORCEWAKE_ACK_TIMEOUT_MS)) 4292296548Sdumbbell DRM_ERROR("Timed out waiting for forcewake to ack request.\n"); 4293296548Sdumbbell 4294296548Sdumbbell __gen6_gt_wait_for_thread_c0(dev_priv); 4295296548Sdumbbell} 4296296548Sdumbbell 4297296548Sdumbbell/* 4298296548Sdumbbell * Generally this is called implicitly by the register read function. However, 4299296548Sdumbbell * if some sequence requires the GT to not power down then this function should 4300296548Sdumbbell * be called at the beginning of the sequence followed by a call to 4301296548Sdumbbell * gen6_gt_force_wake_put() at the end of the sequence. 4302296548Sdumbbell */ 4303296548Sdumbbellvoid gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) 4304296548Sdumbbell{ 4305296548Sdumbbell 4306296548Sdumbbell mtx_lock(&dev_priv->gt_lock); 4307296548Sdumbbell if (dev_priv->forcewake_count++ == 0) 4308296548Sdumbbell dev_priv->gt.force_wake_get(dev_priv); 4309296548Sdumbbell mtx_unlock(&dev_priv->gt_lock); 4310296548Sdumbbell} 4311296548Sdumbbell 4312296548Sdumbbellvoid gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) 4313296548Sdumbbell{ 4314296548Sdumbbell u32 gtfifodbg; 4315296548Sdumbbell gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); 4316296548Sdumbbell if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, 4317296548Sdumbbell "MMIO read or write has been dropped %x\n", gtfifodbg)) 4318296548Sdumbbell I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); 4319296548Sdumbbell} 4320296548Sdumbbell 4321296548Sdumbbellstatic void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) 4322296548Sdumbbell{ 4323296548Sdumbbell I915_WRITE_NOTRACE(FORCEWAKE, 0); 4324296548Sdumbbell /* something from same cacheline, but !FORCEWAKE */ 4325296548Sdumbbell POSTING_READ(ECOBUS); 4326296548Sdumbbell gen6_gt_check_fifodbg(dev_priv); 4327296548Sdumbbell} 4328296548Sdumbbell 4329296548Sdumbbellstatic void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) 4330296548Sdumbbell{ 4331296548Sdumbbell I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); 4332296548Sdumbbell /* something from same cacheline, but !FORCEWAKE_MT */ 4333296548Sdumbbell POSTING_READ(ECOBUS); 4334296548Sdumbbell gen6_gt_check_fifodbg(dev_priv); 4335296548Sdumbbell} 4336296548Sdumbbell 4337296548Sdumbbell/* 4338296548Sdumbbell * see gen6_gt_force_wake_get() 4339296548Sdumbbell */ 4340296548Sdumbbellvoid gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) 4341296548Sdumbbell{ 4342296548Sdumbbell 4343296548Sdumbbell mtx_lock(&dev_priv->gt_lock); 4344296548Sdumbbell if (--dev_priv->forcewake_count == 0) 4345296548Sdumbbell dev_priv->gt.force_wake_put(dev_priv); 4346296548Sdumbbell mtx_unlock(&dev_priv->gt_lock); 4347296548Sdumbbell} 4348296548Sdumbbell 4349296548Sdumbbellint __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) 4350296548Sdumbbell{ 4351296548Sdumbbell int ret = 0; 4352296548Sdumbbell 4353296548Sdumbbell if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { 4354296548Sdumbbell int loop = 500; 4355296548Sdumbbell u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); 4356296548Sdumbbell while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { 4357296548Sdumbbell udelay(10); 4358296548Sdumbbell fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); 4359296548Sdumbbell } 4360296548Sdumbbell if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) 4361296548Sdumbbell ++ret; 4362296548Sdumbbell dev_priv->gt_fifo_count = fifo; 4363296548Sdumbbell } 4364296548Sdumbbell dev_priv->gt_fifo_count--; 4365296548Sdumbbell 4366296548Sdumbbell return ret; 4367296548Sdumbbell} 4368296548Sdumbbell 4369296548Sdumbbellstatic void vlv_force_wake_reset(struct drm_i915_private *dev_priv) 4370296548Sdumbbell{ 4371296548Sdumbbell I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); 4372296548Sdumbbell /* something from same cacheline, but !FORCEWAKE_VLV */ 4373296548Sdumbbell POSTING_READ(FORCEWAKE_ACK_VLV); 4374296548Sdumbbell} 4375296548Sdumbbell 4376296548Sdumbbellstatic void vlv_force_wake_get(struct drm_i915_private *dev_priv) 4377296548Sdumbbell{ 4378296548Sdumbbell if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0, 4379296548Sdumbbell FORCEWAKE_ACK_TIMEOUT_MS)) 4380296548Sdumbbell DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); 4381296548Sdumbbell 4382296548Sdumbbell I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); 4383296548Sdumbbell 4384296548Sdumbbell if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 4385296548Sdumbbell FORCEWAKE_ACK_TIMEOUT_MS)) 4386296548Sdumbbell DRM_ERROR("Timed out waiting for forcewake to ack request.\n"); 4387296548Sdumbbell 4388296548Sdumbbell __gen6_gt_wait_for_thread_c0(dev_priv); 4389296548Sdumbbell} 4390296548Sdumbbell 4391296548Sdumbbellstatic void vlv_force_wake_put(struct drm_i915_private *dev_priv) 4392296548Sdumbbell{ 4393296548Sdumbbell I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); 4394296548Sdumbbell /* something from same cacheline, but !FORCEWAKE_VLV */ 4395296548Sdumbbell POSTING_READ(FORCEWAKE_ACK_VLV); 4396296548Sdumbbell gen6_gt_check_fifodbg(dev_priv); 4397296548Sdumbbell} 4398296548Sdumbbell 4399296548Sdumbbellvoid intel_gt_reset(struct drm_device *dev) 4400296548Sdumbbell{ 4401296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 4402296548Sdumbbell 4403296548Sdumbbell if (IS_VALLEYVIEW(dev)) { 4404296548Sdumbbell vlv_force_wake_reset(dev_priv); 4405296548Sdumbbell } else if (INTEL_INFO(dev)->gen >= 6) { 4406296548Sdumbbell __gen6_gt_force_wake_reset(dev_priv); 4407296548Sdumbbell if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) 4408296548Sdumbbell __gen6_gt_force_wake_mt_reset(dev_priv); 4409296548Sdumbbell } 4410296548Sdumbbell} 4411296548Sdumbbell 4412296548Sdumbbellvoid intel_gt_init(struct drm_device *dev) 4413296548Sdumbbell{ 4414296548Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 4415296548Sdumbbell 4416296548Sdumbbell mtx_init(&dev_priv->gt_lock, "i915_gt_lock", NULL, MTX_DEF); 4417296548Sdumbbell 4418296548Sdumbbell intel_gt_reset(dev); 4419296548Sdumbbell 4420296548Sdumbbell if (IS_VALLEYVIEW(dev)) { 4421296548Sdumbbell dev_priv->gt.force_wake_get = vlv_force_wake_get; 4422296548Sdumbbell dev_priv->gt.force_wake_put = vlv_force_wake_put; 4423296548Sdumbbell } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { 4424296548Sdumbbell dev_priv->gt.force_wake_get = __gen6_gt_force_wake_mt_get; 4425296548Sdumbbell dev_priv->gt.force_wake_put = __gen6_gt_force_wake_mt_put; 4426296548Sdumbbell } else if (IS_GEN6(dev)) { 4427296548Sdumbbell dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; 4428296548Sdumbbell dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; 4429296548Sdumbbell } 4430296548Sdumbbell TIMEOUT_TASK_INIT(dev_priv->wq, &dev_priv->rps.delayed_resume_work, 0, 4431296548Sdumbbell intel_gen6_powersave_work, dev_priv); 4432296548Sdumbbell} 4433296548Sdumbbell 4434296548Sdumbbellint sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val) 4435296548Sdumbbell{ 4436296548Sdumbbell sx_assert(&dev_priv->rps.hw_lock, SA_XLOCKED); 4437296548Sdumbbell 4438296548Sdumbbell if (I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) { 4439296548Sdumbbell DRM_DEBUG_DRIVER("warning: pcode (read) mailbox access failed\n"); 4440296548Sdumbbell return -EAGAIN; 4441296548Sdumbbell } 4442296548Sdumbbell 4443296548Sdumbbell I915_WRITE(GEN6_PCODE_DATA, *val); 4444296548Sdumbbell I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox); 4445296548Sdumbbell 4446296548Sdumbbell if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, 4447296548Sdumbbell 500)) { 4448296548Sdumbbell DRM_ERROR("timeout waiting for pcode read (%d) to finish\n", mbox); 4449296548Sdumbbell return -ETIMEDOUT; 4450296548Sdumbbell } 4451296548Sdumbbell 4452296548Sdumbbell *val = I915_READ(GEN6_PCODE_DATA); 4453296548Sdumbbell I915_WRITE(GEN6_PCODE_DATA, 0); 4454296548Sdumbbell 4455296548Sdumbbell return 0; 4456296548Sdumbbell} 4457296548Sdumbbell 4458296548Sdumbbellint sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) 4459296548Sdumbbell{ 4460296548Sdumbbell sx_assert(&dev_priv->rps.hw_lock, SA_XLOCKED); 4461296548Sdumbbell 4462296548Sdumbbell if (I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) { 4463296548Sdumbbell DRM_DEBUG_DRIVER("warning: pcode (write) mailbox access failed\n"); 4464296548Sdumbbell return -EAGAIN; 4465296548Sdumbbell } 4466296548Sdumbbell 4467296548Sdumbbell I915_WRITE(GEN6_PCODE_DATA, val); 4468296548Sdumbbell I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox); 4469296548Sdumbbell 4470296548Sdumbbell if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, 4471296548Sdumbbell 500)) { 4472296548Sdumbbell DRM_ERROR("timeout waiting for pcode write (%d) to finish\n", mbox); 4473296548Sdumbbell return -ETIMEDOUT; 4474296548Sdumbbell } 4475296548Sdumbbell 4476296548Sdumbbell I915_WRITE(GEN6_PCODE_DATA, 0); 4477296548Sdumbbell 4478296548Sdumbbell return 0; 4479296548Sdumbbell} 4480