diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-06-25 15:02:01 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-07-10 16:13:14 -0400 |
commit | e0b01be41dcdfd28c6855f605983a61b29f65692 (patch) | |
tree | bac0cca79d0ac9be13e49cf139adb92f7560c17a | |
parent | 12030431e9ba407b8c35b3c3bf70b67d609447f3 (diff) |
drm/i915: ->enable hook for WRPLLs
This time around another cute hack to pre-fill the pll->hw_state with
the right values. And also remove a bunch of checks which will be
replaced by lots more checks in the common framework.
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 51 |
1 files changed, 19 insertions, 32 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 7c6e8d549467..150b64b45cb6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -740,6 +740,7 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) | |||
740 | intel_ddi_put_crtc_pll(crtc); | 740 | intel_ddi_put_crtc_pll(crtc); |
741 | 741 | ||
742 | if (type == INTEL_OUTPUT_HDMI) { | 742 | if (type == INTEL_OUTPUT_HDMI) { |
743 | struct intel_shared_dpll *pll; | ||
743 | uint32_t reg, val; | 744 | uint32_t reg, val; |
744 | unsigned p, n2, r2; | 745 | unsigned p, n2, r2; |
745 | 746 | ||
@@ -784,6 +785,9 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) | |||
784 | } | 785 | } |
785 | 786 | ||
786 | intel_crtc->config.dpll_hw_state.wrpll = val; | 787 | intel_crtc->config.dpll_hw_state.wrpll = val; |
788 | |||
789 | pll = &dev_priv->shared_dplls[intel_crtc->config.shared_dpll]; | ||
790 | pll->hw_state.wrpll = val; | ||
787 | } | 791 | } |
788 | 792 | ||
789 | return true; | 793 | return true; |
@@ -798,54 +802,24 @@ void intel_ddi_pll_enable(struct intel_crtc *crtc) | |||
798 | struct drm_device *dev = crtc->base.dev; | 802 | struct drm_device *dev = crtc->base.dev; |
799 | struct drm_i915_private *dev_priv = dev->dev_private; | 803 | struct drm_i915_private *dev_priv = dev->dev_private; |
800 | struct intel_ddi_plls *plls = &dev_priv->ddi_plls; | 804 | struct intel_ddi_plls *plls = &dev_priv->ddi_plls; |
801 | int clock = crtc->config.port_clock; | ||
802 | uint32_t reg, cur_val, new_val; | ||
803 | int refcount; | 805 | int refcount; |
804 | const char *pll_name; | 806 | struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); |
805 | uint32_t enable_bit = (1 << 31); | ||
806 | unsigned int p, n2, r2; | ||
807 | |||
808 | BUILD_BUG_ON(enable_bit != SPLL_PLL_ENABLE); | ||
809 | BUILD_BUG_ON(enable_bit != WRPLL_PLL_ENABLE); | ||
810 | 807 | ||
811 | switch (crtc->config.ddi_pll_sel) { | 808 | switch (crtc->config.ddi_pll_sel) { |
812 | case PORT_CLK_SEL_WRPLL1: | 809 | case PORT_CLK_SEL_WRPLL1: |
813 | case PORT_CLK_SEL_WRPLL2: | 810 | case PORT_CLK_SEL_WRPLL2: |
814 | if (crtc->config.ddi_pll_sel == PORT_CLK_SEL_WRPLL1) { | 811 | if (crtc->config.ddi_pll_sel == PORT_CLK_SEL_WRPLL1) { |
815 | pll_name = "WRPLL1"; | ||
816 | reg = WRPLL_CTL1; | ||
817 | refcount = plls->wrpll1_refcount; | 812 | refcount = plls->wrpll1_refcount; |
818 | } else { | 813 | } else { |
819 | pll_name = "WRPLL2"; | ||
820 | reg = WRPLL_CTL2; | ||
821 | refcount = plls->wrpll2_refcount; | 814 | refcount = plls->wrpll2_refcount; |
822 | } | 815 | } |
823 | |||
824 | intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); | ||
825 | |||
826 | new_val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | | ||
827 | WRPLL_DIVIDER_REFERENCE(r2) | | ||
828 | WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p); | ||
829 | |||
830 | break; | 816 | break; |
831 | |||
832 | case PORT_CLK_SEL_NONE: | ||
833 | WARN(1, "Bad selected pll: PORT_CLK_SEL_NONE\n"); | ||
834 | return; | ||
835 | default: | 817 | default: |
836 | return; | 818 | return; |
837 | } | 819 | } |
838 | 820 | ||
839 | cur_val = I915_READ(reg); | ||
840 | |||
841 | WARN(refcount < 1, "Bad %s refcount: %d\n", pll_name, refcount); | ||
842 | if (refcount == 1) { | 821 | if (refcount == 1) { |
843 | WARN(cur_val & enable_bit, "%s already enabled\n", pll_name); | 822 | pll->enable(dev_priv, pll); |
844 | I915_WRITE(reg, new_val); | ||
845 | POSTING_READ(reg); | ||
846 | udelay(20); | ||
847 | } else { | ||
848 | WARN((cur_val & enable_bit) == 0, "%s disabled\n", pll_name); | ||
849 | } | 823 | } |
850 | } | 824 | } |
851 | 825 | ||
@@ -1311,6 +1285,18 @@ int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) | |||
1311 | } | 1285 | } |
1312 | } | 1286 | } |
1313 | 1287 | ||
1288 | static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, | ||
1289 | struct intel_shared_dpll *pll) | ||
1290 | { | ||
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); | ||
1296 | POSTING_READ(WRPLL_CTL(pll->id)); | ||
1297 | udelay(20); | ||
1298 | } | ||
1299 | |||
1314 | static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv, | 1300 | static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv, |
1315 | struct intel_shared_dpll *pll) | 1301 | struct intel_shared_dpll *pll) |
1316 | { | 1302 | { |
@@ -1356,6 +1342,7 @@ void intel_ddi_pll_init(struct drm_device *dev) | |||
1356 | dev_priv->shared_dplls[i].id = i; | 1342 | dev_priv->shared_dplls[i].id = i; |
1357 | dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; | 1343 | dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; |
1358 | dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable; | 1344 | dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable; |
1345 | dev_priv->shared_dplls[i].enable = hsw_ddi_pll_enable; | ||
1359 | dev_priv->shared_dplls[i].get_hw_state = | 1346 | dev_priv->shared_dplls[i].get_hw_state = |
1360 | hsw_ddi_pll_get_hw_state; | 1347 | hsw_ddi_pll_get_hw_state; |
1361 | } | 1348 | } |