Commit d1ca1a00 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-intel-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/keithp/linux-2.6

* 'drm-intel-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/keithp/linux-2.6:
  drm/i915/ringbuffer: Idling requires waiting for the ring to be empty
  Revert "drm/i915: enable rc6 by default"
  drm/i915: Clean up i915_driver_load failure path
  drm/i915: Enable GPU reset on Ivybridge.
  drm/i915/dp: manage sink power state if possible
  drm/i915/dp: consolidate AUX retry code
  drm/i915/dp: remove DPMS mode tracking from DP
  drm/i915/dp: try to read receiver capabilities 3 times when detecting
  drm/i915/dp: read more receiver capability bits on hotplug
  drm/i915/dp: use DP DPCD defines when looking at DPCD values
  drm/i915/dp: retry link status read 3 times on failure
parents 620917de a94919ea
...@@ -1943,7 +1943,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1943,7 +1943,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (!dev_priv->mm.gtt) { if (!dev_priv->mm.gtt) {
DRM_ERROR("Failed to initialize GTT\n"); DRM_ERROR("Failed to initialize GTT\n");
ret = -ENODEV; ret = -ENODEV;
goto out_iomapfree; goto out_rmmap;
} }
agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
...@@ -1987,7 +1987,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -1987,7 +1987,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (dev_priv->wq == NULL) { if (dev_priv->wq == NULL) {
DRM_ERROR("Failed to create our workqueue.\n"); DRM_ERROR("Failed to create our workqueue.\n");
ret = -ENOMEM; ret = -ENOMEM;
goto out_iomapfree; goto out_mtrrfree;
} }
/* enable GEM by default */ /* enable GEM by default */
...@@ -2074,13 +2074,21 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -2074,13 +2074,21 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
return 0; return 0;
out_gem_unload: out_gem_unload:
if (dev_priv->mm.inactive_shrinker.shrink)
unregister_shrinker(&dev_priv->mm.inactive_shrinker);
if (dev->pdev->msi_enabled) if (dev->pdev->msi_enabled)
pci_disable_msi(dev->pdev); pci_disable_msi(dev->pdev);
intel_teardown_gmbus(dev); intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev); intel_teardown_mchbar(dev);
destroy_workqueue(dev_priv->wq); destroy_workqueue(dev_priv->wq);
out_iomapfree: out_mtrrfree:
if (dev_priv->mm.gtt_mtrr >= 0) {
mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
dev->agp->agp_info.aper_size * 1024 * 1024);
dev_priv->mm.gtt_mtrr = -1;
}
io_mapping_free(dev_priv->mm.gtt_mapping); io_mapping_free(dev_priv->mm.gtt_mapping);
out_rmmap: out_rmmap:
pci_iounmap(dev->pdev, dev_priv->regs); pci_iounmap(dev->pdev, dev_priv->regs);
......
...@@ -52,7 +52,7 @@ module_param_named(powersave, i915_powersave, int, 0600); ...@@ -52,7 +52,7 @@ module_param_named(powersave, i915_powersave, int, 0600);
unsigned int i915_semaphores = 0; unsigned int i915_semaphores = 0;
module_param_named(semaphores, i915_semaphores, int, 0600); module_param_named(semaphores, i915_semaphores, int, 0600);
unsigned int i915_enable_rc6 = 1; unsigned int i915_enable_rc6 = 0;
module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
unsigned int i915_enable_fbc = 0; unsigned int i915_enable_fbc = 0;
...@@ -577,6 +577,7 @@ int i915_reset(struct drm_device *dev, u8 flags) ...@@ -577,6 +577,7 @@ int i915_reset(struct drm_device *dev, u8 flags)
if (get_seconds() - dev_priv->last_gpu_reset < 5) { if (get_seconds() - dev_priv->last_gpu_reset < 5) {
DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
} else switch (INTEL_INFO(dev)->gen) { } else switch (INTEL_INFO(dev)->gen) {
case 7:
case 6: case 6:
ret = gen6_do_reset(dev, flags); ret = gen6_do_reset(dev, flags);
/* If reset with a user forcewake, try to restore */ /* If reset with a user forcewake, try to restore */
......
...@@ -50,7 +50,6 @@ struct intel_dp { ...@@ -50,7 +50,6 @@ struct intel_dp {
bool has_audio; bool has_audio;
int force_audio; int force_audio;
uint32_t color_range; uint32_t color_range;
int dpms_mode;
uint8_t link_bw; uint8_t link_bw;
uint8_t lane_count; uint8_t lane_count;
uint8_t dpcd[4]; uint8_t dpcd[4];
...@@ -138,8 +137,8 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp) ...@@ -138,8 +137,8 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp)
{ {
int max_lane_count = 4; int max_lane_count = 4;
if (intel_dp->dpcd[0] >= 0x11) { if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
max_lane_count = intel_dp->dpcd[2] & 0x1f; max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
switch (max_lane_count) { switch (max_lane_count) {
case 1: case 2: case 4: case 1: case 2: case 4:
break; break;
...@@ -153,7 +152,7 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp) ...@@ -153,7 +152,7 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp)
static int static int
intel_dp_max_link_bw(struct intel_dp *intel_dp) intel_dp_max_link_bw(struct intel_dp *intel_dp)
{ {
int max_link_bw = intel_dp->dpcd[1]; int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
switch (max_link_bw) { switch (max_link_bw) {
case DP_LINK_BW_1_62: case DP_LINK_BW_1_62:
...@@ -774,7 +773,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -774,7 +773,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
/* /*
* Check for DPCD version > 1.1 and enhanced framing support * Check for DPCD version > 1.1 and enhanced framing support
*/ */
if (intel_dp->dpcd[0] >= 0x11 && (intel_dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)) { if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
(intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
intel_dp->DP |= DP_ENHANCED_FRAMING; intel_dp->DP |= DP_ENHANCED_FRAMING;
} }
...@@ -942,11 +942,44 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder) ...@@ -942,11 +942,44 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder)
udelay(200); udelay(200);
} }
/* If the sink supports it, try to set the power state appropriately */
static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
{
int ret, i;
/* Should have a valid DPCD by this point */
if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
return;
if (mode != DRM_MODE_DPMS_ON) {
ret = intel_dp_aux_native_write_1(intel_dp, DP_SET_POWER,
DP_SET_POWER_D3);
if (ret != 1)
DRM_DEBUG_DRIVER("failed to write sink power state\n");
} else {
/*
* When turning on, we need to retry for 1ms to give the sink
* time to wake up.
*/
for (i = 0; i < 3; i++) {
ret = intel_dp_aux_native_write_1(intel_dp,
DP_SET_POWER,
DP_SET_POWER_D0);
if (ret == 1)
break;
msleep(1);
}
}
}
static void intel_dp_prepare(struct drm_encoder *encoder) static void intel_dp_prepare(struct drm_encoder *encoder)
{ {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
/* Wake up the sink first */
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
ironlake_edp_backlight_off(dev); ironlake_edp_backlight_off(dev);
ironlake_edp_panel_off(dev); ironlake_edp_panel_off(dev);
...@@ -990,6 +1023,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ...@@ -990,6 +1023,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
if (mode != DRM_MODE_DPMS_ON) { if (mode != DRM_MODE_DPMS_ON) {
if (is_edp(intel_dp)) if (is_edp(intel_dp))
ironlake_edp_backlight_off(dev); ironlake_edp_backlight_off(dev);
intel_dp_sink_dpms(intel_dp, mode);
intel_dp_link_down(intel_dp); intel_dp_link_down(intel_dp);
if (is_edp(intel_dp)) if (is_edp(intel_dp))
ironlake_edp_panel_off(dev); ironlake_edp_panel_off(dev);
...@@ -998,6 +1032,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ...@@ -998,6 +1032,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
} else { } else {
if (is_edp(intel_dp)) if (is_edp(intel_dp))
ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_panel_vdd_on(intel_dp);
intel_dp_sink_dpms(intel_dp, mode);
if (!(dp_reg & DP_PORT_EN)) { if (!(dp_reg & DP_PORT_EN)) {
intel_dp_start_link_train(intel_dp); intel_dp_start_link_train(intel_dp);
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
...@@ -1009,7 +1044,31 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ...@@ -1009,7 +1044,31 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
if (is_edp(intel_dp)) if (is_edp(intel_dp))
ironlake_edp_backlight_on(dev); ironlake_edp_backlight_on(dev);
} }
intel_dp->dpms_mode = mode; }
/*
* Native read with retry for link status and receiver capability reads for
* cases where the sink may still be asleep.
*/
static bool
intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address,
uint8_t *recv, int recv_bytes)
{
int ret, i;
/*
* Sinks are *supposed* to come up within 1ms from an off state,
* but we're also supposed to retry 3 times per the spec.
*/
for (i = 0; i < 3; i++) {
ret = intel_dp_aux_native_read(intel_dp, address, recv,
recv_bytes);
if (ret == recv_bytes)
return true;
msleep(1);
}
return false;
} }
/* /*
...@@ -1019,14 +1078,10 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) ...@@ -1019,14 +1078,10 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
static bool static bool
intel_dp_get_link_status(struct intel_dp *intel_dp) intel_dp_get_link_status(struct intel_dp *intel_dp)
{ {
int ret; return intel_dp_aux_native_read_retry(intel_dp,
DP_LANE0_1_STATUS,
ret = intel_dp_aux_native_read(intel_dp, intel_dp->link_status,
DP_LANE0_1_STATUS, DP_LINK_STATUS_SIZE);
intel_dp->link_status, DP_LINK_STATUS_SIZE);
if (ret != DP_LINK_STATUS_SIZE)
return false;
return true;
} }
static uint8_t static uint8_t
...@@ -1515,6 +1570,8 @@ intel_dp_link_down(struct intel_dp *intel_dp) ...@@ -1515,6 +1570,8 @@ intel_dp_link_down(struct intel_dp *intel_dp)
static void static void
intel_dp_check_link_status(struct intel_dp *intel_dp) intel_dp_check_link_status(struct intel_dp *intel_dp)
{ {
int ret;
if (!intel_dp->base.base.crtc) if (!intel_dp->base.base.crtc)
return; return;
...@@ -1523,6 +1580,15 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) ...@@ -1523,6 +1580,15 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
return; return;
} }
/* Try to read receiver status if the link appears to be up */
ret = intel_dp_aux_native_read(intel_dp,
0x000, intel_dp->dpcd,
sizeof (intel_dp->dpcd));
if (ret != sizeof(intel_dp->dpcd)) {
intel_dp_link_down(intel_dp);
return;
}
if (!intel_channel_eq_ok(intel_dp)) { if (!intel_channel_eq_ok(intel_dp)) {
intel_dp_start_link_train(intel_dp); intel_dp_start_link_train(intel_dp);
intel_dp_complete_link_train(intel_dp); intel_dp_complete_link_train(intel_dp);
...@@ -1533,6 +1599,7 @@ static enum drm_connector_status ...@@ -1533,6 +1599,7 @@ static enum drm_connector_status
ironlake_dp_detect(struct intel_dp *intel_dp) ironlake_dp_detect(struct intel_dp *intel_dp)
{ {
enum drm_connector_status status; enum drm_connector_status status;
bool ret;
/* Can't disconnect eDP, but you can close the lid... */ /* Can't disconnect eDP, but you can close the lid... */
if (is_edp(intel_dp)) { if (is_edp(intel_dp)) {
...@@ -1543,13 +1610,11 @@ ironlake_dp_detect(struct intel_dp *intel_dp) ...@@ -1543,13 +1610,11 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
} }
status = connector_status_disconnected; status = connector_status_disconnected;
if (intel_dp_aux_native_read(intel_dp, ret = intel_dp_aux_native_read_retry(intel_dp,
0x000, intel_dp->dpcd, 0x000, intel_dp->dpcd,
sizeof (intel_dp->dpcd)) sizeof (intel_dp->dpcd));
== sizeof(intel_dp->dpcd)) { if (ret && intel_dp->dpcd[DP_DPCD_REV] != 0)
if (intel_dp->dpcd[0] != 0) status = connector_status_connected;
status = connector_status_connected;
}
DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0], DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0],
intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]); intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]);
return status; return status;
...@@ -1586,7 +1651,7 @@ g4x_dp_detect(struct intel_dp *intel_dp) ...@@ -1586,7 +1651,7 @@ g4x_dp_detect(struct intel_dp *intel_dp)
if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd, if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd,
sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd)) sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
{ {
if (intel_dp->dpcd[0] != 0) if (intel_dp->dpcd[DP_DPCD_REV] != 0)
status = connector_status_connected; status = connector_status_connected;
} }
...@@ -1790,8 +1855,7 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder) ...@@ -1790,8 +1855,7 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder)
{ {
struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
if (intel_dp->dpms_mode == DRM_MODE_DPMS_ON) intel_dp_check_link_status(intel_dp);
intel_dp_check_link_status(intel_dp);
} }
/* Return which DP Port should be selected for Transcoder DP control */ /* Return which DP Port should be selected for Transcoder DP control */
...@@ -1859,7 +1923,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) ...@@ -1859,7 +1923,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
return; return;
intel_dp->output_reg = output_reg; intel_dp->output_reg = output_reg;
intel_dp->dpms_mode = -1;
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
if (!intel_connector) { if (!intel_connector) {
...@@ -1954,8 +2017,9 @@ intel_dp_init(struct drm_device *dev, int output_reg) ...@@ -1954,8 +2017,9 @@ intel_dp_init(struct drm_device *dev, int output_reg)
sizeof(intel_dp->dpcd)); sizeof(intel_dp->dpcd));
ironlake_edp_panel_vdd_off(intel_dp); ironlake_edp_panel_vdd_off(intel_dp);
if (ret == sizeof(intel_dp->dpcd)) { if (ret == sizeof(intel_dp->dpcd)) {
if (intel_dp->dpcd[0] >= 0x11) if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
dev_priv->no_aux_handshake = intel_dp->dpcd[3] & dev_priv->no_aux_handshake =
intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
DP_NO_AUX_HANDSHAKE_LINK_TRAINING; DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
} else { } else {
/* if this fails, presume the device is a ghost */ /* if this fails, presume the device is a ghost */
......
...@@ -165,7 +165,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring); ...@@ -165,7 +165,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
int __must_check intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n); int __must_check intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n);
static inline int intel_wait_ring_idle(struct intel_ring_buffer *ring) static inline int intel_wait_ring_idle(struct intel_ring_buffer *ring)
{ {
return intel_wait_ring_buffer(ring, ring->space - 8); return intel_wait_ring_buffer(ring, ring->size - 8);
} }
int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n); int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment