int i915_reg_read_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_reg_read *reg = data; struct register_whitelist const *entry = whitelist; int i; for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) { if (entry->offset == reg->offset && (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask)) break; } if (i == ARRAY_SIZE(whitelist)) return -EINVAL; switch (entry->size) { case 8: reg->val = I915_READ64(reg->offset); break; case 4: reg->val = I915_READ(reg->offset); break; case 2: reg->val = I915_READ16(reg->offset); break; case 1: reg->val = I915_READ8(reg->offset); break; default: WARN_ON(1); return -EINVAL; } return 0; }
static int get_context_size(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int ret; u32 reg; switch (INTEL_INFO(dev)->gen) { case 6: reg = I915_READ(CXT_SIZE); ret = GEN6_CXT_TOTAL_SIZE(reg) * 64; break; case 7: reg = I915_READ(GEN7_CXT_SIZE); if (IS_HASWELL(dev)) ret = HSW_CXT_TOTAL_SIZE(reg) * 64; else ret = GEN7_CXT_TOTAL_SIZE(reg) * 64; break; default: BUG(); } return ret; }
void intel_disable_shared_dpll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_shared_dpll *pll = crtc->config->shared_dpll; unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base); /* PCH only available on ILK+ */ if (INTEL_INFO(dev)->gen < 5) return; if (pll == NULL) return; mutex_lock(&dev_priv->dpll_lock); if (WARN_ON(!(pll->active_mask & crtc_mask))) goto out; DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n", pll->name, pll->active_mask, pll->on, crtc->base.base.id); assert_shared_dpll_enabled(dev_priv, pll); WARN_ON(!pll->on); pll->active_mask &= ~crtc_mask; if (pll->active_mask) goto out; DRM_DEBUG_KMS("disabling %s\n", pll->name); pll->funcs.disable(dev_priv, pll); pll->on = false; out: mutex_unlock(&dev_priv->dpll_lock); }
int intel_plane_init(struct drm_device *dev, enum pipe pipe) { struct intel_plane *intel_plane; unsigned long possible_crtcs; const uint32_t *plane_formats; int num_plane_formats; int ret; if (INTEL_INFO(dev)->gen < 5) return -ENODEV; intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); if (!intel_plane) return -ENOMEM; switch (INTEL_INFO(dev)->gen) { case 5: case 6: intel_plane->can_scale = true; intel_plane->max_downscale = 16; intel_plane->update_plane = ilk_update_plane; intel_plane->disable_plane = ilk_disable_plane; intel_plane->update_colorkey = ilk_update_colorkey; intel_plane->get_colorkey = ilk_get_colorkey; if (IS_GEN6(dev)) { plane_formats = snb_plane_formats; num_plane_formats = ARRAY_SIZE(snb_plane_formats); } else { plane_formats = ilk_plane_formats; num_plane_formats = ARRAY_SIZE(ilk_plane_formats); } break; case 7: if (IS_HASWELL(dev) || IS_VALLEYVIEW(dev)) intel_plane->can_scale = false; else intel_plane->can_scale = true; intel_plane->max_downscale = 2; intel_plane->update_plane = ivb_update_plane; intel_plane->disable_plane = ivb_disable_plane; intel_plane->update_colorkey = ivb_update_colorkey; intel_plane->get_colorkey = ivb_get_colorkey; plane_formats = snb_plane_formats; num_plane_formats = ARRAY_SIZE(snb_plane_formats); break; default: kfree(intel_plane); return -ENODEV; } intel_plane->pipe = pipe; possible_crtcs = (1 << pipe); ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, plane_formats, num_plane_formats, false); if (ret) kfree(intel_plane); return ret; }
static bool intel_fbc_can_activate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; if (!cache->plane.visible) { fbc->no_fbc_reason = "primary plane not visible"; return false; } if ((cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) || (cache->crtc.mode_flags & DRM_MODE_FLAG_DBLSCAN)) { fbc->no_fbc_reason = "incompatible mode"; return false; } if (!intel_fbc_hw_tracking_covers_screen(crtc)) { fbc->no_fbc_reason = "mode too large for compression"; return false; } /* The use of a CPU fence is mandatory in order to detect writes * by the CPU to the scanout and trigger updates to the FBC. */ if (cache->fb.tiling_mode != I915_TILING_X || cache->fb.fence_reg == I915_FENCE_REG_NONE) { fbc->no_fbc_reason = "framebuffer not tiled or fenced"; return false; } if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) && cache->plane.rotation != BIT(DRM_ROTATE_0)) { fbc->no_fbc_reason = "rotation unsupported"; return false; } if (!stride_is_valid(dev_priv, cache->fb.stride)) { fbc->no_fbc_reason = "framebuffer stride not supported"; return false; } if (!pixel_format_is_valid(dev_priv, cache->fb.pixel_format)) { fbc->no_fbc_reason = "pixel format is invalid"; return false; } /* WaFbcExceedCdClockThreshold:hsw,bdw */ if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk_freq * 95 / 100) { fbc->no_fbc_reason = "pixel rate is too big"; return false; } /* It is possible for the required CFB size change without a * crtc->disable + crtc->enable since it is possible to change the * stride without triggering a full modeset. Since we try to * over-allocate the CFB, there's a chance we may keep FBC enabled even * if this happens, but if we exceed the current CFB size we'll have to * disable FBC. Notice that it would be possible to disable FBC, wait * for a frame, free the stolen node, then try to reenable FBC in case * we didn't get any invalidate/deactivate calls, but this would require * a lot of tracking just for a specific case. If we conclude it's an * important case, we can implement it later. */ if (intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache) > fbc->compressed_fb.size * fbc->threshold) { fbc->no_fbc_reason = "CFB requirements changed"; return false; } return true; }
static inline bool fbc_on_plane_a_only(struct drm_i915_private *dev_priv) { return INTEL_INFO(dev_priv)->gen < 4; }
/** * i915_reset - reset chip after a hang * @dev: drm device to reset * * Reset the chip. Useful if a hang is detected. Returns zero on successful * reset or otherwise an error code. * * Procedure is fairly simple: * - reset the chip using the reset reg * - re-init context state * - re-init hardware status page * - re-init ring buffer * - re-init interrupt state * - re-init display */ int i915_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; bool simulated; int ret; intel_reset_gt_powersave(dev); mutex_lock(&dev->struct_mutex); i915_gem_reset(dev); simulated = dev_priv->gpu_error.stop_rings != 0; ret = intel_gpu_reset(dev, ALL_ENGINES); /* Also reset the gpu hangman. */ if (simulated) { DRM_INFO("Simulated gpu hang, resetting stop_rings\n"); dev_priv->gpu_error.stop_rings = 0; if (ret == -ENODEV) { DRM_INFO("Reset not implemented, but ignoring " "error for simulated gpu hangs\n"); ret = 0; } } if (i915_stop_ring_allow_warn(dev_priv)) pr_notice("drm/i915: Resetting chip after gpu hang\n"); if (ret) { DRM_ERROR("Failed to reset chip: %i\n", ret); mutex_unlock(&dev->struct_mutex); return ret; } intel_overlay_reset(dev_priv); /* Ok, now get things going again... */ /* * Everything depends on having the GTT running, so we need to start * there. Fortunately we don't need to do this unless we reset the * chip at a PCI level. * * Next we need to restore the context, but we don't use those * yet either... * * Ring buffer needs to be re-initialized in the KMS case, or if X * was running at the time of the reset (i.e. we weren't VT * switched away). */ /* Used to prevent gem_check_wedged returning -EAGAIN during gpu reset */ dev_priv->gpu_error.reload_in_reset = true; ret = i915_gem_init_hw(dev); dev_priv->gpu_error.reload_in_reset = false; mutex_unlock(&dev->struct_mutex); if (ret) { DRM_ERROR("Failed hw init on reset %d\n", ret); return ret; } /* * rps/rc6 re-init is necessary to restore state lost after the * reset and the re-install of gt irqs. Skip for ironlake per * previous concerns that it doesn't respond well to some forms * of re-init after reset. */ if (INTEL_INFO(dev)->gen > 5) intel_enable_gt_powersave(dev); return 0; }
/* * Create as many clients as number of doorbells. Note that there's already * client(s)/doorbell(s) created during driver load, but this test creates * its own and do not interact with the existing ones. */ static int igt_guc_doorbells(void *arg) { struct drm_i915_private *dev_priv = arg; struct intel_guc *guc; int i, err = 0; u16 db_id; GEM_BUG_ON(!HAS_GUC(dev_priv)); mutex_lock(&dev_priv->drm.struct_mutex); intel_runtime_pm_get(dev_priv); guc = &dev_priv->guc; if (!guc) { pr_err("No guc object!\n"); err = -EINVAL; goto unlock; } err = check_all_doorbells(guc); if (err) goto unlock; for (i = 0; i < ATTEMPTS; i++) { clients[i] = guc_client_alloc(dev_priv, INTEL_INFO(dev_priv)->ring_mask, i % GUC_CLIENT_PRIORITY_NUM, dev_priv->kernel_context); if (!clients[i]) { pr_err("[%d] No guc client\n", i); err = -EINVAL; goto out; } if (IS_ERR(clients[i])) { if (PTR_ERR(clients[i]) != -ENOSPC) { pr_err("[%d] unexpected error\n", i); err = PTR_ERR(clients[i]); goto out; } if (available_dbs(guc, i % GUC_CLIENT_PRIORITY_NUM)) { pr_err("[%d] non-db related alloc fail\n", i); err = -EINVAL; goto out; } /* expected, ran out of dbs for this client type */ continue; } /* * The check below is only valid because we keep a doorbell * assigned during the whole life of the client. */ if (clients[i]->stage_id >= GUC_NUM_DOORBELLS) { pr_err("[%d] more clients than doorbells (%d >= %d)\n", i, clients[i]->stage_id, GUC_NUM_DOORBELLS); err = -EINVAL; goto out; } err = validate_client(clients[i], i % GUC_CLIENT_PRIORITY_NUM, false); if (err) { pr_err("[%d] client_alloc sanity check failed!\n", i); err = -EINVAL; goto out; } db_id = clients[i]->doorbell_id; err = __guc_client_enable(clients[i]); if (err) { pr_err("[%d] Failed to create a doorbell\n", i); goto out; } /* doorbell id shouldn't change, we are holding the mutex */ if (db_id != clients[i]->doorbell_id) { pr_err("[%d] doorbell id changed (%d != %d)\n", i, db_id, clients[i]->doorbell_id); err = -EINVAL; goto out; } err = check_all_doorbells(guc); if (err) goto out; err = ring_doorbell_nop(clients[i]); if (err) goto out; } out: for (i = 0; i < ATTEMPTS; i++) if (!IS_ERR_OR_NULL(clients[i])) { __guc_client_disable(clients[i]); guc_client_free(clients[i]); } unlock: intel_runtime_pm_put(dev_priv); mutex_unlock(&dev_priv->drm.struct_mutex); return err; }
/* Check pitch constriants for all chips & tiling formats */ static bool i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) { int tile_width, tile_height; /* Linear is always fine */ if (tiling_mode == I915_TILING_NONE) return true; if (IS_GEN2(dev) || (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) tile_width = 128; else tile_width = 512; /* check maximum stride & object size */ if (INTEL_INFO(dev)->gen >= 4) { /* i965 stores the end address of the gtt mapping in the fence * reg, so dont bother to check the size */ if (stride / 128 > I965_FENCE_MAX_PITCH_VAL) return false; } else { if (stride > 8192) return false; if (IS_GEN3(dev)) { if (size > I830_FENCE_MAX_SIZE_VAL << 20) return false; } else { if (size > I830_FENCE_MAX_SIZE_VAL << 19) return false; } } if (IS_GEN2(dev) || (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) tile_height = 32; else tile_height = 8; /* i8xx is strange: It has 2 interleaved rows of tiles, so needs an even * number of tile rows. */ if (IS_GEN2(dev)) tile_height *= 2; /* Size needs to be aligned to a full tile row */ if (size & (tile_height * stride - 1)) return false; /* 965+ just needs multiples of tile width */ if (INTEL_INFO(dev)->gen >= 4) { if (stride & (tile_width - 1)) return false; return true; } /* Pre-965 needs power of two tile widths */ if (stride < tile_width) return false; if (stride & (stride - 1)) return false; return true; }
static void i915_restore_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; /* Display arbitration */ I915_WRITE(DSPARB, dev_priv->saveDSPARB); /* Display port ratios (must be done before clock is set) */ if (SUPPORTS_INTEGRATED_DP(dev)) { I915_WRITE(_PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M); I915_WRITE(_PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M); I915_WRITE(_PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N); I915_WRITE(_PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N); I915_WRITE(_PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M); I915_WRITE(_PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M); I915_WRITE(_PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); I915_WRITE(_PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); } /* This is only meaningful in non-KMS mode */ /* Don't restore them in KMS mode */ i915_restore_modeset_reg(dev); /* CRT state */ if (HAS_PCH_SPLIT(dev)) I915_WRITE(PCH_ADPA, dev_priv->saveADPA); else I915_WRITE(ADPA, dev_priv->saveADPA); /* LVDS state */ if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); if (HAS_PCH_SPLIT(dev)) { I915_WRITE(PCH_LVDS, dev_priv->saveLVDS); } else if (IS_MOBILE(dev) && !IS_I830(dev)) I915_WRITE(LVDS, dev_priv->saveLVDS); if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev)) I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL); if (HAS_PCH_SPLIT(dev)) { I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL); I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2); I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL); I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->saveBLC_CPU_PWM_CTL2); I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR); I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL); I915_WRITE(RSTDBYCTL, dev_priv->saveMCHBAR_RENDER_STANDBY); } else { I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS); I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); I915_WRITE(BLC_HIST_CTL, dev_priv->saveBLC_HIST_CTL); I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); } /* Display Port state */ if (SUPPORTS_INTEGRATED_DP(dev)) { I915_WRITE(DP_B, dev_priv->saveDP_B); I915_WRITE(DP_C, dev_priv->saveDP_C); I915_WRITE(DP_D, dev_priv->saveDP_D); } /* FIXME: restore TV & SDVO state */ /* only restore FBC info on the platform that supports FBC*/ intel_disable_fbc(dev); if (I915_HAS_FBC(dev)) { if (HAS_PCH_SPLIT(dev)) { I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE); } else if (IS_GM45(dev)) { I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE); } else { I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE); I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE); I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2); I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL); } } /* VGA state */ if (HAS_PCH_SPLIT(dev)) I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL); else I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); I915_WRITE(VGA0, dev_priv->saveVGA0); I915_WRITE(VGA1, dev_priv->saveVGA1); I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); POSTING_READ(VGA_PD); DRM_UDELAY(150); i915_restore_vga(dev); }
int i915_reset(struct drm_device *dev, u8 flags) { drm_i915_private_t *dev_priv = dev->dev_private; bool need_display = true; int ret; if (!i915_try_reset) return 0; if (!mutex_trylock(&dev->struct_mutex)) return -EBUSY; i915_gem_reset(dev); ret = -ENODEV; if (get_seconds() - dev_priv->last_gpu_reset < 5) { DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); } else switch (INTEL_INFO(dev)->gen) { case 7: case 6: ret = gen6_do_reset(dev, flags); break; case 5: ret = ironlake_do_reset(dev, flags); break; case 4: ret = i965_do_reset(dev, flags); break; case 2: ret = i8xx_do_reset(dev, flags); break; } dev_priv->last_gpu_reset = get_seconds(); if (ret) { DRM_ERROR("Failed to reset chip.\n"); mutex_unlock(&dev->struct_mutex); return ret; } if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->mm.suspended) { dev_priv->mm.suspended = 0; i915_gem_init_swizzling(dev); dev_priv->ring[RCS].init(&dev_priv->ring[RCS]); if (HAS_BSD(dev)) dev_priv->ring[VCS].init(&dev_priv->ring[VCS]); if (HAS_BLT(dev)) dev_priv->ring[BCS].init(&dev_priv->ring[BCS]); i915_gem_init_ppgtt(dev); mutex_unlock(&dev->struct_mutex); drm_irq_uninstall(dev); drm_mode_config_reset(dev); drm_irq_install(dev); mutex_lock(&dev->struct_mutex); } mutex_unlock(&dev->struct_mutex); if (need_display) { mutex_lock(&dev->mode_config.mutex); drm_helper_resume_force_mode(dev); mutex_unlock(&dev->mode_config.mutex); } return 0; }
/** * Detects bit 6 swizzling of address lookup between IGD access and CPU * access through main memory. */ void i915_gem_detect_bit_6_swizzle(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; if (INTEL_INFO(dev)->gen >= 8 || IS_VALLEYVIEW(dev)) { /* * On BDW+, swizzling is not used. We leave the CPU memory * controller in charge of optimizing memory accesses without * the extra address manipulation GPU side. * * VLV and CHV don't have GPU swizzling. */ swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; } else if (INTEL_INFO(dev)->gen >= 6) { uint32_t dimm_c0, dimm_c1; dimm_c0 = I915_READ(MAD_DIMM_C0); dimm_c1 = I915_READ(MAD_DIMM_C1); dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK; dimm_c1 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK; /* Enable swizzling when the channels are populated with * identically sized dimms. We don't need to check the 3rd * channel because no cpu with gpu attached ships in that * configuration. Also, swizzling only makes sense for 2 * channels anyway. */ if (dimm_c0 == dimm_c1) { swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; } else { swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; } } else if (IS_GEN5(dev)) { /* On Ironlake whatever DRAM config, GPU always do * same swizzling setup. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; } else if (IS_GEN2(dev)) { /* As far as we know, the 865 doesn't have these bit 6 * swizzling issues. */ swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; } else if (IS_MOBILE(dev) || (IS_GEN3(dev) && !IS_G33(dev))) { uint32_t dcc; /* On 9xx chipsets, channel interleave by the CPU is * determined by DCC. For single-channel, neither the CPU * nor the GPU do swizzling. For dual channel interleaved, * the GPU's interleave is bit 9 and 10 for X tiled, and bit * 9 for Y tiled. The CPU's interleave is independent, and * can be based on either bit 11 (haven't seen this yet) or * bit 17 (common). */ dcc = I915_READ(DCC); switch (dcc & DCC_ADDRESSING_MODE_MASK) { case DCC_ADDRESSING_MODE_SINGLE_CHANNEL: case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC: swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; break; case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED: if (dcc & DCC_CHANNEL_XOR_DISABLE) { /* This is the base swizzling by the GPU for * tiled buffers. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; } else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) { /* Bit 11 swizzling by the CPU in addition. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10_11; swizzle_y = I915_BIT_6_SWIZZLE_9_11; } else { /* Bit 17 swizzling by the CPU in addition. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10_17; swizzle_y = I915_BIT_6_SWIZZLE_9_17; } break; } if (dcc == 0xffffffff) { DRM_ERROR("Couldn't read from MCHBAR. " "Disabling tiling.\n"); swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; } } else { /* The 965, G33, and newer, have a very flexible memory * configuration. It will enable dual-channel mode * (interleaving) on as much memory as it can, and the GPU * will additionally sometimes enable different bit 6 * swizzling for tiled objects from the CPU. * * Here's what I found on the G965: * slot fill memory size swizzling * 0A 0B 1A 1B 1-ch 2-ch * 512 0 0 0 512 0 O * 512 0 512 0 16 1008 X * 512 0 0 512 16 1008 X * 0 512 0 512 16 1008 X * 1024 1024 1024 0 2048 1024 O * * We could probably detect this based on either the DRB * matching, which was the case for the swizzling required in * the table above, or from the 1-ch value being less than * the minimum size of a rank. */ if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) { swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; } else { swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; } } dev_priv->mm.bit_6_swizzle_x = swizzle_x; dev_priv->mm.bit_6_swizzle_y = swizzle_y; }
void intel_uncore_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; INIT_DELAYED_WORK(&dev_priv->uncore.force_wake_work, gen6_force_wake_work); if (IS_VALLEYVIEW(dev)) { dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get; dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put; } else if (IS_HASWELL(dev) || IS_GEN8(dev)) { dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get; dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put; } else if (IS_IVYBRIDGE(dev)) { u32 ecobus; /* IVB configs may use multi-threaded forcewake */ /* A small trick here - if the bios hasn't configured * MT forcewake, and if the device is in RC6, then * force_wake_mt_get will not wake the device and the * ECOBUS read will return zero. Which will be * (correctly) interpreted by the test below as MT * forcewake being disabled. */ mutex_lock(&dev->struct_mutex); __gen6_gt_force_wake_mt_get(dev_priv, FORCEWAKE_ALL); ecobus = __raw_i915_read32(dev_priv, ECOBUS); __gen6_gt_force_wake_mt_put(dev_priv, FORCEWAKE_ALL); mutex_unlock(&dev->struct_mutex); if (ecobus & FORCEWAKE_MT_ENABLE) { dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get; dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put; } else { DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n"); DRM_INFO("when using vblank-synced partial screen updates.\n"); dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_get; dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_put; } } else if (IS_GEN6(dev)) { dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_get; dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_put; } switch (INTEL_INFO(dev)->gen) { default: dev_priv->uncore.funcs.mmio_writeb = gen8_write8; dev_priv->uncore.funcs.mmio_writew = gen8_write16; dev_priv->uncore.funcs.mmio_writel = gen8_write32; dev_priv->uncore.funcs.mmio_writeq = gen8_write64; dev_priv->uncore.funcs.mmio_readb = gen6_read8; dev_priv->uncore.funcs.mmio_readw = gen6_read16; dev_priv->uncore.funcs.mmio_readl = gen6_read32; dev_priv->uncore.funcs.mmio_readq = gen6_read64; break; case 7: case 6: if (IS_HASWELL(dev)) { dev_priv->uncore.funcs.mmio_writeb = hsw_write8; dev_priv->uncore.funcs.mmio_writew = hsw_write16; dev_priv->uncore.funcs.mmio_writel = hsw_write32; dev_priv->uncore.funcs.mmio_writeq = hsw_write64; } else { dev_priv->uncore.funcs.mmio_writeb = gen6_write8; dev_priv->uncore.funcs.mmio_writew = gen6_write16; dev_priv->uncore.funcs.mmio_writel = gen6_write32; dev_priv->uncore.funcs.mmio_writeq = gen6_write64; } if (IS_VALLEYVIEW(dev)) { dev_priv->uncore.funcs.mmio_readb = vlv_read8; dev_priv->uncore.funcs.mmio_readw = vlv_read16; dev_priv->uncore.funcs.mmio_readl = vlv_read32; dev_priv->uncore.funcs.mmio_readq = vlv_read64; } else { dev_priv->uncore.funcs.mmio_readb = gen6_read8; dev_priv->uncore.funcs.mmio_readw = gen6_read16; dev_priv->uncore.funcs.mmio_readl = gen6_read32; dev_priv->uncore.funcs.mmio_readq = gen6_read64; } break; case 5: dev_priv->uncore.funcs.mmio_writeb = gen5_write8; dev_priv->uncore.funcs.mmio_writew = gen5_write16; dev_priv->uncore.funcs.mmio_writel = gen5_write32; dev_priv->uncore.funcs.mmio_writeq = gen5_write64; dev_priv->uncore.funcs.mmio_readb = gen5_read8; dev_priv->uncore.funcs.mmio_readw = gen5_read16; dev_priv->uncore.funcs.mmio_readl = gen5_read32; dev_priv->uncore.funcs.mmio_readq = gen5_read64; break; case 4: case 3: case 2: dev_priv->uncore.funcs.mmio_writeb = gen4_write8; dev_priv->uncore.funcs.mmio_writew = gen4_write16; dev_priv->uncore.funcs.mmio_writel = gen4_write32; dev_priv->uncore.funcs.mmio_writeq = gen4_write64; dev_priv->uncore.funcs.mmio_readb = gen4_read8; dev_priv->uncore.funcs.mmio_readw = gen4_read16; dev_priv->uncore.funcs.mmio_readl = gen4_read32; dev_priv->uncore.funcs.mmio_readq = gen4_read64; break; } }
static struct i915_hw_context * create_hw_context(struct drm_device *dev, struct drm_i915_file_private *file_priv) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_context *ctx; int ret, id; ctx = kmalloc(sizeof(*ctx), DRM_I915_GEM, M_WAITOK | M_ZERO); if (ctx == NULL) return ERR_PTR(-ENOMEM); ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); if (ctx->obj == NULL) { kfree(ctx, DRM_I915_GEM); DRM_DEBUG_DRIVER("Context object allocated failed\n"); return ERR_PTR(-ENOMEM); } if (INTEL_INFO(dev)->gen >= 7) { ret = i915_gem_object_set_cache_level(ctx->obj, I915_CACHE_LLC_MLC); if (ret) goto err_out; } /* The ring associated with the context object is handled by the normal * object tracking code. We give an initial ring value simple to pass an * assertion in the context switch code. */ ctx->ring = &dev_priv->ring[RCS]; /* Default context will never have a file_priv */ if (file_priv == NULL) return ctx; ctx->file_priv = file_priv; again: if (idr_pre_get(&file_priv->context_idr, GFP_KERNEL) == 0) { ret = -ENOMEM; DRM_DEBUG_DRIVER("idr allocation failed\n"); goto err_out; } ret = idr_get_new_above(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID + 1, &id); if (ret == 0) ctx->id = id; if (ret == -EAGAIN) goto again; else if (ret) goto err_out; return ctx; err_out: do_destroy(ctx); return ERR_PTR(ret); }
static struct i915_hw_context * create_hw_context(struct drm_device *dev, struct drm_i915_file_private *file_priv) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_context *ctx; struct i915_ctx_handle *han; int ret; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (ctx == NULL) return ERR_PTR(-ENOMEM); ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); if (ctx->obj == NULL) { kfree(ctx); DRM_DEBUG_DRIVER("Context object allocated failed\n"); return ERR_PTR(-ENOMEM); } if (INTEL_INFO(dev)->gen >= 7) { ret = i915_gem_object_set_cache_level(ctx->obj, I915_CACHE_LLC_MLC); if (ret) goto err_out; } /* The ring associated with the context object is handled by the normal * object tracking code. We give an initial ring value simple to pass an * assertion in the context switch code. */ ctx->ring = &dev_priv->ring[RCS]; /* Default context will never have a file_priv */ if (file_priv == NULL) return ctx; ctx->file_priv = file_priv; han = malloc(sizeof(*han), M_DRM, M_WAITOK | M_CANFAIL | M_ZERO); if (han == NULL) { ret = -ENOMEM; DRM_DEBUG_DRIVER("idr allocation failed\n"); goto err_out; } han->ctx = ctx; again: han->handle = ++file_priv->ctx_id; if (han->handle <= DEFAULT_CONTEXT_ID + 1 || SPLAY_INSERT(i915_ctx_tree, &file_priv->ctx_tree, han)) goto again; ctx->id = han->handle; return ctx; err_out: do_destroy(ctx); return ERR_PTR(ret); }
static void i915_restore_modeset_reg(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int dpll_a_reg, fpa0_reg, fpa1_reg; int dpll_b_reg, fpb0_reg, fpb1_reg; int i; if (drm_core_check_feature(dev, DRIVER_MODESET)) return; /* Fences */ switch (INTEL_INFO(dev)->gen) { case 7: case 6: for (i = 0; i < 16; i++) I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]); break; case 5: case 4: for (i = 0; i < 16; i++) I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]); break; case 3: case 2: if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) for (i = 0; i < 8; i++) I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); for (i = 0; i < 8; i++) I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]); break; } if (HAS_PCH_SPLIT(dev)) { dpll_a_reg = _PCH_DPLL_A; dpll_b_reg = _PCH_DPLL_B; fpa0_reg = _PCH_FPA0; fpb0_reg = _PCH_FPB0; fpa1_reg = _PCH_FPA1; fpb1_reg = _PCH_FPB1; } else { dpll_a_reg = _DPLL_A; dpll_b_reg = _DPLL_B; fpa0_reg = _FPA0; fpb0_reg = _FPB0; fpa1_reg = _FPA1; fpb1_reg = _FPB1; } if (HAS_PCH_SPLIT(dev)) { I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL); I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL); } /* Pipe & plane A info */ /* Prime the clock */ if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE); POSTING_READ(dpll_a_reg); DRM_UDELAY(150); } I915_WRITE(fpa0_reg, dev_priv->saveFPA0); I915_WRITE(fpa1_reg, dev_priv->saveFPA1); /* Actually enable it */ I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A); POSTING_READ(dpll_a_reg); DRM_UDELAY(150); if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { I915_WRITE(_DPLL_A_MD, dev_priv->saveDPLL_A_MD); POSTING_READ(_DPLL_A_MD); } DRM_UDELAY(150); /* Restore mode */ I915_WRITE(_HTOTAL_A, dev_priv->saveHTOTAL_A); I915_WRITE(_HBLANK_A, dev_priv->saveHBLANK_A); I915_WRITE(_HSYNC_A, dev_priv->saveHSYNC_A); I915_WRITE(_VTOTAL_A, dev_priv->saveVTOTAL_A); I915_WRITE(_VBLANK_A, dev_priv->saveVBLANK_A); I915_WRITE(_VSYNC_A, dev_priv->saveVSYNC_A); if (!HAS_PCH_SPLIT(dev)) I915_WRITE(_BCLRPAT_A, dev_priv->saveBCLRPAT_A); if (HAS_PCH_SPLIT(dev)) { I915_WRITE(_PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1); I915_WRITE(_PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1); I915_WRITE(_PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1); I915_WRITE(_PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1); I915_WRITE(_FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL); I915_WRITE(_FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL); I915_WRITE(_PFA_CTL_1, dev_priv->savePFA_CTL_1); I915_WRITE(_PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ); I915_WRITE(_PFA_WIN_POS, dev_priv->savePFA_WIN_POS); I915_WRITE(_TRANSACONF, dev_priv->saveTRANSACONF); I915_WRITE(_TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A); I915_WRITE(_TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A); I915_WRITE(_TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A); I915_WRITE(_TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A); I915_WRITE(_TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A); I915_WRITE(_TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A); } /* Restore plane info */ I915_WRITE(_DSPASIZE, dev_priv->saveDSPASIZE); I915_WRITE(_DSPAPOS, dev_priv->saveDSPAPOS); I915_WRITE(_PIPEASRC, dev_priv->savePIPEASRC); I915_WRITE(_DSPAADDR, dev_priv->saveDSPAADDR); I915_WRITE(_DSPASTRIDE, dev_priv->saveDSPASTRIDE); if (INTEL_INFO(dev)->gen >= 4) { I915_WRITE(_DSPASURF, dev_priv->saveDSPASURF); I915_WRITE(_DSPATILEOFF, dev_priv->saveDSPATILEOFF); } I915_WRITE(_PIPEACONF, dev_priv->savePIPEACONF); i915_restore_palette(dev, PIPE_A); /* Enable the plane */ I915_WRITE(_DSPACNTR, dev_priv->saveDSPACNTR); I915_WRITE(_DSPAADDR, I915_READ(_DSPAADDR)); /* Pipe & plane B info */ if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE); POSTING_READ(dpll_b_reg); DRM_UDELAY(150); } I915_WRITE(fpb0_reg, dev_priv->saveFPB0); I915_WRITE(fpb1_reg, dev_priv->saveFPB1); /* Actually enable it */ I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B); POSTING_READ(dpll_b_reg); DRM_UDELAY(150); if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { I915_WRITE(_DPLL_B_MD, dev_priv->saveDPLL_B_MD); POSTING_READ(_DPLL_B_MD); } DRM_UDELAY(150); /* Restore mode */ I915_WRITE(_HTOTAL_B, dev_priv->saveHTOTAL_B); I915_WRITE(_HBLANK_B, dev_priv->saveHBLANK_B); I915_WRITE(_HSYNC_B, dev_priv->saveHSYNC_B); I915_WRITE(_VTOTAL_B, dev_priv->saveVTOTAL_B); I915_WRITE(_VBLANK_B, dev_priv->saveVBLANK_B); I915_WRITE(_VSYNC_B, dev_priv->saveVSYNC_B); if (!HAS_PCH_SPLIT(dev)) I915_WRITE(_BCLRPAT_B, dev_priv->saveBCLRPAT_B); if (HAS_PCH_SPLIT(dev)) { I915_WRITE(_PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1); I915_WRITE(_PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1); I915_WRITE(_PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1); I915_WRITE(_PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1); I915_WRITE(_FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL); I915_WRITE(_FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL); I915_WRITE(_PFB_CTL_1, dev_priv->savePFB_CTL_1); I915_WRITE(_PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ); I915_WRITE(_PFB_WIN_POS, dev_priv->savePFB_WIN_POS); I915_WRITE(_TRANSBCONF, dev_priv->saveTRANSBCONF); I915_WRITE(_TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B); I915_WRITE(_TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B); I915_WRITE(_TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B); I915_WRITE(_TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B); I915_WRITE(_TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B); I915_WRITE(_TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B); } /* Restore plane info */ I915_WRITE(_DSPBSIZE, dev_priv->saveDSPBSIZE); I915_WRITE(_DSPBPOS, dev_priv->saveDSPBPOS); I915_WRITE(_PIPEBSRC, dev_priv->savePIPEBSRC); I915_WRITE(_DSPBADDR, dev_priv->saveDSPBADDR); I915_WRITE(_DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); if (INTEL_INFO(dev)->gen >= 4) { I915_WRITE(_DSPBSURF, dev_priv->saveDSPBSURF); I915_WRITE(_DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); } I915_WRITE(_PIPEBCONF, dev_priv->savePIPEBCONF); i915_restore_palette(dev, PIPE_B); /* Enable the plane */ I915_WRITE(_DSPBCNTR, dev_priv->saveDSPBCNTR); I915_WRITE(_DSPBADDR, I915_READ(_DSPBADDR)); /* Cursor state */ I915_WRITE(_CURAPOS, dev_priv->saveCURAPOS); I915_WRITE(_CURACNTR, dev_priv->saveCURACNTR); I915_WRITE(_CURABASE, dev_priv->saveCURABASE); I915_WRITE(_CURBPOS, dev_priv->saveCURBPOS); I915_WRITE(_CURBCNTR, dev_priv->saveCURBCNTR); I915_WRITE(_CURBBASE, dev_priv->saveCURBBASE); if (IS_GEN2(dev)) I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); return; }
static void i915_save_display(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; /* Display arbitration control */ dev_priv->saveDSPARB = I915_READ(DSPARB); /* This is only meaningful in non-KMS mode */ /* Don't save them in KMS mode */ i915_save_modeset_reg(dev); /* CRT state */ if (HAS_PCH_SPLIT(dev)) { dev_priv->saveADPA = I915_READ(PCH_ADPA); } else { dev_priv->saveADPA = I915_READ(ADPA); } /* LVDS state */ if (HAS_PCH_SPLIT(dev)) { dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL); dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1); dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2); dev_priv->saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL); dev_priv->saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2); dev_priv->saveLVDS = I915_READ(PCH_LVDS); } else { dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL); if (INTEL_INFO(dev)->gen >= 4) dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); if (IS_MOBILE(dev) && !IS_I830(dev)) dev_priv->saveLVDS = I915_READ(LVDS); } if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev)) dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL); if (HAS_PCH_SPLIT(dev)) { dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS); dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS); dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR); } else { dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS); dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); } /* Display Port state */ if (SUPPORTS_INTEGRATED_DP(dev)) { dev_priv->saveDP_B = I915_READ(DP_B); dev_priv->saveDP_C = I915_READ(DP_C); dev_priv->saveDP_D = I915_READ(DP_D); dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_GMCH_DATA_M); dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_GMCH_DATA_M); dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_GMCH_DATA_N); dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_GMCH_DATA_N); dev_priv->savePIPEA_DP_LINK_M = I915_READ(_PIPEA_DP_LINK_M); dev_priv->savePIPEB_DP_LINK_M = I915_READ(_PIPEB_DP_LINK_M); dev_priv->savePIPEA_DP_LINK_N = I915_READ(_PIPEA_DP_LINK_N); dev_priv->savePIPEB_DP_LINK_N = I915_READ(_PIPEB_DP_LINK_N); } /* FIXME: save TV & SDVO state */ /* Only save FBC state on the platform that supports FBC */ if (I915_HAS_FBC(dev)) { if (HAS_PCH_SPLIT(dev)) { dev_priv->saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE); } else if (IS_GM45(dev)) { dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE); } else { dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE); dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE); dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2); dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL); } } /* VGA state */ dev_priv->saveVGA0 = I915_READ(VGA0); dev_priv->saveVGA1 = I915_READ(VGA1); dev_priv->saveVGA_PD = I915_READ(VGA_PD); if (HAS_PCH_SPLIT(dev)) dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL); else dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); i915_save_vga(dev); }
int i915_save_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int i; pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); /* Hardware status page */ dev_priv->saveHWS = I915_READ(HWS_PGA); i915_save_display(dev); /* Interrupt state */ if (HAS_PCH_SPLIT(dev)) { dev_priv->saveDEIER = I915_READ(DEIER); dev_priv->saveDEIMR = I915_READ(DEIMR); dev_priv->saveGTIER = I915_READ(GTIER); dev_priv->saveGTIMR = I915_READ(GTIMR); dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR); dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR); dev_priv->saveMCHBAR_RENDER_STANDBY = I915_READ(MCHBAR_RENDER_STANDBY); } else { dev_priv->saveIER = I915_READ(IER); dev_priv->saveIMR = I915_READ(IMR); } if (HAS_PCH_SPLIT(dev)) ironlake_disable_drps(dev); /* Cache mode state */ dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); /* Memory Arbitration state */ dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE); /* Scratch space */ for (i = 0; i < 16; i++) { dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2)); dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2)); } for (i = 0; i < 3; i++) dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); /* Fences */ switch (INTEL_INFO(dev)->gen) { case 6: for (i = 0; i < 16; i++) dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); break; case 5: case 4: for (i = 0; i < 16; i++) dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8)); break; case 3: if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) for (i = 0; i < 8; i++) dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4)); case 2: for (i = 0; i < 8; i++) dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); break; } return 0; }
int i915_restore_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int i; pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); /* Hardware status page */ I915_WRITE(HWS_PGA, dev_priv->saveHWS); /* Fences */ switch (INTEL_INFO(dev)->gen) { case 6: for (i = 0; i < 16; i++) I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]); break; case 5: case 4: for (i = 0; i < 16; i++) I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]); break; case 3: case 2: if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) for (i = 0; i < 8; i++) I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); for (i = 0; i < 8; i++) I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]); break; } i915_restore_display(dev); /* Interrupt state */ if (HAS_PCH_SPLIT(dev)) { I915_WRITE(DEIER, dev_priv->saveDEIER); I915_WRITE(DEIMR, dev_priv->saveDEIMR); I915_WRITE(GTIER, dev_priv->saveGTIER); I915_WRITE(GTIMR, dev_priv->saveGTIMR); I915_WRITE(FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR); I915_WRITE(FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR); } else { I915_WRITE (IER, dev_priv->saveIER); I915_WRITE (IMR, dev_priv->saveIMR); } /* Clock gating state */ intel_init_clock_gating(dev); if (HAS_PCH_SPLIT(dev)) ironlake_enable_drps(dev); /* Cache mode state */ I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); /* Memory arbitration state */ I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); for (i = 0; i < 16; i++) { I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]); I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i]); } for (i = 0; i < 3; i++) I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); /* I2C state */ intel_i2c_reset_gmbus(dev); return 0; }
int i915_error_state_to_str(struct drm_i915_error_state_buf *m, const struct i915_error_state_file_priv *error_priv) { struct drm_device *dev = error_priv->dev; drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_error_state *error = error_priv->error; int i, j, page, offset, elt; if (!error) { err_printf(m, "no error state collected\n"); goto out; } err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, error->time.tv_usec); #ifdef __linux__ err_printf(m, "Kernel: " UTS_RELEASE "\n"); #endif err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device); err_printf(m, "EIR: 0x%08x\n", error->eir); err_printf(m, "IER: 0x%08x\n", error->ier); err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); err_printf(m, "DERRMR: 0x%08x\n", error->derrmr); err_printf(m, "CCID: 0x%08x\n", error->ccid); err_printf(m, "Missed interrupts: 0x%08lx\n", dev_priv->gpu_error.missed_irq_rings); for (i = 0; i < dev_priv->num_fence_regs; i++) err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++) err_printf(m, " INSTDONE_%d: 0x%08x\n", i, error->extra_instdone[i]); if (INTEL_INFO(dev)->gen >= 6) { err_printf(m, "ERROR: 0x%08x\n", error->error); err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg); } if (INTEL_INFO(dev)->gen == 7) err_printf(m, "ERR_INT: 0x%08x\n", error->err_int); for (i = 0; i < ARRAY_SIZE(error->ring); i++) i915_ring_error_state(m, dev, error, i); if (error->active_bo) print_error_buffers(m, "Active", error->active_bo[0], error->active_bo_count[0]); if (error->pinned_bo) print_error_buffers(m, "Pinned", error->pinned_bo[0], error->pinned_bo_count[0]); for (i = 0; i < ARRAY_SIZE(error->ring); i++) { struct drm_i915_error_object *obj; if ((obj = error->ring[i].batchbuffer)) { err_printf(m, "%s --- gtt_offset = 0x%08x\n", dev_priv->ring[i].name, obj->gtt_offset); offset = 0; for (page = 0; page < obj->page_count; page++) { for (elt = 0; elt < PAGE_SIZE/4; elt++) { err_printf(m, "%08x : %08x\n", offset, obj->pages[page][elt]); offset += 4; } } } if (error->ring[i].num_requests) { err_printf(m, "%s --- %d requests\n", dev_priv->ring[i].name, error->ring[i].num_requests); for (j = 0; j < error->ring[i].num_requests; j++) { err_printf(m, " seqno 0x%08x, emitted %ld, tail 0x%08x\n", error->ring[i].requests[j].seqno, error->ring[i].requests[j].jiffies, error->ring[i].requests[j].tail); } } if ((obj = error->ring[i].ringbuffer)) { err_printf(m, "%s --- ringbuffer = 0x%08x\n", dev_priv->ring[i].name, obj->gtt_offset); offset = 0; for (page = 0; page < obj->page_count; page++) { for (elt = 0; elt < PAGE_SIZE/4; elt++) { err_printf(m, "%08x : %08x\n", offset, obj->pages[page][elt]); offset += 4; } } } if ((obj = error->ring[i].ctx)) { err_printf(m, "%s --- HW Context = 0x%08x\n", dev_priv->ring[i].name, obj->gtt_offset); offset = 0; for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { err_printf(m, "[%04x] %08x %08x %08x %08x\n", offset, obj->pages[0][elt], obj->pages[0][elt+1], obj->pages[0][elt+2], obj->pages[0][elt+3]); offset += 16; } } } #ifdef notyet if (error->overlay) intel_overlay_print_error_state(m, error->overlay); if (error->display) intel_display_print_error_state(m, dev, error->display); #endif out: if (m->bytes == 0 && m->err) return m->err; return 0; }
static int render_ring_flush(struct intel_ring_buffer *ring, u32 invalidate_domains, u32 flush_domains) { struct drm_device *dev = ring->dev; u32 cmd; int ret; /* * read/write caches: * * I915_GEM_DOMAIN_RENDER is always invalidated, but is * only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is * also flushed at 2d versus 3d pipeline switches. * * read-only caches: * * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if * MI_READ_FLUSH is set, and is always flushed on 965. * * I915_GEM_DOMAIN_COMMAND may not exist? * * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is * invalidated when MI_EXE_FLUSH is set. * * I915_GEM_DOMAIN_VERTEX, which exists on 965, is * invalidated with every MI_FLUSH. * * TLBs: * * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER * are flushed at any MI_FLUSH. */ cmd = MI_FLUSH | MI_NO_WRITE_FLUSH; if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) cmd &= ~MI_NO_WRITE_FLUSH; if (INTEL_INFO(dev)->gen < 4) { /* * On the 965, the sampler cache always gets flushed * and this bit is reserved. */ if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER) cmd |= MI_READ_FLUSH; } if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) cmd |= MI_EXE_FLUSH; if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && (IS_G4X(dev) || IS_GEN5(dev))) cmd |= MI_INVALIDATE_ISP; ret = intel_ring_begin(ring, 2); if (ret) return ret; intel_ring_emit(ring, cmd); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); return 0; }
static unsigned int intel_uxa_pixmap_compute_size(PixmapPtr pixmap, int w, int h, uint32_t *tiling, int *stride, unsigned usage) { ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); int pitch, size; if (*tiling != I915_TILING_NONE) { /* First check whether tiling is necessary. */ pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; pitch = ALIGN(pitch, 64); size = pitch * ALIGN (h, 2); if (INTEL_INFO(intel)->gen < 40) { /* Gen 2/3 has a maximum stride for tiling of * 8192 bytes. */ if (pitch > KB(8)) *tiling = I915_TILING_NONE; /* Narrower than half a tile? */ if (pitch < 256) *tiling = I915_TILING_NONE; /* Older hardware requires fences to be pot size * aligned with a minimum of 1 MiB, so causes * massive overallocation for small textures. */ if (size < 1024*1024/2 && !intel->has_relaxed_fencing) *tiling = I915_TILING_NONE; } else if (!(usage & INTEL_CREATE_PIXMAP_DRI2) && size <= 4096) { /* Disable tiling beneath a page size, we will not see * any benefit from reducing TLB misses and instead * just incur extra cost when we require a fence. */ *tiling = I915_TILING_NONE; } } pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8; if (!(usage & INTEL_CREATE_PIXMAP_DRI2) && pitch <= 256) *tiling = I915_TILING_NONE; if (*tiling != I915_TILING_NONE) { int aligned_h, tile_height; if (IS_GEN2(intel)) tile_height = 16; else if (*tiling == I915_TILING_X) tile_height = 8; else tile_height = 32; aligned_h = ALIGN(h, tile_height); *stride = intel_get_fence_pitch(intel, ALIGN(pitch, 512), *tiling); /* Round the object up to the size of the fence it will live in * if necessary. We could potentially make the kernel allocate * a larger aperture space and just bind the subset of pages in, * but this is easier and also keeps us out of trouble (as much) * with drm_intel_bufmgr_check_aperture(). */ size = intel_get_fence_size(intel, *stride * aligned_h); if (size > intel->max_tiling_size) *tiling = I915_TILING_NONE; } if (*tiling == I915_TILING_NONE) { /* Round the height up so that the GPU's access to a 2x2 aligned * subspan doesn't address an invalid page offset beyond the * end of the GTT. */ *stride = ALIGN(pitch, 64); size = *stride * ALIGN(h, 2); } return size; }
void intel_detect_pch(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct pci_dev *pch = NULL; /* In all current cases, num_pipes is equivalent to the PCH_NOP setting * (which really amounts to a PCH but no South Display). */ if (INTEL_INFO(dev)->num_pipes == 0) { dev_priv->pch_type = PCH_NOP; return; } /* * The reason to probe ISA bridge instead of Dev31:Fun0 is to * make graphics device passthrough work easy for VMM, that only * need to expose ISA bridge to let driver know the real hardware * underneath. This is a requirement from virtualization team. * * In some virtualized environments (e.g. XEN), there is irrelevant * ISA bridge in the system. To work reliably, we should scan trhough * all the ISA bridge devices and check for the first match, instead * of only checking the first one. */ while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) { if (pch->vendor == PCI_VENDOR_ID_INTEL) { unsigned short id = pch->device & INTEL_PCH_DEVICE_ID_MASK; dev_priv->pch_id = id; if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_IBX; DRM_DEBUG_KMS("Found Ibex Peak PCH\n"); WARN_ON(!IS_GEN5(dev)); } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_CPT; DRM_DEBUG_KMS("Found CougarPoint PCH\n"); WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev))); } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { /* PantherPoint is CPT compatible */ dev_priv->pch_type = PCH_CPT; DRM_DEBUG_KMS("Found PantherPoint PCH\n"); WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev))); } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint PCH\n"); WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); WARN_ON(IS_HSW_ULT(dev) || IS_BDW_ULT(dev)); } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_LPT; DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); WARN_ON(!IS_HSW_ULT(dev) && !IS_BDW_ULT(dev)); } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_SPT; DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); WARN_ON(!IS_SKYLAKE(dev) && !IS_KABYLAKE(dev)); } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) { dev_priv->pch_type = PCH_SPT; DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); WARN_ON(!IS_SKYLAKE(dev) && !IS_KABYLAKE(dev)); } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) || (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) || ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) && pch->subsystem_vendor == 0x1af4 && pch->subsystem_device == 0x1100)) { dev_priv->pch_type = intel_virt_detect_pch(dev); } else continue; break; } } if (!pch) DRM_DEBUG_KMS("No PCH found.\n"); pci_dev_put(pch); }
/** * Detects bit 6 swizzling of address lookup between IGD access and CPU * access through main memory. */ void i915_gem_detect_bit_6_swizzle(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; if (INTEL_INFO(dev)->gen >= 6) { swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; } else if (IS_GEN5(dev)) { /* On Ironlake whatever DRAM config, GPU always do * same swizzling setup. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; } else if (IS_GEN2(dev)) { /* As far as we know, the 865 doesn't have these bit 6 * swizzling issues. */ swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; } else if (IS_MOBILE(dev) || (IS_GEN3(dev) && !IS_G33(dev))) { uint32_t dcc; /* On 9xx chipsets, channel interleave by the CPU is * determined by DCC. For single-channel, neither the CPU * nor the GPU do swizzling. For dual channel interleaved, * the GPU's interleave is bit 9 and 10 for X tiled, and bit * 9 for Y tiled. The CPU's interleave is independent, and * can be based on either bit 11 (haven't seen this yet) or * bit 17 (common). */ dcc = I915_READ(DCC); switch (dcc & DCC_ADDRESSING_MODE_MASK) { case DCC_ADDRESSING_MODE_SINGLE_CHANNEL: case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC: swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; break; case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED: if (dcc & DCC_CHANNEL_XOR_DISABLE) { /* This is the base swizzling by the GPU for * tiled buffers. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; } else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) { /* Bit 11 swizzling by the CPU in addition. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10_11; swizzle_y = I915_BIT_6_SWIZZLE_9_11; } else { /* Bit 17 swizzling by the CPU in addition. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10_17; swizzle_y = I915_BIT_6_SWIZZLE_9_17; } break; } if (dcc == 0xffffffff) { DRM_ERROR("Couldn't read from MCHBAR. " "Disabling tiling.\n"); swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; } } else { /* The 965, G33, and newer, have a very flexible memory * configuration. It will enable dual-channel mode * (interleaving) on as much memory as it can, and the GPU * will additionally sometimes enable different bit 6 * swizzling for tiled objects from the CPU. * * Here's what I found on the G965: * slot fill memory size swizzling * 0A 0B 1A 1B 1-ch 2-ch * 512 0 0 0 512 0 O * 512 0 512 0 16 1008 X * 512 0 0 512 16 1008 X * 0 512 0 512 16 1008 X * 1024 1024 1024 0 2048 1024 O * * We could probably detect this based on either the DRB * matching, which was the case for the swizzling required in * the table above, or from the 1-ch value being less than * the minimum size of a rank. */ if (I915_READ16(C0DRB3) != I915_READ16(C1DRB3)) { swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; } else { swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; } } dev_priv->mm.bit_6_swizzle_x = swizzle_x; dev_priv->mm.bit_6_swizzle_y = swizzle_y; }
static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv) { return IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8; }
void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, struct intel_crtc_config *pipe_config, int fitting_mode) { struct drm_device *dev = intel_crtc->base.dev; u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; struct drm_display_mode *mode, *adjusted_mode; mode = &pipe_config->requested_mode; adjusted_mode = &pipe_config->adjusted_mode; /* Native modes don't need fitting */ if (adjusted_mode->hdisplay == mode->hdisplay && adjusted_mode->vdisplay == mode->vdisplay) goto out; switch (fitting_mode) { case DRM_MODE_SCALE_CENTER: /* * For centered modes, we have to calculate border widths & * heights and modify the values programmed into the CRTC. */ centre_horizontally(adjusted_mode, mode->hdisplay); centre_vertically(adjusted_mode, mode->vdisplay); border = LVDS_BORDER_ENABLE; break; case DRM_MODE_SCALE_ASPECT: /* Scale but preserve the aspect ratio */ if (INTEL_INFO(dev)->gen >= 4) { u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; /* 965+ is easy, it does everything in hw */ if (scaled_width > scaled_height) pfit_control |= PFIT_ENABLE | PFIT_SCALING_PILLAR; else if (scaled_width < scaled_height) pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER; else if (adjusted_mode->hdisplay != mode->hdisplay) pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; } else { u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; /* * For earlier chips we have to calculate the scaling * ratio by hand and program it into the * PFIT_PGM_RATIO register */ if (scaled_width > scaled_height) { /* pillar */ centre_horizontally(adjusted_mode, scaled_height / mode->vdisplay); border = LVDS_BORDER_ENABLE; if (mode->vdisplay != adjusted_mode->vdisplay) { u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay); pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | bits << PFIT_VERT_SCALE_SHIFT); pfit_control |= (PFIT_ENABLE | VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); } } else if (scaled_width < scaled_height) { /* letter */ centre_vertically(adjusted_mode, scaled_width / mode->hdisplay); border = LVDS_BORDER_ENABLE; if (mode->hdisplay != adjusted_mode->hdisplay) { u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay); pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | bits << PFIT_VERT_SCALE_SHIFT); pfit_control |= (PFIT_ENABLE | VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); } } else { /* Aspects match, Let hw scale both directions */ pfit_control |= (PFIT_ENABLE | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR); } } break; case DRM_MODE_SCALE_FULLSCREEN: /* * Full scaling, even if it changes the aspect ratio. * Fortunately this is all done for us in hw. */ if (mode->vdisplay != adjusted_mode->vdisplay || mode->hdisplay != adjusted_mode->hdisplay) { pfit_control |= PFIT_ENABLE; if (INTEL_INFO(dev)->gen >= 4) pfit_control |= PFIT_SCALING_AUTO; else pfit_control |= (VERT_AUTO_SCALE | VERT_INTERP_BILINEAR | HORIZ_AUTO_SCALE | HORIZ_INTERP_BILINEAR); } break; default: WARN(1, "bad panel fit mode: %d\n", fitting_mode); return; } /* 965+ wants fuzzy fitting */ /* FIXME: handle multiple panels by failing gracefully */ if (INTEL_INFO(dev)->gen >= 4) pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | PFIT_FILTER_FUZZY); out: if ((pfit_control & PFIT_ENABLE) == 0) { pfit_control = 0; pfit_pgm_ratios = 0; } /* Make sure pre-965 set dither correctly for 18bpp panels. */ if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18) pfit_control |= PANEL_8TO6_DITHER_ENABLE; pipe_config->gmch_pfit.control = pfit_control; pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios; pipe_config->gmch_pfit.lvds_border_bits = border; }
static inline bool no_fbc_on_multiple_pipes(struct drm_i915_private *dev_priv) { return INTEL_INFO(dev_priv)->gen <= 3; }
static void i915_save_modeset_reg(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int i; if (drm_core_check_feature(dev, DRIVER_MODESET)) return; /* Cursor state */ dev_priv->saveCURACNTR = I915_READ(_CURACNTR); dev_priv->saveCURAPOS = I915_READ(_CURAPOS); dev_priv->saveCURABASE = I915_READ(_CURABASE); dev_priv->saveCURBCNTR = I915_READ(_CURBCNTR); dev_priv->saveCURBPOS = I915_READ(_CURBPOS); dev_priv->saveCURBBASE = I915_READ(_CURBBASE); if (IS_GEN2(dev)) dev_priv->saveCURSIZE = I915_READ(CURSIZE); if (HAS_PCH_SPLIT(dev)) { dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL); dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL); } /* Pipe & plane A info */ dev_priv->savePIPEACONF = I915_READ(_PIPEACONF); dev_priv->savePIPEASRC = I915_READ(_PIPEASRC); if (HAS_PCH_SPLIT(dev)) { dev_priv->saveFPA0 = I915_READ(_PCH_FPA0); dev_priv->saveFPA1 = I915_READ(_PCH_FPA1); dev_priv->saveDPLL_A = I915_READ(_PCH_DPLL_A); } else { dev_priv->saveFPA0 = I915_READ(_FPA0); dev_priv->saveFPA1 = I915_READ(_FPA1); dev_priv->saveDPLL_A = I915_READ(_DPLL_A); } if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) dev_priv->saveDPLL_A_MD = I915_READ(_DPLL_A_MD); dev_priv->saveHTOTAL_A = I915_READ(_HTOTAL_A); dev_priv->saveHBLANK_A = I915_READ(_HBLANK_A); dev_priv->saveHSYNC_A = I915_READ(_HSYNC_A); dev_priv->saveVTOTAL_A = I915_READ(_VTOTAL_A); dev_priv->saveVBLANK_A = I915_READ(_VBLANK_A); dev_priv->saveVSYNC_A = I915_READ(_VSYNC_A); if (!HAS_PCH_SPLIT(dev)) dev_priv->saveBCLRPAT_A = I915_READ(_BCLRPAT_A); if (HAS_PCH_SPLIT(dev)) { dev_priv->savePIPEA_DATA_M1 = I915_READ(_PIPEA_DATA_M1); dev_priv->savePIPEA_DATA_N1 = I915_READ(_PIPEA_DATA_N1); dev_priv->savePIPEA_LINK_M1 = I915_READ(_PIPEA_LINK_M1); dev_priv->savePIPEA_LINK_N1 = I915_READ(_PIPEA_LINK_N1); dev_priv->saveFDI_TXA_CTL = I915_READ(_FDI_TXA_CTL); dev_priv->saveFDI_RXA_CTL = I915_READ(_FDI_RXA_CTL); dev_priv->savePFA_CTL_1 = I915_READ(_PFA_CTL_1); dev_priv->savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ); dev_priv->savePFA_WIN_POS = I915_READ(_PFA_WIN_POS); dev_priv->saveTRANSACONF = I915_READ(_TRANSACONF); dev_priv->saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A); dev_priv->saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A); dev_priv->saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A); dev_priv->saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A); dev_priv->saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A); dev_priv->saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A); } dev_priv->saveDSPACNTR = I915_READ(_DSPACNTR); dev_priv->saveDSPASTRIDE = I915_READ(_DSPASTRIDE); dev_priv->saveDSPASIZE = I915_READ(_DSPASIZE); dev_priv->saveDSPAPOS = I915_READ(_DSPAPOS); dev_priv->saveDSPAADDR = I915_READ(_DSPAADDR); if (INTEL_INFO(dev)->gen >= 4) { dev_priv->saveDSPASURF = I915_READ(_DSPASURF); dev_priv->saveDSPATILEOFF = I915_READ(_DSPATILEOFF); } i915_save_palette(dev, PIPE_A); dev_priv->savePIPEASTAT = I915_READ(_PIPEASTAT); /* Pipe & plane B info */ dev_priv->savePIPEBCONF = I915_READ(_PIPEBCONF); dev_priv->savePIPEBSRC = I915_READ(_PIPEBSRC); if (HAS_PCH_SPLIT(dev)) { dev_priv->saveFPB0 = I915_READ(_PCH_FPB0); dev_priv->saveFPB1 = I915_READ(_PCH_FPB1); dev_priv->saveDPLL_B = I915_READ(_PCH_DPLL_B); } else { dev_priv->saveFPB0 = I915_READ(_FPB0); dev_priv->saveFPB1 = I915_READ(_FPB1); dev_priv->saveDPLL_B = I915_READ(_DPLL_B); } if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) dev_priv->saveDPLL_B_MD = I915_READ(_DPLL_B_MD); dev_priv->saveHTOTAL_B = I915_READ(_HTOTAL_B); dev_priv->saveHBLANK_B = I915_READ(_HBLANK_B); dev_priv->saveHSYNC_B = I915_READ(_HSYNC_B); dev_priv->saveVTOTAL_B = I915_READ(_VTOTAL_B); dev_priv->saveVBLANK_B = I915_READ(_VBLANK_B); dev_priv->saveVSYNC_B = I915_READ(_VSYNC_B); if (!HAS_PCH_SPLIT(dev)) dev_priv->saveBCLRPAT_B = I915_READ(_BCLRPAT_B); if (HAS_PCH_SPLIT(dev)) { dev_priv->savePIPEB_DATA_M1 = I915_READ(_PIPEB_DATA_M1); dev_priv->savePIPEB_DATA_N1 = I915_READ(_PIPEB_DATA_N1); dev_priv->savePIPEB_LINK_M1 = I915_READ(_PIPEB_LINK_M1); dev_priv->savePIPEB_LINK_N1 = I915_READ(_PIPEB_LINK_N1); dev_priv->saveFDI_TXB_CTL = I915_READ(_FDI_TXB_CTL); dev_priv->saveFDI_RXB_CTL = I915_READ(_FDI_RXB_CTL); dev_priv->savePFB_CTL_1 = I915_READ(_PFB_CTL_1); dev_priv->savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ); dev_priv->savePFB_WIN_POS = I915_READ(_PFB_WIN_POS); dev_priv->saveTRANSBCONF = I915_READ(_TRANSBCONF); dev_priv->saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B); dev_priv->saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B); dev_priv->saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B); dev_priv->saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B); dev_priv->saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B); dev_priv->saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B); } dev_priv->saveDSPBCNTR = I915_READ(_DSPBCNTR); dev_priv->saveDSPBSTRIDE = I915_READ(_DSPBSTRIDE); dev_priv->saveDSPBSIZE = I915_READ(_DSPBSIZE); dev_priv->saveDSPBPOS = I915_READ(_DSPBPOS); dev_priv->saveDSPBADDR = I915_READ(_DSPBADDR); if (INTEL_INFO(dev)->gen >= 4) { dev_priv->saveDSPBSURF = I915_READ(_DSPBSURF); dev_priv->saveDSPBTILEOFF = I915_READ(_DSPBTILEOFF); } i915_save_palette(dev, PIPE_B); dev_priv->savePIPEBSTAT = I915_READ(_PIPEBSTAT); /* Fences */ switch (INTEL_INFO(dev)->gen) { case 7: case 6: for (i = 0; i < 16; i++) dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); break; case 5: case 4: for (i = 0; i < 16; i++) dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8)); break; case 3: if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) for (i = 0; i < 8; i++) dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4)); case 2: for (i = 0; i < 8; i++) dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); break; } return; }
/** * i965_reset - reset chip after a hang * @dev: drm device to reset * @flags: reset domains * * Reset the chip. Useful if a hang is detected. Returns zero on successful * reset or otherwise an error code. * * Procedure is fairly simple: * - reset the chip using the reset reg * - re-init context state * - re-init hardware status page * - re-init ring buffer * - re-init interrupt state * - re-init display */ int i915_reset(struct drm_device *dev, u8 flags) { drm_i915_private_t *dev_priv = dev->dev_private; /* * We really should only reset the display subsystem if we actually * need to */ bool need_display = true; int ret; if (!i915_try_reset) return 0; if (!mutex_trylock(&dev->struct_mutex)) return -EBUSY; i915_gem_reset(dev); ret = -ENODEV; if (get_seconds() - dev_priv->last_gpu_reset < 5) { DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); } else switch (INTEL_INFO(dev)->gen) { case 7: case 6: ret = gen6_do_reset(dev, flags); break; case 5: ret = ironlake_do_reset(dev, flags); break; case 4: ret = i965_do_reset(dev, flags); break; case 2: ret = i8xx_do_reset(dev, flags); break; } dev_priv->last_gpu_reset = get_seconds(); if (ret) { DRM_ERROR("Failed to reset chip.\n"); mutex_unlock(&dev->struct_mutex); return ret; } /* Ok, now get things going again... */ /* * Everything depends on having the GTT running, so we need to start * there. Fortunately we don't need to do this unless we reset the * chip at a PCI level. * * Next we need to restore the context, but we don't use those * yet either... * * Ring buffer needs to be re-initialized in the KMS case, or if X * was running at the time of the reset (i.e. we weren't VT * switched away). */ if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->mm.suspended) { dev_priv->mm.suspended = 0; dev_priv->ring[RCS].init(&dev_priv->ring[RCS]); if (HAS_BSD(dev)) dev_priv->ring[VCS].init(&dev_priv->ring[VCS]); if (HAS_BLT(dev)) dev_priv->ring[BCS].init(&dev_priv->ring[BCS]); mutex_unlock(&dev->struct_mutex); drm_irq_uninstall(dev); drm_mode_config_reset(dev); drm_irq_install(dev); mutex_lock(&dev->struct_mutex); } mutex_unlock(&dev->struct_mutex); /* * Perform a full modeset as on later generations, e.g. Ironlake, we may * need to retrain the display link and cannot just restore the register * values. */ if (need_display) { mutex_lock(&dev->mode_config.mutex); drm_helper_resume_force_mode(dev); mutex_unlock(&dev->mode_config.mutex); } return 0; }
int i915_restore_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int i; pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); mutex_lock(&dev->struct_mutex); I915_WRITE(HWS_PGA, dev_priv->saveHWS); i915_restore_display(dev); if (HAS_PCH_SPLIT(dev)) { I915_WRITE(DEIER, dev_priv->saveDEIER); I915_WRITE(DEIMR, dev_priv->saveDEIMR); I915_WRITE(GTIER, dev_priv->saveGTIER); I915_WRITE(GTIMR, dev_priv->saveGTIMR); I915_WRITE(_FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR); I915_WRITE(_FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR); I915_WRITE(PCH_PORT_HOTPLUG, dev_priv->savePCH_PORT_HOTPLUG); } else { I915_WRITE(IER, dev_priv->saveIER); I915_WRITE(IMR, dev_priv->saveIMR); } mutex_unlock(&dev->struct_mutex); if (drm_core_check_feature(dev, DRIVER_MODESET)) intel_init_clock_gating(dev); if (IS_IRONLAKE_M(dev)) { ironlake_enable_drps(dev); intel_init_emon(dev); } if (INTEL_INFO(dev)->gen >= 6) { gen6_enable_rps(dev_priv); gen6_update_ring_freq(dev_priv); } mutex_lock(&dev->struct_mutex); I915_WRITE(CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); I915_WRITE(MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); for (i = 0; i < 16; i++) { I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]); I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i]); } for (i = 0; i < 3; i++) I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); mutex_unlock(&dev->struct_mutex); intel_i2c_reset(dev); return 0; }