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