Commit 1f31c69d authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/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
parents a5a0fc67 f8f2ac9a
...@@ -395,13 +395,14 @@ out: ...@@ -395,13 +395,14 @@ out:
* \param adapter : i2c device adaptor * \param adapter : i2c device adaptor
* \return 1 on success * \return 1 on success
*/ */
static bool bool
drm_probe_ddc(struct i2c_adapter *adapter) drm_probe_ddc(struct i2c_adapter *adapter)
{ {
unsigned char out; unsigned char out;
return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0); return (drm_do_probe_ddc_edid(adapter, &out, 0, 1) == 0);
} }
EXPORT_SYMBOL(drm_probe_ddc);
/** /**
* drm_get_edid - get EDID data, if available * drm_get_edid - get EDID data, if available
......
...@@ -1399,10 +1399,16 @@ out: ...@@ -1399,10 +1399,16 @@ out:
case 0: case 0:
case -ERESTARTSYS: case -ERESTARTSYS:
case -EINTR: case -EINTR:
case -EBUSY:
/*
* EBUSY is ok: this just means that another thread
* already did the job.
*/
return VM_FAULT_NOPAGE; return VM_FAULT_NOPAGE;
case -ENOMEM: case -ENOMEM:
return VM_FAULT_OOM; return VM_FAULT_OOM;
default: default:
WARN_ON_ONCE(ret);
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
} }
} }
...@@ -3217,10 +3223,6 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, ...@@ -3217,10 +3223,6 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
enum i915_cache_level level; enum i915_cache_level level;
int ret; int ret;
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
switch (args->caching) { switch (args->caching) {
case I915_CACHING_NONE: case I915_CACHING_NONE:
level = I915_CACHE_NONE; level = I915_CACHE_NONE;
...@@ -3232,6 +3234,10 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, ...@@ -3232,6 +3234,10 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
return -EINVAL; return -EINVAL;
} }
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
if (&obj->base == NULL) { if (&obj->base == NULL) {
ret = -ENOENT; ret = -ENOENT;
......
...@@ -328,7 +328,7 @@ mi_set_context(struct intel_ring_buffer *ring, ...@@ -328,7 +328,7 @@ mi_set_context(struct intel_ring_buffer *ring,
* itlb_before_ctx_switch. * itlb_before_ctx_switch.
*/ */
if (IS_GEN6(ring->dev) && 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) if (ret)
return ret; return ret;
} }
......
...@@ -91,7 +91,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) ...@@ -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_x = I915_BIT_6_SWIZZLE_UNKNOWN;
uint32_t swizzle_y = 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; uint32_t dimm_c0, dimm_c1;
dimm_c0 = I915_READ(MAD_DIMM_C0); dimm_c0 = I915_READ(MAD_DIMM_C0);
dimm_c1 = I915_READ(MAD_DIMM_C1); dimm_c1 = I915_READ(MAD_DIMM_C1);
......
...@@ -697,12 +697,12 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) ...@@ -697,12 +697,12 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
intel_opregion_gse_intr(dev); intel_opregion_gse_intr(dev);
for (i = 0; i < 3; i++) { 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))) { if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
intel_prepare_page_flip(dev, i); intel_prepare_page_flip(dev, i);
intel_finish_page_flip_plane(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 */ /* check event from PCH */
...@@ -784,6 +784,12 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) ...@@ -784,6 +784,12 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
if (de_iir & DE_GSE) if (de_iir & DE_GSE)
intel_opregion_gse_intr(dev); 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) { if (de_iir & DE_PLANEA_FLIP_DONE) {
intel_prepare_page_flip(dev, 0); intel_prepare_page_flip(dev, 0);
intel_finish_page_flip_plane(dev, 0); intel_finish_page_flip_plane(dev, 0);
...@@ -794,12 +800,6 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) ...@@ -794,12 +800,6 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
intel_finish_page_flip_plane(dev, 1); 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 */ /* check event from PCH */
if (de_iir & DE_PCH_EVENT) { if (de_iir & DE_PCH_EVENT) {
if (pch_iir & hotplug_mask) if (pch_iir & hotplug_mask)
......
...@@ -527,6 +527,9 @@ ...@@ -527,6 +527,9 @@
# define VS_TIMER_DISPATCH (1 << 6) # define VS_TIMER_DISPATCH (1 << 6)
# define MI_FLUSH_ENABLE (1 << 12) # 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 0x02520
#define GFX_MODE_GEN7 0x0229c #define GFX_MODE_GEN7 0x0229c
#define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c) #define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c)
......
...@@ -2806,13 +2806,34 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) ...@@ -2806,13 +2806,34 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
udelay(100); 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) static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
if (crtc->fb == NULL) if (crtc->fb == NULL)
return; return;
wait_event(dev_priv->pending_flip_queue,
!intel_crtc_has_pending_flip(crtc));
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
intel_finish_fb(crtc->fb); intel_finish_fb(crtc->fb);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
...@@ -4370,7 +4391,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4370,7 +4391,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
/* default to 8bpc */ /* default to 8bpc */
pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN); pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
if (is_dp) { 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 |= PIPECONF_BPP_6 |
PIPECONF_DITHER_EN | PIPECONF_DITHER_EN |
PIPECONF_DITHER_TYPE_SP; PIPECONF_DITHER_TYPE_SP;
...@@ -4802,7 +4823,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -4802,7 +4823,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
target_clock = adjusted_mode->clock; target_clock = adjusted_mode->clock;
/* determine panel color depth */ /* 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) if (is_lvds && dev_priv->lvds_dither)
dither = true; dither = true;
...@@ -6159,15 +6181,13 @@ static void do_intel_finish_page_flip(struct drm_device *dev, ...@@ -6159,15 +6181,13 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
struct intel_unpin_work *work; struct intel_unpin_work *work;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct drm_pending_vblank_event *e; struct drm_pending_vblank_event *e;
struct timeval tnow, tvbl; struct timeval tvbl;
unsigned long flags; unsigned long flags;
/* Ignore early vblank irqs */ /* Ignore early vblank irqs */
if (intel_crtc == NULL) if (intel_crtc == NULL)
return; return;
do_gettimeofday(&tnow);
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
work = intel_crtc->unpin_work; work = intel_crtc->unpin_work;
if (work == NULL || !work->pending) { if (work == NULL || !work->pending) {
...@@ -6181,25 +6201,6 @@ static void do_intel_finish_page_flip(struct drm_device *dev, ...@@ -6181,25 +6201,6 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
e = work->event; e = work->event;
e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &tvbl); 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_sec = tvbl.tv_sec;
e->event.tv_usec = tvbl.tv_usec; e->event.tv_usec = tvbl.tv_usec;
...@@ -6216,9 +6217,8 @@ static void do_intel_finish_page_flip(struct drm_device *dev, ...@@ -6216,9 +6217,8 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
atomic_clear_mask(1 << intel_crtc->plane, atomic_clear_mask(1 << intel_crtc->plane,
&obj->pending_flip.counter); &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); schedule_work(&work->work);
trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <drm/i915_drm.h> #include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
#define DP_RECEIVER_CAP_SIZE 0xf
#define DP_LINK_STATUS_SIZE 6 #define DP_LINK_STATUS_SIZE 6
#define DP_LINK_CHECK_TIMEOUT (10 * 1000) #define DP_LINK_CHECK_TIMEOUT (10 * 1000)
...@@ -1796,8 +1797,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) ...@@ -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) if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
break; break;
if (i == intel_dp->lane_count && voltage_tries == 5) { 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"); DRM_DEBUG_KMS("too many full retries, give up\n");
break; break;
} }
...@@ -1807,15 +1807,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) ...@@ -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 */ /* Check to see if we've tried the same voltage 5 times */
if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
++voltage_tries; voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
if (voltage_tries == 5) {
DRM_DEBUG_KMS("too many voltage retries, give up\n");
break;
}
} else
voltage_tries = 0; 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 */ /* Compute new intel_dp->train_set as requested by target */
intel_get_adjust_train(intel_dp, link_status); intel_get_adjust_train(intel_dp, link_status);
...@@ -1963,12 +1959,25 @@ static bool ...@@ -1963,12 +1959,25 @@ static bool
intel_dp_get_dpcd(struct intel_dp *intel_dp) intel_dp_get_dpcd(struct intel_dp *intel_dp)
{ {
if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd, if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
sizeof(intel_dp->dpcd)) && sizeof(intel_dp->dpcd)) == 0)
(intel_dp->dpcd[DP_DPCD_REV] != 0)) { return false; /* aux transfer failed */
return true;
}
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 static void
...@@ -2068,11 +2077,43 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) ...@@ -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 static enum drm_connector_status
intel_dp_detect_dpcd(struct intel_dp *intel_dp) 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; 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; return connector_status_disconnected;
} }
......
...@@ -332,6 +332,7 @@ struct intel_hdmi { ...@@ -332,6 +332,7 @@ struct intel_hdmi {
}; };
#define DP_RECEIVER_CAP_SIZE 0xf #define DP_RECEIVER_CAP_SIZE 0xf
#define DP_MAX_DOWNSTREAM_PORTS 0x10
#define DP_LINK_CONFIGURATION_SIZE 9 #define DP_LINK_CONFIGURATION_SIZE 9
struct intel_dp { struct intel_dp {
...@@ -346,6 +347,7 @@ struct intel_dp { ...@@ -346,6 +347,7 @@ struct intel_dp {
uint8_t link_bw; uint8_t link_bw;
uint8_t lane_count; uint8_t lane_count;
uint8_t dpcd[DP_RECEIVER_CAP_SIZE]; uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct i2c_algo_dp_aux_data algo; struct i2c_algo_dp_aux_data algo;
bool is_pch_edp; bool is_pch_edp;
......
...@@ -3474,6 +3474,11 @@ static void gen6_init_clock_gating(struct drm_device *dev) ...@@ -3474,6 +3474,11 @@ static void gen6_init_clock_gating(struct drm_device *dev)
DISPPLANE_TRICKLE_FEED_DISABLE); DISPPLANE_TRICKLE_FEED_DISABLE);
intel_flush_display_plane(dev_priv, pipe); 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) static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
......
...@@ -878,6 +878,7 @@ extern char *drm_get_tv_subconnector_name(int val); ...@@ -878,6 +878,7 @@ extern char *drm_get_tv_subconnector_name(int val);
extern char *drm_get_tv_select_name(int val); extern char *drm_get_tv_select_name(int val);
extern void drm_fb_release(struct drm_file *file_priv); 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 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, extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter); struct i2c_adapter *adapter);
extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
......
...@@ -26,7 +26,19 @@ ...@@ -26,7 +26,19 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/i2c.h> #include <linux/i2c.h>
/* From the VESA DisplayPort spec */ /*
* Unless otherwise noted, all values are from the DP 1.1a spec. Note that
* DP and DPCD versions are independent. Differences from 1.0 are not noted,
* 1.0 devices basically don't exist in the wild.
*
* Abbreviations, in chronological order:
*
* eDP: Embedded DisplayPort version 1
* DPI: DisplayPort Interoperability Guideline v1.1a
* 1.2: DisplayPort 1.2
*
* 1.2 formally includes both eDP and DPI definitions.
*/
#define AUX_NATIVE_WRITE 0x8 #define AUX_NATIVE_WRITE 0x8
#define AUX_NATIVE_READ 0x9 #define AUX_NATIVE_READ 0x9
...@@ -53,7 +65,7 @@ ...@@ -53,7 +65,7 @@
#define DP_MAX_LANE_COUNT 0x002 #define DP_MAX_LANE_COUNT 0x002
# define DP_MAX_LANE_COUNT_MASK 0x1f # define DP_MAX_LANE_COUNT_MASK 0x1f
# define DP_TPS3_SUPPORTED (1 << 6) # define DP_TPS3_SUPPORTED (1 << 6) /* 1.2 */
# define DP_ENHANCED_FRAME_CAP (1 << 7) # define DP_ENHANCED_FRAME_CAP (1 << 7)
#define DP_MAX_DOWNSPREAD 0x003 #define DP_MAX_DOWNSPREAD 0x003
...@@ -69,19 +81,33 @@ ...@@ -69,19 +81,33 @@
/* 10b = TMDS or HDMI */ /* 10b = TMDS or HDMI */
/* 11b = Other */ /* 11b = Other */
# define DP_FORMAT_CONVERSION (1 << 3) # define DP_FORMAT_CONVERSION (1 << 3)
# define DP_DETAILED_CAP_INFO_AVAILABLE (1 << 4) /* DPI */
#define DP_MAIN_LINK_CHANNEL_CODING 0x006 #define DP_MAIN_LINK_CHANNEL_CODING 0x006
#define DP_DOWN_STREAM_PORT_COUNT 0x007 #define DP_DOWN_STREAM_PORT_COUNT 0x007
#define DP_PORT_COUNT_MASK 0x0f # define DP_PORT_COUNT_MASK 0x0f
#define DP_OUI_SUPPORT (1 << 7) # define DP_MSA_TIMING_PAR_IGNORED (1 << 6) /* eDP */
# define DP_OUI_SUPPORT (1 << 7)
#define DP_EDP_CONFIGURATION_CAP 0x00d
#define DP_TRAINING_AUX_RD_INTERVAL 0x00e #define DP_I2C_SPEED_CAP 0x00c /* DPI */
# define DP_I2C_SPEED_1K 0x01
#define DP_PSR_SUPPORT 0x070 # define DP_I2C_SPEED_5K 0x02
# define DP_I2C_SPEED_10K 0x04
# define DP_I2C_SPEED_100K 0x08
# define DP_I2C_SPEED_400K 0x10
# define DP_I2C_SPEED_1M 0x20
#define DP_EDP_CONFIGURATION_CAP 0x00d /* XXX 1.2? */
#define DP_TRAINING_AUX_RD_INTERVAL 0x00e /* XXX 1.2? */
/* Multiple stream transport */
#define DP_MSTM_CAP 0x021 /* 1.2 */
# define DP_MST_CAP (1 << 0)