diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 109 |
1 files changed, 98 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 68dcf36e2793..5e21b3119824 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -862,8 +862,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
862 | intel_clock_t clock; | 862 | intel_clock_t clock; |
863 | int max_n; | 863 | int max_n; |
864 | bool found; | 864 | bool found; |
865 | /* approximately equals target * 0.00488 */ | 865 | /* approximately equals target * 0.00585 */ |
866 | int err_most = (target >> 8) + (target >> 10); | 866 | int err_most = (target >> 8) + (target >> 9); |
867 | found = false; | 867 | found = false; |
868 | 868 | ||
869 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | 869 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { |
@@ -1180,8 +1180,12 @@ static void intel_update_fbc(struct drm_crtc *crtc, | |||
1180 | struct drm_framebuffer *fb = crtc->fb; | 1180 | struct drm_framebuffer *fb = crtc->fb; |
1181 | struct intel_framebuffer *intel_fb; | 1181 | struct intel_framebuffer *intel_fb; |
1182 | struct drm_i915_gem_object *obj_priv; | 1182 | struct drm_i915_gem_object *obj_priv; |
1183 | struct drm_crtc *tmp_crtc; | ||
1183 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1184 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1184 | int plane = intel_crtc->plane; | 1185 | int plane = intel_crtc->plane; |
1186 | int crtcs_enabled = 0; | ||
1187 | |||
1188 | DRM_DEBUG_KMS("\n"); | ||
1185 | 1189 | ||
1186 | if (!i915_powersave) | 1190 | if (!i915_powersave) |
1187 | return; | 1191 | return; |
@@ -1199,10 +1203,21 @@ static void intel_update_fbc(struct drm_crtc *crtc, | |||
1199 | * If FBC is already on, we just have to verify that we can | 1203 | * If FBC is already on, we just have to verify that we can |
1200 | * keep it that way... | 1204 | * keep it that way... |
1201 | * Need to disable if: | 1205 | * Need to disable if: |
1206 | * - more than one pipe is active | ||
1202 | * - changing FBC params (stride, fence, mode) | 1207 | * - changing FBC params (stride, fence, mode) |
1203 | * - new fb is too large to fit in compressed buffer | 1208 | * - new fb is too large to fit in compressed buffer |
1204 | * - going to an unsupported config (interlace, pixel multiply, etc.) | 1209 | * - going to an unsupported config (interlace, pixel multiply, etc.) |
1205 | */ | 1210 | */ |
1211 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { | ||
1212 | if (tmp_crtc->enabled) | ||
1213 | crtcs_enabled++; | ||
1214 | } | ||
1215 | DRM_DEBUG_KMS("%d pipes active\n", crtcs_enabled); | ||
1216 | if (crtcs_enabled > 1) { | ||
1217 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); | ||
1218 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; | ||
1219 | goto out_disable; | ||
1220 | } | ||
1206 | if (intel_fb->obj->size > dev_priv->cfb_size) { | 1221 | if (intel_fb->obj->size > dev_priv->cfb_size) { |
1207 | DRM_DEBUG_KMS("framebuffer too large, disabling " | 1222 | DRM_DEBUG_KMS("framebuffer too large, disabling " |
1208 | "compression\n"); | 1223 | "compression\n"); |
@@ -1255,7 +1270,7 @@ out_disable: | |||
1255 | } | 1270 | } |
1256 | } | 1271 | } |
1257 | 1272 | ||
1258 | static int | 1273 | int |
1259 | intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) | 1274 | intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj) |
1260 | { | 1275 | { |
1261 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 1276 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
@@ -2255,6 +2270,11 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
2255 | intel_wait_for_vblank(dev); | 2270 | intel_wait_for_vblank(dev); |
2256 | } | 2271 | } |
2257 | 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 | |||
2258 | /* Next, disable display pipes */ | 2278 | /* Next, disable display pipes */ |
2259 | temp = I915_READ(pipeconf_reg); | 2279 | temp = I915_READ(pipeconf_reg); |
2260 | if ((temp & PIPEACONF_ENABLE) != 0) { | 2280 | if ((temp & PIPEACONF_ENABLE) != 0) { |
@@ -2270,7 +2290,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
2270 | I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); | 2290 | I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); |
2271 | I915_READ(dpll_reg); | 2291 | I915_READ(dpll_reg); |
2272 | } | 2292 | } |
2273 | 2293 | skip_pipe_off: | |
2274 | /* Wait for the clocks to turn off. */ | 2294 | /* Wait for the clocks to turn off. */ |
2275 | udelay(150); | 2295 | udelay(150); |
2276 | break; | 2296 | break; |
@@ -2356,8 +2376,6 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, | |||
2356 | if (mode->clock * 3 > 27000 * 4) | 2376 | if (mode->clock * 3 > 27000 * 4) |
2357 | return MODE_CLOCK_HIGH; | 2377 | return MODE_CLOCK_HIGH; |
2358 | } | 2378 | } |
2359 | |||
2360 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
2361 | return true; | 2379 | return true; |
2362 | } | 2380 | } |
2363 | 2381 | ||
@@ -3736,6 +3754,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3736 | if (dev_priv->lvds_dither) { | 3754 | if (dev_priv->lvds_dither) { |
3737 | if (HAS_PCH_SPLIT(dev)) { | 3755 | if (HAS_PCH_SPLIT(dev)) { |
3738 | pipeconf |= PIPE_ENABLE_DITHER; | 3756 | pipeconf |= PIPE_ENABLE_DITHER; |
3757 | pipeconf &= ~PIPE_DITHER_TYPE_MASK; | ||
3739 | pipeconf |= PIPE_DITHER_TYPE_ST01; | 3758 | pipeconf |= PIPE_DITHER_TYPE_ST01; |
3740 | } else | 3759 | } else |
3741 | lvds |= LVDS_ENABLE_DITHER; | 3760 | lvds |= LVDS_ENABLE_DITHER; |
@@ -4412,7 +4431,8 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule) | |||
4412 | DRM_DEBUG_DRIVER("upclocking LVDS\n"); | 4431 | DRM_DEBUG_DRIVER("upclocking LVDS\n"); |
4413 | 4432 | ||
4414 | /* Unlock panel regs */ | 4433 | /* Unlock panel regs */ |
4415 | I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16)); | 4434 | I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | |
4435 | PANEL_UNLOCK_REGS); | ||
4416 | 4436 | ||
4417 | dpll &= ~DISPLAY_RATE_SELECT_FPA1; | 4437 | dpll &= ~DISPLAY_RATE_SELECT_FPA1; |
4418 | I915_WRITE(dpll_reg, dpll); | 4438 | I915_WRITE(dpll_reg, dpll); |
@@ -4455,7 +4475,8 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc) | |||
4455 | DRM_DEBUG_DRIVER("downclocking LVDS\n"); | 4475 | DRM_DEBUG_DRIVER("downclocking LVDS\n"); |
4456 | 4476 | ||
4457 | /* Unlock panel regs */ | 4477 | /* Unlock panel regs */ |
4458 | I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16)); | 4478 | I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | |
4479 | PANEL_UNLOCK_REGS); | ||
4459 | 4480 | ||
4460 | dpll |= DISPLAY_RATE_SELECT_FPA1; | 4481 | dpll |= DISPLAY_RATE_SELECT_FPA1; |
4461 | I915_WRITE(dpll_reg, dpll); | 4482 | I915_WRITE(dpll_reg, dpll); |
@@ -4695,7 +4716,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
4695 | struct drm_gem_object *obj; | 4716 | struct drm_gem_object *obj; |
4696 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4717 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
4697 | struct intel_unpin_work *work; | 4718 | struct intel_unpin_work *work; |
4698 | unsigned long flags; | 4719 | unsigned long flags, offset; |
4699 | int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; | 4720 | int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; |
4700 | int ret, pipesrc; | 4721 | int ret, pipesrc; |
4701 | u32 flip_mask; | 4722 | u32 flip_mask; |
@@ -4762,19 +4783,23 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
4762 | while (I915_READ(ISR) & flip_mask) | 4783 | while (I915_READ(ISR) & flip_mask) |
4763 | ; | 4784 | ; |
4764 | 4785 | ||
4786 | /* Offset into the new buffer for cases of shared fbs between CRTCs */ | ||
4787 | offset = obj_priv->gtt_offset; | ||
4788 | offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8); | ||
4789 | |||
4765 | BEGIN_LP_RING(4); | 4790 | BEGIN_LP_RING(4); |
4766 | if (IS_I965G(dev)) { | 4791 | if (IS_I965G(dev)) { |
4767 | OUT_RING(MI_DISPLAY_FLIP | | 4792 | OUT_RING(MI_DISPLAY_FLIP | |
4768 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 4793 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
4769 | OUT_RING(fb->pitch); | 4794 | OUT_RING(fb->pitch); |
4770 | OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); | 4795 | OUT_RING(offset | obj_priv->tiling_mode); |
4771 | pipesrc = I915_READ(pipesrc_reg); | 4796 | pipesrc = I915_READ(pipesrc_reg); |
4772 | OUT_RING(pipesrc & 0x0fff0fff); | 4797 | OUT_RING(pipesrc & 0x0fff0fff); |
4773 | } else { | 4798 | } else { |
4774 | OUT_RING(MI_DISPLAY_FLIP_I915 | | 4799 | OUT_RING(MI_DISPLAY_FLIP_I915 | |
4775 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 4800 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
4776 | OUT_RING(fb->pitch); | 4801 | OUT_RING(fb->pitch); |
4777 | OUT_RING(obj_priv->gtt_offset); | 4802 | OUT_RING(offset); |
4778 | OUT_RING(MI_NOOP); | 4803 | OUT_RING(MI_NOOP); |
4779 | } | 4804 | } |
4780 | ADVANCE_LP_RING(); | 4805 | ADVANCE_LP_RING(); |
@@ -5506,6 +5531,66 @@ static void intel_init_display(struct drm_device *dev) | |||
5506 | } | 5531 | } |
5507 | } | 5532 | } |
5508 | 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 | |||
5509 | void intel_modeset_init(struct drm_device *dev) | 5594 | void intel_modeset_init(struct drm_device *dev) |
5510 | { | 5595 | { |
5511 | struct drm_i915_private *dev_priv = dev->dev_private; | 5596 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -5518,6 +5603,8 @@ void intel_modeset_init(struct drm_device *dev) | |||
5518 | 5603 | ||
5519 | dev->mode_config.funcs = (void *)&intel_mode_funcs; | 5604 | dev->mode_config.funcs = (void *)&intel_mode_funcs; |
5520 | 5605 | ||
5606 | intel_init_quirks(dev); | ||
5607 | |||
5521 | intel_init_display(dev); | 5608 | intel_init_display(dev); |
5522 | 5609 | ||
5523 | if (IS_I965G(dev)) { | 5610 | if (IS_I965G(dev)) { |