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:

Bigger -fixes pile, mostly because I've included Ajax' DP dongle stuff,
as discussed on irc. Otherwise just small things:
- regression fix to finally make 6bpc auto-dither on dp work (Jani)
- reinstate an snb ctx w/a that accidentally got lost in a rework (Chris)
- fixup the DP train sequence, logic-goof-up uncovered by Coverty (Chris)
- fix set_caching locking (Ben)
- fix spurious segfault on con-current gtt mmap faulting (Dimitry and Mika)
- some pageflip correctness fixes (still hunting down some issues, but
  these are the worst offenders of confused code that we've tracked down
  thus far) from Chris and me
- fixup swizzling settings on vlv (Jesse)
- gt_mode w/a from Ben added, fixes snb gt1 rc6+hw ctx hangs.

* 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel:
  drm/i915: Fix GT_MODE default value
  drm/i915: don't frob the vblank ts in finish_page_flip
  drm/i915: call drm_handle_vblank before finish_page_flip
  drm/i915: print warning if vmi915_gem_fault error is not handled
  drm/i915: EBUSY status handling added to i915_gem_fault().
  drm/i915: Try harder to complete DP training pattern 1
  drm/i915: set swizzling to none on VLV
  drm/dp: Make sink count DP 1.2 aware
  drm/dp: Document DP spec versions for various DPCD registers
  drm/i915/dp: Be smarter about connection sense for branch devices
  drm/i915/dp: Fetch downstream port info if needed during DPCD fetch
  drm/dp: Update DPCD defines
  drm: Export drm_probe_ddc()
  drm/i915: Flush the pending flips on the CRTC before modification
  drm/i915: Actually invalidate the TLB for the SandyBridge HW contexts w/a
  drm/i915: Fix set_caching locking
  drm/i915: use adjusted_mode instead of mode for checking the 6bpc force flag
  • Loading branch information
Dave Airlie committed Oct 7, 2012
2 parents a5a0fc6 + f8f2ac9 commit 1f31c69
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 75 deletions.
3 changes: 2 additions & 1 deletion drivers/gpu/drm/drm_edid.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,13 +395,14 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
* \param adapter : i2c device adaptor
* \return 1 on success
*/
static bool
bool
drm_probe_ddc(struct i2c_adapter *adapter)
{
unsigned char out;

return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0);
}
EXPORT_SYMBOL(drm_probe_ddc);

/**
* drm_get_edid - get EDID data, if available
Expand Down
14 changes: 10 additions & 4 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1399,10 +1399,16 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
case 0:
case -ERESTARTSYS:
case -EINTR:
case -EBUSY:
/*
* EBUSY is ok: this just means that another thread
* already did the job.
*/
return VM_FAULT_NOPAGE;
case -ENOMEM:
return VM_FAULT_OOM;
default:
WARN_ON_ONCE(ret);
return VM_FAULT_SIGBUS;
}
}
Expand Down Expand Up @@ -3217,10 +3223,6 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
enum i915_cache_level level;
int ret;

ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;

switch (args->caching) {
case I915_CACHING_NONE:
level = I915_CACHE_NONE;
Expand All @@ -3232,6 +3234,10 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}

ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;

obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
if (&obj->base == NULL) {
ret = -ENOENT;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_gem_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ mi_set_context(struct intel_ring_buffer *ring,
* itlb_before_ctx_switch.
*/
if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) {
ret = ring->flush(ring, 0, 0);
ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0);
if (ret)
return ret;
}
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/i915/i915_gem_tiling.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;

if (INTEL_INFO(dev)->gen >= 6) {
if (IS_VALLEYVIEW(dev)) {
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);
Expand Down
16 changes: 8 additions & 8 deletions drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -697,12 +697,12 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
intel_opregion_gse_intr(dev);

for (i = 0; i < 3; i++) {
if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
drm_handle_vblank(dev, i);
if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
intel_prepare_page_flip(dev, i);
intel_finish_page_flip_plane(dev, i);
}
if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
drm_handle_vblank(dev, i);
}

/* check event from PCH */
Expand Down Expand Up @@ -784,6 +784,12 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
if (de_iir & DE_GSE)
intel_opregion_gse_intr(dev);

if (de_iir & DE_PIPEA_VBLANK)
drm_handle_vblank(dev, 0);

if (de_iir & DE_PIPEB_VBLANK)
drm_handle_vblank(dev, 1);

if (de_iir & DE_PLANEA_FLIP_DONE) {
intel_prepare_page_flip(dev, 0);
intel_finish_page_flip_plane(dev, 0);
Expand All @@ -794,12 +800,6 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
intel_finish_page_flip_plane(dev, 1);
}

