Skip to content

Commit

Permalink
Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danve…
Browse files Browse the repository at this point in the history
…t/drm-intel into drm-next

Daniel writes: (this pull is the one with the bad patch dropped)
First pile of fixes for 3.6 already, and I'm afraid it's a bit larger than
what I'd wish for. But I've moved all the feature-y stuff to -next, so
this really is all -fixes. Most of it is handling fallout from the hw
context stuff, discovered now that mesa git has started using them for
real. Otherwise all just small fixes:
- unbreak modeset=0 on gen6+ (regressed in next)
- const mismatch fix for ->mode_fixup
- simplify overly clever lvds modeset code (current code can totally
  confuse backlights, resulting in broken panels until a full power draw
  restores them).
- fix some fallout from the flushing_list disabling (regression only
  introduced in -next)
- DP link train improvements (this also kills the last 3.2 dp regression
  afaik)
- bugfix for the new ddc VGA detection on newer platforms
- minor backlight fixes (one of them a -next regression)
- only enable the required PM interrupts (to avoid waking up the cpu
  unnecessarily)
- some really minor bits (workaround clarification, make coverty happy,
  hsw init fix)
* 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel: (23 commits)
  drm/i915: unbreak lastclose for failed driver init
  drm/i915: Set the context before setting up regs for the context.
  drm/i915: constify mode in crtc_mode_fixup
  drm/i915/lvds: ditch ->prepare special case
  drm/i915: dereferencing an error pointer
  drm/i915: fix invalid reference handling of the default ctx obj
  drm/i915: Add -EIO to the list of known errors for __wait_seqno
  drm/i915: Flush the context object from the CPU caches upon switching
  drm/i915: Make the lock for pageflips interruptible
  drm/i915: don't forget the PCH backlight registers
  drm/i915: Insert a flush between batches if the breadcrumb was dropped
  drm/i915: missing error case in init status page
  drm/i915: mask tiled bit when updating ILK sprites
  drm/i915: try to train DP even harder
  drm/i915: kill intel_ddc_probe
  drm/i915: check whether we actually received an edid in detect_ddc
  drm/i915: fix up PCH backlight #define mixup
  drm/i915: Add comments to explain the BSD tail write workaround
  drm/i915: Disable the BLT on pre-production SNB hardware
  drm/i915: initialize power wells in modeset_init_hw
  ...
  • Loading branch information
