diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 124 |
1 files changed, 107 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 31f4fe271388..1591576a6101 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -72,6 +72,45 @@ static const u32 hsw_ddi_translations_hdmi[] = { | |||
72 | 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */ | 72 | 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */ |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static const u32 bdw_ddi_translations_edp[] = { | ||
76 | 0x00FFFFFF, 0x00000012, /* DP parameters */ | ||
77 | 0x00EBAFFF, 0x00020011, | ||
78 | 0x00C71FFF, 0x0006000F, | ||
79 | 0x00FFFFFF, 0x00020011, | ||
80 | 0x00DB6FFF, 0x0005000F, | ||
81 | 0x00BEEFFF, 0x000A000C, | ||
82 | 0x00FFFFFF, 0x0005000F, | ||
83 | 0x00DB6FFF, 0x000A000C, | ||
84 | 0x00FFFFFF, 0x000A000C, | ||
85 | 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ | ||
86 | }; | ||
87 | |||
88 | static const u32 bdw_ddi_translations_dp[] = { | ||
89 | 0x00FFFFFF, 0x0007000E, /* DP parameters */ | ||
90 | 0x00D75FFF, 0x000E000A, | ||
91 | 0x00BEFFFF, 0x00140006, | ||
92 | 0x00FFFFFF, 0x000E000A, | ||
93 | 0x00D75FFF, 0x00180004, | ||
94 | 0x80CB2FFF, 0x001B0002, | ||
95 | 0x00F7DFFF, 0x00180004, | ||
96 | 0x80D75FFF, 0x001B0002, | ||
97 | 0x80FFFFFF, 0x001B0002, | ||
98 | 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ | ||
99 | }; | ||
100 | |||
101 | static const u32 bdw_ddi_translations_fdi[] = { | ||
102 | 0x00FFFFFF, 0x0001000E, /* FDI parameters */ | ||
103 | 0x00D75FFF, 0x0004000A, | ||
104 | 0x00C30FFF, 0x00070006, | ||
105 | 0x00AAAFFF, 0x000C0000, | ||
106 | 0x00FFFFFF, 0x0004000A, | ||
107 | 0x00D75FFF, 0x00090004, | ||
108 | 0x00C30FFF, 0x000C0000, | ||
109 | 0x00FFFFFF, 0x00070006, | ||
110 | 0x00D75FFF, 0x000C0000, | ||
111 | 0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/ | ||
112 | }; | ||
113 | |||
75 | enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) | 114 | enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) |
76 | { | 115 | { |
77 | struct drm_encoder *encoder = &intel_encoder->base; | 116 | struct drm_encoder *encoder = &intel_encoder->base; |
@@ -92,8 +131,9 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) | |||
92 | } | 131 | } |
93 | } | 132 | } |
94 | 133 | ||
95 | /* On Haswell, DDI port buffers must be programmed with correct values | 134 | /* |
96 | * in advance. The buffer values are different for FDI and DP modes, | 135 | * Starting with Haswell, DDI port buffers must be programmed with correct |
136 | * values in advance. The buffer values are different for FDI and DP modes, | ||
97 | * but the HDMI/DVI fields are shared among those. So we program the DDI | 137 | * but the HDMI/DVI fields are shared among those. So we program the DDI |
98 | * in either FDI or DP modes only, as HDMI connections will work with both | 138 | * in either FDI or DP modes only, as HDMI connections will work with both |
99 | * of those | 139 | * of those |
@@ -103,10 +143,47 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) | |||
103 | struct drm_i915_private *dev_priv = dev->dev_private; | 143 | struct drm_i915_private *dev_priv = dev->dev_private; |
104 | u32 reg; | 144 | u32 reg; |
105 | int i; | 145 | int i; |
106 | const u32 *ddi_translations = (port == PORT_E) ? | ||
107 | hsw_ddi_translations_fdi : | ||
108 | hsw_ddi_translations_dp; | ||
109 | int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; | 146 | int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; |
147 | const u32 *ddi_translations_fdi; | ||
148 | const u32 *ddi_translations_dp; | ||
149 | const u32 *ddi_translations_edp; | ||
150 | const u32 *ddi_translations; | ||
151 | |||
152 | if (IS_BROADWELL(dev)) { | ||
153 | ddi_translations_fdi = bdw_ddi_translations_fdi; | ||
154 | ddi_translations_dp = bdw_ddi_translations_dp; | ||
155 | ddi_translations_edp = bdw_ddi_translations_edp; | ||
156 | } else if (IS_HASWELL(dev)) { | ||
157 | ddi_translations_fdi = hsw_ddi_translations_fdi; | ||
158 | ddi_translations_dp = hsw_ddi_translations_dp; | ||
159 | ddi_translations_edp = hsw_ddi_translations_dp; | ||
160 | } else { | ||
161 | WARN(1, "ddi translation table missing\n"); | ||
162 | ddi_translations_edp = bdw_ddi_translations_dp; | ||
163 | ddi_translations_fdi = bdw_ddi_translations_fdi; | ||
164 | ddi_translations_dp = bdw_ddi_translations_dp; | ||
165 | } | ||
166 | |||
167 | switch (port) { | ||
168 | case PORT_A: | ||
169 | ddi_translations = ddi_translations_edp; | ||
170 | break; | ||
171 | case PORT_B: | ||
172 | case PORT_C: | ||
173 | ddi_translations = ddi_translations_dp; | ||
174 | break; | ||
175 | case PORT_D: | ||
176 | if (intel_dpd_is_edp(dev)) | ||
177 | ddi_translations = ddi_translations_edp; | ||
178 | else | ||
179 | ddi_translations = ddi_translations_dp; | ||
180 | break; | ||
181 | case PORT_E: | ||
182 | ddi_translations = ddi_translations_fdi; | ||
183 | break; | ||
184 | default: | ||
185 | BUG(); | ||
186 | } | ||
110 | 187 | ||
111 | for (i = 0, reg = DDI_BUF_TRANS(port); | 188 | for (i = 0, reg = DDI_BUF_TRANS(port); |
112 | i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { | 189 | i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { |
@@ -756,7 +833,8 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) | |||
756 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 833 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
757 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); | 834 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
758 | struct drm_encoder *encoder = &intel_encoder->base; | 835 | struct drm_encoder *encoder = &intel_encoder->base; |
759 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; | 836 | struct drm_device *dev = crtc->dev; |
837 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
760 | enum pipe pipe = intel_crtc->pipe; | 838 | enum pipe pipe = intel_crtc->pipe; |
761 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; | 839 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
762 | enum port port = intel_ddi_get_encoder_port(intel_encoder); | 840 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
@@ -792,10 +870,11 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) | |||
792 | if (cpu_transcoder == TRANSCODER_EDP) { | 870 | if (cpu_transcoder == TRANSCODER_EDP) { |
793 | switch (pipe) { | 871 | switch (pipe) { |
794 | case PIPE_A: | 872 | case PIPE_A: |
795 | /* Can only use the always-on power well for eDP when | 873 | /* On Haswell, can only use the always-on power well for |
796 | * not using the panel fitter, and when not using motion | 874 | * eDP when not using the panel fitter, and when not |
797 | * blur mitigation (which we don't support). */ | 875 | * using motion blur mitigation (which we don't |
798 | if (intel_crtc->config.pch_pfit.enabled) | 876 | * support). */ |
877 | if (IS_HASWELL(dev) && intel_crtc->config.pch_pfit.enabled) | ||
799 | temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; | 878 | temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; |
800 | else | 879 | else |
801 | temp |= TRANS_DDI_EDP_INPUT_A_ON; | 880 | temp |= TRANS_DDI_EDP_INPUT_A_ON; |
@@ -1156,18 +1235,29 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder) | |||
1156 | 1235 | ||
1157 | int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) | 1236 | int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) |
1158 | { | 1237 | { |
1238 | struct drm_device *dev = dev_priv->dev; | ||
1159 | uint32_t lcpll = I915_READ(LCPLL_CTL); | 1239 | uint32_t lcpll = I915_READ(LCPLL_CTL); |
1240 | uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; | ||
1160 | 1241 | ||
1161 | if (lcpll & LCPLL_CD_SOURCE_FCLK) | 1242 | if (lcpll & LCPLL_CD_SOURCE_FCLK) { |
1162 | return 800000; | 1243 | return 800000; |
1163 | else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) | 1244 | } else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) { |
1164 | return 450000; | 1245 | return 450000; |
1165 | else if ((lcpll & LCPLL_CLK_FREQ_MASK) == LCPLL_CLK_FREQ_450) | 1246 | } else if (freq == LCPLL_CLK_FREQ_450) { |
1166 | return 450000; | 1247 | return 450000; |
1167 | else if (IS_ULT(dev_priv->dev)) | 1248 | } else if (IS_HASWELL(dev)) { |
1168 | return 337500; | 1249 | if (IS_ULT(dev)) |
1169 | else | 1250 | return 337500; |
1170 | return 540000; | 1251 | else |
1252 | return 540000; | ||
1253 | } else { | ||
1254 | if (freq == LCPLL_CLK_FREQ_54O_BDW) | ||
1255 | return 540000; | ||
1256 | else if (freq == LCPLL_CLK_FREQ_337_5_BDW) | ||
1257 | return 337500; | ||
1258 | else | ||
1259 | return 675000; | ||
1260 | } | ||
1171 | } | 1261 | } |
1172 | 1262 | ||
1173 | void intel_ddi_pll_init(struct drm_device *dev) | 1263 | void intel_ddi_pll_init(struct drm_device *dev) |