if (de_iir & DE_PIPEA_VBLANK)
drm_handle_vblank(dev, 0);

if (de_iir & DE_PIPEB_VBLANK)
drm_handle_vblank(dev, 1);

/* check event from PCH */
if (de_iir & DE_PCH_EVENT) {
if (pch_iir & hotplug_mask)
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,9 @@
# define VS_TIMER_DISPATCH (1 << 6)
# define MI_FLUSH_ENABLE (1 << 12)

#define GEN6_GT_MODE 0x20d0
#define GEN6_GT_MODE_HI (1 << 9)

#define GFX_MODE 0x02520
#define GFX_MODE_GEN7 0x0229c
#define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c)
Expand Down
52 changes: 26 additions & 26 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2806,13 +2806,34 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
udelay(100);
}

static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long flags;
bool pending;

if (atomic_read(&dev_priv->mm.wedged))
return false;

spin_lock_irqsave(&dev->event_lock, flags);
pending = to_intel_crtc(crtc)->unpin_work != NULL;
spin_unlock_irqrestore(&dev->event_lock, flags);

return pending;
}

static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;

if (crtc->fb == NULL)
return;

wait_event(dev_priv->pending_flip_queue,
!intel_crtc_has_pending_flip(crtc));

mutex_lock(&dev->struct_mutex);
intel_finish_fb(crtc->fb);
mutex_unlock(&dev->struct_mutex);
Expand Down Expand Up @@ -4370,7 +4391,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
/* default to 8bpc */
pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
if (is_dp) {
if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
pipeconf |= PIPECONF_BPP_6 |
PIPECONF_DITHER_EN |
PIPECONF_DITHER_TYPE_SP;
Expand Down Expand Up @@ -4802,7 +4823,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
target_clock = adjusted_mode->clock;

/* determine panel color depth */
dither = intel_choose_pipe_bpp_dither(crtc, fb, &pipe_bpp, mode);
dither = intel_choose_pipe_bpp_dither(crtc, fb, &pipe_bpp,
adjusted_mode);
if (is_lvds && dev_priv->lvds_dither)
dither = true;

Expand Down Expand Up @@ -6159,15 +6181,13 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
struct intel_unpin_work *work;
struct drm_i915_gem_object *obj;
struct drm_pending_vblank_event *e;
struct timeval tnow, tvbl;
struct timeval tvbl;
unsigned long flags;

/* Ignore early vblank irqs */
if (intel_crtc == NULL)
return;

do_gettimeofday(&tnow);

spin_lock_irqsave(&dev->event_lock, flags);
work = intel_crtc->unpin_work;
if (work == NULL || !work->pending) {
Expand All @@ -6181,25 +6201,6 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
e = work->event;
e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &tvbl);

/* Called before vblank count and timestamps have
* been updated for the vblank interval of flip
* completion? Need to increment vblank count and
* add one videorefresh duration to returned timestamp
* to account for this. We assume this happened if we
* get called over 0.9 frame durations after the last
* timestamped vblank.
*
* This calculation can not be used with vrefresh rates
* below 5Hz (10Hz to be on the safe side) without
* promoting to 64 integers.
*/
if (10 * (timeval_to_ns(&tnow) - timeval_to_ns(&tvbl)) >
9 * crtc->framedur_ns) {
e->event.sequence++;
tvbl = ns_to_timeval(timeval_to_ns(&tvbl) +
crtc->framedur_ns);
}

e->event.tv_sec = tvbl.tv_sec;
e->event.tv_usec = tvbl.tv_usec;

Expand All @@ -6216,9 +6217,8 @@ static void do_intel_finish_page_flip(struct drm_device *dev,

atomic_clear_mask(1 << intel_crtc->plane,
&obj->pending_flip.counter);
if (atomic_read(&obj->pending_flip) == 0)
wake_up(&dev_priv->pending_flip_queue);

wake_up(&dev_priv->pending_flip_queue);
schedule_work(&work->work);

trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
Expand Down
73 changes: 57 additions & 16 deletions drivers/gpu/drm/i915/intel_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <drm/i915_drm.h>
#include "i915_drv.h"

#define DP_RECEIVER_CAP_SIZE 0xf
#define DP_LINK_STATUS_SIZE 6
#define DP_LINK_CHECK_TIMEOUT (10 * 1000)

Expand Down Expand Up @@ -1796,8 +1797,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
break;
if (i == intel_dp->lane_count && voltage_tries == 5) {
++loop_tries;
if (loop_tries == 5) {
if (++loop_tries == 5) {
DRM_DEBUG_KMS("too many full retries, give up\n");
break;
}
Expand All @@ -1807,15 +1807,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
}

/* Check to see if we've tried the same voltage 5 times */
if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
++voltage_tries;
if (voltage_tries == 5) {
DRM_DEBUG_KMS("too many voltage retries, give up\n");
break;
}
} else
if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
voltage_tries = 0;
voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
} else
++voltage_tries;

/* Compute new intel_dp->train_set as requested by target */
intel_get_adjust_train(intel_dp, link_status);
Expand Down Expand Up @@ -1963,12 +1959,25 @@ static bool
intel_dp_get_dpcd(struct intel_dp *intel_dp)
{
if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
sizeof(intel_dp->dpcd)) &&
(intel_dp->dpcd[DP_DPCD_REV] != 0)) {
return true;
}
sizeof(intel_dp->dpcd)) == 0)
return false; /* aux transfer failed */

