aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h4
-rw-r--r--drivers/gpu/drm/i915/intel_display.c69
2 files changed, 72 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1d82de1618ab..2e1744d37ad5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -223,6 +223,8 @@ enum intel_pch {
223 PCH_CPT, /* Cougarpoint PCH */ 223 PCH_CPT, /* Cougarpoint PCH */
224}; 224};
225 225
226#define QUIRK_PIPEA_FORCE (1<<0)
227
226struct intel_fbdev; 228struct intel_fbdev;
227 229
228typedef struct drm_i915_private { 230typedef struct drm_i915_private {
@@ -338,6 +340,8 @@ typedef struct drm_i915_private {
338 /* PCH chipset type */ 340 /* PCH chipset type */
339 enum intel_pch pch_type; 341 enum intel_pch pch_type;
340 342
343 unsigned long quirks;
344
341 /* Register state */ 345 /* Register state */
342 bool modeset_on_lid; 346 bool modeset_on_lid;
343 u8 saveLBB; 347 u8 saveLBB;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index dbd9f09465f8..5e21b3119824 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2270,6 +2270,11 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
2270 intel_wait_for_vblank(dev); 2270 intel_wait_for_vblank(dev);
2271 } 2271 }
2272 2272
2273 /* Don't disable pipe A or pipe A PLLs if needed */
2274 if (pipeconf_reg == PIPEACONF &&
2275 (dev_priv->quirks & QUIRK_PIPEA_FORCE))
2276 goto skip_pipe_off;
2277
2273 /* Next, disable display pipes */ 2278 /* Next, disable display pipes */
2274 temp = I915_READ(pipeconf_reg); 2279 temp = I915_READ(pipeconf_reg);
2275 if ((temp & PIPEACONF_ENABLE) != 0) { 2280 if ((temp & PIPEACONF_ENABLE) != 0) {
@@ -2285,7 +2290,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
2285 I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); 2290 I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
2286 I915_READ(dpll_reg); 2291 I915_READ(dpll_reg);
2287 } 2292 }
2288 2293 skip_pipe_off:
2289 /* Wait for the clocks to turn off. */ 2294 /* Wait for the clocks to turn off. */
2290 udelay(150); 2295 udelay(150);
2291 break; 2296 break;
@@ -5526,6 +5531,66 @@ static void intel_init_display(struct drm_device *dev)
5526 } 5531 }
5527} 5532}
5528 5533
5534/*
5535 * Some BIOSes insist on assuming the GPU's pipe A is enabled at suspend,
5536 * resume, or other times. This quirk makes sure that's the case for
5537 * affected systems.
5538 */
5539static void quirk_pipea_force (struct drm_device *dev)
5540{
5541 struct drm_i915_private *dev_priv = dev->dev_private;
5542
5543 dev_priv->quirks |= QUIRK_PIPEA_FORCE;
5544 DRM_DEBUG_DRIVER("applying pipe a force quirk\n");
5545}
5546
5547struct intel_quirk {
5548 int device;
5549 int subsystem_vendor;
5550 int subsystem_device;
5551 void (*hook)(struct drm_device *dev);
5552};
5553
5554struct intel_quirk intel_quirks[] = {
5555 /* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */
5556 { 0x2a42, 0x103c, 0x30eb, quirk_pipea_force },
5557 /* HP Mini needs pipe A force quirk (LP: #322104) */
5558 { 0x27ae,0x103c, 0x361a, quirk_pipea_force },
5559
5560 /* Thinkpad R31 needs pipe A force quirk */
5561 { 0x3577, 0x1014, 0x0505, quirk_pipea_force },
5562 /* Toshiba Protege R-205, S-209 needs pipe A force quirk */
5563 { 0x2592, 0x1179, 0x0001, quirk_pipea_force },
5564
5565 /* ThinkPad X30 needs pipe A force quirk (LP: #304614) */
5566 { 0x3577, 0x1014, 0x0513, quirk_pipea_force },
5567 /* ThinkPad X40 needs pipe A force quirk */
5568
5569 /* ThinkPad T60 needs pipe A force quirk (bug #16494) */
5570 { 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
5571
5572 /* 855 & before need to leave pipe A & dpll A up */
5573 { 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
5574 { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
5575};
5576
5577static void intel_init_quirks(struct drm_device *dev)
5578{
5579 struct pci_dev *d = dev->pdev;
5580 int i;
5581
5582 for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) {
5583 struct intel_quirk *q = &intel_quirks[i];
5584
5585 if (d->device == q->device &&
5586 (d->subsystem_vendor == q->subsystem_vendor ||
5587 q->subsystem_vendor == PCI_ANY_ID) &&
5588 (d->subsystem_device == q->subsystem_device ||
5589 q->subsystem_device == PCI_ANY_ID))
5590 q->hook(dev);
5591 }
5592}
5593
5529void intel_modeset_init(struct drm_device *dev) 5594void intel_modeset_init(struct drm_device *dev)
5530{ 5595{
5531 struct drm_i915_private *dev_priv = dev->dev_private; 5596 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5538,6 +5603,8 @@ void intel_modeset_init(struct drm_device *dev)
5538 5603
5539 dev->mode_config.funcs = (void *)&intel_mode_funcs; 5604 dev->mode_config.funcs = (void *)&intel_mode_funcs;
5540 5605
5606 intel_init_quirks(dev);
5607
5541 intel_init_display(dev); 5608 intel_init_display(dev);
5542 5609
5543 if (IS_I965G(dev)) { 5610 if (IS_I965G(dev)) {