Merge tag 'drm-intel-next-2014-10-24' of git://anongit.freedesktop.org/drm-intel into drm-next
- suspend/resume/freeze/thaw unification from Imre - wa list improvements from Mika&Arun - display pll precomputation from Ander Conselvan, this removed the last ->mode_set callbacks, a big step towards implementing atomic modesets - more kerneldoc for the interrupt code - 180 rotation for cursors (Ville&Sonika) - ULT/ULX feature check macros cleaned up thanks to Damien - piles and piles of fixes all over, bug team seems to work! * tag 'drm-intel-next-2014-10-24' of git://anongit.freedesktop.org/drm-intel: (61 commits) drm/i915: Update DRIVER_DATE to 20141024 drm/i915: add comments on what stage a given PM handler is called drm/i915: unify switcheroo and legacy suspend/resume handlers drm/i915: add poweroff_late handler drm/i915: sanitize suspend/resume helper function names drm/i915: unify S3 and S4 suspend/resume handlers drm/i915: disable/re-enable PCI device around S4 freeze/thaw drm/i915: enable output polling during S4 thaw drm/i915: check for GT faults in all resume handlers and driver load time drm/i915: remove unused restore_gtt_mappings optimization during suspend drm/i915: fix S4 suspend while switcheroo state is off drm/i915: vlv: fix switcheroo/legacy suspend/resume drm/i915: propagate error from legacy resume handler drm/i915: unify legacy S3 suspend and S4 freeze handlers drm/i915: factor out i915_drm_suspend_late drm/i915: Emit even number of dwords when emitting LRIs drm/i915: Add rotation support for cursor plane (v5) drm/i915: Correctly reject invalid flags for wait_ioctl drm/i915: use macros to assign mmio access functions drm/i915: only run hsw_power_well_post_enable when really needed ...
This commit is contained in:
@@ -665,80 +665,108 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void intel_ring_emit_wa(struct intel_engine_cs *ring,
|
||||
u32 addr, u32 value)
|
||||
static int intel_ring_workarounds_emit(struct intel_engine_cs *ring)
|
||||
{
|
||||
int ret, i;
|
||||
struct drm_device *dev = ring->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct i915_workarounds *w = &dev_priv->workarounds;
|
||||
|
||||
if (WARN_ON(dev_priv->num_wa_regs >= I915_MAX_WA_REGS))
|
||||
return;
|
||||
if (WARN_ON(w->count == 0))
|
||||
return 0;
|
||||
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
||||
intel_ring_emit(ring, addr);
|
||||
intel_ring_emit(ring, value);
|
||||
|
||||
dev_priv->intel_wa_regs[dev_priv->num_wa_regs].addr = addr;
|
||||
dev_priv->intel_wa_regs[dev_priv->num_wa_regs].mask = value & 0xFFFF;
|
||||
/* value is updated with the status of remaining bits of this
|
||||
* register when it is read from debugfs file
|
||||
*/
|
||||
dev_priv->intel_wa_regs[dev_priv->num_wa_regs].value = value;
|
||||
dev_priv->num_wa_regs++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int bdw_init_workarounds(struct intel_engine_cs *ring)
|
||||
{
|
||||
int ret;
|
||||
struct drm_device *dev = ring->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
/*
|
||||
* workarounds applied in this fn are part of register state context,
|
||||
* they need to be re-initialized followed by gpu reset, suspend/resume,
|
||||
* module reload.
|
||||
*/
|
||||
dev_priv->num_wa_regs = 0;
|
||||
memset(dev_priv->intel_wa_regs, 0, sizeof(dev_priv->intel_wa_regs));
|
||||
|
||||
/*
|
||||
* update the number of dwords required based on the
|
||||
* actual number of workarounds applied
|
||||
*/
|
||||
ret = intel_ring_begin(ring, 18);
|
||||
ring->gpu_caches_dirty = true;
|
||||
ret = intel_ring_flush_all_caches(ring);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_ring_begin(ring, (w->count * 2 + 2));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count));
|
||||
for (i = 0; i < w->count; i++) {
|
||||
intel_ring_emit(ring, w->reg[i].addr);
|
||||
intel_ring_emit(ring, w->reg[i].value);
|
||||
}
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
|
||||
intel_ring_advance(ring);
|
||||
|
||||
ring->gpu_caches_dirty = true;
|
||||
ret = intel_ring_flush_all_caches(ring);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wa_add(struct drm_i915_private *dev_priv,
|
||||
const u32 addr, const u32 val, const u32 mask)
|
||||
{
|
||||
const u32 idx = dev_priv->workarounds.count;
|
||||
|
||||
if (WARN_ON(idx >= I915_MAX_WA_REGS))
|
||||
return -ENOSPC;
|
||||
|
||||
dev_priv->workarounds.reg[idx].addr = addr;
|
||||
dev_priv->workarounds.reg[idx].value = val;
|
||||
dev_priv->workarounds.reg[idx].mask = mask;
|
||||
|
||||
dev_priv->workarounds.count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define WA_REG(addr, val, mask) { \
|
||||
const int r = wa_add(dev_priv, (addr), (val), (mask)); \
|
||||
if (r) \
|
||||
return r; \
|
||||
}
|
||||
|
||||
#define WA_SET_BIT_MASKED(addr, mask) \
|
||||
WA_REG(addr, _MASKED_BIT_ENABLE(mask), (mask) & 0xffff)
|
||||
|
||||
#define WA_CLR_BIT_MASKED(addr, mask) \
|
||||
WA_REG(addr, _MASKED_BIT_DISABLE(mask), (mask) & 0xffff)
|
||||
|
||||
#define WA_SET_BIT(addr, mask) WA_REG(addr, I915_READ(addr) | (mask), mask)
|
||||
#define WA_CLR_BIT(addr, mask) WA_REG(addr, I915_READ(addr) & ~(mask), mask)
|
||||
|
||||
#define WA_WRITE(addr, val) WA_REG(addr, val, 0xffffffff)
|
||||
|
||||
static int bdw_init_workarounds(struct intel_engine_cs *ring)
|
||||
{
|
||||
struct drm_device *dev = ring->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
/* WaDisablePartialInstShootdown:bdw */
|
||||
/* WaDisableThreadStallDopClockGating:bdw */
|
||||
/* FIXME: Unclear whether we really need this on production bdw. */
|
||||
intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN,
|
||||
_MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE
|
||||
| STALL_DOP_GATING_DISABLE));
|
||||
/* WaDisableThreadStallDopClockGating:bdw (pre-production) */
|
||||
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
|
||||
PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE |
|
||||
STALL_DOP_GATING_DISABLE);
|
||||
|
||||
/* WaDisableDopClockGating:bdw May not be needed for production */
|
||||
intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2,
|
||||
_MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
|
||||
/* WaDisableDopClockGating:bdw */
|
||||
WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
|
||||
DOP_CLOCK_GATING_DISABLE);
|
||||
|
||||
intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3,
|
||||
_MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS));
|
||||
WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
|
||||
GEN8_SAMPLER_POWER_BYPASS_DIS);
|
||||
|
||||
/* Use Force Non-Coherent whenever executing a 3D context. This is a
|
||||
* workaround for for a possible hang in the unlikely event a TLB
|
||||
* invalidation occurs during a PSD flush.
|
||||
*/
|
||||
/* WaDisableFenceDestinationToSLM:bdw (GT3 pre-production) */
|
||||
intel_ring_emit_wa(ring, HDC_CHICKEN0,
|
||||
_MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT |
|
||||
(IS_BDW_GT3(dev) ?
|
||||
HDC_FENCE_DEST_SLM_DISABLE : 0)
|
||||
));
|
||||
WA_SET_BIT_MASKED(HDC_CHICKEN0,
|
||||
HDC_FORCE_NON_COHERENT |
|
||||
(IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
|
||||
|
||||
/* Wa4x4STCOptimizationDisable:bdw */
|
||||
intel_ring_emit_wa(ring, CACHE_MODE_1,
|
||||
_MASKED_BIT_ENABLE(GEN8_4x4_STC_OPTIMIZATION_DISABLE));
|
||||
WA_SET_BIT_MASKED(CACHE_MODE_1,
|
||||
GEN8_4x4_STC_OPTIMIZATION_DISABLE);
|
||||
|
||||
/*
|
||||
* BSpec recommends 8x4 when MSAA is used,
|
||||
@@ -748,52 +776,50 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
|
||||
* disable bit, which we don't touch here, but it's good
|
||||
* to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
|
||||
*/
|
||||
intel_ring_emit_wa(ring, GEN7_GT_MODE,
|
||||
GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4);
|
||||
|
||||
intel_ring_advance(ring);
|
||||
|
||||
DRM_DEBUG_DRIVER("Number of Workarounds applied: %d\n",
|
||||
dev_priv->num_wa_regs);
|
||||
WA_SET_BIT_MASKED(GEN7_GT_MODE,
|
||||
GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chv_init_workarounds(struct intel_engine_cs *ring)
|
||||
{
|
||||
int ret;
|
||||
struct drm_device *dev = ring->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
/*
|
||||
* workarounds applied in this fn are part of register state context,
|
||||
* they need to be re-initialized followed by gpu reset, suspend/resume,
|
||||
* module reload.
|
||||
*/
|
||||
dev_priv->num_wa_regs = 0;
|
||||
memset(dev_priv->intel_wa_regs, 0, sizeof(dev_priv->intel_wa_regs));
|
||||
|
||||
ret = intel_ring_begin(ring, 12);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* WaDisablePartialInstShootdown:chv */
|
||||
intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN,
|
||||
_MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE));
|
||||
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
|
||||
PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
|
||||
|
||||
/* WaDisableThreadStallDopClockGating:chv */
|
||||
intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN,
|
||||
_MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE));
|
||||
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
|
||||
STALL_DOP_GATING_DISABLE);
|
||||
|
||||
/* WaDisableDopClockGating:chv (pre-production hw) */
|
||||
intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2,
|
||||
_MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
|
||||
WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
|
||||
DOP_CLOCK_GATING_DISABLE);
|
||||
|
||||
/* WaDisableSamplerPowerBypass:chv (pre-production hw) */
|
||||
intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3,
|
||||
_MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS));
|
||||
WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
|
||||
GEN8_SAMPLER_POWER_BYPASS_DIS);
|
||||
|
||||
intel_ring_advance(ring);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_workarounds_ring(struct intel_engine_cs *ring)
|
||||
{
|
||||
struct drm_device *dev = ring->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
WARN_ON(ring->id != RCS);
|
||||
|
||||
dev_priv->workarounds.count = 0;
|
||||
|
||||
if (IS_BROADWELL(dev))
|
||||
return bdw_init_workarounds(ring);
|
||||
|
||||
if (IS_CHERRYVIEW(dev))
|
||||
return chv_init_workarounds(ring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -853,7 +879,7 @@ static int init_render_ring(struct intel_engine_cs *ring)
|
||||
if (HAS_L3_DPF(dev))
|
||||
I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
|
||||
|
||||
return ret;
|
||||
return init_workarounds_ring(ring);
|
||||
}
|
||||
|
||||
static void render_ring_cleanup(struct intel_engine_cs *ring)
|
||||
@@ -2299,10 +2325,8 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
|
||||
dev_priv->semaphore_obj = obj;
|
||||
}
|
||||
}
|
||||
if (IS_CHERRYVIEW(dev))
|
||||
ring->init_context = chv_init_workarounds;
|
||||
else
|
||||
ring->init_context = bdw_init_workarounds;
|
||||
|
||||
ring->init_context = intel_ring_workarounds_emit;
|
||||
ring->add_request = gen6_add_request;
|
||||
ring->flush = gen8_render_ring_flush;
|
||||
ring->irq_get = gen8_ring_get_irq;
|
||||
|
Reference in New Issue
Block a user