Rev 3031 | Rev 3480 | 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 | |||
31 | /* HDMI/DVI modes ignore everything but the last 2 items. So we share |
||
32 | * them for both DP and FDI transports, allowing those ports to |
||
33 | * automatically adapt to HDMI connections as well |
||
34 | */ |
||
35 | static const u32 hsw_ddi_translations_dp[] = { |
||
36 | 0x00FFFFFF, 0x0006000E, /* DP parameters */ |
||
37 | 0x00D75FFF, 0x0005000A, |
||
38 | 0x00C30FFF, 0x00040006, |
||
39 | 0x80AAAFFF, 0x000B0000, |
||
40 | 0x00FFFFFF, 0x0005000A, |
||
41 | 0x00D75FFF, 0x000C0004, |
||
42 | 0x80C30FFF, 0x000B0000, |
||
43 | 0x00FFFFFF, 0x00040006, |
||
44 | 0x80D75FFF, 0x000B0000, |
||
45 | 0x00FFFFFF, 0x00040006 /* HDMI parameters */ |
||
46 | }; |
||
47 | |||
48 | static const u32 hsw_ddi_translations_fdi[] = { |
||
49 | 0x00FFFFFF, 0x0007000E, /* FDI parameters */ |
||
50 | 0x00D75FFF, 0x000F000A, |
||
51 | 0x00C30FFF, 0x00060006, |
||
52 | 0x00AAAFFF, 0x001E0000, |
||
53 | 0x00FFFFFF, 0x000F000A, |
||
54 | 0x00D75FFF, 0x00160004, |
||
55 | 0x00C30FFF, 0x001E0000, |
||
56 | 0x00FFFFFF, 0x00060006, |
||
57 | 0x00D75FFF, 0x001E0000, |
||
58 | 0x00FFFFFF, 0x00040006 /* HDMI parameters */ |
||
59 | }; |
||
60 | |||
3243 | Serge | 61 | static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder) |
62 | { |
||
63 | struct drm_encoder *encoder = &intel_encoder->base; |
||
64 | int type = intel_encoder->type; |
||
65 | |||
66 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || |
||
67 | type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) { |
||
68 | struct intel_digital_port *intel_dig_port = |
||
69 | enc_to_dig_port(encoder); |
||
70 | return intel_dig_port->port; |
||
71 | |||
72 | } else if (type == INTEL_OUTPUT_ANALOG) { |
||
73 | return PORT_E; |
||
74 | |||
75 | } else { |
||
76 | DRM_ERROR("Invalid DDI encoder type %d\n", type); |
||
77 | BUG(); |
||
78 | } |
||
79 | } |
||
80 | |||
3031 | serge | 81 | /* On Haswell, DDI port buffers must be programmed with correct values |
82 | * in advance. The buffer values are different for FDI and DP modes, |
||
83 | * but the HDMI/DVI fields are shared among those. So we program the DDI |
||
84 | * in either FDI or DP modes only, as HDMI connections will work with both |
||
85 | * of those |
||
86 | */ |
||
87 | void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool use_fdi_mode) |
||
88 | { |
||
89 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
90 | u32 reg; |
||
91 | int i; |
||
92 | const u32 *ddi_translations = ((use_fdi_mode) ? |
||
93 | hsw_ddi_translations_fdi : |
||
94 | hsw_ddi_translations_dp); |
||
95 | |||
96 | DRM_DEBUG_DRIVER("Initializing DDI buffers for port %c in %s mode\n", |
||
97 | port_name(port), |
||
98 | use_fdi_mode ? "FDI" : "DP"); |
||
99 | |||
100 | WARN((use_fdi_mode && (port != PORT_E)), |
||
101 | "Programming port %c in FDI mode, this probably will not work.\n", |
||
102 | port_name(port)); |
||
103 | |||
104 | for (i=0, reg=DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { |
||
105 | I915_WRITE(reg, ddi_translations[i]); |
||
106 | reg += 4; |
||
107 | } |
||
108 | } |
||
109 | |||
110 | /* Program DDI buffers translations for DP. By default, program ports A-D in DP |
||
111 | * mode and port E for FDI. |
||
112 | */ |
||
113 | void intel_prepare_ddi(struct drm_device *dev) |
||
114 | { |
||
115 | int port; |
||
116 | |||
117 | if (IS_HASWELL(dev)) { |
||
118 | for (port = PORT_A; port < PORT_E; port++) |
||
119 | intel_prepare_ddi_buffers(dev, port, false); |
||
120 | |||
121 | /* DDI E is the suggested one to work in FDI mode, so program is as such by |
||
122 | * default. It will have to be re-programmed in case a digital DP output |
||
123 | * will be detected on it |
||
124 | */ |
||
125 | intel_prepare_ddi_buffers(dev, PORT_E, true); |
||
126 | } |
||
127 | } |
||
128 | |||
129 | static const long hsw_ddi_buf_ctl_values[] = { |
||
130 | DDI_BUF_EMP_400MV_0DB_HSW, |
||
131 | DDI_BUF_EMP_400MV_3_5DB_HSW, |
||
132 | DDI_BUF_EMP_400MV_6DB_HSW, |
||
133 | DDI_BUF_EMP_400MV_9_5DB_HSW, |
||
134 | DDI_BUF_EMP_600MV_0DB_HSW, |
||
135 | DDI_BUF_EMP_600MV_3_5DB_HSW, |
||
136 | DDI_BUF_EMP_600MV_6DB_HSW, |
||
137 | DDI_BUF_EMP_800MV_0DB_HSW, |
||
138 | DDI_BUF_EMP_800MV_3_5DB_HSW |
||
139 | }; |
||
140 | |||
3243 | Serge | 141 | static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, |
142 | enum port port) |
||
143 | { |
||
144 | uint32_t reg = DDI_BUF_CTL(port); |
||
145 | int i; |
||
3031 | serge | 146 | |
3243 | Serge | 147 | for (i = 0; i < 8; i++) { |
148 | udelay(1); |
||
149 | if (I915_READ(reg) & DDI_BUF_IS_IDLE) |
||
150 | return; |
||
151 | } |
||
152 | DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port)); |
||
153 | } |
||
154 | |||
3031 | serge | 155 | /* Starting with Haswell, different DDI ports can work in FDI mode for |
156 | * connection to the PCH-located connectors. For this, it is necessary to train |
||
157 | * both the DDI port and PCH receiver for the desired DDI buffer settings. |
||
158 | * |
||
159 | * The recommended port to work in FDI mode is DDI E, which we use here. Also, |
||
160 | * please note that when FDI mode is active on DDI E, it shares 2 lines with |
||
161 | * DDI A (which is used for eDP) |
||
162 | */ |
||
163 | |||
164 | void hsw_fdi_link_train(struct drm_crtc *crtc) |
||
165 | { |
||
166 | struct drm_device *dev = crtc->dev; |
||
167 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
168 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
3243 | Serge | 169 | u32 temp, i, rx_ctl_val; |
3031 | serge | 170 | |
3243 | Serge | 171 | /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the |
172 | * mode set "sequence for CRT port" document: |
||
173 | * - TP1 to TP2 time with the default value |
||
174 | * - FDI delay to 90h |
||
175 | */ |
||
176 | I915_WRITE(_FDI_RXA_MISC, FDI_RX_PWRDN_LANE1_VAL(2) | |
||
177 | FDI_RX_PWRDN_LANE0_VAL(2) | |
||
178 | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90); |
||
3031 | serge | 179 | |
3243 | Serge | 180 | /* Enable the PCH Receiver FDI PLL */ |
181 | rx_ctl_val = FDI_RX_PLL_ENABLE | FDI_RX_ENHANCE_FRAME_ENABLE | |
||
182 | ((intel_crtc->fdi_lanes - 1) << 19); |
||
183 | if (dev_priv->fdi_rx_polarity_reversed) |
||
184 | rx_ctl_val |= FDI_RX_POLARITY_REVERSED_LPT; |
||
185 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
186 | POSTING_READ(_FDI_RXA_CTL); |
||
187 | udelay(220); |
||
3031 | serge | 188 | |
3243 | Serge | 189 | /* Switch from Rawclk to PCDclk */ |
190 | rx_ctl_val |= FDI_PCDCLK; |
||
191 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
3031 | serge | 192 | |
3243 | Serge | 193 | /* Configure Port Clock Select */ |
194 | I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->ddi_pll_sel); |
||
195 | |||
196 | /* Start the training iterating through available voltages and emphasis, |
||
197 | * testing each value twice. */ |
||
198 | for (i = 0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values) * 2; i++) { |
||
3031 | serge | 199 | /* Configure DP_TP_CTL with auto-training */ |
200 | I915_WRITE(DP_TP_CTL(PORT_E), |
||
201 | DP_TP_CTL_FDI_AUTOTRAIN | |
||
202 | DP_TP_CTL_ENHANCED_FRAME_ENABLE | |
||
203 | DP_TP_CTL_LINK_TRAIN_PAT1 | |
||
204 | DP_TP_CTL_ENABLE); |
||
205 | |||
206 | /* Configure and enable DDI_BUF_CTL for DDI E with next voltage */ |
||
207 | I915_WRITE(DDI_BUF_CTL(PORT_E), |
||
208 | DDI_BUF_CTL_ENABLE | |
||
3243 | Serge | 209 | ((intel_crtc->fdi_lanes - 1) << 1) | |
210 | hsw_ddi_buf_ctl_values[i / 2]); |
||
211 | POSTING_READ(DDI_BUF_CTL(PORT_E)); |
||
3031 | serge | 212 | |
213 | udelay(600); |
||
214 | |||
3243 | Serge | 215 | /* Program PCH FDI Receiver TU */ |
216 | I915_WRITE(_FDI_RXA_TUSIZE1, TU_SIZE(64)); |
||
3031 | serge | 217 | |
3243 | Serge | 218 | /* Enable PCH FDI Receiver with auto-training */ |
219 | rx_ctl_val |= FDI_RX_ENABLE | FDI_LINK_TRAIN_AUTO; |
||
220 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
221 | POSTING_READ(_FDI_RXA_CTL); |
||
3031 | serge | 222 | |
3243 | Serge | 223 | /* Wait for FDI receiver lane calibration */ |
224 | udelay(30); |
||
225 | |||
226 | /* Unset FDI_RX_MISC pwrdn lanes */ |
||
227 | temp = I915_READ(_FDI_RXA_MISC); |
||
228 | temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); |
||
229 | I915_WRITE(_FDI_RXA_MISC, temp); |
||
230 | POSTING_READ(_FDI_RXA_MISC); |
||
231 | |||
232 | /* Wait for FDI auto training time */ |
||
233 | udelay(5); |
||
234 | |||
3031 | serge | 235 | temp = I915_READ(DP_TP_STATUS(PORT_E)); |
236 | if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) { |
||
3243 | Serge | 237 | DRM_DEBUG_KMS("FDI link training done on step %d\n", i); |
3031 | serge | 238 | |
239 | /* Enable normal pixel sending for FDI */ |
||
240 | I915_WRITE(DP_TP_CTL(PORT_E), |
||
241 | DP_TP_CTL_FDI_AUTOTRAIN | |
||
242 | DP_TP_CTL_LINK_TRAIN_NORMAL | |
||
243 | DP_TP_CTL_ENHANCED_FRAME_ENABLE | |
||
244 | DP_TP_CTL_ENABLE); |
||
245 | |||
3243 | Serge | 246 | return; |
3031 | serge | 247 | } |
248 | |||
3243 | Serge | 249 | temp = I915_READ(DDI_BUF_CTL(PORT_E)); |
250 | temp &= ~DDI_BUF_CTL_ENABLE; |
||
251 | I915_WRITE(DDI_BUF_CTL(PORT_E), temp); |
||
252 | POSTING_READ(DDI_BUF_CTL(PORT_E)); |
||
3031 | serge | 253 | |
3243 | Serge | 254 | /* Disable DP_TP_CTL and FDI_RX_CTL and retry */ |
255 | temp = I915_READ(DP_TP_CTL(PORT_E)); |
||
256 | temp &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); |
||
257 | temp |= DP_TP_CTL_LINK_TRAIN_PAT1; |
||
258 | I915_WRITE(DP_TP_CTL(PORT_E), temp); |
||
259 | POSTING_READ(DP_TP_CTL(PORT_E)); |
||
3031 | serge | 260 | |
3243 | Serge | 261 | intel_wait_ddi_buf_idle(dev_priv, PORT_E); |
262 | |||
263 | rx_ctl_val &= ~FDI_RX_ENABLE; |
||
264 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
265 | POSTING_READ(_FDI_RXA_CTL); |
||
266 | |||
267 | /* Reset FDI_RX_MISC pwrdn lanes */ |
||
268 | temp = I915_READ(_FDI_RXA_MISC); |
||
269 | temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); |
||
270 | temp |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); |
||
271 | I915_WRITE(_FDI_RXA_MISC, temp); |
||
272 | POSTING_READ(_FDI_RXA_MISC); |
||
3031 | serge | 273 | } |
3243 | Serge | 274 | |
275 | DRM_ERROR("FDI link training failed!\n"); |
||
3031 | serge | 276 | } |
277 | |||
278 | /* WRPLL clock dividers */ |
||
279 | struct wrpll_tmds_clock { |
||
280 | u32 clock; |
||
281 | u16 p; /* Post divider */ |
||
282 | u16 n2; /* Feedback divider */ |
||
283 | u16 r2; /* Reference divider */ |
||
284 | }; |
||
285 | |||
286 | /* Table of matching values for WRPLL clocks programming for each frequency. |
||
287 | * The code assumes this table is sorted. */ |
||
288 | static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = { |
||
289 | {19750, 38, 25, 18}, |
||
290 | {20000, 48, 32, 18}, |
||
291 | {21000, 36, 21, 15}, |
||
292 | {21912, 42, 29, 17}, |
||
293 | {22000, 36, 22, 15}, |
||
294 | {23000, 36, 23, 15}, |
||
295 | {23500, 40, 40, 23}, |
||
296 | {23750, 26, 16, 14}, |
||
297 | {24000, 36, 24, 15}, |
||
298 | {25000, 36, 25, 15}, |
||
299 | {25175, 26, 40, 33}, |
||
300 | {25200, 30, 21, 15}, |
||
301 | {26000, 36, 26, 15}, |
||
302 | {27000, 30, 21, 14}, |
||
303 | {27027, 18, 100, 111}, |
||
304 | {27500, 30, 29, 19}, |
||
305 | {28000, 34, 30, 17}, |
||
306 | {28320, 26, 30, 22}, |
||
307 | {28322, 32, 42, 25}, |
||
308 | {28750, 24, 23, 18}, |
||
309 | {29000, 30, 29, 18}, |
||
310 | {29750, 32, 30, 17}, |
||
311 | {30000, 30, 25, 15}, |
||
312 | {30750, 30, 41, 24}, |
||
313 | {31000, 30, 31, 18}, |
||
314 | {31500, 30, 28, 16}, |
||
315 | {32000, 30, 32, 18}, |
||
316 | {32500, 28, 32, 19}, |
||
317 | {33000, 24, 22, 15}, |
||
318 | {34000, 28, 30, 17}, |
||
319 | {35000, 26, 32, 19}, |
||
320 | {35500, 24, 30, 19}, |
||
321 | {36000, 26, 26, 15}, |
||
322 | {36750, 26, 46, 26}, |
||
323 | {37000, 24, 23, 14}, |
||
324 | {37762, 22, 40, 26}, |
||
325 | {37800, 20, 21, 15}, |
||
326 | {38000, 24, 27, 16}, |
||
327 | {38250, 24, 34, 20}, |
||
328 | {39000, 24, 26, 15}, |
||
329 | {40000, 24, 32, 18}, |
||
330 | {40500, 20, 21, 14}, |
||
331 | {40541, 22, 147, 89}, |
||
332 | {40750, 18, 19, 14}, |
||
333 | {41000, 16, 17, 14}, |
||
334 | {41500, 22, 44, 26}, |
||
335 | {41540, 22, 44, 26}, |
||
336 | {42000, 18, 21, 15}, |
||
337 | {42500, 22, 45, 26}, |
||
338 | {43000, 20, 43, 27}, |
||
339 | {43163, 20, 24, 15}, |
||
340 | {44000, 18, 22, 15}, |
||
341 | {44900, 20, 108, 65}, |
||
342 | {45000, 20, 25, 15}, |
||
343 | {45250, 20, 52, 31}, |
||
344 | {46000, 18, 23, 15}, |
||
345 | {46750, 20, 45, 26}, |
||
346 | {47000, 20, 40, 23}, |
||
347 | {48000, 18, 24, 15}, |
||
348 | {49000, 18, 49, 30}, |
||
349 | {49500, 16, 22, 15}, |
||
350 | {50000, 18, 25, 15}, |
||
351 | {50500, 18, 32, 19}, |
||
352 | {51000, 18, 34, 20}, |
||
353 | {52000, 18, 26, 15}, |
||
354 | {52406, 14, 34, 25}, |
||
355 | {53000, 16, 22, 14}, |
||
356 | {54000, 16, 24, 15}, |
||
357 | {54054, 16, 173, 108}, |
||
358 | {54500, 14, 24, 17}, |
||
359 | {55000, 12, 22, 18}, |
||
360 | {56000, 14, 45, 31}, |
||
361 | {56250, 16, 25, 15}, |
||
362 | {56750, 14, 25, 17}, |
||
363 | {57000, 16, 27, 16}, |
||
364 | {58000, 16, 43, 25}, |
||
365 | {58250, 16, 38, 22}, |
||
366 | {58750, 16, 40, 23}, |
||
367 | {59000, 14, 26, 17}, |
||
368 | {59341, 14, 40, 26}, |
||
369 | {59400, 16, 44, 25}, |
||
370 | {60000, 16, 32, 18}, |
||
371 | {60500, 12, 39, 29}, |
||
372 | {61000, 14, 49, 31}, |
||
373 | {62000, 14, 37, 23}, |
||
374 | {62250, 14, 42, 26}, |
||
375 | {63000, 12, 21, 15}, |
||
376 | {63500, 14, 28, 17}, |
||
377 | {64000, 12, 27, 19}, |
||
378 | {65000, 14, 32, 19}, |
||
379 | {65250, 12, 29, 20}, |
||
380 | {65500, 12, 32, 22}, |
||
381 | {66000, 12, 22, 15}, |
||
382 | {66667, 14, 38, 22}, |
||
383 | {66750, 10, 21, 17}, |
||
384 | {67000, 14, 33, 19}, |
||
385 | {67750, 14, 58, 33}, |
||
386 | {68000, 14, 30, 17}, |
||
387 | {68179, 14, 46, 26}, |
||
388 | {68250, 14, 46, 26}, |
||
389 | {69000, 12, 23, 15}, |
||
390 | {70000, 12, 28, 18}, |
||
391 | {71000, 12, 30, 19}, |
||
392 | {72000, 12, 24, 15}, |
||
393 | {73000, 10, 23, 17}, |
||
394 | {74000, 12, 23, 14}, |
||
395 | {74176, 8, 100, 91}, |
||
396 | {74250, 10, 22, 16}, |
||
397 | {74481, 12, 43, 26}, |
||
398 | {74500, 10, 29, 21}, |
||
399 | {75000, 12, 25, 15}, |
||
400 | {75250, 10, 39, 28}, |
||
401 | {76000, 12, 27, 16}, |
||
402 | {77000, 12, 53, 31}, |
||
403 | {78000, 12, 26, 15}, |
||
404 | {78750, 12, 28, 16}, |
||
405 | {79000, 10, 38, 26}, |
||
406 | {79500, 10, 28, 19}, |
||
407 | {80000, 12, 32, 18}, |
||
408 | {81000, 10, 21, 14}, |
||
409 | {81081, 6, 100, 111}, |
||
410 | {81624, 8, 29, 24}, |
||
411 | {82000, 8, 17, 14}, |
||
412 | {83000, 10, 40, 26}, |
||
413 | {83950, 10, 28, 18}, |
||
414 | {84000, 10, 28, 18}, |
||
415 | {84750, 6, 16, 17}, |
||
416 | {85000, 6, 17, 18}, |
||
417 | {85250, 10, 30, 19}, |
||
418 | {85750, 10, 27, 17}, |
||
419 | {86000, 10, 43, 27}, |
||
420 | {87000, 10, 29, 18}, |
||
421 | {88000, 10, 44, 27}, |
||
422 | {88500, 10, 41, 25}, |
||
423 | {89000, 10, 28, 17}, |
||
424 | {89012, 6, 90, 91}, |
||
425 | {89100, 10, 33, 20}, |
||
426 | {90000, 10, 25, 15}, |
||
427 | {91000, 10, 32, 19}, |
||
428 | {92000, 10, 46, 27}, |
||
429 | {93000, 10, 31, 18}, |
||
430 | {94000, 10, 40, 23}, |
||
431 | {94500, 10, 28, 16}, |
||
432 | {95000, 10, 44, 25}, |
||
433 | {95654, 10, 39, 22}, |
||
434 | {95750, 10, 39, 22}, |
||
435 | {96000, 10, 32, 18}, |
||
436 | {97000, 8, 23, 16}, |
||
437 | {97750, 8, 42, 29}, |
||
438 | {98000, 8, 45, 31}, |
||
439 | {99000, 8, 22, 15}, |
||
440 | {99750, 8, 34, 23}, |
||
441 | {100000, 6, 20, 18}, |
||
442 | {100500, 6, 19, 17}, |
||
443 | {101000, 6, 37, 33}, |
||
444 | {101250, 8, 21, 14}, |
||
445 | {102000, 6, 17, 15}, |
||
446 | {102250, 6, 25, 22}, |
||
447 | {103000, 8, 29, 19}, |
||
448 | {104000, 8, 37, 24}, |
||
449 | {105000, 8, 28, 18}, |
||
450 | {106000, 8, 22, 14}, |
||
451 | {107000, 8, 46, 29}, |
||
452 | {107214, 8, 27, 17}, |
||
453 | {108000, 8, 24, 15}, |
||
454 | {108108, 8, 173, 108}, |
||
455 | {109000, 6, 23, 19}, |
||
456 | {110000, 6, 22, 18}, |
||
457 | {110013, 6, 22, 18}, |
||
458 | {110250, 8, 49, 30}, |
||
459 | {110500, 8, 36, 22}, |
||
460 | {111000, 8, 23, 14}, |
||
461 | {111264, 8, 150, 91}, |
||
462 | {111375, 8, 33, 20}, |
||
463 | {112000, 8, 63, 38}, |
||
464 | {112500, 8, 25, 15}, |
||
465 | {113100, 8, 57, 34}, |
||
466 | {113309, 8, 42, 25}, |
||
467 | {114000, 8, 27, 16}, |
||
468 | {115000, 6, 23, 18}, |
||
469 | {116000, 8, 43, 25}, |
||
470 | {117000, 8, 26, 15}, |
||
471 | {117500, 8, 40, 23}, |
||
472 | {118000, 6, 38, 29}, |
||
473 | {119000, 8, 30, 17}, |
||
474 | {119500, 8, 46, 26}, |
||
475 | {119651, 8, 39, 22}, |
||
476 | {120000, 8, 32, 18}, |
||
477 | {121000, 6, 39, 29}, |
||
478 | {121250, 6, 31, 23}, |
||
479 | {121750, 6, 23, 17}, |
||
480 | {122000, 6, 42, 31}, |
||
481 | {122614, 6, 30, 22}, |
||
482 | {123000, 6, 41, 30}, |
||
483 | {123379, 6, 37, 27}, |
||
484 | {124000, 6, 51, 37}, |
||
485 | {125000, 6, 25, 18}, |
||
486 | {125250, 4, 13, 14}, |
||
487 | {125750, 4, 27, 29}, |
||
488 | {126000, 6, 21, 15}, |
||
489 | {127000, 6, 24, 17}, |
||
490 | {127250, 6, 41, 29}, |
||
491 | {128000, 6, 27, 19}, |
||
492 | {129000, 6, 43, 30}, |
||
493 | {129859, 4, 25, 26}, |
||
494 | {130000, 6, 26, 18}, |
||
495 | {130250, 6, 42, 29}, |
||
496 | {131000, 6, 32, 22}, |
||
497 | {131500, 6, 38, 26}, |
||
498 | {131850, 6, 41, 28}, |
||
499 | {132000, 6, 22, 15}, |
||
500 | {132750, 6, 28, 19}, |
||
501 | {133000, 6, 34, 23}, |
||
502 | {133330, 6, 37, 25}, |
||
503 | {134000, 6, 61, 41}, |
||
504 | {135000, 6, 21, 14}, |
||
505 | {135250, 6, 167, 111}, |
||
506 | {136000, 6, 62, 41}, |
||
507 | {137000, 6, 35, 23}, |
||
508 | {138000, 6, 23, 15}, |
||
509 | {138500, 6, 40, 26}, |
||
510 | {138750, 6, 37, 24}, |
||
511 | {139000, 6, 34, 22}, |
||
512 | {139050, 6, 34, 22}, |
||
513 | {139054, 6, 34, 22}, |
||
514 | {140000, 6, 28, 18}, |
||
515 | {141000, 6, 36, 23}, |
||
516 | {141500, 6, 22, 14}, |
||
517 | {142000, 6, 30, 19}, |
||
518 | {143000, 6, 27, 17}, |
||
519 | {143472, 4, 17, 16}, |
||
520 | {144000, 6, 24, 15}, |
||
521 | {145000, 6, 29, 18}, |
||
522 | {146000, 6, 47, 29}, |
||
523 | {146250, 6, 26, 16}, |
||
524 | {147000, 6, 49, 30}, |
||
525 | {147891, 6, 23, 14}, |
||
526 | {148000, 6, 23, 14}, |
||
527 | {148250, 6, 28, 17}, |
||
528 | {148352, 4, 100, 91}, |
||
529 | {148500, 6, 33, 20}, |
||
530 | {149000, 6, 48, 29}, |
||
531 | {150000, 6, 25, 15}, |
||
532 | {151000, 4, 19, 17}, |
||
533 | {152000, 6, 27, 16}, |
||
534 | {152280, 6, 44, 26}, |
||
535 | {153000, 6, 34, 20}, |
||
536 | {154000, 6, 53, 31}, |
||
537 | {155000, 6, 31, 18}, |
||
538 | {155250, 6, 50, 29}, |
||
539 | {155750, 6, 45, 26}, |
||
540 | {156000, 6, 26, 15}, |
||
541 | {157000, 6, 61, 35}, |
||
542 | {157500, 6, 28, 16}, |
||
543 | {158000, 6, 65, 37}, |
||
544 | {158250, 6, 44, 25}, |
||
545 | {159000, 6, 53, 30}, |
||
546 | {159500, 6, 39, 22}, |
||
547 | {160000, 6, 32, 18}, |
||
548 | {161000, 4, 31, 26}, |
||
549 | {162000, 4, 18, 15}, |
||
550 | {162162, 4, 131, 109}, |
||
551 | {162500, 4, 53, 44}, |
||
552 | {163000, 4, 29, 24}, |
||
553 | {164000, 4, 17, 14}, |
||
554 | {165000, 4, 22, 18}, |
||
555 | {166000, 4, 32, 26}, |
||
556 | {167000, 4, 26, 21}, |
||
557 | {168000, 4, 46, 37}, |
||
558 | {169000, 4, 104, 83}, |
||
559 | {169128, 4, 64, 51}, |
||
560 | {169500, 4, 39, 31}, |
||
561 | {170000, 4, 34, 27}, |
||
562 | {171000, 4, 19, 15}, |
||
563 | {172000, 4, 51, 40}, |
||
564 | {172750, 4, 32, 25}, |
||
565 | {172800, 4, 32, 25}, |
||
566 | {173000, 4, 41, 32}, |
||
567 | {174000, 4, 49, 38}, |
||
568 | {174787, 4, 22, 17}, |
||
569 | {175000, 4, 35, 27}, |
||
570 | {176000, 4, 30, 23}, |
||
571 | {177000, 4, 38, 29}, |
||
572 | {178000, 4, 29, 22}, |
||
573 | {178500, 4, 37, 28}, |
||
574 | {179000, 4, 53, 40}, |
||
575 | {179500, 4, 73, 55}, |
||
576 | {180000, 4, 20, 15}, |
||
577 | {181000, 4, 55, 41}, |
||
578 | {182000, 4, 31, 23}, |
||
579 | {183000, 4, 42, 31}, |
||
580 | {184000, 4, 30, 22}, |
||
581 | {184750, 4, 26, 19}, |
||
582 | {185000, 4, 37, 27}, |
||
583 | {186000, 4, 51, 37}, |
||
584 | {187000, 4, 36, 26}, |
||
585 | {188000, 4, 32, 23}, |
||
586 | {189000, 4, 21, 15}, |
||
587 | {190000, 4, 38, 27}, |
||
588 | {190960, 4, 41, 29}, |
||
589 | {191000, 4, 41, 29}, |
||
590 | {192000, 4, 27, 19}, |
||
591 | {192250, 4, 37, 26}, |
||
592 | {193000, 4, 20, 14}, |
||
593 | {193250, 4, 53, 37}, |
||
594 | {194000, 4, 23, 16}, |
||
595 | {194208, 4, 23, 16}, |
||
596 | {195000, 4, 26, 18}, |
||
597 | {196000, 4, 45, 31}, |
||
598 | {197000, 4, 35, 24}, |
||
599 | {197750, 4, 41, 28}, |
||
600 | {198000, 4, 22, 15}, |
||
601 | {198500, 4, 25, 17}, |
||
602 | {199000, 4, 28, 19}, |
||
603 | {200000, 4, 37, 25}, |
||
604 | {201000, 4, 61, 41}, |
||
605 | {202000, 4, 112, 75}, |
||
606 | {202500, 4, 21, 14}, |
||
607 | {203000, 4, 146, 97}, |
||
608 | {204000, 4, 62, 41}, |
||
609 | {204750, 4, 44, 29}, |
||
610 | {205000, 4, 38, 25}, |
||
611 | {206000, 4, 29, 19}, |
||
612 | {207000, 4, 23, 15}, |
||
613 | {207500, 4, 40, 26}, |
||
614 | {208000, 4, 37, 24}, |
||
615 | {208900, 4, 48, 31}, |
||
616 | {209000, 4, 48, 31}, |
||
617 | {209250, 4, 31, 20}, |
||
618 | {210000, 4, 28, 18}, |
||
619 | {211000, 4, 25, 16}, |
||
620 | {212000, 4, 22, 14}, |
||
621 | {213000, 4, 30, 19}, |
||
622 | {213750, 4, 38, 24}, |
||
623 | {214000, 4, 46, 29}, |
||
624 | {214750, 4, 35, 22}, |
||
625 | {215000, 4, 43, 27}, |
||
626 | {216000, 4, 24, 15}, |
||
627 | {217000, 4, 37, 23}, |
||
628 | {218000, 4, 42, 26}, |
||
629 | {218250, 4, 42, 26}, |
||
630 | {218750, 4, 34, 21}, |
||
631 | {219000, 4, 47, 29}, |
||
632 | {220000, 4, 44, 27}, |
||
633 | {220640, 4, 49, 30}, |
||
634 | {220750, 4, 36, 22}, |
||
635 | {221000, 4, 36, 22}, |
||
636 | {222000, 4, 23, 14}, |
||
637 | {222525, 4, 28, 17}, |
||
638 | {222750, 4, 33, 20}, |
||
639 | {227000, 4, 37, 22}, |
||
640 | {230250, 4, 29, 17}, |
||
641 | {233500, 4, 38, 22}, |
||
642 | {235000, 4, 40, 23}, |
||
643 | {238000, 4, 30, 17}, |
||
644 | {241500, 2, 17, 19}, |
||
645 | {245250, 2, 20, 22}, |
||
646 | {247750, 2, 22, 24}, |
||
647 | {253250, 2, 15, 16}, |
||
648 | {256250, 2, 18, 19}, |
||
649 | {262500, 2, 31, 32}, |
||
650 | {267250, 2, 66, 67}, |
||
651 | {268500, 2, 94, 95}, |
||
652 | {270000, 2, 14, 14}, |
||
653 | {272500, 2, 77, 76}, |
||
654 | {273750, 2, 57, 56}, |
||
655 | {280750, 2, 24, 23}, |
||
656 | {281250, 2, 23, 22}, |
||
657 | {286000, 2, 17, 16}, |
||
658 | {291750, 2, 26, 24}, |
||
659 | {296703, 2, 56, 51}, |
||
660 | {297000, 2, 22, 20}, |
||
661 | {298000, 2, 21, 19}, |
||
662 | }; |
||
663 | |||
3243 | Serge | 664 | static void intel_ddi_mode_set(struct drm_encoder *encoder, |
3031 | serge | 665 | struct drm_display_mode *mode, |
666 | struct drm_display_mode *adjusted_mode) |
||
667 | { |
||
668 | struct drm_crtc *crtc = encoder->crtc; |
||
669 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
3243 | Serge | 670 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); |
671 | int port = intel_ddi_get_encoder_port(intel_encoder); |
||
3031 | serge | 672 | int pipe = intel_crtc->pipe; |
3243 | Serge | 673 | int type = intel_encoder->type; |
3031 | serge | 674 | |
3243 | Serge | 675 | DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n", |
676 | port_name(port), pipe_name(pipe)); |
||
3031 | serge | 677 | |
3243 | Serge | 678 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
679 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
680 | |||
681 | intel_dp->DP = DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW; |
||
682 | switch (intel_dp->lane_count) { |
||
683 | case 1: |
||
684 | intel_dp->DP |= DDI_PORT_WIDTH_X1; |
||
685 | break; |
||
686 | case 2: |
||
687 | intel_dp->DP |= DDI_PORT_WIDTH_X2; |
||
688 | break; |
||
689 | case 4: |
||
690 | intel_dp->DP |= DDI_PORT_WIDTH_X4; |
||
691 | break; |
||
692 | default: |
||
693 | intel_dp->DP |= DDI_PORT_WIDTH_X4; |
||
694 | WARN(1, "Unexpected DP lane count %d\n", |
||
695 | intel_dp->lane_count); |
||
696 | break; |
||
697 | } |
||
698 | |||
699 | if (intel_dp->has_audio) { |
||
700 | DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n", |
||
701 | pipe_name(intel_crtc->pipe)); |
||
702 | |||
703 | /* write eld */ |
||
704 | DRM_DEBUG_DRIVER("DP audio: write eld information\n"); |
||
705 | intel_write_eld(encoder, adjusted_mode); |
||
706 | } |
||
707 | |||
708 | intel_dp_init_link_config(intel_dp); |
||
709 | |||
710 | } else if (type == INTEL_OUTPUT_HDMI) { |
||
711 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
||
712 | |||
713 | if (intel_hdmi->has_audio) { |
||
714 | /* Proper support for digital audio needs a new logic |
||
715 | * and a new set of registers, so we leave it for future |
||
716 | * patch bombing. |
||
717 | */ |
||
718 | DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n", |
||
719 | pipe_name(intel_crtc->pipe)); |
||
720 | |||
721 | /* write eld */ |
||
722 | DRM_DEBUG_DRIVER("HDMI audio: write eld information\n"); |
||
723 | intel_write_eld(encoder, adjusted_mode); |
||
724 | } |
||
725 | |||
726 | intel_hdmi->set_infoframes(encoder, adjusted_mode); |
||
727 | } |
||
728 | } |
||
729 | |||
730 | static struct intel_encoder * |
||
731 | intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) |
||
732 | { |
||
733 | struct drm_device *dev = crtc->dev; |
||
734 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
735 | struct intel_encoder *intel_encoder, *ret = NULL; |
||
736 | int num_encoders = 0; |
||
737 | |||
738 | for_each_encoder_on_crtc(dev, crtc, intel_encoder) { |
||
739 | ret = intel_encoder; |
||
740 | num_encoders++; |
||
741 | } |
||
742 | |||
743 | if (num_encoders != 1) |
||
744 | WARN(1, "%d encoders on crtc for pipe %d\n", num_encoders, |
||
745 | intel_crtc->pipe); |
||
746 | |||
747 | BUG_ON(ret == NULL); |
||
748 | return ret; |
||
749 | } |
||
750 | |||
751 | void intel_ddi_put_crtc_pll(struct drm_crtc *crtc) |
||
752 | { |
||
753 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
754 | struct intel_ddi_plls *plls = &dev_priv->ddi_plls; |
||
755 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
756 | uint32_t val; |
||
757 | |||
758 | switch (intel_crtc->ddi_pll_sel) { |
||
759 | case PORT_CLK_SEL_SPLL: |
||
760 | plls->spll_refcount--; |
||
761 | if (plls->spll_refcount == 0) { |
||
762 | DRM_DEBUG_KMS("Disabling SPLL\n"); |
||
763 | val = I915_READ(SPLL_CTL); |
||
764 | WARN_ON(!(val & SPLL_PLL_ENABLE)); |
||
765 | I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE); |
||
766 | POSTING_READ(SPLL_CTL); |
||
767 | } |
||
768 | break; |
||
769 | case PORT_CLK_SEL_WRPLL1: |
||
770 | plls->wrpll1_refcount--; |
||
771 | if (plls->wrpll1_refcount == 0) { |
||
772 | DRM_DEBUG_KMS("Disabling WRPLL 1\n"); |
||
773 | val = I915_READ(WRPLL_CTL1); |
||
774 | WARN_ON(!(val & WRPLL_PLL_ENABLE)); |
||
775 | I915_WRITE(WRPLL_CTL1, val & ~WRPLL_PLL_ENABLE); |
||
776 | POSTING_READ(WRPLL_CTL1); |
||
777 | } |
||
778 | break; |
||
779 | case PORT_CLK_SEL_WRPLL2: |
||
780 | plls->wrpll2_refcount--; |
||
781 | if (plls->wrpll2_refcount == 0) { |
||
782 | DRM_DEBUG_KMS("Disabling WRPLL 2\n"); |
||
783 | val = I915_READ(WRPLL_CTL2); |
||
784 | WARN_ON(!(val & WRPLL_PLL_ENABLE)); |
||
785 | I915_WRITE(WRPLL_CTL2, val & ~WRPLL_PLL_ENABLE); |
||
786 | POSTING_READ(WRPLL_CTL2); |
||
787 | } |
||
788 | break; |
||
789 | } |
||
790 | |||
791 | WARN(plls->spll_refcount < 0, "Invalid SPLL refcount\n"); |
||
792 | WARN(plls->wrpll1_refcount < 0, "Invalid WRPLL1 refcount\n"); |
||
793 | WARN(plls->wrpll2_refcount < 0, "Invalid WRPLL2 refcount\n"); |
||
794 | |||
795 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE; |
||
796 | } |
||
797 | |||
798 | static void intel_ddi_calculate_wrpll(int clock, int *p, int *n2, int *r2) |
||
799 | { |
||
800 | u32 i; |
||
801 | |||
3031 | serge | 802 | for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++) |
3243 | Serge | 803 | if (clock <= wrpll_tmds_clock_table[i].clock) |
3031 | serge | 804 | break; |
805 | |||
806 | if (i == ARRAY_SIZE(wrpll_tmds_clock_table)) |
||
807 | i--; |
||
808 | |||
3243 | Serge | 809 | *p = wrpll_tmds_clock_table[i].p; |
810 | *n2 = wrpll_tmds_clock_table[i].n2; |
||
811 | *r2 = wrpll_tmds_clock_table[i].r2; |
||
3031 | serge | 812 | |
3243 | Serge | 813 | if (wrpll_tmds_clock_table[i].clock != clock) |
814 | DRM_INFO("WRPLL: using settings for %dKHz on %dKHz mode\n", |
||
815 | wrpll_tmds_clock_table[i].clock, clock); |
||
3031 | serge | 816 | |
3243 | Serge | 817 | DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n", |
818 | clock, *p, *n2, *r2); |
||
819 | } |
||
3031 | serge | 820 | |
3243 | Serge | 821 | bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock) |
822 | { |
||
823 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
824 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
825 | struct drm_encoder *encoder = &intel_encoder->base; |
||
826 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
827 | struct intel_ddi_plls *plls = &dev_priv->ddi_plls; |
||
828 | int type = intel_encoder->type; |
||
829 | enum pipe pipe = intel_crtc->pipe; |
||
830 | uint32_t reg, val; |
||
3031 | serge | 831 | |
3243 | Serge | 832 | /* TODO: reuse PLLs when possible (compare values) */ |
3031 | serge | 833 | |
3243 | Serge | 834 | intel_ddi_put_crtc_pll(crtc); |
3031 | serge | 835 | |
3243 | Serge | 836 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
837 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
3031 | serge | 838 | |
3243 | Serge | 839 | switch (intel_dp->link_bw) { |
840 | case DP_LINK_BW_1_62: |
||
841 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810; |
||
842 | break; |
||
843 | case DP_LINK_BW_2_7: |
||
844 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350; |
||
845 | break; |
||
846 | case DP_LINK_BW_5_4: |
||
847 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700; |
||
848 | break; |
||
849 | default: |
||
850 | DRM_ERROR("Link bandwidth %d unsupported\n", |
||
851 | intel_dp->link_bw); |
||
852 | return false; |
||
853 | } |
||
854 | |||
855 | /* We don't need to turn any PLL on because we'll use LCPLL. */ |
||
856 | return true; |
||
857 | |||
858 | } else if (type == INTEL_OUTPUT_HDMI) { |
||
859 | int p, n2, r2; |
||
860 | |||
861 | if (plls->wrpll1_refcount == 0) { |
||
862 | DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n", |
||
863 | pipe_name(pipe)); |
||
864 | plls->wrpll1_refcount++; |
||
865 | reg = WRPLL_CTL1; |
||
866 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1; |
||
867 | } else if (plls->wrpll2_refcount == 0) { |
||
868 | DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n", |
||
869 | pipe_name(pipe)); |
||
870 | plls->wrpll2_refcount++; |
||
871 | reg = WRPLL_CTL2; |
||
872 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2; |
||
873 | } else { |
||
874 | DRM_ERROR("No WRPLLs available!\n"); |
||
875 | return false; |
||
876 | } |
||
877 | |||
878 | WARN(I915_READ(reg) & WRPLL_PLL_ENABLE, |
||
879 | "WRPLL already enabled\n"); |
||
880 | |||
881 | intel_ddi_calculate_wrpll(clock, &p, &n2, &r2); |
||
882 | |||
883 | val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | |
||
884 | WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | |
||
885 | WRPLL_DIVIDER_POST(p); |
||
886 | |||
887 | } else if (type == INTEL_OUTPUT_ANALOG) { |
||
888 | if (plls->spll_refcount == 0) { |
||
889 | DRM_DEBUG_KMS("Using SPLL on pipe %c\n", |
||
890 | pipe_name(pipe)); |
||
891 | plls->spll_refcount++; |
||
892 | reg = SPLL_CTL; |
||
893 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL; |
||
894 | } |
||
895 | |||
896 | WARN(I915_READ(reg) & SPLL_PLL_ENABLE, |
||
897 | "SPLL already enabled\n"); |
||
898 | |||
899 | val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC; |
||
900 | |||
901 | } else { |
||
902 | WARN(1, "Invalid DDI encoder type %d\n", type); |
||
903 | return false; |
||
904 | } |
||
905 | |||
906 | I915_WRITE(reg, val); |
||
3031 | serge | 907 | udelay(20); |
908 | |||
3243 | Serge | 909 | return true; |
910 | } |
||
3031 | serge | 911 | |
3243 | Serge | 912 | void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) |
913 | { |
||
914 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
915 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
916 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
917 | enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; |
||
918 | int type = intel_encoder->type; |
||
919 | uint32_t temp; |
||
920 | |||
921 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
||
922 | |||
923 | temp = TRANS_MSA_SYNC_CLK; |
||
924 | switch (intel_crtc->bpp) { |
||
925 | case 18: |
||
926 | temp |= TRANS_MSA_6_BPC; |
||
927 | break; |
||
928 | case 24: |
||
929 | temp |= TRANS_MSA_8_BPC; |
||
930 | break; |
||
931 | case 30: |
||
932 | temp |= TRANS_MSA_10_BPC; |
||
933 | break; |
||
934 | case 36: |
||
935 | temp |= TRANS_MSA_12_BPC; |
||
936 | break; |
||
937 | default: |
||
938 | temp |= TRANS_MSA_8_BPC; |
||
939 | WARN(1, "%d bpp unsupported by DDI function\n", |
||
940 | intel_crtc->bpp); |
||
3031 | serge | 941 | } |
3243 | Serge | 942 | I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp); |
943 | } |
||
944 | } |
||
3031 | serge | 945 | |
3243 | Serge | 946 | void intel_ddi_enable_pipe_func(struct drm_crtc *crtc) |
947 | { |
||
948 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
949 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
950 | struct drm_encoder *encoder = &intel_encoder->base; |
||
951 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
952 | enum pipe pipe = intel_crtc->pipe; |
||
953 | enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; |
||
954 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
955 | int type = intel_encoder->type; |
||
956 | uint32_t temp; |
||
3031 | serge | 957 | |
3243 | Serge | 958 | /* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */ |
959 | temp = TRANS_DDI_FUNC_ENABLE; |
||
960 | temp |= TRANS_DDI_SELECT_PORT(port); |
||
961 | |||
3031 | serge | 962 | switch (intel_crtc->bpp) { |
963 | case 18: |
||
3243 | Serge | 964 | temp |= TRANS_DDI_BPC_6; |
3031 | serge | 965 | break; |
966 | case 24: |
||
3243 | Serge | 967 | temp |= TRANS_DDI_BPC_8; |
3031 | serge | 968 | break; |
969 | case 30: |
||
3243 | Serge | 970 | temp |= TRANS_DDI_BPC_10; |
3031 | serge | 971 | break; |
972 | case 36: |
||
3243 | Serge | 973 | temp |= TRANS_DDI_BPC_12; |
3031 | serge | 974 | break; |
975 | default: |
||
3243 | Serge | 976 | WARN(1, "%d bpp unsupported by transcoder DDI function\n", |
3031 | serge | 977 | intel_crtc->bpp); |
978 | } |
||
979 | |||
3243 | Serge | 980 | if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) |
981 | temp |= TRANS_DDI_PVSYNC; |
||
982 | if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) |
||
983 | temp |= TRANS_DDI_PHSYNC; |
||
984 | |||
985 | if (cpu_transcoder == TRANSCODER_EDP) { |
||
986 | switch (pipe) { |
||
987 | case PIPE_A: |
||
988 | temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; |
||
989 | break; |
||
990 | case PIPE_B: |
||
991 | temp |= TRANS_DDI_EDP_INPUT_B_ONOFF; |
||
992 | break; |
||
993 | case PIPE_C: |
||
994 | temp |= TRANS_DDI_EDP_INPUT_C_ONOFF; |
||
995 | break; |
||
996 | default: |
||
997 | BUG(); |
||
998 | break; |
||
999 | } |
||
1000 | } |
||
1001 | |||
1002 | if (type == INTEL_OUTPUT_HDMI) { |
||
1003 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
||
1004 | |||
3031 | serge | 1005 | if (intel_hdmi->has_hdmi_sink) |
3243 | Serge | 1006 | temp |= TRANS_DDI_MODE_SELECT_HDMI; |
3031 | serge | 1007 | else |
3243 | Serge | 1008 | temp |= TRANS_DDI_MODE_SELECT_DVI; |
3031 | serge | 1009 | |
3243 | Serge | 1010 | } else if (type == INTEL_OUTPUT_ANALOG) { |
1011 | temp |= TRANS_DDI_MODE_SELECT_FDI; |
||
1012 | temp |= (intel_crtc->fdi_lanes - 1) << 1; |
||
3031 | serge | 1013 | |
3243 | Serge | 1014 | } else if (type == INTEL_OUTPUT_DISPLAYPORT || |
1015 | type == INTEL_OUTPUT_EDP) { |
||
1016 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
3031 | serge | 1017 | |
3243 | Serge | 1018 | temp |= TRANS_DDI_MODE_SELECT_DP_SST; |
1019 | |||
1020 | switch (intel_dp->lane_count) { |
||
1021 | case 1: |
||
1022 | temp |= TRANS_DDI_PORT_WIDTH_X1; |
||
1023 | break; |
||
1024 | case 2: |
||
1025 | temp |= TRANS_DDI_PORT_WIDTH_X2; |
||
1026 | break; |
||
1027 | case 4: |
||
1028 | temp |= TRANS_DDI_PORT_WIDTH_X4; |
||
1029 | break; |
||
1030 | default: |
||
1031 | temp |= TRANS_DDI_PORT_WIDTH_X4; |
||
1032 | WARN(1, "Unsupported lane count %d\n", |
||
1033 | intel_dp->lane_count); |
||
1034 | } |
||
1035 | |||
1036 | } else { |
||
1037 | WARN(1, "Invalid encoder type %d for pipe %d\n", |
||
1038 | intel_encoder->type, pipe); |
||
1039 | } |
||
1040 | |||
1041 | I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp); |
||
3031 | serge | 1042 | } |
1043 | |||
3243 | Serge | 1044 | void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, |
1045 | enum transcoder cpu_transcoder) |
||
1046 | { |
||
1047 | uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder); |
||
1048 | uint32_t val = I915_READ(reg); |
||
1049 | |||
1050 | val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK); |
||
1051 | val |= TRANS_DDI_PORT_NONE; |
||
1052 | I915_WRITE(reg, val); |
||
1053 | } |
||
1054 | |||
1055 | bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) |
||
1056 | { |
||
1057 | struct drm_device *dev = intel_connector->base.dev; |
||
1058 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
1059 | struct intel_encoder *intel_encoder = intel_connector->encoder; |
||
1060 | int type = intel_connector->base.connector_type; |
||
1061 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
1062 | enum pipe pipe = 0; |
||
1063 | enum transcoder cpu_transcoder; |
||
1064 | uint32_t tmp; |
||
1065 | |||
1066 | if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) |
||
1067 | return false; |
||
1068 | |||
1069 | if (port == PORT_A) |
||
1070 | cpu_transcoder = TRANSCODER_EDP; |
||
1071 | else |
||
1072 | cpu_transcoder = pipe; |
||
1073 | |||
1074 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
||
1075 | |||
1076 | switch (tmp & TRANS_DDI_MODE_SELECT_MASK) { |
||
1077 | case TRANS_DDI_MODE_SELECT_HDMI: |
||
1078 | case TRANS_DDI_MODE_SELECT_DVI: |
||
1079 | return (type == DRM_MODE_CONNECTOR_HDMIA); |
||
1080 | |||
1081 | case TRANS_DDI_MODE_SELECT_DP_SST: |
||
1082 | if (type == DRM_MODE_CONNECTOR_eDP) |
||
1083 | return true; |
||
1084 | case TRANS_DDI_MODE_SELECT_DP_MST: |
||
1085 | return (type == DRM_MODE_CONNECTOR_DisplayPort); |
||
1086 | |||
1087 | case TRANS_DDI_MODE_SELECT_FDI: |
||
1088 | return (type == DRM_MODE_CONNECTOR_VGA); |
||
1089 | |||
1090 | default: |
||
1091 | return false; |
||
1092 | } |
||
1093 | } |
||
1094 | |||
3031 | serge | 1095 | bool intel_ddi_get_hw_state(struct intel_encoder *encoder, |
1096 | enum pipe *pipe) |
||
1097 | { |
||
1098 | struct drm_device *dev = encoder->base.dev; |
||
1099 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
3243 | Serge | 1100 | enum port port = intel_ddi_get_encoder_port(encoder); |
3031 | serge | 1101 | u32 tmp; |
1102 | int i; |
||
1103 | |||
3243 | Serge | 1104 | tmp = I915_READ(DDI_BUF_CTL(port)); |
3031 | serge | 1105 | |
1106 | if (!(tmp & DDI_BUF_CTL_ENABLE)) |
||
1107 | return false; |
||
1108 | |||
3243 | Serge | 1109 | if (port == PORT_A) { |
1110 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); |
||
3031 | serge | 1111 | |
3243 | Serge | 1112 | switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { |
1113 | case TRANS_DDI_EDP_INPUT_A_ON: |
||
1114 | case TRANS_DDI_EDP_INPUT_A_ONOFF: |
||
1115 | *pipe = PIPE_A; |
||
1116 | break; |
||
1117 | case TRANS_DDI_EDP_INPUT_B_ONOFF: |
||
1118 | *pipe = PIPE_B; |
||
1119 | break; |
||
1120 | case TRANS_DDI_EDP_INPUT_C_ONOFF: |
||
1121 | *pipe = PIPE_C; |
||
1122 | break; |
||
1123 | } |
||
1124 | |||
1125 | return true; |
||
1126 | } else { |
||
1127 | for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) { |
||
1128 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(i)); |
||
1129 | |||
1130 | if ((tmp & TRANS_DDI_PORT_MASK) |
||
1131 | == TRANS_DDI_SELECT_PORT(port)) { |
||
3031 | serge | 1132 | *pipe = i; |
1133 | return true; |
||
1134 | } |
||
1135 | } |
||
3243 | Serge | 1136 | } |
3031 | serge | 1137 | |
3243 | Serge | 1138 | DRM_DEBUG_KMS("No pipe for ddi port %i found\n", port); |
3031 | serge | 1139 | |
1140 | return true; |
||
1141 | } |
||
1142 | |||
3243 | Serge | 1143 | static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv, |
1144 | enum pipe pipe) |
||
3031 | serge | 1145 | { |
3243 | Serge | 1146 | uint32_t temp, ret; |
1147 | enum port port; |
||
1148 | enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, |
||
1149 | pipe); |
||
1150 | int i; |
||
1151 | |||
1152 | if (cpu_transcoder == TRANSCODER_EDP) { |
||
1153 | port = PORT_A; |
||
1154 | } else { |
||
1155 | temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
||
1156 | temp &= TRANS_DDI_PORT_MASK; |
||
1157 | |||
1158 | for (i = PORT_B; i <= PORT_E; i++) |
||
1159 | if (temp == TRANS_DDI_SELECT_PORT(i)) |
||
1160 | port = i; |
||
1161 | } |
||
1162 | |||
1163 | ret = I915_READ(PORT_CLK_SEL(port)); |
||
1164 | |||
1165 | DRM_DEBUG_KMS("Pipe %c connected to port %c using clock 0x%08x\n", |
||
1166 | pipe_name(pipe), port_name(port), ret); |
||
1167 | |||
1168 | return ret; |
||
1169 | } |
||
1170 | |||
1171 | void intel_ddi_setup_hw_pll_state(struct drm_device *dev) |
||
1172 | { |
||
3031 | serge | 1173 | struct drm_i915_private *dev_priv = dev->dev_private; |
3243 | Serge | 1174 | enum pipe pipe; |
1175 | struct intel_crtc *intel_crtc; |
||
3031 | serge | 1176 | |
3243 | Serge | 1177 | for_each_pipe(pipe) { |
1178 | intel_crtc = |
||
1179 | to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
||
3031 | serge | 1180 | |
3243 | Serge | 1181 | if (!intel_crtc->active) |
1182 | continue; |
||
1183 | |||
1184 | intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv, |
||
1185 | pipe); |
||
1186 | |||
1187 | switch (intel_crtc->ddi_pll_sel) { |
||
1188 | case PORT_CLK_SEL_SPLL: |
||
1189 | dev_priv->ddi_plls.spll_refcount++; |
||
1190 | break; |
||
1191 | case PORT_CLK_SEL_WRPLL1: |
||
1192 | dev_priv->ddi_plls.wrpll1_refcount++; |
||
1193 | break; |
||
1194 | case PORT_CLK_SEL_WRPLL2: |
||
1195 | dev_priv->ddi_plls.wrpll2_refcount++; |
||
1196 | break; |
||
1197 | } |
||
1198 | } |
||
3031 | serge | 1199 | } |
1200 | |||
3243 | Serge | 1201 | void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc) |
3031 | serge | 1202 | { |
3243 | Serge | 1203 | struct drm_crtc *crtc = &intel_crtc->base; |
1204 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
1205 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
1206 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
1207 | enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; |
||
1208 | |||
1209 | if (cpu_transcoder != TRANSCODER_EDP) |
||
1210 | I915_WRITE(TRANS_CLK_SEL(cpu_transcoder), |
||
1211 | TRANS_CLK_SEL_PORT(port)); |
||
1212 | } |
||
1213 | |||
1214 | void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) |
||
1215 | { |
||
1216 | struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; |
||
1217 | enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; |
||
1218 | |||
1219 | if (cpu_transcoder != TRANSCODER_EDP) |
||
1220 | I915_WRITE(TRANS_CLK_SEL(cpu_transcoder), |
||
1221 | TRANS_CLK_SEL_DISABLED); |
||
1222 | } |
||
1223 | |||
1224 | static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) |
||
1225 | { |
||
1226 | struct drm_encoder *encoder = &intel_encoder->base; |
||
1227 | struct drm_crtc *crtc = encoder->crtc; |
||
1228 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
||
1229 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
1230 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
1231 | int type = intel_encoder->type; |
||
1232 | |||
1233 | if (type == INTEL_OUTPUT_EDP) { |
||
1234 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1235 | ironlake_edp_panel_vdd_on(intel_dp); |
||
1236 | ironlake_edp_panel_on(intel_dp); |
||
1237 | ironlake_edp_panel_vdd_off(intel_dp, true); |
||
1238 | } |
||
1239 | |||
1240 | WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE); |
||
1241 | I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel); |
||
1242 | |||
1243 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
||
1244 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1245 | |||
1246 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); |
||
1247 | intel_dp_start_link_train(intel_dp); |
||
1248 | intel_dp_complete_link_train(intel_dp); |
||
1249 | } |
||
1250 | } |
||
1251 | |||
1252 | static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) |
||
1253 | { |
||
1254 | struct drm_encoder *encoder = &intel_encoder->base; |
||
1255 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
||
1256 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
1257 | int type = intel_encoder->type; |
||
1258 | uint32_t val; |
||
1259 | bool wait = false; |
||
1260 | |||
1261 | val = I915_READ(DDI_BUF_CTL(port)); |
||
1262 | if (val & DDI_BUF_CTL_ENABLE) { |
||
1263 | val &= ~DDI_BUF_CTL_ENABLE; |
||
1264 | I915_WRITE(DDI_BUF_CTL(port), val); |
||
1265 | wait = true; |
||
1266 | } |
||
1267 | |||
1268 | val = I915_READ(DP_TP_CTL(port)); |
||
1269 | val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); |
||
1270 | val |= DP_TP_CTL_LINK_TRAIN_PAT1; |
||
1271 | I915_WRITE(DP_TP_CTL(port), val); |
||
1272 | |||
1273 | if (wait) |
||
1274 | intel_wait_ddi_buf_idle(dev_priv, port); |
||
1275 | |||
1276 | if (type == INTEL_OUTPUT_EDP) { |
||
1277 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1278 | ironlake_edp_panel_vdd_on(intel_dp); |
||
1279 | ironlake_edp_panel_off(intel_dp); |
||
1280 | } |
||
1281 | |||
1282 | I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); |
||
1283 | } |
||
1284 | |||
1285 | static void intel_enable_ddi(struct intel_encoder *intel_encoder) |
||
1286 | { |
||
1287 | struct drm_encoder *encoder = &intel_encoder->base; |
||
1288 | struct drm_device *dev = encoder->dev; |
||
3031 | serge | 1289 | struct drm_i915_private *dev_priv = dev->dev_private; |
3243 | Serge | 1290 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
1291 | int type = intel_encoder->type; |
||
3031 | serge | 1292 | |
3243 | Serge | 1293 | if (type == INTEL_OUTPUT_HDMI) { |
1294 | /* In HDMI/DVI mode, the port width, and swing/emphasis values |
||
1295 | * are ignored so nothing special needs to be done besides |
||
1296 | * enabling the port. |
||
1297 | */ |
||
1298 | I915_WRITE(DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE); |
||
1299 | } else if (type == INTEL_OUTPUT_EDP) { |
||
1300 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
3031 | serge | 1301 | |
3243 | Serge | 1302 | ironlake_edp_backlight_on(intel_dp); |
1303 | } |
||
3031 | serge | 1304 | } |
3243 | Serge | 1305 | |
1306 | static void intel_disable_ddi(struct intel_encoder *intel_encoder) |
||
1307 | { |
||
1308 | struct drm_encoder *encoder = &intel_encoder->base; |
||
1309 | int type = intel_encoder->type; |
||
1310 | |||
1311 | if (type == INTEL_OUTPUT_EDP) { |
||
1312 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1313 | |||
1314 | ironlake_edp_backlight_off(intel_dp); |
||
1315 | } |
||
1316 | } |
||
1317 | |||
1318 | int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) |
||
1319 | { |
||
1320 | if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) |
||
1321 | return 450; |
||
1322 | else if ((I915_READ(LCPLL_CTL) & LCPLL_CLK_FREQ_MASK) == |
||
1323 | LCPLL_CLK_FREQ_450) |
||
1324 | return 450; |
||
1325 | else if (IS_ULT(dev_priv->dev)) |
||
1326 | return 338; |
||
1327 | else |
||
1328 | return 540; |
||
1329 | } |
||
1330 | |||
1331 | void intel_ddi_pll_init(struct drm_device *dev) |
||
1332 | { |
||
1333 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
1334 | uint32_t val = I915_READ(LCPLL_CTL); |
||
1335 | |||
1336 | /* The LCPLL register should be turned on by the BIOS. For now let's |
||
1337 | * just check its state and print errors in case something is wrong. |
||
1338 | * Don't even try to turn it on. |
||
1339 | */ |
||
1340 | |||
1341 | DRM_DEBUG_KMS("CDCLK running at %dMHz\n", |
||
1342 | intel_ddi_get_cdclk_freq(dev_priv)); |
||
1343 | |||
1344 | if (val & LCPLL_CD_SOURCE_FCLK) |
||
1345 | DRM_ERROR("CDCLK source is not LCPLL\n"); |
||
1346 | |||
1347 | if (val & LCPLL_PLL_DISABLE) |
||
1348 | DRM_ERROR("LCPLL is disabled\n"); |
||
1349 | } |
||
1350 | |||
1351 | void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder) |
||
1352 | { |
||
1353 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
||
1354 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
||
1355 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
||
1356 | enum port port = intel_dig_port->port; |
||
1357 | bool wait; |
||
1358 | uint32_t val; |
||
1359 | |||
1360 | if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) { |
||
1361 | val = I915_READ(DDI_BUF_CTL(port)); |
||
1362 | if (val & DDI_BUF_CTL_ENABLE) { |
||
1363 | val &= ~DDI_BUF_CTL_ENABLE; |
||
1364 | I915_WRITE(DDI_BUF_CTL(port), val); |
||
1365 | wait = true; |
||
1366 | } |
||
1367 | |||
1368 | val = I915_READ(DP_TP_CTL(port)); |
||
1369 | val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); |
||
1370 | val |= DP_TP_CTL_LINK_TRAIN_PAT1; |
||
1371 | I915_WRITE(DP_TP_CTL(port), val); |
||
1372 | POSTING_READ(DP_TP_CTL(port)); |
||
1373 | |||
1374 | if (wait) |
||
1375 | intel_wait_ddi_buf_idle(dev_priv, port); |
||
1376 | } |
||
1377 | |||
1378 | val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST | |
||
1379 | DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; |
||
1380 | if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) |
||
1381 | val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; |
||
1382 | I915_WRITE(DP_TP_CTL(port), val); |
||
1383 | POSTING_READ(DP_TP_CTL(port)); |
||
1384 | |||
1385 | intel_dp->DP |= DDI_BUF_CTL_ENABLE; |
||
1386 | I915_WRITE(DDI_BUF_CTL(port), intel_dp->DP); |
||
1387 | POSTING_READ(DDI_BUF_CTL(port)); |
||
1388 | |||
1389 | udelay(600); |
||
1390 | } |
||
1391 | |||
1392 | void intel_ddi_fdi_disable(struct drm_crtc *crtc) |
||
1393 | { |
||
1394 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
1395 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
1396 | uint32_t val; |
||
1397 | |||
1398 | intel_ddi_post_disable(intel_encoder); |
||
1399 | |||
1400 | val = I915_READ(_FDI_RXA_CTL); |
||
1401 | val &= ~FDI_RX_ENABLE; |
||
1402 | I915_WRITE(_FDI_RXA_CTL, val); |
||
1403 | |||
1404 | val = I915_READ(_FDI_RXA_MISC); |
||
1405 | val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); |
||
1406 | val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); |
||
1407 | I915_WRITE(_FDI_RXA_MISC, val); |
||
1408 | |||
1409 | val = I915_READ(_FDI_RXA_CTL); |
||
1410 | val &= ~FDI_PCDCLK; |
||
1411 | I915_WRITE(_FDI_RXA_CTL, val); |
||
1412 | |||
1413 | val = I915_READ(_FDI_RXA_CTL); |
||
1414 | val &= ~FDI_RX_PLL_ENABLE; |
||
1415 | I915_WRITE(_FDI_RXA_CTL, val); |
||
1416 | } |
||
1417 | |||
1418 | static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) |
||
1419 | { |
||
1420 | struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); |
||
1421 | int type = intel_encoder->type; |
||
1422 | |||
1423 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) |
||
1424 | intel_dp_check_link_status(intel_dp); |
||
1425 | } |
||
1426 | |||
1427 | static void intel_ddi_destroy(struct drm_encoder *encoder) |
||
1428 | { |
||
1429 | /* HDMI has nothing special to destroy, so we can go with this. */ |
||
1430 | intel_dp_encoder_destroy(encoder); |
||
1431 | } |
||
1432 | |||
1433 | static bool intel_ddi_mode_fixup(struct drm_encoder *encoder, |
||
1434 | const struct drm_display_mode *mode, |
||
1435 | struct drm_display_mode *adjusted_mode) |
||
1436 | { |
||
1437 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); |
||
1438 | int type = intel_encoder->type; |
||
1439 | |||
1440 | WARN(type == INTEL_OUTPUT_UNKNOWN, "mode_fixup() on unknown output!\n"); |
||
1441 | |||
1442 | if (type == INTEL_OUTPUT_HDMI) |
||
1443 | return intel_hdmi_mode_fixup(encoder, mode, adjusted_mode); |
||
1444 | else |
||
1445 | return intel_dp_mode_fixup(encoder, mode, adjusted_mode); |
||
1446 | } |
||
1447 | |||
1448 | static const struct drm_encoder_funcs intel_ddi_funcs = { |
||
1449 | .destroy = intel_ddi_destroy, |
||
1450 | }; |
||
1451 | |||
1452 | static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = { |
||
1453 | .mode_fixup = intel_ddi_mode_fixup, |
||
1454 | .mode_set = intel_ddi_mode_set, |
||
1455 | .disable = intel_encoder_noop, |
||
1456 | }; |
||
1457 | |||
1458 | void intel_ddi_init(struct drm_device *dev, enum port port) |
||
1459 | { |
||
1460 | struct intel_digital_port *intel_dig_port; |
||
1461 | struct intel_encoder *intel_encoder; |
||
1462 | struct drm_encoder *encoder; |
||
1463 | struct intel_connector *hdmi_connector = NULL; |
||
1464 | struct intel_connector *dp_connector = NULL; |
||
1465 | |||
1466 | intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); |
||
1467 | if (!intel_dig_port) |
||
1468 | return; |
||
1469 | |||
1470 | dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
||
1471 | if (!dp_connector) { |
||
1472 | kfree(intel_dig_port); |
||
1473 | return; |
||
1474 | } |
||
1475 | |||
1476 | if (port != PORT_A) { |
||
1477 | hdmi_connector = kzalloc(sizeof(struct intel_connector), |
||
1478 | GFP_KERNEL); |
||
1479 | if (!hdmi_connector) { |
||
1480 | kfree(dp_connector); |
||
1481 | kfree(intel_dig_port); |
||
1482 | return; |
||
1483 | } |
||
1484 | } |
||
1485 | |||
1486 | intel_encoder = &intel_dig_port->base; |
||
1487 | encoder = &intel_encoder->base; |
||
1488 | |||
1489 | drm_encoder_init(dev, encoder, &intel_ddi_funcs, |
||
1490 | DRM_MODE_ENCODER_TMDS); |
||
1491 | drm_encoder_helper_add(encoder, &intel_ddi_helper_funcs); |
||
1492 | |||
1493 | intel_encoder->enable = intel_enable_ddi; |
||
1494 | intel_encoder->pre_enable = intel_ddi_pre_enable; |
||
1495 | intel_encoder->disable = intel_disable_ddi; |
||
1496 | intel_encoder->post_disable = intel_ddi_post_disable; |
||
1497 | intel_encoder->get_hw_state = intel_ddi_get_hw_state; |
||
1498 | |||
1499 | intel_dig_port->port = port; |
||
1500 | if (hdmi_connector) |
||
1501 | intel_dig_port->hdmi.sdvox_reg = DDI_BUF_CTL(port); |
||
1502 | else |
||
1503 | intel_dig_port->hdmi.sdvox_reg = 0; |
||
1504 | intel_dig_port->dp.output_reg = DDI_BUF_CTL(port); |
||
1505 | |||
1506 | intel_encoder->type = INTEL_OUTPUT_UNKNOWN; |
||
1507 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
||
1508 | intel_encoder->cloneable = false; |
||
1509 | intel_encoder->hot_plug = intel_ddi_hot_plug; |
||
1510 | |||
1511 | if (hdmi_connector) |
||
1512 | intel_hdmi_init_connector(intel_dig_port, hdmi_connector); |
||
1513 | intel_dp_init_connector(intel_dig_port, dp_connector); |
||
1514 | }><>><>><>=>=>><>=>>>>>><>>><>>>> |