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