Dave Airlie committed Jul 26, 2012
2 parents 2536f7d + e8aeaee commit 98c7b42
Show file tree
Hide file tree
Showing 18 changed files with 140 additions and 119 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ static void i915_ring_error_state(struct seq_file *m,
seq_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]);
seq_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]);
if (INTEL_INFO(dev)->gen >= 6) {
seq_printf(m, " RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
seq_printf(m, " SYNC_0: 0x%08x\n",
error->semaphore_mboxes[ring][0]);
Expand Down
8 changes: 7 additions & 1 deletion drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1781,7 +1781,13 @@ void i915_driver_lastclose(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;

if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
/* On gen6+ we refuse to init without kms enabled, but then the drm core
* goes right around and calls lastclose. Check for this and don't clean
* up anything. */
if (!dev_priv)
return;

if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_fb_restore_mode(dev);
vga_switcheroo_process_delayed_switch();
return;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ struct drm_i915_error_state {
u32 instdone[I915_NUM_RINGS];
u32 acthd[I915_NUM_RINGS];
u32 semaphore_mboxes[I915_NUM_RINGS][I915_NUM_RINGS - 1];
u32 rc_psmi[I915_NUM_RINGS]; /* sleep state */
/* our own tracking of ring head and tail */
u32 cpu_ring_head[I915_NUM_RINGS];
u32 cpu_ring_tail[I915_NUM_RINGS];
Expand Down
19 changes: 18 additions & 1 deletion drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -2003,6 +2003,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
}

switch (end) {
case -EIO:
case -EAGAIN: /* Wedged */
case -ERESTARTSYS: /* Signal */
return (int)end;
Expand Down Expand Up @@ -3726,6 +3727,22 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
}
}

static bool
intel_enable_blt(struct drm_device *dev)
{
if (!HAS_BLT(dev))
return false;

/* The blitter was dysfunctional on early prototypes */
if (IS_GEN6(dev) && dev->pdev->revision < 8) {
DRM_INFO("BLT not supported on this pre-production hardware;"
" graphics performance will be degraded.\n");
return false;
}

return true;
}

int
i915_gem_init_hw(struct drm_device *dev)
{
Expand All @@ -3749,7 +3766,7 @@ i915_gem_init_hw(struct drm_device *dev)
goto cleanup_render_ring;
}

if (HAS_BLT(dev)) {
if (intel_enable_blt(dev)) {
ret = intel_init_blt_ring_buffer(dev);
if (ret)
goto cleanup_bsd_ring;
Expand Down
37 changes: 20 additions & 17 deletions drivers/gpu/drm/i915/i915_gem_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ static int get_context_size(struct drm_device *dev)
ret = GEN6_CXT_TOTAL_SIZE(reg) * 64;
break;
case 7:
reg = I915_READ(GEN7_CTX_SIZE);
ret = GEN7_CTX_TOTAL_SIZE(reg) * 64;
reg = I915_READ(GEN7_CXT_SIZE);
ret = GEN7_CXT_TOTAL_SIZE(reg) * 64;
break;
default:
BUG();
Expand Down Expand Up @@ -374,6 +374,17 @@ static int do_switch(struct drm_i915_gem_object *from_obj,
if (ret)
return ret;

/* Clear this page out of any CPU caches for coherent swap-in/out. Note
* that thanks to write = false in this call and us not setting any gpu
* write domains when putting a context object onto the active list
* (when switching away from it), this won't block.
* XXX: We need a real interface to do this instead of trickery. */
ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
if (ret) {
i915_gem_object_unpin(to->obj);
return ret;
}

if (!to->obj->has_global_gtt_mapping)
i915_gem_gtt_bind_object(to->obj, to->obj->cache_level);

Expand Down Expand Up @@ -408,8 +419,11 @@ static int do_switch(struct drm_i915_gem_object *from_obj,
from_obj->dirty = 1;
BUG_ON(from_obj->ring != to->ring);
i915_gem_object_unpin(from_obj);

drm_gem_object_unreference(&from_obj->base);
}

drm_gem_object_reference(&to->obj->base);
ring->last_context_obj = to->obj;
to->is_initialized = true;

Expand Down Expand Up @@ -459,20 +473,7 @@ int i915_switch_context(struct intel_ring_buffer *ring,
if (from_obj == to->obj)
return 0;

ret = do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring));
if (ret)
return ret;

/* Just to make the code a little cleaner we take the object reference
* after the switch was successful. It would be more intuitive to ref
* the 'to' object before the switch but we know the refcount must be >0
* if context_get() succeeded, and we hold struct mutex. So it's safe to
* do this here/now
*/
drm_gem_object_reference(&to->obj->base);
if (from_obj != NULL)
drm_gem_object_unreference(&from_obj->base);
return ret;
return do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring));
}

int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
Expand All @@ -496,11 +497,13 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,

ctx = create_hw_context(dev, file_priv);
mutex_unlock(&dev->struct_mutex);
if (IS_ERR(ctx))
return PTR_ERR(ctx);

args->ctx_id = ctx->id;
DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id);

return PTR_RET(ctx);
return 0;
}

int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
Expand Down
17 changes: 11 additions & 6 deletions drivers/gpu/drm/i915/i915_gem_execbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -885,11 +885,16 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
return ret;
}

/* Unconditionally invalidate gpu caches. */
ret = i915_gem_flush_ring(ring, I915_GEM_GPU_DOMAINS, 0);
/* Unconditionally invalidate gpu caches and ensure that we do flush
* any residual writes from the previous batch.
*/
ret = i915_gem_flush_ring(ring,
I915_GEM_GPU_DOMAINS,
ring->gpu_caches_dirty ? I915_GEM_GPU_DOMAINS : 0);
if (ret)
return ret;

ring->gpu_caches_dirty = false;
return 0;
}

Expand Down Expand Up @@ -1223,6 +1228,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
}
}

ret = i915_switch_context(ring, file, ctx_id);
if (ret)
goto err;

