diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 141 |
1 files changed, 13 insertions, 128 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 150b64b45cb6..60e67a11791b 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -388,30 +388,12 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) | |||
388 | 388 | ||
389 | void intel_ddi_put_crtc_pll(struct drm_crtc *crtc) | 389 | void intel_ddi_put_crtc_pll(struct drm_crtc *crtc) |
390 | { | 390 | { |
391 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; | ||
392 | struct intel_ddi_plls *plls = &dev_priv->ddi_plls; | ||
393 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 391 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
394 | struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(intel_crtc); | ||
395 | 392 | ||
396 | switch (intel_crtc->config.ddi_pll_sel) { | 393 | if (intel_crtc_to_shared_dpll(intel_crtc)) |
397 | case PORT_CLK_SEL_WRPLL1: | 394 | intel_disable_shared_dpll(intel_crtc); |
398 | plls->wrpll1_refcount--; | ||
399 | if (plls->wrpll1_refcount == 0) { | ||
400 | pll->disable(dev_priv, pll); | ||
401 | } | ||
402 | intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_NONE; | ||
403 | break; | ||
404 | case PORT_CLK_SEL_WRPLL2: | ||
405 | plls->wrpll2_refcount--; | ||
406 | if (plls->wrpll2_refcount == 0) { | ||
407 | pll->disable(dev_priv, pll); | ||
408 | } | ||
409 | intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_NONE; | ||
410 | break; | ||
411 | } | ||
412 | 395 | ||
413 | WARN(plls->wrpll1_refcount < 0, "Invalid WRPLL1 refcount\n"); | 396 | intel_put_shared_dpll(intel_crtc); |
414 | WARN(plls->wrpll2_refcount < 0, "Invalid WRPLL2 refcount\n"); | ||
415 | } | 397 | } |
416 | 398 | ||
417 | #define LC_FREQ 2700 | 399 | #define LC_FREQ 2700 |
@@ -731,17 +713,14 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) | |||
731 | { | 713 | { |
732 | struct drm_crtc *crtc = &intel_crtc->base; | 714 | struct drm_crtc *crtc = &intel_crtc->base; |
733 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); | 715 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
734 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; | ||
735 | struct intel_ddi_plls *plls = &dev_priv->ddi_plls; | ||
736 | int type = intel_encoder->type; | 716 | int type = intel_encoder->type; |
737 | enum pipe pipe = intel_crtc->pipe; | ||
738 | int clock = intel_crtc->config.port_clock; | 717 | int clock = intel_crtc->config.port_clock; |
739 | 718 | ||
740 | intel_ddi_put_crtc_pll(crtc); | 719 | intel_ddi_put_crtc_pll(crtc); |
741 | 720 | ||
742 | if (type == INTEL_OUTPUT_HDMI) { | 721 | if (type == INTEL_OUTPUT_HDMI) { |
743 | struct intel_shared_dpll *pll; | 722 | struct intel_shared_dpll *pll; |
744 | uint32_t reg, val; | 723 | uint32_t val; |
745 | unsigned p, n2, r2; | 724 | unsigned p, n2, r2; |
746 | 725 | ||
747 | intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); | 726 | intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); |
@@ -750,79 +729,21 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) | |||
750 | WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | | 729 | WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | |
751 | WRPLL_DIVIDER_POST(p); | 730 | WRPLL_DIVIDER_POST(p); |
752 | 731 | ||
753 | if (val == I915_READ(WRPLL_CTL1)) { | 732 | intel_crtc->config.dpll_hw_state.wrpll = val; |
754 | DRM_DEBUG_KMS("Reusing WRPLL 1 on pipe %c\n", | ||
755 | pipe_name(pipe)); | ||
756 | reg = WRPLL_CTL1; | ||
757 | } else if (val == I915_READ(WRPLL_CTL2)) { | ||
758 | DRM_DEBUG_KMS("Reusing WRPLL 2 on pipe %c\n", | ||
759 | pipe_name(pipe)); | ||
760 | reg = WRPLL_CTL2; | ||
761 | } else if (plls->wrpll1_refcount == 0) { | ||
762 | DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n", | ||
763 | pipe_name(pipe)); | ||
764 | reg = WRPLL_CTL1; | ||
765 | } else if (plls->wrpll2_refcount == 0) { | ||
766 | DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n", | ||
767 | pipe_name(pipe)); | ||
768 | reg = WRPLL_CTL2; | ||
769 | } else { | ||
770 | DRM_ERROR("No WRPLLs available!\n"); | ||
771 | return false; | ||
772 | } | ||
773 | 733 | ||
774 | DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n", | 734 | pll = intel_get_shared_dpll(intel_crtc); |
775 | clock, p, n2, r2); | 735 | if (pll == NULL) { |
776 | 736 | DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", | |
777 | if (reg == WRPLL_CTL1) { | 737 | pipe_name(intel_crtc->pipe)); |
778 | plls->wrpll1_refcount++; | 738 | return false; |
779 | intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_WRPLL1; | ||
780 | intel_crtc->config.shared_dpll = DPLL_ID_WRPLL1; | ||
781 | } else { | ||
782 | plls->wrpll2_refcount++; | ||
783 | intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_WRPLL2; | ||
784 | intel_crtc->config.shared_dpll = DPLL_ID_WRPLL2; | ||
785 | } | 739 | } |
786 | 740 | ||
787 | intel_crtc->config.dpll_hw_state.wrpll = val; | 741 | intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id); |
788 | |||
789 | pll = &dev_priv->shared_dplls[intel_crtc->config.shared_dpll]; | ||
790 | pll->hw_state.wrpll = val; | ||
791 | } | 742 | } |
792 | 743 | ||
793 | return true; | 744 | return true; |
794 | } | 745 | } |
795 | 746 | ||
796 | /* | ||
797 | * To be called after intel_ddi_pll_select(). That one selects the PLL to be | ||
798 | * used, this one actually enables the PLL. | ||
799 | */ | ||
800 | void intel_ddi_pll_enable(struct intel_crtc *crtc) | ||
801 | { | ||
802 | struct drm_device *dev = crtc->base.dev; | ||
803 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
804 | struct intel_ddi_plls *plls = &dev_priv->ddi_plls; | ||
805 | int refcount; | ||
806 | struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); | ||
807 | |||
808 | switch (crtc->config.ddi_pll_sel) { | ||
809 | case PORT_CLK_SEL_WRPLL1: | ||
810 | case PORT_CLK_SEL_WRPLL2: | ||
811 | if (crtc->config.ddi_pll_sel == PORT_CLK_SEL_WRPLL1) { | ||
812 | refcount = plls->wrpll1_refcount; | ||
813 | } else { | ||
814 | refcount = plls->wrpll2_refcount; | ||
815 | } | ||
816 | break; | ||
817 | default: | ||
818 | return; | ||
819 | } | ||
820 | |||
821 | if (refcount == 1) { | ||
822 | pll->enable(dev_priv, pll); | ||
823 | } | ||
824 | } | ||
825 | |||
826 | void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) | 747 | void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) |
827 | { | 748 | { |
828 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; | 749 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
@@ -1054,35 +975,6 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, | |||
1054 | return false; | 975 | return false; |
1055 | } | 976 | } |
1056 | 977 | ||
1057 | void intel_ddi_setup_hw_pll_state(struct drm_device *dev) | ||
1058 | { | ||
1059 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1060 | enum pipe pipe; | ||
1061 | struct intel_crtc *intel_crtc; | ||
1062 | |||
1063 | dev_priv->ddi_plls.wrpll1_refcount = 0; | ||
1064 | dev_priv->ddi_plls.wrpll2_refcount = 0; | ||
1065 | |||
1066 | for_each_pipe(pipe) { | ||
1067 | intel_crtc = | ||
1068 | to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); | ||
1069 | |||
1070 | if (!intel_crtc->active) { | ||
1071 | intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_NONE; | ||
1072 | continue; | ||
1073 | } | ||
1074 | |||
1075 | switch (intel_crtc->config.ddi_pll_sel) { | ||
1076 | case PORT_CLK_SEL_WRPLL1: | ||
1077 | dev_priv->ddi_plls.wrpll1_refcount++; | ||
1078 | break; | ||
1079 | case PORT_CLK_SEL_WRPLL2: | ||
1080 | dev_priv->ddi_plls.wrpll2_refcount++; | ||
1081 | break; | ||
1082 | } | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1086 | void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc) | 978 | void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc) |
1087 | { | 979 | { |
1088 | struct drm_crtc *crtc = &intel_crtc->base; | 980 | struct drm_crtc *crtc = &intel_crtc->base; |
@@ -1288,10 +1180,6 @@ int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) | |||
1288 | static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, | 1180 | static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, |
1289 | struct intel_shared_dpll *pll) | 1181 | struct intel_shared_dpll *pll) |
1290 | { | 1182 | { |
1291 | uint32_t cur_val; | ||
1292 | |||
1293 | cur_val = I915_READ(WRPLL_CTL(pll->id)); | ||
1294 | WARN(cur_val & WRPLL_PLL_ENABLE, "%s already enabled\n", pll->name); | ||
1295 | I915_WRITE(WRPLL_CTL(pll->id), pll->hw_state.wrpll); | 1183 | I915_WRITE(WRPLL_CTL(pll->id), pll->hw_state.wrpll); |
1296 | POSTING_READ(WRPLL_CTL(pll->id)); | 1184 | POSTING_READ(WRPLL_CTL(pll->id)); |
1297 | udelay(20); | 1185 | udelay(20); |
@@ -1303,7 +1191,6 @@ static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv, | |||
1303 | uint32_t val; | 1191 | uint32_t val; |
1304 | 1192 | ||
1305 | val = I915_READ(WRPLL_CTL(pll->id)); | 1193 | val = I915_READ(WRPLL_CTL(pll->id)); |
1306 | WARN_ON(!(val & WRPLL_PLL_ENABLE)); | ||
1307 | I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE); | 1194 | I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE); |
1308 | POSTING_READ(WRPLL_CTL(pll->id)); | 1195 | POSTING_READ(WRPLL_CTL(pll->id)); |
1309 | } | 1196 | } |
@@ -1334,11 +1221,9 @@ void intel_ddi_pll_init(struct drm_device *dev) | |||
1334 | uint32_t val = I915_READ(LCPLL_CTL); | 1221 | uint32_t val = I915_READ(LCPLL_CTL); |
1335 | int i; | 1222 | int i; |
1336 | 1223 | ||
1337 | /* Dummy setup until everything is moved over to avoid upsetting the hw | 1224 | dev_priv->num_shared_dpll = 2; |
1338 | * state cross checker. */ | ||
1339 | dev_priv->num_shared_dpll = 0; | ||
1340 | 1225 | ||
1341 | for (i = 0; i < 2; i++) { | 1226 | for (i = 0; i < dev_priv->num_shared_dpll; i++) { |
1342 | dev_priv->shared_dplls[i].id = i; | 1227 | dev_priv->shared_dplls[i].id = i; |
1343 | dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; | 1228 | dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; |
1344 | dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable; | 1229 | dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable; |