diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 69 |
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 | |||
226 | struct intel_fbdev; | 228 | struct intel_fbdev; |
227 | 229 | ||
228 | typedef struct drm_i915_private { | 230 | typedef 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 | */ | ||
5539 | static 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 | |||
5547 | struct intel_quirk { | ||
5548 | int device; | ||
5549 | int subsystem_vendor; | ||
5550 | int subsystem_device; | ||
5551 | void (*hook)(struct drm_device *dev); | ||
5552 | }; | ||
5553 | |||
5554 | struct 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 | |||
5577 | static 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 | |||
5529 | void intel_modeset_init(struct drm_device *dev) | 5594 | void 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)) { |