aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorPaulo Zanoni <paulo.r.zanoni@intel.com>2013-11-25 12:27:08 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-12-12 09:30:47 -0500
commit566b734a190766f25f21c8c44633c14a122e61fa (patch)
tree26e2b16fb646bb56abce5d94c05d81555c35441d /drivers/gpu/drm/i915
parent47e9766df0298739aab87c9874a21feb71560953 (diff)
drm/i915: split intel_ddi_pll_mode_set in 2 pieces
The first piece, intel_ddi_pll_select, finds a PLL and assigns it to the CRTC, but doesn't write any register. It can also fail in case it doesn't find a PLL. The second piece, intel_ddi_pll_enable, uses the information stored by intel_ddi_pll_select to actually enable the PLL by writing to its register. This function can't fail. We also have some refcount sanity checks here. The idea is that one day we'll remove all the functions that touch registers from haswell_crtc_mode_set to haswell_crtc_enable, so we'll call intel_ddi_pll_select at haswell_crtc_mode_set and then call intel_ddi_pll_enable at haswell_crtc_enable. Since I'm already touching this code, let's take care of this particular split today. v2: - Clock on the debug message is in KHz - Add missing POSTING_READ Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> [danvet: Bikeshed comments.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c108
-rw-r--r--drivers/gpu/drm/i915/intel_display.c3
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h3
3 files changed, 94 insertions, 20 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 8b0e96ff76c9..cec06a5453cc 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -696,21 +696,23 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */,
696 *n2_out = best.n2; 696 *n2_out = best.n2;
697 *p_out = best.p; 697 *p_out = best.p;
698 *r2_out = best.r2; 698 *r2_out = best.r2;
699
700 DRM_DEBUG_KMS("WRPLL: %dHz refresh rate with p=%d, n2=%d r2=%d\n",
701 clock, *p_out, *n2_out, *r2_out);
702} 699}
703 700
704bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) 701/*
702 * Tries to find a PLL for the CRTC. If it finds, it increases the refcount and
703 * stores it in intel_crtc->ddi_pll_sel, so other mode sets won't be able to
704 * steal the selected PLL. You need to call intel_ddi_pll_enable to actually
705 * enable the PLL.
706 */
707bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
705{ 708{
706 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 709 struct drm_crtc *crtc = &intel_crtc->base;
707 struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); 710 struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
708 struct drm_encoder *encoder = &intel_encoder->base; 711 struct drm_encoder *encoder = &intel_encoder->base;
709 struct drm_i915_private *dev_priv = crtc->dev->dev_private; 712 struct drm_i915_private *dev_priv = crtc->dev->dev_private;
710 struct intel_ddi_plls *plls = &dev_priv->ddi_plls; 713 struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
711 int type = intel_encoder->type; 714 int type = intel_encoder->type;
712 enum pipe pipe = intel_crtc->pipe; 715 enum pipe pipe = intel_crtc->pipe;
713 uint32_t reg, val;
714 int clock = intel_crtc->config.port_clock; 716 int clock = intel_crtc->config.port_clock;
715 717
716 intel_ddi_put_crtc_pll(crtc); 718 intel_ddi_put_crtc_pll(crtc);
@@ -734,10 +736,8 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
734 return false; 736 return false;
735 } 737 }
736 738
737 /* We don't need to turn any PLL on because we'll use LCPLL. */
738 return true;
739
740 } else if (type == INTEL_OUTPUT_HDMI) { 739 } else if (type == INTEL_OUTPUT_HDMI) {
740 uint32_t reg, val;
741 unsigned p, n2, r2; 741 unsigned p, n2, r2;
742 742
743 intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); 743 intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
@@ -767,6 +767,9 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
767 return false; 767 return false;
768 } 768 }
769 769
770 DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
771 clock, p, n2, r2);
772
770 if (reg == WRPLL_CTL1) { 773 if (reg == WRPLL_CTL1) {
771 plls->wrpll1_refcount++; 774 plls->wrpll1_refcount++;
772 intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1; 775 intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
@@ -780,29 +783,98 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
780 DRM_DEBUG_KMS("Using SPLL on pipe %c\n", 783 DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
781 pipe_name(pipe)); 784 pipe_name(pipe));
782 plls->spll_refcount++; 785 plls->spll_refcount++;
783 reg = SPLL_CTL;
784 intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL; 786 intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
785 } else { 787 } else {
786 DRM_ERROR("SPLL already in use\n"); 788 DRM_ERROR("SPLL already in use\n");
787 return false; 789 return false;
788 } 790 }
789 791
790 WARN(I915_READ(reg) & SPLL_PLL_ENABLE,
791 "SPLL already enabled\n");
792
793 val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
794
795 } else { 792 } else {
796 WARN(1, "Invalid DDI encoder type %d\n", type); 793 WARN(1, "Invalid DDI encoder type %d\n", type);
797 return false; 794 return false;
798 } 795 }
799 796
800 I915_WRITE(reg, val);
801 udelay(20);
802
803 return true; 797 return true;
804} 798}
805 799
800/*
801 * To be called after intel_ddi_pll_select(). That one selects the PLL to be
802 * used, this one actually enables the PLL.
803 */
804void intel_ddi_pll_enable(struct intel_crtc *crtc)
805{
806 struct drm_device *dev = crtc->base.dev;
807 struct drm_i915_private *dev_priv = dev->dev_private;
808 struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
809 int clock = crtc->config.port_clock;
810 uint32_t reg, cur_val, new_val;
811 int refcount;
812 const char *pll_name;
813 uint32_t enable_bit = (1 << 31);
814 unsigned int p, n2, r2;
815
816 BUILD_BUG_ON(enable_bit != SPLL_PLL_ENABLE);
817 BUILD_BUG_ON(enable_bit != WRPLL_PLL_ENABLE);
818
819 switch (crtc->ddi_pll_sel) {
820 case PORT_CLK_SEL_LCPLL_2700:
821 case PORT_CLK_SEL_LCPLL_1350:
822 case PORT_CLK_SEL_LCPLL_810:
823 /*
824 * LCPLL should always be enabled at this point of the mode set
825 * sequence, so nothing to do.
826 */
827 return;
828
829 case PORT_CLK_SEL_SPLL:
830 pll_name = "SPLL";
831 reg = SPLL_CTL;
832 refcount = plls->spll_refcount;
833 new_val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz |
834 SPLL_PLL_SSC;
835 break;
836
837 case PORT_CLK_SEL_WRPLL1:
838 case PORT_CLK_SEL_WRPLL2:
839 if (crtc->ddi_pll_sel == PORT_CLK_SEL_WRPLL1) {
840 pll_name = "WRPLL1";
841 reg = WRPLL_CTL1;
842 refcount = plls->wrpll1_refcount;
843 } else {
844 pll_name = "WRPLL2";
845 reg = WRPLL_CTL2;
846 refcount = plls->wrpll2_refcount;
847 }
848
849 intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
850
851 new_val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
852 WRPLL_DIVIDER_REFERENCE(r2) |
853 WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p);
854
855 break;
856
857 case PORT_CLK_SEL_NONE:
858 WARN(1, "Bad selected pll: PORT_CLK_SEL_NONE\n");
859 return;
860 default:
861 WARN(1, "Bad selected pll: 0x%08x\n", crtc->ddi_pll_sel);
862 return;
863 }
864
865 cur_val = I915_READ(reg);
866
867 WARN(refcount < 1, "Bad %s refcount: %d\n", pll_name, refcount);
868 if (refcount == 1) {
869 WARN(cur_val & enable_bit, "%s already enabled\n", pll_name);
870 I915_WRITE(reg, new_val);
871 POSTING_READ(reg);
872 udelay(20);
873 } else {
874 WARN((cur_val & enable_bit) == 0, "%s disabled\n", pll_name);
875 }
876}
877
806void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) 878void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
807{ 879{
808 struct drm_i915_private *dev_priv = crtc->dev->dev_private; 880 struct drm_i915_private *dev_priv = crtc->dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c01aff8a36bb..a40651ef525c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6902,8 +6902,9 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
6902 int plane = intel_crtc->plane; 6902 int plane = intel_crtc->plane;
6903 int ret; 6903 int ret;
6904 6904
6905 if (!intel_ddi_pll_mode_set(crtc)) 6905 if (!intel_ddi_pll_select(intel_crtc))
6906 return -EINVAL; 6906 return -EINVAL;
6907 intel_ddi_pll_enable(intel_crtc);
6907 6908
6908 if (intel_crtc->config.has_dp_encoder) 6909 if (intel_crtc->config.has_dp_encoder)
6909 intel_dp_set_m_n(intel_crtc); 6910 intel_dp_set_m_n(intel_crtc);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a829ab5516f4..e903432c7c37 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -613,7 +613,8 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
613void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc); 613void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
614void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc); 614void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
615void intel_ddi_setup_hw_pll_state(struct drm_device *dev); 615void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
616bool intel_ddi_pll_mode_set(struct drm_crtc *crtc); 616bool intel_ddi_pll_select(struct intel_crtc *crtc);
617void intel_ddi_pll_enable(struct intel_crtc *crtc);
617void intel_ddi_put_crtc_pll(struct drm_crtc *crtc); 618void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
618void intel_ddi_set_pipe_settings(struct drm_crtc *crtc); 619void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
619void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder); 620void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);