aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ddi.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-12-22 19:46:07 -0500
committerDave Airlie <airlied@redhat.com>2013-12-22 19:46:07 -0500
commit859ae233cd0ee76b6143f948ba1cb6b0b4c342f8 (patch)
treeb2071654cf0ef520e047035720a101d3222e47bc /drivers/gpu/drm/i915/intel_ddi.c
parent785e15ecefbfe8ea311ae320fdacd482a84b3cc3 (diff)
parentab57fff1302c485d74992d34df24ccb5efda244e (diff)
Merge tag 'drm-intel-next-2013-12-13' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
- fbc1 improvements from Ville (pre-gm45). - vlv forcewake improvements from Deepak S. - Some corner-cases fixes from Mika for the context hang stat code. - pc8 improvements and prep work for runtime D3 from Paulo, almost ready for primetime. - gen2 dpll fixes from Ville. - DSI improvements from Shobhit Kumar. - A few smaller fixes and improvements all over. [airlied: intel_ddi.c conflict fixed up] * tag 'drm-intel-next-2013-12-13' of git://people.freedesktop.org/~danvet/drm-intel: (61 commits) drm/i915/bdw: Implement ff workarounds drm/i915/bdw: Force all Data Cache Data Port access to be Non-Coherent drm/i915/bdw: Don't use forcewake needlessly drm/i915: Clear out old GT FIFO errors in intel_uncore_early_sanitize() drm/i915: dont call irq_put when irq test is on drm/i915: Rework the FBC interval/stall stuff a bit drm/i915: Enable FBC for all mobile gen2 and gen3 platforms drm/i915: FBC_CONTROL2 is gen4 only drm/i915: Gen2 FBC1 CFB pitch wants 32B units drm/i915: split intel_ddi_pll_mode_set in 2 pieces drm/i915: Fix timeout with missed interrupts in __wait_seqno drm/i915: touch VGA MSR after we enable the power well drm/i915: extract hsw_power_well_post_{enable, disable} drm/i915: remove i915_disable_vga_mem declaration drm/i915: Parametrize the dphy and other spec specific parameters drm/i915: Remove redundant DSI PLL enabling drm/i915: Reorganize the DSI enable/disable sequence drm/i915: Try harder to get best m, n, p values with minimal error drm/i915: Compute dsi_clk from pixel clock drm/i915: Use FLISDSI interface for band gap reset ... Conflicts: drivers/gpu/drm/i915/intel_ddi.c
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c113
1 files changed, 91 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index c8382f55870c..d7d2683b89df 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = {
73}; 73};
74 74
75static const u32 bdw_ddi_translations_edp[] = { 75static const u32 bdw_ddi_translations_edp[] = {
76 0x00FFFFFF, 0x00000012, /* DP parameters */ 76 0x00FFFFFF, 0x00000012, /* eDP parameters */
77 0x00EBAFFF, 0x00020011, 77 0x00EBAFFF, 0x00020011,
78 0x00C71FFF, 0x0006000F, 78 0x00C71FFF, 0x0006000F,
79 0x00FFFFFF, 0x00020011, 79 0x00FFFFFF, 0x00020011,
@@ -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;
@@ -1122,9 +1194,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
1122 1194
1123 if (type == INTEL_OUTPUT_EDP) { 1195 if (type == INTEL_OUTPUT_EDP) {
1124 struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1196 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1125 ironlake_edp_panel_vdd_on(intel_dp);
1126 ironlake_edp_panel_on(intel_dp); 1197 ironlake_edp_panel_on(intel_dp);
1127 ironlake_edp_panel_vdd_off(intel_dp, true);
1128 } 1198 }
1129 1199
1130 WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE); 1200 WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
@@ -1167,7 +1237,6 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
1167 1237
1168 if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { 1238 if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
1169 struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1239 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1170 ironlake_edp_panel_vdd_on(intel_dp);
1171 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); 1240 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
1172 ironlake_edp_panel_off(intel_dp); 1241 ironlake_edp_panel_off(intel_dp);
1173 } 1242 }