Merge tag 'drm-intel-fixes-2013-07-22' of git://people.freedesktop.org/~danvet/drm-intel into drm-fixes
- fixup panel fitter readout for gen2/3 (just quitens dmesg noise) - fix pft computations for non-autoscaled resolutions (i.e. letter/pillar boxing on gen2/3) - preserve the DDI A/E lane sharing bit (Stéphane Marchesin) - fix the "rc6 fails to work after resume" regression, big thanks to Konstantin Khlebnikov for the patch and debug insight about what actually might be going on here - fix Oops in is_crtc_connector_off (Chris) - sanitize shared dpll state - our new paranoid state checker tripped up over dirt left behind by the BIOS - correctly restore fences, fixes the "my screen is all messed up after resume" regression introduced in the final 3.10 pull request - quirk backlights harder, this time for Dell XPS13 machines to fix a regression (patch from Kamal Mostafa) - 90% fix for some haswell hangs when accessing registers concurrently, the 100% solution is simply too invasive for -fixes and what we have here seems to be good enough (Chris) * tag 'drm-intel-fixes-2013-07-22' of git://people.freedesktop.org/~danvet/drm-intel: drm/i915: fix up gt init sequence fallout drm/i915: Serialize almost all register access drm/i915: quirk no PCH_PWM_ENABLE for Dell XPS13 backlight drm/i915: correctly restore fences with objects attached drm/i915: Fix dereferencing invalid connectors in is_crtc_connector_off() drm/i915: Sanitize shared dpll state drm/i915: fix long-standing SNB regression in power consumption after resume v2 drm/i915: Preserve the DDI_A_4_LANES bit from the bios drm/i915: fix pfit regression for non-autoscaled resolutions drm/i915: fix up readout of the lvds dither bit on gen2/3
This commit is contained in:
commit
058ca4a22e
10 changed files with 110 additions and 49 deletions
|
@ -1495,6 +1495,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
dev_priv->dev = dev;
|
||||
dev_priv->info = info;
|
||||
|
||||
spin_lock_init(&dev_priv->irq_lock);
|
||||
spin_lock_init(&dev_priv->gpu_error.lock);
|
||||
spin_lock_init(&dev_priv->rps.lock);
|
||||
spin_lock_init(&dev_priv->backlight.lock);
|
||||
mutex_init(&dev_priv->dpio_lock);
|
||||
mutex_init(&dev_priv->rps.hw_lock);
|
||||
mutex_init(&dev_priv->modeset_restore_lock);
|
||||
|
||||
i915_dump_device_info(dev_priv);
|
||||
|
||||
if (i915_get_bridge_dev(dev)) {
|
||||
|
@ -1585,6 +1593,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
intel_detect_pch(dev);
|
||||
|
||||
intel_irq_init(dev);
|
||||
intel_gt_sanitize(dev);
|
||||
intel_gt_init(dev);
|
||||
|
||||
/* Try to make sure MCHBAR is enabled before poking at it */
|
||||
|
@ -1610,15 +1619,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
if (!IS_I945G(dev) && !IS_I945GM(dev))
|
||||
pci_enable_msi(dev->pdev);
|
||||
|
||||
spin_lock_init(&dev_priv->irq_lock);
|
||||
spin_lock_init(&dev_priv->gpu_error.lock);
|
||||
spin_lock_init(&dev_priv->rps.lock);
|
||||
spin_lock_init(&dev_priv->backlight.lock);
|
||||
mutex_init(&dev_priv->dpio_lock);
|
||||
|
||||
mutex_init(&dev_priv->rps.hw_lock);
|
||||
mutex_init(&dev_priv->modeset_restore_lock);
|
||||
|
||||
dev_priv->num_plane = 1;
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
dev_priv->num_plane = 2;
|
||||
|
|
|
@ -706,7 +706,7 @@ static int i915_drm_thaw(struct drm_device *dev)
|
|||
{
|
||||
int error = 0;
|
||||
|
||||
intel_gt_reset(dev);
|
||||
intel_gt_sanitize(dev);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
@ -732,7 +732,7 @@ int i915_resume(struct drm_device *dev)
|
|||
|
||||
pci_set_master(dev->pdev);
|
||||
|
||||
intel_gt_reset(dev);
|
||||
intel_gt_sanitize(dev);
|
||||
|
||||
/*
|
||||
* Platforms with opregion should have sane BIOS, older ones (gen3 and
|
||||
|
@ -1253,21 +1253,21 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
|
|||
|
||||
#define __i915_read(x, y) \
|
||||
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
|
||||
unsigned long irqflags; \
|
||||
u##x val = 0; \
|
||||
spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
|
||||
if (IS_GEN5(dev_priv->dev)) \
|
||||
ilk_dummy_write(dev_priv); \
|
||||
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
|
||||
unsigned long irqflags; \
|
||||
spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
|
||||
if (dev_priv->forcewake_count == 0) \
|
||||
dev_priv->gt.force_wake_get(dev_priv); \
|
||||
val = read##y(dev_priv->regs + reg); \
|
||||
if (dev_priv->forcewake_count == 0) \
|
||||
dev_priv->gt.force_wake_put(dev_priv); \
|
||||
spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
|
||||
} else { \
|
||||
val = read##y(dev_priv->regs + reg); \
|
||||
} \
|
||||
spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
|
||||
trace_i915_reg_rw(false, reg, val, sizeof(val)); \
|
||||
return val; \
|
||||
}
|
||||
|
@ -1280,8 +1280,10 @@ __i915_read(64, q)
|
|||
|
||||
#define __i915_write(x, y) \
|
||||
void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
|
||||
unsigned long irqflags; \
|
||||
u32 __fifo_ret = 0; \
|
||||
trace_i915_reg_rw(true, reg, val, sizeof(val)); \
|
||||
spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
|
||||
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
|
||||
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
|
||||
} \
|
||||
|
@ -1293,6 +1295,7 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
|
|||
gen6_gt_check_fifodbg(dev_priv); \
|
||||
} \
|
||||
hsw_unclaimed_reg_check(dev_priv, reg); \
|
||||
spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
|
||||
}
|
||||
__i915_write(8, b)
|
||||
__i915_write(16, w)
|
||||
|
|
|
@ -555,6 +555,7 @@ enum intel_sbi_destination {
|
|||
#define QUIRK_PIPEA_FORCE (1<<0)
|
||||
#define QUIRK_LVDS_SSC_DISABLE (1<<1)
|
||||
#define QUIRK_INVERT_BRIGHTNESS (1<<2)
|
||||
#define QUIRK_NO_PCH_PWM_ENABLE (1<<3)
|
||||
|
||||
struct intel_fbdev;
|
||||
struct intel_fbc_work;
|
||||
|
@ -1583,7 +1584,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged);
|
|||
extern void intel_irq_init(struct drm_device *dev);
|
||||
extern void intel_hpd_init(struct drm_device *dev);
|
||||
extern void intel_gt_init(struct drm_device *dev);
|
||||
extern void intel_gt_reset(struct drm_device *dev);
|
||||
extern void intel_gt_sanitize(struct drm_device *dev);
|
||||
|
||||
void i915_error_state_free(struct kref *error_ref);
|
||||
|
||||
|
|
|
@ -2258,7 +2258,17 @@ void i915_gem_restore_fences(struct drm_device *dev)
|
|||
|
||||
for (i = 0; i < dev_priv->num_fence_regs; i++) {
|
||||
struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
|
||||
i915_gem_write_fence(dev, i, reg->obj);
|
||||
|
||||
/*
|
||||
* Commit delayed tiling changes if we have an object still
|
||||
* attached to the fence, otherwise just clear the fence.
|
||||
*/
|
||||
if (reg->obj) {
|
||||
i915_gem_object_update_fence(reg->obj, reg,
|
||||
reg->obj->tiling_mode);
|
||||
} else {
|
||||
i915_gem_write_fence(dev, i, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2795,6 +2805,10 @@ static void i915_gem_write_fence(struct drm_device *dev, int reg,
|
|||
if (i915_gem_object_needs_mb(dev_priv->fence_regs[reg].obj))
|
||||
mb();
|
||||
|
||||
WARN(obj && (!obj->stride || !obj->tiling_mode),
|
||||
"bogus fence setup with stride: 0x%x, tiling mode: %i\n",
|
||||
obj->stride, obj->tiling_mode);
|
||||
|
||||
switch (INTEL_INFO(dev)->gen) {
|
||||
case 7:
|
||||
case 6:
|
||||
|
@ -2836,6 +2850,7 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
|
|||
fence->obj = NULL;
|
||||
list_del_init(&fence->lru_list);
|
||||
}
|
||||
obj->fence_dirty = false;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2965,7 +2980,6 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj)
|
|||
return 0;
|
||||
|
||||
i915_gem_object_update_fence(obj, reg, enable);
|
||||
obj->fence_dirty = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -301,7 +301,7 @@ static void intel_ddi_mode_set(struct drm_encoder *encoder,
|
|||
struct intel_digital_port *intel_dig_port =
|
||||
enc_to_dig_port(encoder);
|
||||
|
||||
intel_dp->DP = intel_dig_port->port_reversal |
|
||||
intel_dp->DP = intel_dig_port->saved_port_bits |
|
||||
DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
|
||||
intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
|
||||
|
||||
|
@ -1109,7 +1109,8 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
|
|||
* enabling the port.
|
||||
*/
|
||||
I915_WRITE(DDI_BUF_CTL(port),
|
||||
intel_dig_port->port_reversal | DDI_BUF_CTL_ENABLE);
|
||||
intel_dig_port->saved_port_bits |
|
||||
DDI_BUF_CTL_ENABLE);
|
||||
} else if (type == INTEL_OUTPUT_EDP) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
||||
|
@ -1347,8 +1348,9 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
|
|||
intel_encoder->get_config = intel_ddi_get_config;
|
||||
|
||||
intel_dig_port->port = port;
|
||||
intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
|
||||
DDI_BUF_PORT_REVERSAL;
|
||||
intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
|
||||
(DDI_BUF_PORT_REVERSAL |
|
||||
DDI_A_4_LANES);
|
||||
intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
|
||||
|
||||
intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
|
||||
|
|
|
@ -4913,22 +4913,19 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc,
|
|||
uint32_t tmp;
|
||||
|
||||
tmp = I915_READ(PFIT_CONTROL);
|
||||
if (!(tmp & PFIT_ENABLE))
|
||||
return;
|
||||
|
||||
/* Check whether the pfit is attached to our pipe. */
|
||||
if (INTEL_INFO(dev)->gen < 4) {
|
||||
if (crtc->pipe != PIPE_B)
|
||||
return;
|
||||
|
||||
/* gen2/3 store dither state in pfit control, needs to match */
|
||||
pipe_config->gmch_pfit.control = tmp & PANEL_8TO6_DITHER_ENABLE;
|
||||
} else {
|
||||
if ((tmp & PFIT_PIPE_MASK) != (crtc->pipe << PFIT_PIPE_SHIFT))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(tmp & PFIT_ENABLE))
|
||||
return;
|
||||
|
||||
pipe_config->gmch_pfit.control = I915_READ(PFIT_CONTROL);
|
||||
pipe_config->gmch_pfit.control = tmp;
|
||||
pipe_config->gmch_pfit.pgm_ratios = I915_READ(PFIT_PGM_RATIOS);
|
||||
if (INTEL_INFO(dev)->gen < 5)
|
||||
pipe_config->gmch_pfit.lvds_border_bits =
|
||||
|
@ -8317,6 +8314,8 @@ check_shared_dpll_state(struct drm_device *dev)
|
|||
pll->active, pll->refcount);
|
||||
WARN(pll->active && !pll->on,
|
||||
"pll in active use but not on in sw tracking\n");
|
||||
WARN(pll->on && !pll->active,
|
||||
"pll in on but not on in use in sw tracking\n");
|
||||
WARN(pll->on != active,
|
||||
"pll on state mismatch (expected %i, found %i)\n",
|
||||
pll->on, active);
|
||||
|
@ -8541,15 +8540,20 @@ static void intel_set_config_restore_state(struct drm_device *dev,
|
|||
}
|
||||
|
||||
static bool
|
||||
is_crtc_connector_off(struct drm_crtc *crtc, struct drm_connector *connectors,
|
||||
int num_connectors)
|
||||
is_crtc_connector_off(struct drm_mode_set *set)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_connectors; i++)
|
||||
if (connectors[i].encoder &&
|
||||
connectors[i].encoder->crtc == crtc &&
|
||||
connectors[i].dpms != DRM_MODE_DPMS_ON)
|
||||
if (set->num_connectors == 0)
|
||||
return false;
|
||||
|
||||
if (WARN_ON(set->connectors == NULL))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < set->num_connectors; i++)
|
||||
if (set->connectors[i]->encoder &&
|
||||
set->connectors[i]->encoder->crtc == set->crtc &&
|
||||
set->connectors[i]->dpms != DRM_MODE_DPMS_ON)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -8562,10 +8566,8 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
|
|||
|
||||
/* We should be able to check here if the fb has the same properties
|
||||
* and then just flip_or_move it */
|
||||
if (set->connectors != NULL &&
|
||||
is_crtc_connector_off(set->crtc, *set->connectors,
|
||||
set->num_connectors)) {
|
||||
config->mode_changed = true;
|
||||
if (is_crtc_connector_off(set)) {
|
||||
config->mode_changed = true;
|
||||
} else if (set->crtc->fb != set->fb) {
|
||||
/* If we have no fb then treat it as a full mode set */
|
||||
if (set->crtc->fb == NULL) {
|
||||
|
@ -9398,6 +9400,17 @@ static void quirk_invert_brightness(struct drm_device *dev)
|
|||
DRM_INFO("applying inverted panel brightness quirk\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Some machines (Dell XPS13) suffer broken backlight controls if
|
||||
* BLM_PCH_PWM_ENABLE is set.
|
||||
*/
|
||||
static void quirk_no_pcm_pwm_enable(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE;
|
||||
DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n");
|
||||
}
|
||||
|
||||
struct intel_quirk {
|
||||
int device;
|
||||
int subsystem_vendor;
|
||||
|
@ -9467,6 +9480,11 @@ static struct intel_quirk intel_quirks[] = {
|
|||
|
||||
/* Acer Aspire 4736Z */
|
||||
{ 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
|
||||
|
||||
/* Dell XPS13 HD Sandy Bridge */
|
||||
{ 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable },
|
||||
/* Dell XPS13 HD and XPS13 FHD Ivy Bridge */
|
||||
{ 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable },
|
||||
};
|
||||
|
||||
static void intel_init_quirks(struct drm_device *dev)
|
||||
|
@ -9817,8 +9835,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
|||
}
|
||||
pll->refcount = pll->active;
|
||||
|
||||
DRM_DEBUG_KMS("%s hw state readout: refcount %i\n",
|
||||
pll->name, pll->refcount);
|
||||
DRM_DEBUG_KMS("%s hw state readout: refcount %i, on %i\n",
|
||||
pll->name, pll->refcount, pll->on);
|
||||
}
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
||||
|
@ -9869,6 +9887,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|||
struct drm_plane *plane;
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_encoder *encoder;
|
||||
int i;
|
||||
|
||||
intel_modeset_readout_hw_state(dev);
|
||||
|
||||
|
@ -9884,6 +9903,18 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|||
intel_dump_pipe_config(crtc, &crtc->config, "[setup_hw_state]");
|
||||
}
|
||||
|
||||
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
||||
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
||||
|
||||
if (!pll->on || pll->active)
|
||||
continue;
|
||||
|
||||
DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name);
|
||||
|
||||
pll->disable(dev_priv, pll);
|
||||
pll->on = false;
|
||||
}
|
||||
|
||||
if (force_restore) {
|
||||
/*
|
||||
* We need to use raw interfaces for restoring state to avoid
|
||||
|
|
|
@ -504,7 +504,7 @@ struct intel_dp {
|
|||
struct intel_digital_port {
|
||||
struct intel_encoder base;
|
||||
enum port port;
|
||||
u32 port_reversal;
|
||||
u32 saved_port_bits;
|
||||
struct intel_dp dp;
|
||||
struct intel_hdmi hdmi;
|
||||
};
|
||||
|
|
|
@ -109,6 +109,13 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
|
|||
flags |= DRM_MODE_FLAG_PVSYNC;
|
||||
|
||||
pipe_config->adjusted_mode.flags |= flags;
|
||||
|
||||
/* gen2/3 store dither state in pfit control, needs to match */
|
||||
if (INTEL_INFO(dev)->gen < 4) {
|
||||
tmp = I915_READ(PFIT_CONTROL);
|
||||
|
||||
pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/* The LVDS pin pair needs to be on before the DPLLs are enabled.
|
||||
|
@ -290,14 +297,11 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
|
|||
|
||||
intel_pch_panel_fitting(intel_crtc, pipe_config,
|
||||
intel_connector->panel.fitting_mode);
|
||||
return true;
|
||||
} else {
|
||||
intel_gmch_panel_fitting(intel_crtc, pipe_config,
|
||||
intel_connector->panel.fitting_mode);
|
||||
}
|
||||
|
||||
drm_mode_set_crtcinfo(adjusted_mode, 0);
|
||||
pipe_config->timings_set = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: It would be nice to support lower refresh rates on the
|
||||
|
|
|
@ -194,6 +194,9 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
|
|||
adjusted_mode->vdisplay == mode->vdisplay)
|
||||
goto out;
|
||||
|
||||
drm_mode_set_crtcinfo(adjusted_mode, 0);
|
||||
pipe_config->timings_set = true;
|
||||
|
||||
switch (fitting_mode) {
|
||||
case DRM_MODE_SCALE_CENTER:
|
||||
/*
|
||||
|
@ -580,7 +583,8 @@ void intel_panel_enable_backlight(struct drm_device *dev,
|
|||
POSTING_READ(reg);
|
||||
I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
if (HAS_PCH_SPLIT(dev) &&
|
||||
!(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) {
|
||||
tmp = I915_READ(BLC_PWM_PCH_CTL1);
|
||||
tmp |= BLM_PCH_PWM_ENABLE;
|
||||
tmp &= ~BLM_PCH_OVERRIDE_ENABLE;
|
||||
|
|
|
@ -5476,7 +5476,7 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
|
|||
gen6_gt_check_fifodbg(dev_priv);
|
||||
}
|
||||
|
||||
void intel_gt_reset(struct drm_device *dev)
|
||||
void intel_gt_sanitize(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
|
@ -5487,6 +5487,10 @@ void intel_gt_reset(struct drm_device *dev)
|
|||
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
|
||||
__gen6_gt_force_wake_mt_reset(dev_priv);
|
||||
}
|
||||
|
||||
/* BIOS often leaves RC6 enabled, but disable it for hw init */
|
||||
if (INTEL_INFO(dev)->gen >= 6)
|
||||
intel_disable_gt_powersave(dev);
|
||||
}
|
||||
|
||||
void intel_gt_init(struct drm_device *dev)
|
||||
|
@ -5495,8 +5499,6 @@ void intel_gt_init(struct drm_device *dev)
|
|||
|
||||
spin_lock_init(&dev_priv->gt_lock);
|
||||
|
||||
intel_gt_reset(dev);
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
dev_priv->gt.force_wake_get = vlv_force_wake_get;
|
||||
dev_priv->gt.force_wake_put = vlv_force_wake_put;
|
||||
|
|
Loading…
Reference in a new issue