Rev 5060 | Rev 6084 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3031 | serge | 1 | /* |
2 | * Copyright © 2012 Intel Corporation |
||
3 | * |
||
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
5 | * copy of this software and associated documentation files (the "Software"), |
||
6 | * to deal in the Software without restriction, including without limitation |
||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
8 | * and/or sell copies of the Software, and to permit persons to whom the |
||
9 | * Software is furnished to do so, subject to the following conditions: |
||
10 | * |
||
11 | * The above copyright notice and this permission notice (including the next |
||
12 | * paragraph) shall be included in all copies or substantial portions of the |
||
13 | * Software. |
||
14 | * |
||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||
21 | * IN THE SOFTWARE. |
||
22 | * |
||
23 | * Authors: |
||
24 | * Eugeni Dodonov |
||
25 | * |
||
26 | */ |
||
27 | |||
28 | #include "i915_drv.h" |
||
29 | #include "intel_drv.h" |
||
30 | |||
5354 | serge | 31 | struct ddi_buf_trans { |
32 | u32 trans1; /* balance leg enable, de-emph level */ |
||
33 | u32 trans2; /* vref sel, vswing */ |
||
34 | }; |
||
35 | |||
3031 | serge | 36 | /* HDMI/DVI modes ignore everything but the last 2 items. So we share |
37 | * them for both DP and FDI transports, allowing those ports to |
||
38 | * automatically adapt to HDMI connections as well |
||
39 | */ |
||
5354 | serge | 40 | static const struct ddi_buf_trans hsw_ddi_translations_dp[] = { |
41 | { 0x00FFFFFF, 0x0006000E }, |
||
42 | { 0x00D75FFF, 0x0005000A }, |
||
43 | { 0x00C30FFF, 0x00040006 }, |
||
44 | { 0x80AAAFFF, 0x000B0000 }, |
||
45 | { 0x00FFFFFF, 0x0005000A }, |
||
46 | { 0x00D75FFF, 0x000C0004 }, |
||
47 | { 0x80C30FFF, 0x000B0000 }, |
||
48 | { 0x00FFFFFF, 0x00040006 }, |
||
49 | { 0x80D75FFF, 0x000B0000 }, |
||
3031 | serge | 50 | }; |
51 | |||
5354 | serge | 52 | static const struct ddi_buf_trans hsw_ddi_translations_fdi[] = { |
53 | { 0x00FFFFFF, 0x0007000E }, |
||
54 | { 0x00D75FFF, 0x000F000A }, |
||
55 | { 0x00C30FFF, 0x00060006 }, |
||
56 | { 0x00AAAFFF, 0x001E0000 }, |
||
57 | { 0x00FFFFFF, 0x000F000A }, |
||
58 | { 0x00D75FFF, 0x00160004 }, |
||
59 | { 0x00C30FFF, 0x001E0000 }, |
||
60 | { 0x00FFFFFF, 0x00060006 }, |
||
61 | { 0x00D75FFF, 0x001E0000 }, |
||
3031 | serge | 62 | }; |
63 | |||
5354 | serge | 64 | static const struct ddi_buf_trans hsw_ddi_translations_hdmi[] = { |
65 | /* Idx NT mV d T mV d db */ |
||
66 | { 0x00FFFFFF, 0x0006000E }, /* 0: 400 400 0 */ |
||
67 | { 0x00E79FFF, 0x000E000C }, /* 1: 400 500 2 */ |
||
68 | { 0x00D75FFF, 0x0005000A }, /* 2: 400 600 3.5 */ |
||
69 | { 0x00FFFFFF, 0x0005000A }, /* 3: 600 600 0 */ |
||
70 | { 0x00E79FFF, 0x001D0007 }, /* 4: 600 750 2 */ |
||
71 | { 0x00D75FFF, 0x000C0004 }, /* 5: 600 900 3.5 */ |
||
72 | { 0x00FFFFFF, 0x00040006 }, /* 6: 800 800 0 */ |
||
73 | { 0x80E79FFF, 0x00030002 }, /* 7: 800 1000 2 */ |
||
74 | { 0x00FFFFFF, 0x00140005 }, /* 8: 850 850 0 */ |
||
75 | { 0x00FFFFFF, 0x000C0004 }, /* 9: 900 900 0 */ |
||
76 | { 0x00FFFFFF, 0x001C0003 }, /* 10: 950 950 0 */ |
||
77 | { 0x80FFFFFF, 0x00030002 }, /* 11: 1000 1000 0 */ |
||
4560 | Serge | 78 | }; |
79 | |||
5354 | serge | 80 | static const struct ddi_buf_trans bdw_ddi_translations_edp[] = { |
81 | { 0x00FFFFFF, 0x00000012 }, |
||
82 | { 0x00EBAFFF, 0x00020011 }, |
||
83 | { 0x00C71FFF, 0x0006000F }, |
||
84 | { 0x00AAAFFF, 0x000E000A }, |
||
85 | { 0x00FFFFFF, 0x00020011 }, |
||
86 | { 0x00DB6FFF, 0x0005000F }, |
||
87 | { 0x00BEEFFF, 0x000A000C }, |
||
88 | { 0x00FFFFFF, 0x0005000F }, |
||
89 | { 0x00DB6FFF, 0x000A000C }, |
||
4560 | Serge | 90 | }; |
91 | |||
5354 | serge | 92 | static const struct ddi_buf_trans bdw_ddi_translations_dp[] = { |
93 | { 0x00FFFFFF, 0x0007000E }, |
||
94 | { 0x00D75FFF, 0x000E000A }, |
||
95 | { 0x00BEFFFF, 0x00140006 }, |
||
96 | { 0x80B2CFFF, 0x001B0002 }, |
||
97 | { 0x00FFFFFF, 0x000E000A }, |
||
98 | { 0x00DB6FFF, 0x00160005 }, |
||
99 | { 0x80C71FFF, 0x001A0002 }, |
||
100 | { 0x00F7DFFF, 0x00180004 }, |
||
101 | { 0x80D75FFF, 0x001B0002 }, |
||
4560 | Serge | 102 | }; |
103 | |||
5354 | serge | 104 | static const struct ddi_buf_trans bdw_ddi_translations_fdi[] = { |
105 | { 0x00FFFFFF, 0x0001000E }, |
||
106 | { 0x00D75FFF, 0x0004000A }, |
||
107 | { 0x00C30FFF, 0x00070006 }, |
||
108 | { 0x00AAAFFF, 0x000C0000 }, |
||
109 | { 0x00FFFFFF, 0x0004000A }, |
||
110 | { 0x00D75FFF, 0x00090004 }, |
||
111 | { 0x00C30FFF, 0x000C0000 }, |
||
112 | { 0x00FFFFFF, 0x00070006 }, |
||
113 | { 0x00D75FFF, 0x000C0000 }, |
||
4560 | Serge | 114 | }; |
115 | |||
5354 | serge | 116 | static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = { |
117 | /* Idx NT mV d T mV df db */ |
||
118 | { 0x00FFFFFF, 0x0007000E }, /* 0: 400 400 0 */ |
||
119 | { 0x00D75FFF, 0x000E000A }, /* 1: 400 600 3.5 */ |
||
120 | { 0x00BEFFFF, 0x00140006 }, /* 2: 400 800 6 */ |
||
121 | { 0x00FFFFFF, 0x0009000D }, /* 3: 450 450 0 */ |
||
122 | { 0x00FFFFFF, 0x000E000A }, /* 4: 600 600 0 */ |
||
123 | { 0x00D7FFFF, 0x00140006 }, /* 5: 600 800 2.5 */ |
||
124 | { 0x80CB2FFF, 0x001B0002 }, /* 6: 600 1000 4.5 */ |
||
125 | { 0x00FFFFFF, 0x00140006 }, /* 7: 800 800 0 */ |
||
126 | { 0x80E79FFF, 0x001B0002 }, /* 8: 800 1000 2 */ |
||
127 | { 0x80FFFFFF, 0x001B0002 }, /* 9: 1000 1000 0 */ |
||
128 | }; |
||
129 | |||
130 | static const struct ddi_buf_trans skl_ddi_translations_dp[] = { |
||
131 | { 0x00000018, 0x000000a0 }, |
||
132 | { 0x00004014, 0x00000098 }, |
||
133 | { 0x00006012, 0x00000088 }, |
||
134 | { 0x00008010, 0x00000080 }, |
||
135 | { 0x00000018, 0x00000098 }, |
||
136 | { 0x00004014, 0x00000088 }, |
||
137 | { 0x00006012, 0x00000080 }, |
||
138 | { 0x00000018, 0x00000088 }, |
||
139 | { 0x00004014, 0x00000080 }, |
||
140 | }; |
||
141 | |||
142 | static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { |
||
143 | /* Idx NT mV T mV db */ |
||
144 | { 0x00000018, 0x000000a0 }, /* 0: 400 400 0 */ |
||
145 | { 0x00004014, 0x00000098 }, /* 1: 400 600 3.5 */ |
||
146 | { 0x00006012, 0x00000088 }, /* 2: 400 800 6 */ |
||
147 | { 0x00000018, 0x0000003c }, /* 3: 450 450 0 */ |
||
148 | { 0x00000018, 0x00000098 }, /* 4: 600 600 0 */ |
||
149 | { 0x00003015, 0x00000088 }, /* 5: 600 800 2.5 */ |
||
150 | { 0x00005013, 0x00000080 }, /* 6: 600 1000 4.5 */ |
||
151 | { 0x00000018, 0x00000088 }, /* 7: 800 800 0 */ |
||
152 | { 0x00000096, 0x00000080 }, /* 8: 800 1000 2 */ |
||
153 | { 0x00000018, 0x00000080 }, /* 9: 1200 1200 0 */ |
||
154 | }; |
||
155 | |||
4560 | Serge | 156 | enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) |
3243 | Serge | 157 | { |
158 | struct drm_encoder *encoder = &intel_encoder->base; |
||
159 | int type = intel_encoder->type; |
||
160 | |||
5060 | serge | 161 | if (type == INTEL_OUTPUT_DP_MST) { |
162 | struct intel_digital_port *intel_dig_port = enc_to_mst(encoder)->primary; |
||
163 | return intel_dig_port->port; |
||
164 | } else if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || |
||
3243 | Serge | 165 | type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) { |
166 | struct intel_digital_port *intel_dig_port = |
||
167 | enc_to_dig_port(encoder); |
||
168 | return intel_dig_port->port; |
||
169 | |||
170 | } else if (type == INTEL_OUTPUT_ANALOG) { |
||
171 | return PORT_E; |
||
172 | |||
173 | } else { |
||
174 | DRM_ERROR("Invalid DDI encoder type %d\n", type); |
||
175 | BUG(); |
||
176 | } |
||
177 | } |
||
178 | |||
4560 | Serge | 179 | /* |
180 | * Starting with Haswell, DDI port buffers must be programmed with correct |
||
181 | * values in advance. The buffer values are different for FDI and DP modes, |
||
3031 | serge | 182 | * but the HDMI/DVI fields are shared among those. So we program the DDI |
183 | * in either FDI or DP modes only, as HDMI connections will work with both |
||
184 | * of those |
||
185 | */ |
||
4104 | Serge | 186 | static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) |
3031 | serge | 187 | { |
188 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
189 | u32 reg; |
||
5354 | serge | 190 | int i, n_hdmi_entries, hdmi_800mV_0dB; |
4560 | Serge | 191 | int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; |
5354 | serge | 192 | const struct ddi_buf_trans *ddi_translations_fdi; |
193 | const struct ddi_buf_trans *ddi_translations_dp; |
||
194 | const struct ddi_buf_trans *ddi_translations_edp; |
||
195 | const struct ddi_buf_trans *ddi_translations_hdmi; |
||
196 | const struct ddi_buf_trans *ddi_translations; |
||
3031 | serge | 197 | |
5354 | serge | 198 | if (IS_SKYLAKE(dev)) { |
199 | ddi_translations_fdi = NULL; |
||
200 | ddi_translations_dp = skl_ddi_translations_dp; |
||
201 | ddi_translations_edp = skl_ddi_translations_dp; |
||
202 | ddi_translations_hdmi = skl_ddi_translations_hdmi; |
||
203 | n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); |
||
204 | hdmi_800mV_0dB = 7; |
||
205 | } else if (IS_BROADWELL(dev)) { |
||
4560 | Serge | 206 | ddi_translations_fdi = bdw_ddi_translations_fdi; |
207 | ddi_translations_dp = bdw_ddi_translations_dp; |
||
208 | ddi_translations_edp = bdw_ddi_translations_edp; |
||
5354 | serge | 209 | ddi_translations_hdmi = bdw_ddi_translations_hdmi; |
210 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); |
||
211 | hdmi_800mV_0dB = 7; |
||
4560 | Serge | 212 | } else if (IS_HASWELL(dev)) { |
213 | ddi_translations_fdi = hsw_ddi_translations_fdi; |
||
214 | ddi_translations_dp = hsw_ddi_translations_dp; |
||
215 | ddi_translations_edp = hsw_ddi_translations_dp; |
||
5354 | serge | 216 | ddi_translations_hdmi = hsw_ddi_translations_hdmi; |
217 | n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); |
||
218 | hdmi_800mV_0dB = 6; |
||
4560 | Serge | 219 | } else { |
220 | WARN(1, "ddi translation table missing\n"); |
||
221 | ddi_translations_edp = bdw_ddi_translations_dp; |
||
222 | ddi_translations_fdi = bdw_ddi_translations_fdi; |
||
223 | ddi_translations_dp = bdw_ddi_translations_dp; |
||
5354 | serge | 224 | ddi_translations_hdmi = bdw_ddi_translations_hdmi; |
225 | n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); |
||
226 | hdmi_800mV_0dB = 7; |
||
4560 | Serge | 227 | } |
228 | |||
229 | switch (port) { |
||
230 | case PORT_A: |
||
231 | ddi_translations = ddi_translations_edp; |
||
232 | break; |
||
233 | case PORT_B: |
||
234 | case PORT_C: |
||
235 | ddi_translations = ddi_translations_dp; |
||
236 | break; |
||
237 | case PORT_D: |
||
238 | if (intel_dp_is_edp(dev, PORT_D)) |
||
239 | ddi_translations = ddi_translations_edp; |
||
240 | else |
||
241 | ddi_translations = ddi_translations_dp; |
||
242 | break; |
||
243 | case PORT_E: |
||
5354 | serge | 244 | if (ddi_translations_fdi) |
4560 | Serge | 245 | ddi_translations = ddi_translations_fdi; |
5354 | serge | 246 | else |
247 | ddi_translations = ddi_translations_dp; |
||
4560 | Serge | 248 | break; |
249 | default: |
||
250 | BUG(); |
||
251 | } |
||
252 | |||
4104 | Serge | 253 | for (i = 0, reg = DDI_BUF_TRANS(port); |
254 | i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { |
||
5354 | serge | 255 | I915_WRITE(reg, ddi_translations[i].trans1); |
3031 | serge | 256 | reg += 4; |
5354 | serge | 257 | I915_WRITE(reg, ddi_translations[i].trans2); |
258 | reg += 4; |
||
3031 | serge | 259 | } |
5354 | serge | 260 | |
261 | /* Choose a good default if VBT is badly populated */ |
||
262 | if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN || |
||
263 | hdmi_level >= n_hdmi_entries) |
||
264 | hdmi_level = hdmi_800mV_0dB; |
||
265 | |||
4560 | Serge | 266 | /* Entry 9 is for HDMI: */ |
5354 | serge | 267 | I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans1); |
268 | reg += 4; |
||
269 | I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans2); |
||
4560 | Serge | 270 | reg += 4; |
3031 | serge | 271 | } |
272 | |||
273 | /* Program DDI buffers translations for DP. By default, program ports A-D in DP |
||
274 | * mode and port E for FDI. |
||
275 | */ |
||
276 | void intel_prepare_ddi(struct drm_device *dev) |
||
277 | { |
||
278 | int port; |
||
279 | |||
3480 | Serge | 280 | if (!HAS_DDI(dev)) |
281 | return; |
||
282 | |||
4104 | Serge | 283 | for (port = PORT_A; port <= PORT_E; port++) |
284 | intel_prepare_ddi_buffers(dev, port); |
||
3031 | serge | 285 | } |
286 | |||
3243 | Serge | 287 | static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, |
288 | enum port port) |
||
289 | { |
||
290 | uint32_t reg = DDI_BUF_CTL(port); |
||
291 | int i; |
||
3031 | serge | 292 | |
3243 | Serge | 293 | for (i = 0; i < 8; i++) { |
294 | udelay(1); |
||
295 | if (I915_READ(reg) & DDI_BUF_IS_IDLE) |
||
296 | return; |
||
297 | } |
||
298 | DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port)); |
||
299 | } |
||
300 | |||
3031 | serge | 301 | /* Starting with Haswell, different DDI ports can work in FDI mode for |
302 | * connection to the PCH-located connectors. For this, it is necessary to train |
||
303 | * both the DDI port and PCH receiver for the desired DDI buffer settings. |
||
304 | * |
||
305 | * The recommended port to work in FDI mode is DDI E, which we use here. Also, |
||
306 | * please note that when FDI mode is active on DDI E, it shares 2 lines with |
||
307 | * DDI A (which is used for eDP) |
||
308 | */ |
||
309 | |||
310 | void hsw_fdi_link_train(struct drm_crtc *crtc) |
||
311 | { |
||
312 | struct drm_device *dev = crtc->dev; |
||
313 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
314 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
3243 | Serge | 315 | u32 temp, i, rx_ctl_val; |
3031 | serge | 316 | |
3243 | Serge | 317 | /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the |
318 | * mode set "sequence for CRT port" document: |
||
319 | * - TP1 to TP2 time with the default value |
||
320 | * - FDI delay to 90h |
||
4104 | Serge | 321 | * |
322 | * WaFDIAutoLinkSetTimingOverrride:hsw |
||
3243 | Serge | 323 | */ |
324 | I915_WRITE(_FDI_RXA_MISC, FDI_RX_PWRDN_LANE1_VAL(2) | |
||
325 | FDI_RX_PWRDN_LANE0_VAL(2) | |
||
326 | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90); |
||
3031 | serge | 327 | |
3243 | Serge | 328 | /* Enable the PCH Receiver FDI PLL */ |
3480 | Serge | 329 | rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE | |
4104 | Serge | 330 | FDI_RX_PLL_ENABLE | |
331 | FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes); |
||
3243 | Serge | 332 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
333 | POSTING_READ(_FDI_RXA_CTL); |
||
334 | udelay(220); |
||
3031 | serge | 335 | |
3243 | Serge | 336 | /* Switch from Rawclk to PCDclk */ |
337 | rx_ctl_val |= FDI_PCDCLK; |
||
338 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
3031 | serge | 339 | |
3243 | Serge | 340 | /* Configure Port Clock Select */ |
5060 | serge | 341 | I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->config.ddi_pll_sel); |
342 | WARN_ON(intel_crtc->config.ddi_pll_sel != PORT_CLK_SEL_SPLL); |
||
3243 | Serge | 343 | |
344 | /* Start the training iterating through available voltages and emphasis, |
||
345 | * testing each value twice. */ |
||
5354 | serge | 346 | for (i = 0; i < ARRAY_SIZE(hsw_ddi_translations_fdi) * 2; i++) { |
3031 | serge | 347 | /* Configure DP_TP_CTL with auto-training */ |
348 | I915_WRITE(DP_TP_CTL(PORT_E), |
||
349 | DP_TP_CTL_FDI_AUTOTRAIN | |
||
350 | DP_TP_CTL_ENHANCED_FRAME_ENABLE | |
||
351 | DP_TP_CTL_LINK_TRAIN_PAT1 | |
||
352 | DP_TP_CTL_ENABLE); |
||
353 | |||
3480 | Serge | 354 | /* Configure and enable DDI_BUF_CTL for DDI E with next voltage. |
355 | * DDI E does not support port reversal, the functionality is |
||
356 | * achieved on the PCH side in FDI_RX_CTL, so no need to set the |
||
357 | * port reversal bit */ |
||
3031 | serge | 358 | I915_WRITE(DDI_BUF_CTL(PORT_E), |
359 | DDI_BUF_CTL_ENABLE | |
||
4104 | Serge | 360 | ((intel_crtc->config.fdi_lanes - 1) << 1) | |
5354 | serge | 361 | DDI_BUF_TRANS_SELECT(i / 2)); |
3243 | Serge | 362 | POSTING_READ(DDI_BUF_CTL(PORT_E)); |
3031 | serge | 363 | |
364 | udelay(600); |
||
365 | |||
3243 | Serge | 366 | /* Program PCH FDI Receiver TU */ |
367 | I915_WRITE(_FDI_RXA_TUSIZE1, TU_SIZE(64)); |
||
3031 | serge | 368 | |
3243 | Serge | 369 | /* Enable PCH FDI Receiver with auto-training */ |
370 | rx_ctl_val |= FDI_RX_ENABLE | FDI_LINK_TRAIN_AUTO; |
||
371 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
372 | POSTING_READ(_FDI_RXA_CTL); |
||
3031 | serge | 373 | |
3243 | Serge | 374 | /* Wait for FDI receiver lane calibration */ |
375 | udelay(30); |
||
376 | |||
377 | /* Unset FDI_RX_MISC pwrdn lanes */ |
||
378 | temp = I915_READ(_FDI_RXA_MISC); |
||
379 | temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); |
||
380 | I915_WRITE(_FDI_RXA_MISC, temp); |
||
381 | POSTING_READ(_FDI_RXA_MISC); |
||
382 | |||
383 | /* Wait for FDI auto training time */ |
||
384 | udelay(5); |
||
385 | |||
3031 | serge | 386 | temp = I915_READ(DP_TP_STATUS(PORT_E)); |
387 | if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) { |
||
3243 | Serge | 388 | DRM_DEBUG_KMS("FDI link training done on step %d\n", i); |
3031 | serge | 389 | |
390 | /* Enable normal pixel sending for FDI */ |
||
391 | I915_WRITE(DP_TP_CTL(PORT_E), |
||
392 | DP_TP_CTL_FDI_AUTOTRAIN | |
||
393 | DP_TP_CTL_LINK_TRAIN_NORMAL | |
||
394 | DP_TP_CTL_ENHANCED_FRAME_ENABLE | |
||
395 | DP_TP_CTL_ENABLE); |
||
396 | |||
3243 | Serge | 397 | return; |
3031 | serge | 398 | } |
399 | |||
3243 | Serge | 400 | temp = I915_READ(DDI_BUF_CTL(PORT_E)); |
401 | temp &= ~DDI_BUF_CTL_ENABLE; |
||
402 | I915_WRITE(DDI_BUF_CTL(PORT_E), temp); |
||
403 | POSTING_READ(DDI_BUF_CTL(PORT_E)); |
||
3031 | serge | 404 | |
3243 | Serge | 405 | /* Disable DP_TP_CTL and FDI_RX_CTL and retry */ |
406 | temp = I915_READ(DP_TP_CTL(PORT_E)); |
||
407 | temp &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); |
||
408 | temp |= DP_TP_CTL_LINK_TRAIN_PAT1; |
||
409 | I915_WRITE(DP_TP_CTL(PORT_E), temp); |
||
410 | POSTING_READ(DP_TP_CTL(PORT_E)); |
||
3031 | serge | 411 | |
3243 | Serge | 412 | intel_wait_ddi_buf_idle(dev_priv, PORT_E); |
413 | |||
414 | rx_ctl_val &= ~FDI_RX_ENABLE; |
||
415 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
416 | POSTING_READ(_FDI_RXA_CTL); |
||
417 | |||
418 | /* Reset FDI_RX_MISC pwrdn lanes */ |
||
419 | temp = I915_READ(_FDI_RXA_MISC); |
||
420 | temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); |
||
421 | temp |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); |
||
422 | I915_WRITE(_FDI_RXA_MISC, temp); |
||
423 | POSTING_READ(_FDI_RXA_MISC); |
||
3031 | serge | 424 | } |
3243 | Serge | 425 | |
426 | DRM_ERROR("FDI link training failed!\n"); |
||
3031 | serge | 427 | } |
428 | |||
5060 | serge | 429 | void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder) |
3031 | serge | 430 | { |
5060 | serge | 431 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
432 | struct intel_digital_port *intel_dig_port = |
||
433 | enc_to_dig_port(&encoder->base); |
||
3031 | serge | 434 | |
5060 | serge | 435 | intel_dp->DP = intel_dig_port->saved_port_bits | |
5354 | serge | 436 | DDI_BUF_CTL_ENABLE | DDI_BUF_TRANS_SELECT(0); |
5060 | serge | 437 | intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count); |
3031 | serge | 438 | |
3243 | Serge | 439 | } |
440 | |||
441 | static struct intel_encoder * |
||
442 | intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) |
||
443 | { |
||
444 | struct drm_device *dev = crtc->dev; |
||
445 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
446 | struct intel_encoder *intel_encoder, *ret = NULL; |
||
447 | int num_encoders = 0; |
||
448 | |||
449 | for_each_encoder_on_crtc(dev, crtc, intel_encoder) { |
||
450 | ret = intel_encoder; |
||
451 | num_encoders++; |
||
452 | } |
||
453 | |||
454 | if (num_encoders != 1) |
||
4104 | Serge | 455 | WARN(1, "%d encoders on crtc for pipe %c\n", num_encoders, |
456 | pipe_name(intel_crtc->pipe)); |
||
3243 | Serge | 457 | |
458 | BUG_ON(ret == NULL); |
||
459 | return ret; |
||
460 | } |
||
461 | |||
5354 | serge | 462 | static struct intel_encoder * |
463 | intel_ddi_get_crtc_new_encoder(struct intel_crtc *crtc) |
||
464 | { |
||
465 | struct drm_device *dev = crtc->base.dev; |
||
466 | struct intel_encoder *intel_encoder, *ret = NULL; |
||
467 | int num_encoders = 0; |
||
468 | |||
469 | for_each_intel_encoder(dev, intel_encoder) { |
||
470 | if (intel_encoder->new_crtc == crtc) { |
||
471 | ret = intel_encoder; |
||
472 | num_encoders++; |
||
473 | } |
||
474 | } |
||
475 | |||
476 | WARN(num_encoders != 1, "%d encoders on crtc for pipe %c\n", num_encoders, |
||
477 | pipe_name(crtc->pipe)); |
||
478 | |||
479 | BUG_ON(ret == NULL); |
||
480 | return ret; |
||
481 | } |
||
482 | |||
4104 | Serge | 483 | #define LC_FREQ 2700 |
5354 | serge | 484 | #define LC_FREQ_2K U64_C(LC_FREQ * 2000) |
4104 | Serge | 485 | |
486 | #define P_MIN 2 |
||
487 | #define P_MAX 64 |
||
488 | #define P_INC 2 |
||
489 | |||
490 | /* Constraints for PLL good behavior */ |
||
491 | #define REF_MIN 48 |
||
492 | #define REF_MAX 400 |
||
493 | #define VCO_MIN 2400 |
||
494 | #define VCO_MAX 4800 |
||
495 | |||
5354 | serge | 496 | #define abs_diff(a, b) ({ \ |
497 | typeof(a) __a = (a); \ |
||
498 | typeof(b) __b = (b); \ |
||
499 | (void) (&__a == &__b); \ |
||
500 | __a > __b ? (__a - __b) : (__b - __a); }) |
||
4104 | Serge | 501 | |
502 | struct wrpll_rnp { |
||
503 | unsigned p, n2, r2; |
||
504 | }; |
||
505 | |||
506 | static unsigned wrpll_get_budget_for_freq(int clock) |
||
3243 | Serge | 507 | { |
4104 | Serge | 508 | unsigned budget; |
3243 | Serge | 509 | |
4104 | Serge | 510 | switch (clock) { |
511 | case 25175000: |
||
512 | case 25200000: |
||
513 | case 27000000: |
||
514 | case 27027000: |
||
515 | case 37762500: |
||
516 | case 37800000: |
||
517 | case 40500000: |
||
518 | case 40541000: |
||
519 | case 54000000: |
||
520 | case 54054000: |
||
521 | case 59341000: |
||
522 | case 59400000: |
||
523 | case 72000000: |
||
524 | case 74176000: |
||
525 | case 74250000: |
||
526 | case 81000000: |
||
527 | case 81081000: |
||
528 | case 89012000: |
||
529 | case 89100000: |
||
530 | case 108000000: |
||
531 | case 108108000: |
||
532 | case 111264000: |
||
533 | case 111375000: |
||
534 | case 148352000: |
||
535 | case 148500000: |
||
536 | case 162000000: |
||
537 | case 162162000: |
||
538 | case 222525000: |
||
539 | case 222750000: |
||
540 | case 296703000: |
||
541 | case 297000000: |
||
542 | budget = 0; |
||
543 | break; |
||
544 | case 233500000: |
||
545 | case 245250000: |
||
546 | case 247750000: |
||
547 | case 253250000: |
||
548 | case 298000000: |
||
549 | budget = 1500; |
||
550 | break; |
||
551 | case 169128000: |
||
552 | case 169500000: |
||
553 | case 179500000: |
||
554 | case 202000000: |
||
555 | budget = 2000; |
||
556 | break; |
||
557 | case 256250000: |
||
558 | case 262500000: |
||
559 | case 270000000: |
||
560 | case 272500000: |
||
561 | case 273750000: |
||
562 | case 280750000: |
||
563 | case 281250000: |
||
564 | case 286000000: |
||
565 | case 291750000: |
||
566 | budget = 4000; |
||
567 | break; |
||
568 | case 267250000: |
||
569 | case 268500000: |
||
570 | budget = 5000; |
||
3031 | serge | 571 | break; |
4104 | Serge | 572 | default: |
573 | budget = 1000; |
||
574 | break; |
||
575 | } |
||
3031 | serge | 576 | |
4104 | Serge | 577 | return budget; |
578 | } |
||
3031 | serge | 579 | |
4104 | Serge | 580 | static void wrpll_update_rnp(uint64_t freq2k, unsigned budget, |
581 | unsigned r2, unsigned n2, unsigned p, |
||
582 | struct wrpll_rnp *best) |
||
583 | { |
||
584 | uint64_t a, b, c, d, diff, diff_best; |
||
3031 | serge | 585 | |
4104 | Serge | 586 | /* No best (r,n,p) yet */ |
587 | if (best->p == 0) { |
||
588 | best->p = p; |
||
589 | best->n2 = n2; |
||
590 | best->r2 = r2; |
||
591 | return; |
||
592 | } |
||
3031 | serge | 593 | |
4104 | Serge | 594 | /* |
595 | * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to |
||
596 | * freq2k. |
||
597 | * |
||
598 | * delta = 1e6 * |
||
599 | * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) / |
||
600 | * freq2k; |
||
601 | * |
||
602 | * and we would like delta <= budget. |
||
603 | * |
||
604 | * If the discrepancy is above the PPM-based budget, always prefer to |
||
605 | * improve upon the previous solution. However, if you're within the |
||
606 | * budget, try to maximize Ref * VCO, that is N / (P * R^2). |
||
607 | */ |
||
608 | a = freq2k * budget * p * r2; |
||
609 | b = freq2k * budget * best->p * best->r2; |
||
5354 | serge | 610 | diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2); |
611 | diff_best = abs_diff(freq2k * best->p * best->r2, |
||
612 | LC_FREQ_2K * best->n2); |
||
4104 | Serge | 613 | c = 1000000 * diff; |
614 | d = 1000000 * diff_best; |
||
615 | |||
616 | if (a < c && b < d) { |
||
617 | /* If both are above the budget, pick the closer */ |
||
618 | if (best->p * best->r2 * diff < p * r2 * diff_best) { |
||
619 | best->p = p; |
||
620 | best->n2 = n2; |
||
621 | best->r2 = r2; |
||
622 | } |
||
623 | } else if (a >= c && b < d) { |
||
624 | /* If A is below the threshold but B is above it? Update. */ |
||
625 | best->p = p; |
||
626 | best->n2 = n2; |
||
627 | best->r2 = r2; |
||
628 | } else if (a >= c && b >= d) { |
||
629 | /* Both are below the limit, so pick the higher n2/(r2*r2) */ |
||
630 | if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) { |
||
631 | best->p = p; |
||
632 | best->n2 = n2; |
||
633 | best->r2 = r2; |
||
634 | } |
||
635 | } |
||
636 | /* Otherwise a < c && b >= d, do nothing */ |
||
3243 | Serge | 637 | } |
3031 | serge | 638 | |
5060 | serge | 639 | static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, |
640 | int reg) |
||
641 | { |
||
642 | int refclk = LC_FREQ; |
||
643 | int n, p, r; |
||
644 | u32 wrpll; |
||
645 | |||
646 | wrpll = I915_READ(reg); |
||
647 | switch (wrpll & WRPLL_PLL_REF_MASK) { |
||
648 | case WRPLL_PLL_SSC: |
||
649 | case WRPLL_PLL_NON_SSC: |
||
650 | /* |
||
651 | * We could calculate spread here, but our checking |
||
652 | * code only cares about 5% accuracy, and spread is a max of |
||
653 | * 0.5% downspread. |
||
654 | */ |
||
655 | refclk = 135; |
||
656 | break; |
||
657 | case WRPLL_PLL_LCPLL: |
||
658 | refclk = LC_FREQ; |
||
659 | break; |
||
660 | default: |
||
661 | WARN(1, "bad wrpll refclk\n"); |
||
662 | return 0; |
||
663 | } |
||
664 | |||
665 | r = wrpll & WRPLL_DIVIDER_REF_MASK; |
||
666 | p = (wrpll & WRPLL_DIVIDER_POST_MASK) >> WRPLL_DIVIDER_POST_SHIFT; |
||
667 | n = (wrpll & WRPLL_DIVIDER_FB_MASK) >> WRPLL_DIVIDER_FB_SHIFT; |
||
668 | |||
669 | /* Convert to KHz, p & r have a fixed point portion */ |
||
670 | return (refclk * n * 100) / (p * r); |
||
671 | } |
||
672 | |||
5354 | serge | 673 | static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv, |
674 | uint32_t dpll) |
||
675 | { |
||
676 | uint32_t cfgcr1_reg, cfgcr2_reg; |
||
677 | uint32_t cfgcr1_val, cfgcr2_val; |
||
678 | uint32_t p0, p1, p2, dco_freq; |
||
679 | |||
680 | cfgcr1_reg = GET_CFG_CR1_REG(dpll); |
||
681 | cfgcr2_reg = GET_CFG_CR2_REG(dpll); |
||
682 | |||
683 | cfgcr1_val = I915_READ(cfgcr1_reg); |
||
684 | cfgcr2_val = I915_READ(cfgcr2_reg); |
||
685 | |||
686 | p0 = cfgcr2_val & DPLL_CFGCR2_PDIV_MASK; |
||
687 | p2 = cfgcr2_val & DPLL_CFGCR2_KDIV_MASK; |
||
688 | |||
689 | if (cfgcr2_val & DPLL_CFGCR2_QDIV_MODE(1)) |
||
690 | p1 = (cfgcr2_val & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8; |
||
691 | else |
||
692 | p1 = 1; |
||
693 | |||
694 | |||
695 | switch (p0) { |
||
696 | case DPLL_CFGCR2_PDIV_1: |
||
697 | p0 = 1; |
||
698 | break; |
||
699 | case DPLL_CFGCR2_PDIV_2: |
||
700 | p0 = 2; |
||
701 | break; |
||
702 | case DPLL_CFGCR2_PDIV_3: |
||
703 | p0 = 3; |
||
704 | break; |
||
705 | case DPLL_CFGCR2_PDIV_7: |
||
706 | p0 = 7; |
||
707 | break; |
||
708 | } |
||
709 | |||
710 | switch (p2) { |
||
711 | case DPLL_CFGCR2_KDIV_5: |
||
712 | p2 = 5; |
||
713 | break; |
||
714 | case DPLL_CFGCR2_KDIV_2: |
||
715 | p2 = 2; |
||
716 | break; |
||
717 | case DPLL_CFGCR2_KDIV_3: |
||
718 | p2 = 3; |
||
719 | break; |
||
720 | case DPLL_CFGCR2_KDIV_1: |
||
721 | p2 = 1; |
||
722 | break; |
||
723 | } |
||
724 | |||
725 | dco_freq = (cfgcr1_val & DPLL_CFGCR1_DCO_INTEGER_MASK) * 24 * 1000; |
||
726 | |||
727 | dco_freq += (((cfgcr1_val & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9) * 24 * |
||
728 | 1000) / 0x8000; |
||
729 | |||
730 | return dco_freq / (p0 * p1 * p2 * 5); |
||
731 | } |
||
732 | |||
733 | |||
734 | static void skl_ddi_clock_get(struct intel_encoder *encoder, |
||
5060 | serge | 735 | struct intel_crtc_config *pipe_config) |
736 | { |
||
737 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
||
738 | int link_clock = 0; |
||
5354 | serge | 739 | uint32_t dpll_ctl1, dpll; |
740 | |||
741 | dpll = pipe_config->ddi_pll_sel; |
||
742 | |||
743 | dpll_ctl1 = I915_READ(DPLL_CTRL1); |
||
744 | |||
745 | if (dpll_ctl1 & DPLL_CTRL1_HDMI_MODE(dpll)) { |
||
746 | link_clock = skl_calc_wrpll_link(dev_priv, dpll); |
||
747 | } else { |
||
748 | link_clock = dpll_ctl1 & DPLL_CRTL1_LINK_RATE_MASK(dpll); |
||
749 | link_clock >>= DPLL_CRTL1_LINK_RATE_SHIFT(dpll); |
||
750 | |||
751 | switch (link_clock) { |
||
752 | case DPLL_CRTL1_LINK_RATE_810: |
||
753 | link_clock = 81000; |
||
754 | break; |
||
755 | case DPLL_CRTL1_LINK_RATE_1350: |
||
756 | link_clock = 135000; |
||
757 | break; |
||
758 | case DPLL_CRTL1_LINK_RATE_2700: |
||
759 | link_clock = 270000; |
||
760 | break; |
||
761 | default: |
||
762 | WARN(1, "Unsupported link rate\n"); |
||
763 | break; |
||
764 | } |
||
765 | link_clock *= 2; |
||
766 | } |
||
767 | |||
768 | pipe_config->port_clock = link_clock; |
||
769 | |||
770 | if (pipe_config->has_dp_encoder) |
||
771 | pipe_config->adjusted_mode.crtc_clock = |
||
772 | intel_dotclock_calculate(pipe_config->port_clock, |
||
773 | &pipe_config->dp_m_n); |
||
774 | else |
||
775 | pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; |
||
776 | } |
||
777 | |||
778 | static void hsw_ddi_clock_get(struct intel_encoder *encoder, |
||
779 | struct intel_crtc_config *pipe_config) |
||
780 | { |
||
781 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
||
782 | int link_clock = 0; |
||
5060 | serge | 783 | u32 val, pll; |
784 | |||
785 | val = pipe_config->ddi_pll_sel; |
||
786 | switch (val & PORT_CLK_SEL_MASK) { |
||
787 | case PORT_CLK_SEL_LCPLL_810: |
||
788 | link_clock = 81000; |
||
789 | break; |
||
790 | case PORT_CLK_SEL_LCPLL_1350: |
||
791 | link_clock = 135000; |
||
792 | break; |
||
793 | case PORT_CLK_SEL_LCPLL_2700: |
||
794 | link_clock = 270000; |
||
795 | break; |
||
796 | case PORT_CLK_SEL_WRPLL1: |
||
797 | link_clock = intel_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL1); |
||
798 | break; |
||
799 | case PORT_CLK_SEL_WRPLL2: |
||
800 | link_clock = intel_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL2); |
||
801 | break; |
||
802 | case PORT_CLK_SEL_SPLL: |
||
803 | pll = I915_READ(SPLL_CTL) & SPLL_PLL_FREQ_MASK; |
||
804 | if (pll == SPLL_PLL_FREQ_810MHz) |
||
805 | link_clock = 81000; |
||
806 | else if (pll == SPLL_PLL_FREQ_1350MHz) |
||
807 | link_clock = 135000; |
||
808 | else if (pll == SPLL_PLL_FREQ_2700MHz) |
||
809 | link_clock = 270000; |
||
810 | else { |
||
811 | WARN(1, "bad spll freq\n"); |
||
812 | return; |
||
813 | } |
||
814 | break; |
||
815 | default: |
||
816 | WARN(1, "bad port clock sel\n"); |
||
817 | return; |
||
818 | } |
||
819 | |||
820 | pipe_config->port_clock = link_clock * 2; |
||
821 | |||
822 | if (pipe_config->has_pch_encoder) |
||
823 | pipe_config->adjusted_mode.crtc_clock = |
||
824 | intel_dotclock_calculate(pipe_config->port_clock, |
||
825 | &pipe_config->fdi_m_n); |
||
826 | else if (pipe_config->has_dp_encoder) |
||
827 | pipe_config->adjusted_mode.crtc_clock = |
||
828 | intel_dotclock_calculate(pipe_config->port_clock, |
||
829 | &pipe_config->dp_m_n); |
||
830 | else |
||
831 | pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; |
||
832 | } |
||
833 | |||
5354 | serge | 834 | void intel_ddi_clock_get(struct intel_encoder *encoder, |
835 | struct intel_crtc_config *pipe_config) |
||
836 | { |
||
837 | hsw_ddi_clock_get(encoder, pipe_config); |
||
838 | } |
||
839 | |||
4104 | Serge | 840 | static void |
5354 | serge | 841 | hsw_ddi_calculate_wrpll(int clock /* in Hz */, |
4104 | Serge | 842 | unsigned *r2_out, unsigned *n2_out, unsigned *p_out) |
3243 | Serge | 843 | { |
4104 | Serge | 844 | uint64_t freq2k; |
845 | unsigned p, n2, r2; |
||
846 | struct wrpll_rnp best = { 0, 0, 0 }; |
||
847 | unsigned budget; |
||
848 | |||
849 | freq2k = clock / 100; |
||
850 | |||
851 | budget = wrpll_get_budget_for_freq(clock); |
||
852 | |||
853 | /* Special case handling for 540 pixel clock: bypass WR PLL entirely |
||
854 | * and directly pass the LC PLL to it. */ |
||
855 | if (freq2k == 5400000) { |
||
856 | *n2_out = 2; |
||
857 | *p_out = 1; |
||
858 | *r2_out = 2; |
||
859 | return; |
||
860 | } |
||
861 | |||
862 | /* |
||
863 | * Ref = LC_FREQ / R, where Ref is the actual reference input seen by |
||
864 | * the WR PLL. |
||
865 | * |
||
866 | * We want R so that REF_MIN <= Ref <= REF_MAX. |
||
867 | * Injecting R2 = 2 * R gives: |
||
868 | * REF_MAX * r2 > LC_FREQ * 2 and |
||
869 | * REF_MIN * r2 < LC_FREQ * 2 |
||
870 | * |
||
871 | * Which means the desired boundaries for r2 are: |
||
872 | * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN |
||
873 | * |
||
874 | */ |
||
875 | for (r2 = LC_FREQ * 2 / REF_MAX + 1; |
||
876 | r2 <= LC_FREQ * 2 / REF_MIN; |
||
877 | r2++) { |
||
878 | |||
879 | /* |
||
880 | * VCO = N * Ref, that is: VCO = N * LC_FREQ / R |
||
881 | * |
||
882 | * Once again we want VCO_MIN <= VCO <= VCO_MAX. |
||
883 | * Injecting R2 = 2 * R and N2 = 2 * N, we get: |
||
884 | * VCO_MAX * r2 > n2 * LC_FREQ and |
||
885 | * VCO_MIN * r2 < n2 * LC_FREQ) |
||
886 | * |
||
887 | * Which means the desired boundaries for n2 are: |
||
888 | * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ |
||
889 | */ |
||
890 | for (n2 = VCO_MIN * r2 / LC_FREQ + 1; |
||
891 | n2 <= VCO_MAX * r2 / LC_FREQ; |
||
892 | n2++) { |
||
893 | |||
894 | for (p = P_MIN; p <= P_MAX; p += P_INC) |
||
895 | wrpll_update_rnp(freq2k, budget, |
||
896 | r2, n2, p, &best); |
||
897 | } |
||
898 | } |
||
899 | |||
900 | *n2_out = best.n2; |
||
901 | *p_out = best.p; |
||
902 | *r2_out = best.r2; |
||
903 | } |
||
904 | |||
5354 | serge | 905 | static bool |
906 | hsw_ddi_pll_select(struct intel_crtc *intel_crtc, |
||
907 | struct intel_encoder *intel_encoder, |
||
908 | int clock) |
||
4104 | Serge | 909 | { |
5354 | serge | 910 | if (intel_encoder->type == INTEL_OUTPUT_HDMI) { |
5060 | serge | 911 | struct intel_shared_dpll *pll; |
912 | uint32_t val; |
||
4104 | Serge | 913 | unsigned p, n2, r2; |
3243 | Serge | 914 | |
5354 | serge | 915 | hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); |
4560 | Serge | 916 | |
5060 | serge | 917 | val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | |
4560 | Serge | 918 | WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | |
919 | WRPLL_DIVIDER_POST(p); |
||
920 | |||
5354 | serge | 921 | intel_crtc->new_config->dpll_hw_state.wrpll = val; |
3243 | Serge | 922 | |
5060 | serge | 923 | pll = intel_get_shared_dpll(intel_crtc); |
924 | if (pll == NULL) { |
||
925 | DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", |
||
926 | pipe_name(intel_crtc->pipe)); |
||
3746 | Serge | 927 | return false; |
3243 | Serge | 928 | } |
929 | |||
5354 | serge | 930 | intel_crtc->new_config->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id); |
3243 | Serge | 931 | } |
932 | |||
933 | return true; |
||
934 | } |
||
3031 | serge | 935 | |
5354 | serge | 936 | struct skl_wrpll_params { |
937 | uint32_t dco_fraction; |
||
938 | uint32_t dco_integer; |
||
939 | uint32_t qdiv_ratio; |
||
940 | uint32_t qdiv_mode; |
||
941 | uint32_t kdiv; |
||
942 | uint32_t pdiv; |
||
943 | uint32_t central_freq; |
||
944 | }; |
||
945 | |||
946 | static void |
||
947 | skl_ddi_calculate_wrpll(int clock /* in Hz */, |
||
948 | struct skl_wrpll_params *wrpll_params) |
||
949 | { |
||
950 | uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */ |
||
951 | uint64_t dco_central_freq[3] = {8400000000ULL, |
||
952 | 9000000000ULL, |
||
953 | 9600000000ULL}; |
||
954 | uint32_t min_dco_deviation = 400; |
||
955 | uint32_t min_dco_index = 3; |
||
956 | uint32_t P0[4] = {1, 2, 3, 7}; |
||
957 | uint32_t P2[4] = {1, 2, 3, 5}; |
||
958 | bool found = false; |
||
959 | uint32_t candidate_p = 0; |
||
960 | uint32_t candidate_p0[3] = {0}, candidate_p1[3] = {0}; |
||
961 | uint32_t candidate_p2[3] = {0}; |
||
962 | uint32_t dco_central_freq_deviation[3]; |
||
963 | uint32_t i, P1, k, dco_count; |
||
964 | bool retry_with_odd = false; |
||
965 | uint64_t dco_freq; |
||
966 | |||
967 | /* Determine P0, P1 or P2 */ |
||
968 | for (dco_count = 0; dco_count < 3; dco_count++) { |
||
969 | found = false; |
||
970 | candidate_p = |
||
971 | div64_u64(dco_central_freq[dco_count], afe_clock); |
||
972 | if (retry_with_odd == false) |
||
973 | candidate_p = (candidate_p % 2 == 0 ? |
||
974 | candidate_p : candidate_p + 1); |
||
975 | |||
976 | for (P1 = 1; P1 < candidate_p; P1++) { |
||
977 | for (i = 0; i < 4; i++) { |
||
978 | if (!(P0[i] != 1 || P1 == 1)) |
||
979 | continue; |
||
980 | |||
981 | for (k = 0; k < 4; k++) { |
||
982 | if (P1 != 1 && P2[k] != 2) |
||
983 | continue; |
||
984 | |||
985 | if (candidate_p == P0[i] * P1 * P2[k]) { |
||
986 | /* Found possible P0, P1, P2 */ |
||
987 | found = true; |
||
988 | candidate_p0[dco_count] = P0[i]; |
||
989 | candidate_p1[dco_count] = P1; |
||
990 | candidate_p2[dco_count] = P2[k]; |
||
991 | goto found; |
||
992 | } |
||
993 | |||
994 | } |
||
995 | } |
||
996 | } |
||
997 | |||
998 | found: |
||
999 | if (found) { |
||
1000 | dco_central_freq_deviation[dco_count] = |
||
1001 | div64_u64(10000 * |
||
1002 | abs_diff((candidate_p * afe_clock), |
||
1003 | dco_central_freq[dco_count]), |
||
1004 | dco_central_freq[dco_count]); |
||
1005 | |||
1006 | if (dco_central_freq_deviation[dco_count] < |
||
1007 | min_dco_deviation) { |
||
1008 | min_dco_deviation = |
||
1009 | dco_central_freq_deviation[dco_count]; |
||
1010 | min_dco_index = dco_count; |
||
1011 | } |
||
1012 | } |
||
1013 | |||
1014 | if (min_dco_index > 2 && dco_count == 2) { |
||
1015 | retry_with_odd = true; |
||
1016 | dco_count = 0; |
||
1017 | } |
||
1018 | } |
||
1019 | |||
1020 | if (min_dco_index > 2) { |
||
1021 | WARN(1, "No valid values found for the given pixel clock\n"); |
||
1022 | } else { |
||
1023 | wrpll_params->central_freq = dco_central_freq[min_dco_index]; |
||
1024 | |||
1025 | switch (dco_central_freq[min_dco_index]) { |
||
1026 | case 9600000000ULL: |
||
1027 | wrpll_params->central_freq = 0; |
||
1028 | break; |
||
1029 | case 9000000000ULL: |
||
1030 | wrpll_params->central_freq = 1; |
||
1031 | break; |
||
1032 | case 8400000000ULL: |
||
1033 | wrpll_params->central_freq = 3; |
||
1034 | } |
||
1035 | |||
1036 | switch (candidate_p0[min_dco_index]) { |
||
1037 | case 1: |
||
1038 | wrpll_params->pdiv = 0; |
||
1039 | break; |
||
1040 | case 2: |
||
1041 | wrpll_params->pdiv = 1; |
||
1042 | break; |
||
1043 | case 3: |
||
1044 | wrpll_params->pdiv = 2; |
||
1045 | break; |
||
1046 | case 7: |
||
1047 | wrpll_params->pdiv = 4; |
||
1048 | break; |
||
1049 | default: |
||
1050 | WARN(1, "Incorrect PDiv\n"); |
||
1051 | } |
||
1052 | |||
1053 | switch (candidate_p2[min_dco_index]) { |
||
1054 | case 5: |
||
1055 | wrpll_params->kdiv = 0; |
||
1056 | break; |
||
1057 | case 2: |
||
1058 | wrpll_params->kdiv = 1; |
||
1059 | break; |
||
1060 | case 3: |
||
1061 | wrpll_params->kdiv = 2; |
||
1062 | break; |
||
1063 | case 1: |
||
1064 | wrpll_params->kdiv = 3; |
||
1065 | break; |
||
1066 | default: |
||
1067 | WARN(1, "Incorrect KDiv\n"); |
||
1068 | } |
||
1069 | |||
1070 | wrpll_params->qdiv_ratio = candidate_p1[min_dco_index]; |
||
1071 | wrpll_params->qdiv_mode = |
||
1072 | (wrpll_params->qdiv_ratio == 1) ? 0 : 1; |
||
1073 | |||
1074 | dco_freq = candidate_p0[min_dco_index] * |
||
1075 | candidate_p1[min_dco_index] * |
||
1076 | candidate_p2[min_dco_index] * afe_clock; |
||
1077 | |||
1078 | /* |
||
1079 | * Intermediate values are in Hz. |
||
1080 | * Divide by MHz to match bsepc |
||
1081 | */ |
||
1082 | wrpll_params->dco_integer = div_u64(dco_freq, (24 * MHz(1))); |
||
1083 | wrpll_params->dco_fraction = |
||
1084 | div_u64(((div_u64(dco_freq, 24) - |
||
1085 | wrpll_params->dco_integer * MHz(1)) * 0x8000), MHz(1)); |
||
1086 | |||
1087 | } |
||
1088 | } |
||
1089 | |||
1090 | |||
1091 | static bool |
||
1092 | skl_ddi_pll_select(struct intel_crtc *intel_crtc, |
||
1093 | struct intel_encoder *intel_encoder, |
||
1094 | int clock) |
||
1095 | { |
||
1096 | struct intel_shared_dpll *pll; |
||
1097 | uint32_t ctrl1, cfgcr1, cfgcr2; |
||
1098 | |||
1099 | /* |
||
1100 | * See comment in intel_dpll_hw_state to understand why we always use 0 |
||
1101 | * as the DPLL id in this function. |
||
1102 | */ |
||
1103 | |||
1104 | ctrl1 = DPLL_CTRL1_OVERRIDE(0); |
||
1105 | |||
1106 | if (intel_encoder->type == INTEL_OUTPUT_HDMI) { |
||
1107 | struct skl_wrpll_params wrpll_params = { 0, }; |
||
1108 | |||
1109 | ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); |
||
1110 | |||
1111 | skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params); |
||
1112 | |||
1113 | cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | |
||
1114 | DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | |
||
1115 | wrpll_params.dco_integer; |
||
1116 | |||
1117 | cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) | |
||
1118 | DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) | |
||
1119 | DPLL_CFGCR2_KDIV(wrpll_params.kdiv) | |
||
1120 | DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | |
||
1121 | wrpll_params.central_freq; |
||
1122 | } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) { |
||
1123 | struct drm_encoder *encoder = &intel_encoder->base; |
||
1124 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1125 | |||
1126 | switch (intel_dp->link_bw) { |
||
1127 | case DP_LINK_BW_1_62: |
||
1128 | ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_810, 0); |
||
1129 | break; |
||
1130 | case DP_LINK_BW_2_7: |
||
1131 | ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_1350, 0); |
||
1132 | break; |
||
1133 | case DP_LINK_BW_5_4: |
||
1134 | ctrl1 |= DPLL_CRTL1_LINK_RATE(DPLL_CRTL1_LINK_RATE_2700, 0); |
||
1135 | break; |
||
1136 | } |
||
1137 | |||
1138 | cfgcr1 = cfgcr2 = 0; |
||
1139 | } else /* eDP */ |
||
1140 | return true; |
||
1141 | |||
1142 | intel_crtc->new_config->dpll_hw_state.ctrl1 = ctrl1; |
||
1143 | intel_crtc->new_config->dpll_hw_state.cfgcr1 = cfgcr1; |
||
1144 | intel_crtc->new_config->dpll_hw_state.cfgcr2 = cfgcr2; |
||
1145 | |||
1146 | pll = intel_get_shared_dpll(intel_crtc); |
||
1147 | if (pll == NULL) { |
||
1148 | DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", |
||
1149 | pipe_name(intel_crtc->pipe)); |
||
1150 | return false; |
||
1151 | } |
||
1152 | |||
1153 | /* shared DPLL id 0 is DPLL 1 */ |
||
1154 | intel_crtc->new_config->ddi_pll_sel = pll->id + 1; |
||
1155 | |||
1156 | return true; |
||
1157 | } |
||
1158 | |||
1159 | /* |
||
1160 | * Tries to find a *shared* PLL for the CRTC and store it in |
||
1161 | * intel_crtc->ddi_pll_sel. |
||
1162 | * |
||
1163 | * For private DPLLs, compute_config() should do the selection for us. This |
||
1164 | * function should be folded into compute_config() eventually. |
||
1165 | */ |
||
1166 | bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) |
||
1167 | { |
||
1168 | struct drm_device *dev = intel_crtc->base.dev; |
||
1169 | struct intel_encoder *intel_encoder = |
||
1170 | intel_ddi_get_crtc_new_encoder(intel_crtc); |
||
1171 | int clock = intel_crtc->new_config->port_clock; |
||
1172 | |||
1173 | if (IS_SKYLAKE(dev)) |
||
1174 | return skl_ddi_pll_select(intel_crtc, intel_encoder, clock); |
||
1175 | else |
||
1176 | return hsw_ddi_pll_select(intel_crtc, intel_encoder, clock); |
||
1177 | } |
||
1178 | |||
3243 | Serge | 1179 | void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) |
1180 | { |
||
1181 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
1182 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
1183 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
3746 | Serge | 1184 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
3243 | Serge | 1185 | int type = intel_encoder->type; |
1186 | uint32_t temp; |
||
1187 | |||
5060 | serge | 1188 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP_MST) { |
3243 | Serge | 1189 | temp = TRANS_MSA_SYNC_CLK; |
3746 | Serge | 1190 | switch (intel_crtc->config.pipe_bpp) { |
3243 | Serge | 1191 | case 18: |
1192 | temp |= TRANS_MSA_6_BPC; |
||
1193 | break; |
||
1194 | case 24: |
||
1195 | temp |= TRANS_MSA_8_BPC; |
||
1196 | break; |
||
1197 | case 30: |
||
1198 | temp |= TRANS_MSA_10_BPC; |
||
1199 | break; |
||
1200 | case 36: |
||
1201 | temp |= TRANS_MSA_12_BPC; |
||
1202 | break; |
||
1203 | default: |
||
3746 | Serge | 1204 | BUG(); |
3031 | serge | 1205 | } |
3243 | Serge | 1206 | I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp); |
1207 | } |
||
1208 | } |
||
3031 | serge | 1209 | |
5060 | serge | 1210 | void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state) |
1211 | { |
||
1212 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
1213 | struct drm_device *dev = crtc->dev; |
||
1214 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
1215 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
||
1216 | uint32_t temp; |
||
1217 | temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
||
1218 | if (state == true) |
||
1219 | temp |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC; |
||
1220 | else |
||
1221 | temp &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC; |
||
1222 | I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp); |
||
1223 | } |
||
1224 | |||
3746 | Serge | 1225 | void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) |
3243 | Serge | 1226 | { |
1227 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
1228 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
1229 | struct drm_encoder *encoder = &intel_encoder->base; |
||
4560 | Serge | 1230 | struct drm_device *dev = crtc->dev; |
1231 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
3243 | Serge | 1232 | enum pipe pipe = intel_crtc->pipe; |
3746 | Serge | 1233 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
3243 | Serge | 1234 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
1235 | int type = intel_encoder->type; |
||
1236 | uint32_t temp; |
||
3031 | serge | 1237 | |
3243 | Serge | 1238 | /* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */ |
1239 | temp = TRANS_DDI_FUNC_ENABLE; |
||
1240 | temp |= TRANS_DDI_SELECT_PORT(port); |
||
1241 | |||
3746 | Serge | 1242 | switch (intel_crtc->config.pipe_bpp) { |
3031 | serge | 1243 | case 18: |
3243 | Serge | 1244 | temp |= TRANS_DDI_BPC_6; |
3031 | serge | 1245 | break; |
1246 | case 24: |
||
3243 | Serge | 1247 | temp |= TRANS_DDI_BPC_8; |
3031 | serge | 1248 | break; |
1249 | case 30: |
||
3243 | Serge | 1250 | temp |= TRANS_DDI_BPC_10; |
3031 | serge | 1251 | break; |
1252 | case 36: |
||
3243 | Serge | 1253 | temp |= TRANS_DDI_BPC_12; |
3031 | serge | 1254 | break; |
1255 | default: |
||
3746 | Serge | 1256 | BUG(); |
3031 | serge | 1257 | } |
1258 | |||
4560 | Serge | 1259 | if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC) |
3243 | Serge | 1260 | temp |= TRANS_DDI_PVSYNC; |
4560 | Serge | 1261 | if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC) |
3243 | Serge | 1262 | temp |= TRANS_DDI_PHSYNC; |
1263 | |||
1264 | if (cpu_transcoder == TRANSCODER_EDP) { |
||
1265 | switch (pipe) { |
||
1266 | case PIPE_A: |
||
4560 | Serge | 1267 | /* On Haswell, can only use the always-on power well for |
1268 | * eDP when not using the panel fitter, and when not |
||
1269 | * using motion blur mitigation (which we don't |
||
1270 | * support). */ |
||
5060 | serge | 1271 | if (IS_HASWELL(dev) && |
1272 | (intel_crtc->config.pch_pfit.enabled || |
||
1273 | intel_crtc->config.pch_pfit.force_thru)) |
||
3243 | Serge | 1274 | temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; |
3480 | Serge | 1275 | else |
1276 | temp |= TRANS_DDI_EDP_INPUT_A_ON; |
||
3243 | Serge | 1277 | break; |
1278 | case PIPE_B: |
||
1279 | temp |= TRANS_DDI_EDP_INPUT_B_ONOFF; |
||
1280 | break; |
||
1281 | case PIPE_C: |
||
1282 | temp |= TRANS_DDI_EDP_INPUT_C_ONOFF; |
||
1283 | break; |
||
1284 | default: |
||
1285 | BUG(); |
||
1286 | break; |
||
1287 | } |
||
1288 | } |
||
1289 | |||
1290 | if (type == INTEL_OUTPUT_HDMI) { |
||
5060 | serge | 1291 | if (intel_crtc->config.has_hdmi_sink) |
3243 | Serge | 1292 | temp |= TRANS_DDI_MODE_SELECT_HDMI; |
3031 | serge | 1293 | else |
3243 | Serge | 1294 | temp |= TRANS_DDI_MODE_SELECT_DVI; |
3031 | serge | 1295 | |
3243 | Serge | 1296 | } else if (type == INTEL_OUTPUT_ANALOG) { |
1297 | temp |= TRANS_DDI_MODE_SELECT_FDI; |
||
4104 | Serge | 1298 | temp |= (intel_crtc->config.fdi_lanes - 1) << 1; |
3031 | serge | 1299 | |
3243 | Serge | 1300 | } else if (type == INTEL_OUTPUT_DISPLAYPORT || |
1301 | type == INTEL_OUTPUT_EDP) { |
||
1302 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
3031 | serge | 1303 | |
5060 | serge | 1304 | if (intel_dp->is_mst) { |
1305 | temp |= TRANS_DDI_MODE_SELECT_DP_MST; |
||
1306 | } else |
||
1307 | temp |= TRANS_DDI_MODE_SELECT_DP_SST; |
||
1308 | |||
1309 | temp |= DDI_PORT_WIDTH(intel_dp->lane_count); |
||
1310 | } else if (type == INTEL_OUTPUT_DP_MST) { |
||
1311 | struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp; |
||
1312 | |||
1313 | if (intel_dp->is_mst) { |
||
1314 | temp |= TRANS_DDI_MODE_SELECT_DP_MST; |
||
1315 | } else |
||
3243 | Serge | 1316 | temp |= TRANS_DDI_MODE_SELECT_DP_SST; |
1317 | |||
4104 | Serge | 1318 | temp |= DDI_PORT_WIDTH(intel_dp->lane_count); |
3243 | Serge | 1319 | } else { |
4104 | Serge | 1320 | WARN(1, "Invalid encoder type %d for pipe %c\n", |
1321 | intel_encoder->type, pipe_name(pipe)); |
||
3243 | Serge | 1322 | } |
1323 | |||
1324 | I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp); |
||
3031 | serge | 1325 | } |
1326 | |||
3243 | Serge | 1327 | void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, |
1328 | enum transcoder cpu_transcoder) |
||
1329 | { |
||
1330 | uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder); |
||
1331 | uint32_t val = I915_READ(reg); |
||
1332 | |||
5060 | serge | 1333 | val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK | TRANS_DDI_DP_VC_PAYLOAD_ALLOC); |
3243 | Serge | 1334 | val |= TRANS_DDI_PORT_NONE; |
1335 | I915_WRITE(reg, val); |
||
1336 | } |
||
1337 | |||
1338 | bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) |
||
1339 | { |
||
1340 | struct drm_device *dev = intel_connector->base.dev; |
||
1341 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
1342 | struct intel_encoder *intel_encoder = intel_connector->encoder; |
||
1343 | int type = intel_connector->base.connector_type; |
||
1344 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
1345 | enum pipe pipe = 0; |
||
1346 | enum transcoder cpu_transcoder; |
||
5060 | serge | 1347 | enum intel_display_power_domain power_domain; |
3243 | Serge | 1348 | uint32_t tmp; |
1349 | |||
5060 | serge | 1350 | power_domain = intel_display_port_power_domain(intel_encoder); |
5354 | serge | 1351 | if (!intel_display_power_is_enabled(dev_priv, power_domain)) |
5060 | serge | 1352 | return false; |
1353 | |||
3243 | Serge | 1354 | if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) |
1355 | return false; |
||
1356 | |||
1357 | if (port == PORT_A) |
||
1358 | cpu_transcoder = TRANSCODER_EDP; |
||
1359 | else |
||
3480 | Serge | 1360 | cpu_transcoder = (enum transcoder) pipe; |
3243 | Serge | 1361 | |
1362 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
||
1363 | |||
1364 | switch (tmp & TRANS_DDI_MODE_SELECT_MASK) { |
||
1365 | case TRANS_DDI_MODE_SELECT_HDMI: |
||
1366 | case TRANS_DDI_MODE_SELECT_DVI: |
||
1367 | return (type == DRM_MODE_CONNECTOR_HDMIA); |
||
1368 | |||
1369 | case TRANS_DDI_MODE_SELECT_DP_SST: |
||
1370 | if (type == DRM_MODE_CONNECTOR_eDP) |
||
1371 | return true; |
||
5060 | serge | 1372 | return (type == DRM_MODE_CONNECTOR_DisplayPort); |
3243 | Serge | 1373 | case TRANS_DDI_MODE_SELECT_DP_MST: |
5060 | serge | 1374 | /* if the transcoder is in MST state then |
1375 | * connector isn't connected */ |
||
1376 | return false; |
||
3243 | Serge | 1377 | |
1378 | case TRANS_DDI_MODE_SELECT_FDI: |
||
1379 | return (type == DRM_MODE_CONNECTOR_VGA); |
||
1380 | |||
1381 | default: |
||
1382 | return false; |
||
1383 | } |
||
1384 | } |
||
1385 | |||
3031 | serge | 1386 | bool intel_ddi_get_hw_state(struct intel_encoder *encoder, |
1387 | enum pipe *pipe) |
||
1388 | { |
||
1389 | struct drm_device *dev = encoder->base.dev; |
||
1390 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
3243 | Serge | 1391 | enum port port = intel_ddi_get_encoder_port(encoder); |
5060 | serge | 1392 | enum intel_display_power_domain power_domain; |
3031 | serge | 1393 | u32 tmp; |
1394 | int i; |
||
1395 | |||
5060 | serge | 1396 | power_domain = intel_display_port_power_domain(encoder); |
5354 | serge | 1397 | if (!intel_display_power_is_enabled(dev_priv, power_domain)) |
5060 | serge | 1398 | return false; |
1399 | |||
3243 | Serge | 1400 | tmp = I915_READ(DDI_BUF_CTL(port)); |
3031 | serge | 1401 | |
1402 | if (!(tmp & DDI_BUF_CTL_ENABLE)) |
||
1403 | return false; |
||
1404 | |||
3243 | Serge | 1405 | if (port == PORT_A) { |
1406 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); |
||
3031 | serge | 1407 | |
3243 | Serge | 1408 | switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { |
1409 | case TRANS_DDI_EDP_INPUT_A_ON: |
||
1410 | case TRANS_DDI_EDP_INPUT_A_ONOFF: |
||
1411 | *pipe = PIPE_A; |
||
1412 | break; |
||
1413 | case TRANS_DDI_EDP_INPUT_B_ONOFF: |
||
1414 | *pipe = PIPE_B; |
||
1415 | break; |
||
1416 | case TRANS_DDI_EDP_INPUT_C_ONOFF: |
||
1417 | *pipe = PIPE_C; |
||
1418 | break; |
||
1419 | } |
||
1420 | |||
1421 | return true; |
||
1422 | } else { |
||
1423 | for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) { |
||
1424 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(i)); |
||
1425 | |||
1426 | if ((tmp & TRANS_DDI_PORT_MASK) |
||
1427 | == TRANS_DDI_SELECT_PORT(port)) { |
||
5060 | serge | 1428 | if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST) |
1429 | return false; |
||
1430 | |||
3031 | serge | 1431 | *pipe = i; |
1432 | return true; |
||
1433 | } |
||
1434 | } |
||
3243 | Serge | 1435 | } |
3031 | serge | 1436 | |
4104 | Serge | 1437 | DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port)); |
3031 | serge | 1438 | |
3746 | Serge | 1439 | return false; |
3031 | serge | 1440 | } |
1441 | |||
3243 | Serge | 1442 | void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc) |
3031 | serge | 1443 | { |
3243 | Serge | 1444 | struct drm_crtc *crtc = &intel_crtc->base; |
1445 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
1446 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
1447 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
3746 | Serge | 1448 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
3243 | Serge | 1449 | |
1450 | if (cpu_transcoder != TRANSCODER_EDP) |
||
1451 | I915_WRITE(TRANS_CLK_SEL(cpu_transcoder), |
||
1452 | TRANS_CLK_SEL_PORT(port)); |
||
1453 | } |
||
1454 | |||
1455 | void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) |
||
1456 | { |
||
1457 | struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; |
||
3746 | Serge | 1458 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
3243 | Serge | 1459 | |
1460 | if (cpu_transcoder != TRANSCODER_EDP) |
||
1461 | I915_WRITE(TRANS_CLK_SEL(cpu_transcoder), |
||
1462 | TRANS_CLK_SEL_DISABLED); |
||
1463 | } |
||
1464 | |||
1465 | static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) |
||
1466 | { |
||
1467 | struct drm_encoder *encoder = &intel_encoder->base; |
||
5354 | serge | 1468 | struct drm_device *dev = encoder->dev; |
1469 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
5060 | serge | 1470 | struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); |
3243 | Serge | 1471 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
1472 | int type = intel_encoder->type; |
||
1473 | |||
1474 | if (type == INTEL_OUTPUT_EDP) { |
||
1475 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
5060 | serge | 1476 | intel_edp_panel_on(intel_dp); |
3243 | Serge | 1477 | } |
1478 | |||
5354 | serge | 1479 | if (IS_SKYLAKE(dev)) { |
1480 | uint32_t dpll = crtc->config.ddi_pll_sel; |
||
1481 | uint32_t val; |
||
1482 | |||
1483 | /* |
||
1484 | * DPLL0 is used for eDP and is the only "private" DPLL (as |
||
1485 | * opposed to shared) on SKL |
||
1486 | */ |
||
1487 | if (type == INTEL_OUTPUT_EDP) { |
||
1488 | WARN_ON(dpll != SKL_DPLL0); |
||
1489 | |||
1490 | val = I915_READ(DPLL_CTRL1); |
||
1491 | |||
1492 | val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | |
||
1493 | DPLL_CTRL1_SSC(dpll) | |
||
1494 | DPLL_CRTL1_LINK_RATE_MASK(dpll)); |
||
1495 | val |= crtc->config.dpll_hw_state.ctrl1 << (dpll * 6); |
||
1496 | |||
1497 | I915_WRITE(DPLL_CTRL1, val); |
||
1498 | POSTING_READ(DPLL_CTRL1); |
||
1499 | } |
||
1500 | |||
1501 | /* DDI -> PLL mapping */ |
||
1502 | val = I915_READ(DPLL_CTRL2); |
||
1503 | |||
1504 | val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | |
||
1505 | DPLL_CTRL2_DDI_CLK_SEL_MASK(port)); |
||
1506 | val |= (DPLL_CTRL2_DDI_CLK_SEL(dpll, port) | |
||
1507 | DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); |
||
1508 | |||
1509 | I915_WRITE(DPLL_CTRL2, val); |
||
1510 | |||
1511 | } else { |
||
5060 | serge | 1512 | WARN_ON(crtc->config.ddi_pll_sel == PORT_CLK_SEL_NONE); |
1513 | I915_WRITE(PORT_CLK_SEL(port), crtc->config.ddi_pll_sel); |
||
5354 | serge | 1514 | } |
3243 | Serge | 1515 | |
1516 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
||
1517 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1518 | |||
5060 | serge | 1519 | intel_ddi_init_dp_buf_reg(intel_encoder); |
1520 | |||
3243 | Serge | 1521 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); |
1522 | intel_dp_start_link_train(intel_dp); |
||
1523 | intel_dp_complete_link_train(intel_dp); |
||
5354 | serge | 1524 | if (port != PORT_A || INTEL_INFO(dev)->gen >= 9) |
3746 | Serge | 1525 | intel_dp_stop_link_train(intel_dp); |
5060 | serge | 1526 | } else if (type == INTEL_OUTPUT_HDMI) { |
1527 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
||
1528 | |||
1529 | intel_hdmi->set_infoframes(encoder, |
||
1530 | crtc->config.has_hdmi_sink, |
||
1531 | &crtc->config.adjusted_mode); |
||
3243 | Serge | 1532 | } |
1533 | } |
||
1534 | |||
1535 | static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) |
||
1536 | { |
||
1537 | struct drm_encoder *encoder = &intel_encoder->base; |
||
5354 | serge | 1538 | struct drm_device *dev = encoder->dev; |
1539 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
3243 | Serge | 1540 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
1541 | int type = intel_encoder->type; |
||
1542 | uint32_t val; |
||
1543 | bool wait = false; |
||
1544 | |||
1545 | val = I915_READ(DDI_BUF_CTL(port)); |
||
1546 | if (val & DDI_BUF_CTL_ENABLE) { |
||
1547 | val &= ~DDI_BUF_CTL_ENABLE; |
||
1548 | I915_WRITE(DDI_BUF_CTL(port), val); |
||
1549 | wait = true; |
||
1550 | } |
||
1551 | |||
1552 | val = I915_READ(DP_TP_CTL(port)); |
||
1553 | val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); |
||
1554 | val |= DP_TP_CTL_LINK_TRAIN_PAT1; |
||
1555 | I915_WRITE(DP_TP_CTL(port), val); |
||
1556 | |||
1557 | if (wait) |
||
1558 | intel_wait_ddi_buf_idle(dev_priv, port); |
||
1559 | |||
4560 | Serge | 1560 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
3243 | Serge | 1561 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
4560 | Serge | 1562 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); |
5060 | serge | 1563 | intel_edp_panel_vdd_on(intel_dp); |
1564 | intel_edp_panel_off(intel_dp); |
||
3243 | Serge | 1565 | } |
1566 | |||
5354 | serge | 1567 | if (IS_SKYLAKE(dev)) |
1568 | I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) | |
||
1569 | DPLL_CTRL2_DDI_CLK_OFF(port))); |
||
1570 | else |
||
3243 | Serge | 1571 | I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); |
1572 | } |
||
1573 | |||
1574 | static void intel_enable_ddi(struct intel_encoder *intel_encoder) |
||
1575 | { |
||
1576 | struct drm_encoder *encoder = &intel_encoder->base; |
||
3480 | Serge | 1577 | struct drm_crtc *crtc = encoder->crtc; |
1578 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
3243 | Serge | 1579 | struct drm_device *dev = encoder->dev; |
3031 | serge | 1580 | struct drm_i915_private *dev_priv = dev->dev_private; |
3243 | Serge | 1581 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
1582 | int type = intel_encoder->type; |
||
3031 | serge | 1583 | |
3243 | Serge | 1584 | if (type == INTEL_OUTPUT_HDMI) { |
3480 | Serge | 1585 | struct intel_digital_port *intel_dig_port = |
1586 | enc_to_dig_port(encoder); |
||
1587 | |||
3243 | Serge | 1588 | /* In HDMI/DVI mode, the port width, and swing/emphasis values |
1589 | * are ignored so nothing special needs to be done besides |
||
1590 | * enabling the port. |
||
1591 | */ |
||
3480 | Serge | 1592 | I915_WRITE(DDI_BUF_CTL(port), |
4104 | Serge | 1593 | intel_dig_port->saved_port_bits | |
1594 | DDI_BUF_CTL_ENABLE); |
||
3243 | Serge | 1595 | } else if (type == INTEL_OUTPUT_EDP) { |
1596 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
3031 | serge | 1597 | |
5354 | serge | 1598 | if (port == PORT_A && INTEL_INFO(dev)->gen < 9) |
3746 | Serge | 1599 | intel_dp_stop_link_train(intel_dp); |
1600 | |||
5060 | serge | 1601 | intel_edp_backlight_on(intel_dp); |
5354 | serge | 1602 | intel_psr_enable(intel_dp); |
3243 | Serge | 1603 | } |
3480 | Serge | 1604 | |
5060 | serge | 1605 | if (intel_crtc->config.has_audio) { |
1606 | intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); |
||
5354 | serge | 1607 | intel_audio_codec_enable(intel_encoder); |
3480 | Serge | 1608 | } |
3031 | serge | 1609 | } |
3243 | Serge | 1610 | |
1611 | static void intel_disable_ddi(struct intel_encoder *intel_encoder) |
||
1612 | { |
||
1613 | struct drm_encoder *encoder = &intel_encoder->base; |
||
3480 | Serge | 1614 | struct drm_crtc *crtc = encoder->crtc; |
1615 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
3243 | Serge | 1616 | int type = intel_encoder->type; |
3480 | Serge | 1617 | struct drm_device *dev = encoder->dev; |
1618 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
3243 | Serge | 1619 | |
5060 | serge | 1620 | if (intel_crtc->config.has_audio) { |
5354 | serge | 1621 | intel_audio_codec_disable(intel_encoder); |
5060 | serge | 1622 | intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); |
4104 | Serge | 1623 | } |
3746 | Serge | 1624 | |
3243 | Serge | 1625 | if (type == INTEL_OUTPUT_EDP) { |
1626 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1627 | |||
5354 | serge | 1628 | intel_psr_disable(intel_dp); |
5060 | serge | 1629 | intel_edp_backlight_off(intel_dp); |
3243 | Serge | 1630 | } |
1631 | } |
||
1632 | |||
5354 | serge | 1633 | static int skl_get_cdclk_freq(struct drm_i915_private *dev_priv) |
3243 | Serge | 1634 | { |
5354 | serge | 1635 | uint32_t lcpll1 = I915_READ(LCPLL1_CTL); |
1636 | uint32_t cdctl = I915_READ(CDCLK_CTL); |
||
1637 | uint32_t linkrate; |
||
1638 | |||
1639 | if (!(lcpll1 & LCPLL_PLL_ENABLE)) { |
||
1640 | WARN(1, "LCPLL1 not enabled\n"); |
||
1641 | return 24000; /* 24MHz is the cd freq with NSSC ref */ |
||
1642 | } |
||
1643 | |||
1644 | if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540) |
||
1645 | return 540000; |
||
1646 | |||
1647 | linkrate = (I915_READ(DPLL_CTRL1) & |
||
1648 | DPLL_CRTL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1; |
||
1649 | |||
1650 | if (linkrate == DPLL_CRTL1_LINK_RATE_2160 || |
||
1651 | linkrate == DPLL_CRTL1_LINK_RATE_1080) { |
||
1652 | /* vco 8640 */ |
||
1653 | switch (cdctl & CDCLK_FREQ_SEL_MASK) { |
||
1654 | case CDCLK_FREQ_450_432: |
||
1655 | return 432000; |
||
1656 | case CDCLK_FREQ_337_308: |
||
1657 | return 308570; |
||
1658 | case CDCLK_FREQ_675_617: |
||
1659 | return 617140; |
||
1660 | default: |
||
1661 | WARN(1, "Unknown cd freq selection\n"); |
||
1662 | } |
||
1663 | } else { |
||
1664 | /* vco 8100 */ |
||
1665 | switch (cdctl & CDCLK_FREQ_SEL_MASK) { |
||
1666 | case CDCLK_FREQ_450_432: |
||
1667 | return 450000; |
||
1668 | case CDCLK_FREQ_337_308: |
||
1669 | return 337500; |
||
1670 | case CDCLK_FREQ_675_617: |
||
1671 | return 675000; |
||
1672 | default: |
||
1673 | WARN(1, "Unknown cd freq selection\n"); |
||
1674 | } |
||
1675 | } |
||
1676 | |||
1677 | /* error case, do as if DPLL0 isn't enabled */ |
||
1678 | return 24000; |
||
1679 | } |
||
1680 | |||
1681 | static int bdw_get_cdclk_freq(struct drm_i915_private *dev_priv) |
||
1682 | { |
||
4104 | Serge | 1683 | uint32_t lcpll = I915_READ(LCPLL_CTL); |
4560 | Serge | 1684 | uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; |
4104 | Serge | 1685 | |
5354 | serge | 1686 | if (lcpll & LCPLL_CD_SOURCE_FCLK) |
4104 | Serge | 1687 | return 800000; |
5354 | serge | 1688 | else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) |
4104 | Serge | 1689 | return 450000; |
5354 | serge | 1690 | else if (freq == LCPLL_CLK_FREQ_450) |
4104 | Serge | 1691 | return 450000; |
5354 | serge | 1692 | else if (freq == LCPLL_CLK_FREQ_54O_BDW) |
4560 | Serge | 1693 | return 540000; |
1694 | else if (freq == LCPLL_CLK_FREQ_337_5_BDW) |
||
1695 | return 337500; |
||
1696 | else |
||
1697 | return 675000; |
||
3243 | Serge | 1698 | } |
1699 | |||
5354 | serge | 1700 | static int hsw_get_cdclk_freq(struct drm_i915_private *dev_priv) |
1701 | { |
||
1702 | struct drm_device *dev = dev_priv->dev; |
||
1703 | uint32_t lcpll = I915_READ(LCPLL_CTL); |
||
1704 | uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK; |
||
1705 | |||
1706 | if (lcpll & LCPLL_CD_SOURCE_FCLK) |
||
1707 | return 800000; |
||
1708 | else if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) |
||
1709 | return 450000; |
||
1710 | else if (freq == LCPLL_CLK_FREQ_450) |
||
1711 | return 450000; |
||
1712 | else if (IS_HSW_ULT(dev)) |
||
1713 | return 337500; |
||
1714 | else |
||
1715 | return 540000; |
||
1716 | } |
||
1717 | |||
1718 | int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) |
||
1719 | { |
||
1720 | struct drm_device *dev = dev_priv->dev; |
||
1721 | |||
1722 | if (IS_SKYLAKE(dev)) |
||
1723 | return skl_get_cdclk_freq(dev_priv); |
||
1724 | |||
1725 | if (IS_BROADWELL(dev)) |
||
1726 | return bdw_get_cdclk_freq(dev_priv); |
||
1727 | |||
1728 | /* Haswell */ |
||
1729 | return hsw_get_cdclk_freq(dev_priv); |
||
1730 | } |
||
1731 | |||
5060 | serge | 1732 | static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, |
1733 | struct intel_shared_dpll *pll) |
||
1734 | { |
||
5354 | serge | 1735 | I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll); |
5060 | serge | 1736 | POSTING_READ(WRPLL_CTL(pll->id)); |
1737 | udelay(20); |
||
1738 | } |
||
1739 | |||
1740 | static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv, |
||
1741 | struct intel_shared_dpll *pll) |
||
1742 | { |
||
1743 | uint32_t val; |
||
1744 | |||
1745 | val = I915_READ(WRPLL_CTL(pll->id)); |
||
1746 | I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE); |
||
1747 | POSTING_READ(WRPLL_CTL(pll->id)); |
||
1748 | } |
||
1749 | |||
1750 | static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, |
||
1751 | struct intel_shared_dpll *pll, |
||
1752 | struct intel_dpll_hw_state *hw_state) |
||
1753 | { |
||
1754 | uint32_t val; |
||
1755 | |||
5354 | serge | 1756 | if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) |
5060 | serge | 1757 | return false; |
1758 | |||
1759 | val = I915_READ(WRPLL_CTL(pll->id)); |
||
1760 | hw_state->wrpll = val; |
||
1761 | |||
1762 | return val & WRPLL_PLL_ENABLE; |
||
1763 | } |
||
1764 | |||
1765 | static const char * const hsw_ddi_pll_names[] = { |
||
1766 | "WRPLL 1", |
||
1767 | "WRPLL 2", |
||
1768 | }; |
||
1769 | |||
5354 | serge | 1770 | static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv) |
3243 | Serge | 1771 | { |
5060 | serge | 1772 | int i; |
3243 | Serge | 1773 | |
5060 | serge | 1774 | dev_priv->num_shared_dpll = 2; |
1775 | |||
1776 | for (i = 0; i < dev_priv->num_shared_dpll; i++) { |
||
1777 | dev_priv->shared_dplls[i].id = i; |
||
1778 | dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; |
||
1779 | dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable; |
||
1780 | dev_priv->shared_dplls[i].enable = hsw_ddi_pll_enable; |
||
1781 | dev_priv->shared_dplls[i].get_hw_state = |
||
1782 | hsw_ddi_pll_get_hw_state; |
||
1783 | } |
||
5354 | serge | 1784 | } |
5060 | serge | 1785 | |
5354 | serge | 1786 | static const char * const skl_ddi_pll_names[] = { |
1787 | "DPLL 1", |
||
1788 | "DPLL 2", |
||
1789 | "DPLL 3", |
||
1790 | }; |
||
3243 | Serge | 1791 | |
5354 | serge | 1792 | struct skl_dpll_regs { |
1793 | u32 ctl, cfgcr1, cfgcr2; |
||
1794 | }; |
||
1795 | |||
1796 | /* this array is indexed by the *shared* pll id */ |
||
1797 | static const struct skl_dpll_regs skl_dpll_regs[3] = { |
||
1798 | { |
||
1799 | /* DPLL 1 */ |
||
1800 | .ctl = LCPLL2_CTL, |
||
1801 | .cfgcr1 = DPLL1_CFGCR1, |
||
1802 | .cfgcr2 = DPLL1_CFGCR2, |
||
1803 | }, |
||
1804 | { |
||
1805 | /* DPLL 2 */ |
||
1806 | .ctl = WRPLL_CTL1, |
||
1807 | .cfgcr1 = DPLL2_CFGCR1, |
||
1808 | .cfgcr2 = DPLL2_CFGCR2, |
||
1809 | }, |
||
1810 | { |
||
1811 | /* DPLL 3 */ |
||
1812 | .ctl = WRPLL_CTL2, |
||
1813 | .cfgcr1 = DPLL3_CFGCR1, |
||
1814 | .cfgcr2 = DPLL3_CFGCR2, |
||
1815 | }, |
||
1816 | }; |
||
1817 | |||
1818 | static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, |
||
1819 | struct intel_shared_dpll *pll) |
||
1820 | { |
||
1821 | uint32_t val; |
||
1822 | unsigned int dpll; |
||
1823 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
||
1824 | |||
1825 | /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ |
||
1826 | dpll = pll->id + 1; |
||
1827 | |||
1828 | val = I915_READ(DPLL_CTRL1); |
||
1829 | |||
1830 | val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) | |
||
1831 | DPLL_CRTL1_LINK_RATE_MASK(dpll)); |
||
1832 | val |= pll->config.hw_state.ctrl1 << (dpll * 6); |
||
1833 | |||
1834 | I915_WRITE(DPLL_CTRL1, val); |
||
1835 | POSTING_READ(DPLL_CTRL1); |
||
1836 | |||
1837 | I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1); |
||
1838 | I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2); |
||
1839 | POSTING_READ(regs[pll->id].cfgcr1); |
||
1840 | POSTING_READ(regs[pll->id].cfgcr2); |
||
1841 | |||
1842 | /* the enable bit is always bit 31 */ |
||
1843 | I915_WRITE(regs[pll->id].ctl, |
||
1844 | I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE); |
||
1845 | |||
1846 | if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5)) |
||
1847 | DRM_ERROR("DPLL %d not locked\n", dpll); |
||
1848 | } |
||
1849 | |||
1850 | static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, |
||
1851 | struct intel_shared_dpll *pll) |
||
1852 | { |
||
1853 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
||
1854 | |||
1855 | /* the enable bit is always bit 31 */ |
||
1856 | I915_WRITE(regs[pll->id].ctl, |
||
1857 | I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE); |
||
1858 | POSTING_READ(regs[pll->id].ctl); |
||
1859 | } |
||
1860 | |||
1861 | static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, |
||
1862 | struct intel_shared_dpll *pll, |
||
1863 | struct intel_dpll_hw_state *hw_state) |
||
1864 | { |
||
1865 | uint32_t val; |
||
1866 | unsigned int dpll; |
||
1867 | const struct skl_dpll_regs *regs = skl_dpll_regs; |
||
1868 | |||
1869 | if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS)) |
||
1870 | return false; |
||
1871 | |||
1872 | /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ |
||
1873 | dpll = pll->id + 1; |
||
1874 | |||
1875 | val = I915_READ(regs[pll->id].ctl); |
||
1876 | if (!(val & LCPLL_PLL_ENABLE)) |
||
1877 | return false; |
||
1878 | |||
1879 | val = I915_READ(DPLL_CTRL1); |
||
1880 | hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f; |
||
1881 | |||
1882 | /* avoid reading back stale values if HDMI mode is not enabled */ |
||
1883 | if (val & DPLL_CTRL1_HDMI_MODE(dpll)) { |
||
1884 | hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); |
||
1885 | hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); |
||
1886 | } |
||
1887 | |||
1888 | return true; |
||
1889 | } |
||
1890 | |||
1891 | static void skl_shared_dplls_init(struct drm_i915_private *dev_priv) |
||
1892 | { |
||
1893 | int i; |
||
1894 | |||
1895 | dev_priv->num_shared_dpll = 3; |
||
1896 | |||
1897 | for (i = 0; i < dev_priv->num_shared_dpll; i++) { |
||
1898 | dev_priv->shared_dplls[i].id = i; |
||
1899 | dev_priv->shared_dplls[i].name = skl_ddi_pll_names[i]; |
||
1900 | dev_priv->shared_dplls[i].disable = skl_ddi_pll_disable; |
||
1901 | dev_priv->shared_dplls[i].enable = skl_ddi_pll_enable; |
||
1902 | dev_priv->shared_dplls[i].get_hw_state = |
||
1903 | skl_ddi_pll_get_hw_state; |
||
1904 | } |
||
1905 | } |
||
1906 | |||
1907 | void intel_ddi_pll_init(struct drm_device *dev) |
||
1908 | { |
||
1909 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
1910 | uint32_t val = I915_READ(LCPLL_CTL); |
||
1911 | |||
1912 | if (IS_SKYLAKE(dev)) |
||
1913 | skl_shared_dplls_init(dev_priv); |
||
1914 | else |
||
1915 | hsw_shared_dplls_init(dev_priv); |
||
1916 | |||
4104 | Serge | 1917 | DRM_DEBUG_KMS("CDCLK running at %dKHz\n", |
3243 | Serge | 1918 | intel_ddi_get_cdclk_freq(dev_priv)); |
1919 | |||
5354 | serge | 1920 | if (IS_SKYLAKE(dev)) { |
1921 | if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) |
||
1922 | DRM_ERROR("LCPLL1 is disabled\n"); |
||
1923 | } else { |
||
1924 | /* |
||
1925 | * The LCPLL register should be turned on by the BIOS. For now |
||
1926 | * let's just check its state and print errors in case |
||
1927 | * something is wrong. Don't even try to turn it on. |
||
1928 | */ |
||
1929 | |||
3243 | Serge | 1930 | if (val & LCPLL_CD_SOURCE_FCLK) |
1931 | DRM_ERROR("CDCLK source is not LCPLL\n"); |
||
1932 | |||
1933 | if (val & LCPLL_PLL_DISABLE) |
||
1934 | DRM_ERROR("LCPLL is disabled\n"); |
||
5354 | serge | 1935 | } |
3243 | Serge | 1936 | } |
1937 | |||
1938 | void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder) |
||
1939 | { |
||
1940 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
||
1941 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
||
1942 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
||
1943 | enum port port = intel_dig_port->port; |
||
1944 | uint32_t val; |
||
3480 | Serge | 1945 | bool wait = false; |
3243 | Serge | 1946 | |
1947 | if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) { |
||
1948 | val = I915_READ(DDI_BUF_CTL(port)); |
||
1949 | if (val & DDI_BUF_CTL_ENABLE) { |
||
1950 | val &= ~DDI_BUF_CTL_ENABLE; |
||
1951 | I915_WRITE(DDI_BUF_CTL(port), val); |
||
1952 | wait = true; |
||
1953 | } |
||
1954 | |||
1955 | val = I915_READ(DP_TP_CTL(port)); |
||
1956 | val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); |
||
1957 | val |= DP_TP_CTL_LINK_TRAIN_PAT1; |
||
1958 | I915_WRITE(DP_TP_CTL(port), val); |
||
1959 | POSTING_READ(DP_TP_CTL(port)); |
||
1960 | |||
1961 | if (wait) |
||
1962 | intel_wait_ddi_buf_idle(dev_priv, port); |
||
1963 | } |
||
1964 | |||
5060 | serge | 1965 | val = DP_TP_CTL_ENABLE | |
3243 | Serge | 1966 | DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; |
5060 | serge | 1967 | if (intel_dp->is_mst) |
1968 | val |= DP_TP_CTL_MODE_MST; |
||
1969 | else { |
||
1970 | val |= DP_TP_CTL_MODE_SST; |
||
4560 | Serge | 1971 | if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) |
3243 | Serge | 1972 | val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; |
5060 | serge | 1973 | } |
3243 | Serge | 1974 | I915_WRITE(DP_TP_CTL(port), val); |
1975 | POSTING_READ(DP_TP_CTL(port)); |
||
1976 | |||
1977 | intel_dp->DP |= DDI_BUF_CTL_ENABLE; |
||
1978 | I915_WRITE(DDI_BUF_CTL(port), intel_dp->DP); |
||
1979 | POSTING_READ(DDI_BUF_CTL(port)); |
||
1980 | |||
1981 | udelay(600); |
||
1982 | } |
||
1983 | |||
1984 | void intel_ddi_fdi_disable(struct drm_crtc *crtc) |
||
1985 | { |
||
1986 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
1987 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
1988 | uint32_t val; |
||
1989 | |||
1990 | intel_ddi_post_disable(intel_encoder); |
||
1991 | |||
1992 | val = I915_READ(_FDI_RXA_CTL); |
||
1993 | val &= ~FDI_RX_ENABLE; |
||
1994 | I915_WRITE(_FDI_RXA_CTL, val); |
||
1995 | |||
1996 | val = I915_READ(_FDI_RXA_MISC); |
||
1997 | val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); |
||
1998 | val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); |
||
1999 | I915_WRITE(_FDI_RXA_MISC, val); |
||
2000 | |||
2001 | val = I915_READ(_FDI_RXA_CTL); |
||
2002 | val &= ~FDI_PCDCLK; |
||
2003 | I915_WRITE(_FDI_RXA_CTL, val); |
||
2004 | |||
2005 | val = I915_READ(_FDI_RXA_CTL); |
||
2006 | val &= ~FDI_RX_PLL_ENABLE; |
||
2007 | I915_WRITE(_FDI_RXA_CTL, val); |
||
2008 | } |
||
2009 | |||
2010 | static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) |
||
2011 | { |
||
5060 | serge | 2012 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(&intel_encoder->base); |
2013 | int type = intel_dig_port->base.type; |
||
3243 | Serge | 2014 | |
5060 | serge | 2015 | if (type != INTEL_OUTPUT_DISPLAYPORT && |
2016 | type != INTEL_OUTPUT_EDP && |
||
2017 | type != INTEL_OUTPUT_UNKNOWN) { |
||
2018 | return; |
||
2019 | } |
||
2020 | |||
2021 | intel_dp_hot_plug(intel_encoder); |
||
3243 | Serge | 2022 | } |
2023 | |||
4280 | Serge | 2024 | void intel_ddi_get_config(struct intel_encoder *encoder, |
4104 | Serge | 2025 | struct intel_crtc_config *pipe_config) |
2026 | { |
||
2027 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
||
2028 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
||
2029 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
||
5354 | serge | 2030 | struct intel_hdmi *intel_hdmi; |
4104 | Serge | 2031 | u32 temp, flags = 0; |
5354 | serge | 2032 | struct drm_device *dev = dev_priv->dev; |
4104 | Serge | 2033 | |
2034 | temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
||
2035 | if (temp & TRANS_DDI_PHSYNC) |
||
2036 | flags |= DRM_MODE_FLAG_PHSYNC; |
||
2037 | else |
||
2038 | flags |= DRM_MODE_FLAG_NHSYNC; |
||
2039 | if (temp & TRANS_DDI_PVSYNC) |
||
2040 | flags |= DRM_MODE_FLAG_PVSYNC; |
||
2041 | else |
||
2042 | flags |= DRM_MODE_FLAG_NVSYNC; |
||
2043 | |||
2044 | pipe_config->adjusted_mode.flags |= flags; |
||
4280 | Serge | 2045 | |
2046 | switch (temp & TRANS_DDI_BPC_MASK) { |
||
2047 | case TRANS_DDI_BPC_6: |
||
2048 | pipe_config->pipe_bpp = 18; |
||
2049 | break; |
||
2050 | case TRANS_DDI_BPC_8: |
||
2051 | pipe_config->pipe_bpp = 24; |
||
2052 | break; |
||
2053 | case TRANS_DDI_BPC_10: |
||
2054 | pipe_config->pipe_bpp = 30; |
||
2055 | break; |
||
2056 | case TRANS_DDI_BPC_12: |
||
2057 | pipe_config->pipe_bpp = 36; |
||
2058 | break; |
||
2059 | default: |
||
2060 | break; |
||
2061 | } |
||
4371 | Serge | 2062 | |
4560 | Serge | 2063 | switch (temp & TRANS_DDI_MODE_SELECT_MASK) { |
2064 | case TRANS_DDI_MODE_SELECT_HDMI: |
||
5060 | serge | 2065 | pipe_config->has_hdmi_sink = true; |
5354 | serge | 2066 | intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
2067 | |||
2068 | if (intel_hdmi->infoframe_enabled(&encoder->base)) |
||
2069 | pipe_config->has_infoframe = true; |
||
2070 | break; |
||
4560 | Serge | 2071 | case TRANS_DDI_MODE_SELECT_DVI: |
2072 | case TRANS_DDI_MODE_SELECT_FDI: |
||
2073 | break; |
||
2074 | case TRANS_DDI_MODE_SELECT_DP_SST: |
||
2075 | case TRANS_DDI_MODE_SELECT_DP_MST: |
||
2076 | pipe_config->has_dp_encoder = true; |
||
2077 | intel_dp_get_m_n(intel_crtc, pipe_config); |
||
2078 | break; |
||
2079 | default: |
||
2080 | break; |
||
2081 | } |
||
2082 | |||
5354 | serge | 2083 | if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { |
5060 | serge | 2084 | temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); |
5354 | serge | 2085 | if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) |
5060 | serge | 2086 | pipe_config->has_audio = true; |
2087 | } |
||
2088 | |||
4371 | Serge | 2089 | if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp && |
2090 | pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { |
||
2091 | /* |
||
2092 | * This is a big fat ugly hack. |
||
2093 | * |
||
2094 | * Some machines in UEFI boot mode provide us a VBT that has 18 |
||
2095 | * bpp and 1.62 GHz link bandwidth for eDP, which for reasons |
||
2096 | * unknown we fail to light up. Yet the same BIOS boots up with |
||
2097 | * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as |
||
2098 | * max, not what it tells us to use. |
||
2099 | * |
||
2100 | * Note: This will still be broken if the eDP panel is not lit |
||
2101 | * up by the BIOS, and thus we can't get the mode at module |
||
2102 | * load. |
||
2103 | */ |
||
2104 | DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", |
||
2105 | pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp); |
||
2106 | dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; |
||
2107 | } |
||
5060 | serge | 2108 | |
5354 | serge | 2109 | if (INTEL_INFO(dev)->gen <= 8) |
2110 | hsw_ddi_clock_get(encoder, pipe_config); |
||
2111 | else |
||
2112 | skl_ddi_clock_get(encoder, pipe_config); |
||
4104 | Serge | 2113 | } |
2114 | |||
3243 | Serge | 2115 | static void intel_ddi_destroy(struct drm_encoder *encoder) |
2116 | { |
||
2117 | /* HDMI has nothing special to destroy, so we can go with this. */ |
||
2118 | intel_dp_encoder_destroy(encoder); |
||
2119 | } |
||
2120 | |||
3746 | Serge | 2121 | static bool intel_ddi_compute_config(struct intel_encoder *encoder, |
2122 | struct intel_crtc_config *pipe_config) |
||
3243 | Serge | 2123 | { |
3746 | Serge | 2124 | int type = encoder->type; |
4104 | Serge | 2125 | int port = intel_ddi_get_encoder_port(encoder); |
3243 | Serge | 2126 | |
3746 | Serge | 2127 | WARN(type == INTEL_OUTPUT_UNKNOWN, "compute_config() on unknown output!\n"); |
3243 | Serge | 2128 | |
4104 | Serge | 2129 | if (port == PORT_A) |
2130 | pipe_config->cpu_transcoder = TRANSCODER_EDP; |
||
2131 | |||
3243 | Serge | 2132 | if (type == INTEL_OUTPUT_HDMI) |
3746 | Serge | 2133 | return intel_hdmi_compute_config(encoder, pipe_config); |
3243 | Serge | 2134 | else |
3746 | Serge | 2135 | return intel_dp_compute_config(encoder, pipe_config); |
3243 | Serge | 2136 | } |
2137 | |||
2138 | static const struct drm_encoder_funcs intel_ddi_funcs = { |
||
2139 | .destroy = intel_ddi_destroy, |
||
2140 | }; |
||
2141 | |||
4560 | Serge | 2142 | static struct intel_connector * |
2143 | intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port) |
||
2144 | { |
||
2145 | struct intel_connector *connector; |
||
2146 | enum port port = intel_dig_port->port; |
||
2147 | |||
2148 | connector = kzalloc(sizeof(*connector), GFP_KERNEL); |
||
2149 | if (!connector) |
||
2150 | return NULL; |
||
2151 | |||
2152 | intel_dig_port->dp.output_reg = DDI_BUF_CTL(port); |
||
2153 | if (!intel_dp_init_connector(intel_dig_port, connector)) { |
||
2154 | kfree(connector); |
||
2155 | return NULL; |
||
2156 | } |
||
2157 | |||
2158 | return connector; |
||
2159 | } |
||
2160 | |||
2161 | static struct intel_connector * |
||
2162 | intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) |
||
2163 | { |
||
2164 | struct intel_connector *connector; |
||
2165 | enum port port = intel_dig_port->port; |
||
2166 | |||
2167 | connector = kzalloc(sizeof(*connector), GFP_KERNEL); |
||
2168 | if (!connector) |
||
2169 | return NULL; |
||
2170 | |||
2171 | intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); |
||
2172 | intel_hdmi_init_connector(intel_dig_port, connector); |
||
2173 | |||
2174 | return connector; |
||
2175 | } |
||
2176 | |||
3243 | Serge | 2177 | void intel_ddi_init(struct drm_device *dev, enum port port) |
2178 | { |
||
3480 | Serge | 2179 | struct drm_i915_private *dev_priv = dev->dev_private; |
3243 | Serge | 2180 | struct intel_digital_port *intel_dig_port; |
2181 | struct intel_encoder *intel_encoder; |
||
2182 | struct drm_encoder *encoder; |
||
4560 | Serge | 2183 | bool init_hdmi, init_dp; |
3243 | Serge | 2184 | |
4560 | Serge | 2185 | init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || |
2186 | dev_priv->vbt.ddi_port_info[port].supports_hdmi); |
||
2187 | init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp; |
||
2188 | if (!init_dp && !init_hdmi) { |
||
5060 | serge | 2189 | DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, assuming it is\n", |
4560 | Serge | 2190 | port_name(port)); |
2191 | init_hdmi = true; |
||
2192 | init_dp = true; |
||
2193 | } |
||
2194 | |||
2195 | intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); |
||
3243 | Serge | 2196 | if (!intel_dig_port) |
2197 | return; |
||
2198 | |||
2199 | intel_encoder = &intel_dig_port->base; |
||
2200 | encoder = &intel_encoder->base; |
||
2201 | |||
2202 | drm_encoder_init(dev, encoder, &intel_ddi_funcs, |
||
2203 | DRM_MODE_ENCODER_TMDS); |
||
2204 | |||
3746 | Serge | 2205 | intel_encoder->compute_config = intel_ddi_compute_config; |
3243 | Serge | 2206 | intel_encoder->enable = intel_enable_ddi; |
2207 | intel_encoder->pre_enable = intel_ddi_pre_enable; |
||
2208 | intel_encoder->disable = intel_disable_ddi; |
||
2209 | intel_encoder->post_disable = intel_ddi_post_disable; |
||
2210 | intel_encoder->get_hw_state = intel_ddi_get_hw_state; |
||
4104 | Serge | 2211 | intel_encoder->get_config = intel_ddi_get_config; |
3243 | Serge | 2212 | |
2213 | intel_dig_port->port = port; |
||
4104 | Serge | 2214 | intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & |
2215 | (DDI_BUF_PORT_REVERSAL | |
||
2216 | DDI_A_4_LANES); |
||
3243 | Serge | 2217 | |
2218 | intel_encoder->type = INTEL_OUTPUT_UNKNOWN; |
||
2219 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
||
5060 | serge | 2220 | intel_encoder->cloneable = 0; |
3243 | Serge | 2221 | intel_encoder->hot_plug = intel_ddi_hot_plug; |
2222 | |||
5060 | serge | 2223 | if (init_dp) { |
2224 | if (!intel_ddi_init_dp_connector(intel_dig_port)) |
||
2225 | goto err; |
||
4560 | Serge | 2226 | |
5060 | serge | 2227 | intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; |
2228 | dev_priv->hpd_irq_port[port] = intel_dig_port; |
||
2229 | } |
||
2230 | |||
4560 | Serge | 2231 | /* In theory we don't need the encoder->type check, but leave it just in |
2232 | * case we have some really bad VBTs... */ |
||
5060 | serge | 2233 | if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) { |
2234 | if (!intel_ddi_init_hdmi_connector(intel_dig_port)) |
||
2235 | goto err; |
||
2236 | } |
||
4560 | Serge | 2237 | |
5060 | serge | 2238 | return; |
2239 | |||
2240 | err: |
||
4104 | Serge | 2241 | drm_encoder_cleanup(encoder); |
2242 | kfree(intel_dig_port); |
||
3243 | Serge | 2243 | }><>><>><>=>>><>>>><>=>><> |