return false;
if (intel_dp->dpcd[DP_DPCD_REV] == 0)
return false; /* DPCD not present */

if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
DP_DWN_STRM_PORT_PRESENT))
return true; /* native DP sink */

if (intel_dp->dpcd[DP_DPCD_REV] == 0x10)
return true; /* no per-port downstream info */

if (intel_dp_aux_native_read_retry(intel_dp, DP_DOWNSTREAM_PORT_0,
intel_dp->downstream_ports,
DP_MAX_DOWNSTREAM_PORTS) == 0)
return false; /* downstream port status fetch failed */

return true;
}

static void
Expand Down Expand Up @@ -2068,11 +2077,43 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
}
}

/* XXX this is probably wrong for multiple downstream ports */
static enum drm_connector_status
intel_dp_detect_dpcd(struct intel_dp *intel_dp)
{
if (intel_dp_get_dpcd(intel_dp))
uint8_t *dpcd = intel_dp->dpcd;
bool hpd;
uint8_t type;

if (!intel_dp_get_dpcd(intel_dp))
return connector_status_disconnected;

/* if there's no downstream port, we're done */
if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
return connector_status_connected;

/* If we're HPD-aware, SINK_COUNT changes dynamically */
hpd = !!(intel_dp->downstream_ports[0] & DP_DS_PORT_HPD);
if (hpd) {
uint8_t reg;
if (!intel_dp_aux_native_read_retry(intel_dp, DP_SINK_COUNT,
&reg, 1))
return connector_status_unknown;
return DP_GET_SINK_COUNT(reg) ? connector_status_connected
: connector_status_disconnected;
}

/* If no HPD, poke DDC gently */
if (drm_probe_ddc(&intel_dp->adapter))
return connector_status_connected;

/* Well we tried, say unknown for unreliable port types */
type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
if (type == DP_DS_PORT_TYPE_VGA || type == DP_DS_PORT_TYPE_NON_EDID)
return connector_status_unknown;

/* Anything else is out of spec, warn and ignore */
DRM_DEBUG_KMS("Broken DP branch device, ignoring\n");
return connector_status_disconnected;
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ struct intel_hdmi {
};

#define DP_RECEIVER_CAP_SIZE 0xf
#define DP_MAX_DOWNSTREAM_PORTS 0x10
#define DP_LINK_CONFIGURATION_SIZE 9

struct intel_dp {
Expand All @@ -346,6 +347,7 @@ struct intel_dp {
uint8_t link_bw;
uint8_t lane_count;
uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
struct i2c_adapter adapter;
struct i2c_algo_dp_aux_data algo;
bool is_pch_edp;
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/i915/intel_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3474,6 +3474,11 @@ static void gen6_init_clock_gating(struct drm_device *dev)
DISPPLANE_TRICKLE_FEED_DISABLE);
intel_flush_display_plane(dev_priv, pipe);
}

/* The default value should be 0x200 according to docs, but the two
* platforms I checked have a 0 for this. (Maybe BIOS overrides?) */
I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_DISABLE(0xffff));
I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_GT_MODE_HI));
}

static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
Expand Down
1 change: 1 addition & 0 deletions include/drm/drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,7 @@ extern char *drm_get_tv_subconnector_name(int val);
extern char *drm_get_tv_select_name(int val);
extern void drm_fb_release(struct drm_file *file_priv);
extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group);
extern bool drm_probe_ddc(struct i2c_adapter *adapter);
extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter);
extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
Expand Down
Loading

0 comments on commit 1f31c69

Please sign in to comment.