if (ring == &dev_priv->ring[RCS] &&
mode != dev_priv->relative_constants_mode) {
ret = intel_ring_begin(ring, 4);
Expand All @@ -1244,10 +1253,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
goto err;
}

ret = i915_switch_context(ring, file, ctx_id);
if (ret)
goto err;

trace_i915_gem_ring_dispatch(ring, seqno);

exec_start = batch_obj->gtt_offset + args->batch_start_offset;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,7 @@ static void i915_record_ring_state(struct drm_device *dev,
struct drm_i915_private *dev_priv = dev->dev_private;

if (INTEL_INFO(dev)->gen >= 6) {
error->rc_psmi[ring->id] = I915_READ(ring->mmio_base + 0x50);
error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));
error->semaphore_mboxes[ring->id][0]
= I915_READ(RING_SYNC_0(ring->mmio_base));
Expand Down
32 changes: 18 additions & 14 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -690,10 +690,10 @@
#define GEN6_BLITTER_FBC_NOTIFY (1<<3)

#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050
#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16)
#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0)
#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0
#define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3)
#define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0)
#define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2)
#define GEN6_BSD_SLEEP_INDICATOR (1 << 3)
#define GEN6_BSD_GO_INDICATOR (1 << 4)

#define GEN6_BSD_HWSTAM 0x12098
#define GEN6_BSD_IMR 0x120a8
Expand Down Expand Up @@ -1482,15 +1482,19 @@
GEN6_CXT_RENDER_SIZE(cxt_reg) + \
GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \
GEN6_CXT_PIPELINE_SIZE(cxt_reg))
#define GEN7_CTX_SIZE 0x21a8
#define GEN7_CTX_RENDER_SIZE(ctx_reg) ((ctx_reg >> 16) & 0x3f)
#define GEN7_CTX_EXTENDED_SIZE(ctx_reg) ((ctx_reg >> 9) & 0x7f)
#define GEN7_CTX_GT1_SIZE(ctx_reg) ((ctx_reg >> 6) & 0x7)
#define GEN7_CTX_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f)
#define GEN7_CTX_TOTAL_SIZE(ctx_reg) (GEN7_CTX_RENDER_SIZE(ctx_reg) + \
GEN7_CTX_EXTENDED_SIZE(ctx_reg) + \
GEN7_CTX_GT1_SIZE(ctx_reg) + \
GEN7_CTX_VFSTATE_SIZE(ctx_reg))
#define GEN7_CXT_SIZE 0x21a8
#define GEN7_CXT_POWER_SIZE(ctx_reg) ((ctx_reg >> 25) & 0x7f)
#define GEN7_CXT_RING_SIZE(ctx_reg) ((ctx_reg >> 22) & 0x7)
#define GEN7_CXT_RENDER_SIZE(ctx_reg) ((ctx_reg >> 16) & 0x3f)
#define GEN7_CXT_EXTENDED_SIZE(ctx_reg) ((ctx_reg >> 9) & 0x7f)
#define GEN7_CXT_GT1_SIZE(ctx_reg) ((ctx_reg >> 6) & 0x7)
#define GEN7_CXT_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f)
#define GEN7_CXT_TOTAL_SIZE(ctx_reg) (GEN7_CXT_POWER_SIZE(ctx_reg) + \
GEN7_CXT_RING_SIZE(ctx_reg) + \
GEN7_CXT_RENDER_SIZE(ctx_reg) + \
GEN7_CXT_EXTENDED_SIZE(ctx_reg) + \
GEN7_CXT_GT1_SIZE(ctx_reg) + \
GEN7_CXT_VFSTATE_SIZE(ctx_reg))

/*
* Overlay regs
Expand Down Expand Up @@ -1896,7 +1900,7 @@
/* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is
* like the normal CTL from gen4 and earlier. Hooray for confusing naming. */
#define BLC_PWM_PCH_CTL1 0xc8250
#define BLM_PCH_PWM_ENABLE (1 << 30)
#define BLM_PCH_PWM_ENABLE (1 << 31)
#define BLM_PCH_OVERRIDE_ENABLE (1 << 30)
#define BLM_PCH_POLARITY (1 << 29)
#define BLC_PWM_PCH_CTL2 0xc8254
Expand Down
33 changes: 14 additions & 19 deletions drivers/gpu/drm/i915/intel_crt.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,39 +330,34 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
{
struct intel_crt *crt = intel_attached_crt(connector);
struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private;
struct edid *edid;
struct i2c_adapter *i2c;

BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);

