diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 123 |
1 files changed, 77 insertions, 46 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 84f3054a066f..cc431f4581c3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4463,6 +4463,81 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) | |||
4463 | return dev_priv->lvds_use_ssc && i915_panel_use_ssc; | 4463 | return dev_priv->lvds_use_ssc && i915_panel_use_ssc; |
4464 | } | 4464 | } |
4465 | 4465 | ||
4466 | static void intel_update_dref(struct drm_i915_private *dev_priv) | ||
4467 | { | ||
4468 | struct drm_device *dev = dev_priv->dev; | ||
4469 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
4470 | struct intel_encoder *encoder; | ||
4471 | struct drm_crtc *crtc; | ||
4472 | u32 temp; | ||
4473 | bool lvds_on = false, edp_on = false, pch_edp_on = false, other_on = false; | ||
4474 | |||
4475 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | ||
4476 | crtc = encoder->base.crtc; | ||
4477 | |||
4478 | if (!crtc || !crtc->enabled) | ||
4479 | continue; | ||
4480 | |||
4481 | switch (encoder->type) { | ||
4482 | case INTEL_OUTPUT_LVDS: | ||
4483 | lvds_on = true; | ||
4484 | break; | ||
4485 | case INTEL_OUTPUT_EDP: | ||
4486 | edp_on = true; | ||
4487 | if (!pch_edp_on) | ||
4488 | pch_edp_on = intel_encoder_is_pch_edp(&encoder->base); | ||
4489 | break; | ||
4490 | default: | ||
4491 | other_on = true; | ||
4492 | break; | ||
4493 | } | ||
4494 | } | ||
4495 | |||
4496 | /*XXX BIOS treats 16:31 as a mask for 0:15 */ | ||
4497 | |||
4498 | temp = I915_READ(PCH_DREF_CONTROL); | ||
4499 | |||
4500 | /* First clear the current state for output switching */ | ||
4501 | temp &= ~DREF_SSC1_ENABLE; | ||
4502 | temp &= ~DREF_SSC4_ENABLE; | ||
4503 | temp &= ~DREF_SUPERSPREAD_SOURCE_MASK; | ||
4504 | temp &= ~DREF_NONSPREAD_SOURCE_MASK; | ||
4505 | temp &= ~DREF_SSC_SOURCE_MASK; | ||
4506 | temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; | ||
4507 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
4508 | |||
4509 | POSTING_READ(PCH_DREF_CONTROL); | ||
4510 | udelay(200); | ||
4511 | |||
4512 | if ((lvds_on || edp_on) && intel_panel_use_ssc(dev_priv)) { | ||
4513 | temp |= DREF_SSC_SOURCE_ENABLE; | ||
4514 | if (edp_on) { | ||
4515 | if (!pch_edp_on) { | ||
4516 | /* Enable CPU source on CPU attached eDP */ | ||
4517 | temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; | ||
4518 | } else { | ||
4519 | /* Enable SSC on PCH eDP if needed */ | ||
4520 | temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; | ||
4521 | } | ||
4522 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
4523 | } | ||
4524 | if (!dev_priv->display_clock_mode) | ||
4525 | temp |= DREF_SSC1_ENABLE; | ||
4526 | } | ||
4527 | |||
4528 | if (other_on && dev_priv->display_clock_mode) | ||
4529 | temp |= DREF_NONSPREAD_CK505_ENABLE; | ||
4530 | else if (other_on) { | ||
4531 | temp |= DREF_NONSPREAD_SOURCE_ENABLE; | ||
4532 | if (edp_on && !pch_edp_on) | ||
4533 | temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; | ||
4534 | } | ||
4535 | |||
4536 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
4537 | POSTING_READ(PCH_DREF_CONTROL); | ||
4538 | udelay(200); | ||
4539 | } | ||
4540 | |||
4466 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | 4541 | static int intel_crtc_mode_set(struct drm_crtc *crtc, |
4467 | struct drm_display_mode *mode, | 4542 | struct drm_display_mode *mode, |
4468 | struct drm_display_mode *adjusted_mode, | 4543 | struct drm_display_mode *adjusted_mode, |
@@ -4688,52 +4763,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4688 | * PCH B stepping, previous chipset stepping should be | 4763 | * PCH B stepping, previous chipset stepping should be |
4689 | * ignoring this setting. | 4764 | * ignoring this setting. |
4690 | */ | 4765 | */ |
4691 | if (HAS_PCH_SPLIT(dev)) { | 4766 | if (HAS_PCH_SPLIT(dev)) |
4692 | /*XXX BIOS treats 16:31 as a mask for 0:15 */ | 4767 | intel_update_dref(dev_priv); |
4693 | |||
4694 | temp = I915_READ(PCH_DREF_CONTROL); | ||
4695 | |||
4696 | /* First clear the current state for output switching */ | ||
4697 | temp &= ~DREF_SSC1_ENABLE; | ||
4698 | temp &= ~DREF_SSC4_ENABLE; | ||
4699 | temp &= ~DREF_SUPERSPREAD_SOURCE_MASK; | ||
4700 | temp &= ~DREF_NONSPREAD_SOURCE_MASK; | ||
4701 | temp &= ~DREF_SSC_SOURCE_MASK; | ||
4702 | temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; | ||
4703 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
4704 | |||
4705 | POSTING_READ(PCH_DREF_CONTROL); | ||
4706 | udelay(200); | ||
4707 | |||
4708 | if ((is_lvds || has_edp_encoder) && | ||
4709 | intel_panel_use_ssc(dev_priv)) { | ||
4710 | temp |= DREF_SSC_SOURCE_ENABLE; | ||
4711 | if (has_edp_encoder) { | ||
4712 | if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { | ||
4713 | /* Enable CPU source on CPU attached eDP */ | ||
4714 | temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; | ||
4715 | } else { | ||
4716 | /* Enable SSC on PCH eDP if needed */ | ||
4717 | temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; | ||
4718 | } | ||
4719 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
4720 | } | ||
4721 | if (!dev_priv->display_clock_mode) | ||
4722 | temp |= DREF_SSC1_ENABLE; | ||
4723 | } else { | ||
4724 | if (dev_priv->display_clock_mode) | ||
4725 | temp |= DREF_NONSPREAD_CK505_ENABLE; | ||
4726 | else | ||
4727 | temp |= DREF_NONSPREAD_SOURCE_ENABLE; | ||
4728 | if (has_edp_encoder && | ||
4729 | !intel_encoder_is_pch_edp(&has_edp_encoder->base)) | ||
4730 | temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; | ||
4731 | } | ||
4732 | |||
4733 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
4734 | POSTING_READ(PCH_DREF_CONTROL); | ||
4735 | udelay(200); | ||
4736 | } | ||
4737 | 4768 | ||
4738 | if (IS_PINEVIEW(dev)) { | 4769 | if (IS_PINEVIEW(dev)) { |
4739 | fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; | 4770 | fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; |