/* CRT should always be at 0, but check anyway */
if (crt->base.type != INTEL_OUTPUT_ANALOG)
return false;
i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
edid = drm_get_edid(connector, i2c);

if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
struct edid *edid;
bool is_digital = false;
struct i2c_adapter *i2c;
if (edid) {
bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;

i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
edid = drm_get_edid(connector, i2c);
/*
* This may be a DVI-I connector with a shared DDC
* link between analog and digital outputs, so we
* have to check the EDID input spec of the attached device.
*
* On the other hand, what should we do if it is a broken EDID?
*/
if (edid != NULL) {
is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
connector->display_info.raw_edid = NULL;
kfree(edid);
}

if (!is_digital) {
DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
return true;
} else {
DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
}

DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
} else {
DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [no valid EDID found]\n");
}

kfree(edid);

return false;
}

Expand Down
12 changes: 10 additions & 2 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -3573,7 +3573,7 @@ void intel_encoder_destroy(struct drm_encoder *encoder)
}

static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = crtc->dev;
Expand Down Expand Up @@ -6486,7 +6486,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
intel_fb = to_intel_framebuffer(fb);
obj = intel_fb->obj;

mutex_lock(&dev->struct_mutex);
ret = i915_mutex_lock_interruptible(dev);
if (ret)
goto cleanup;

/* Reference the objects for the scheduled work. */
drm_gem_object_reference(&work->old_fb_obj->base);
Expand Down Expand Up @@ -6521,6 +6523,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
drm_gem_object_unreference(&obj->base);
mutex_unlock(&dev->struct_mutex);

cleanup:
spin_lock_irqsave(&dev->event_lock, flags);
intel_crtc->unpin_work = NULL;
spin_unlock_irqrestore(&dev->event_lock, flags);
Expand Down Expand Up @@ -7174,6 +7177,11 @@ static void i915_disable_vga(struct drm_device *dev)

void intel_modeset_init_hw(struct drm_device *dev)
{
/* We attempt to init the necessary power wells early in the initialization
* time, so the subsystems that expect power to be enabled can work.
*/
intel_init_power_wells(dev);

intel_prepare_ddi(dev);

intel_init_clock_gating(dev);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/intel_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1771,7 +1771,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
for (i = 0; i < intel_dp->lane_count; i++)
if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
break;
if (i == intel_dp->lane_count) {
if (i == intel_dp->lane_count && voltage_tries == 5) {
++loop_tries;
if (loop_tries == 5) {
DRM_DEBUG_KMS("too many full retries, give up\n");
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@ struct intel_fbc_work {
};

int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);

extern void intel_attach_force_audio_property(struct drm_connector *connector);
extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
Expand Down Expand Up @@ -496,6 +495,7 @@ extern void intel_update_fbc(struct drm_device *dev);
extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
extern void intel_gpu_ips_teardown(void);

extern void intel_init_power_wells(struct drm_device *dev);
extern void intel_enable_gt_powersave(struct drm_device *dev);
extern void intel_disable_gt_powersave(struct drm_device *dev);
extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv);
Expand Down
8 changes: 1 addition & 7 deletions drivers/gpu/drm/i915/intel_lvds.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,13 +409,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
{
struct intel_lvds *intel_lvds = to_intel_lvds(encoder);

/*
* Prior to Ironlake, we must disable the pipe if we want to adjust
* the panel fitter. However at all other times we can just reset
* the registers regardless.
*/
if (!HAS_PCH_SPLIT(encoder->dev) && intel_lvds->pfit_dirty)
intel_lvds_disable(intel_lvds);
intel_lvds_disable(intel_lvds);
}

static void intel_lvds_commit(struct drm_encoder *encoder)
Expand Down
Loading

0 comments on commit 98c7b42

Please sign in to comment.