Rev 3243 | Go to most recent revision | Details | 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 | |||
61 | /* On Haswell, DDI port buffers must be programmed with correct values |
||
62 | * in advance. The buffer values are different for FDI and DP modes, |
||
63 | * but the HDMI/DVI fields are shared among those. So we program the DDI |
||
64 | * in either FDI or DP modes only, as HDMI connections will work with both |
||
65 | * of those |
||
66 | */ |
||
67 | void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool use_fdi_mode) |
||
68 | { |
||
69 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
70 | u32 reg; |
||
71 | int i; |
||
72 | const u32 *ddi_translations = ((use_fdi_mode) ? |
||
73 | hsw_ddi_translations_fdi : |
||
74 | hsw_ddi_translations_dp); |
||
75 | |||
76 | DRM_DEBUG_DRIVER("Initializing DDI buffers for port %c in %s mode\n", |
||
77 | port_name(port), |
||
78 | use_fdi_mode ? "FDI" : "DP"); |
||
79 | |||
80 | WARN((use_fdi_mode && (port != PORT_E)), |
||
81 | "Programming port %c in FDI mode, this probably will not work.\n", |
||
82 | port_name(port)); |
||
83 | |||
84 | for (i=0, reg=DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { |
||
85 | I915_WRITE(reg, ddi_translations[i]); |
||
86 | reg += 4; |
||
87 | } |
||
88 | } |
||
89 | |||
90 | /* Program DDI buffers translations for DP. By default, program ports A-D in DP |
||
91 | * mode and port E for FDI. |
||
92 | */ |
||
93 | void intel_prepare_ddi(struct drm_device *dev) |
||
94 | { |
||
95 | int port; |
||
96 | |||
97 | if (IS_HASWELL(dev)) { |
||
98 | for (port = PORT_A; port < PORT_E; port++) |
||
99 | intel_prepare_ddi_buffers(dev, port, false); |
||
100 | |||
101 | /* DDI E is the suggested one to work in FDI mode, so program is as such by |
||
102 | * default. It will have to be re-programmed in case a digital DP output |
||
103 | * will be detected on it |
||
104 | */ |
||
105 | intel_prepare_ddi_buffers(dev, PORT_E, true); |
||
106 | } |
||
107 | } |
||
108 | |||
109 | static const long hsw_ddi_buf_ctl_values[] = { |
||
110 | DDI_BUF_EMP_400MV_0DB_HSW, |
||
111 | DDI_BUF_EMP_400MV_3_5DB_HSW, |
||
112 | DDI_BUF_EMP_400MV_6DB_HSW, |
||
113 | DDI_BUF_EMP_400MV_9_5DB_HSW, |
||
114 | DDI_BUF_EMP_600MV_0DB_HSW, |
||
115 | DDI_BUF_EMP_600MV_3_5DB_HSW, |
||
116 | DDI_BUF_EMP_600MV_6DB_HSW, |
||
117 | DDI_BUF_EMP_800MV_0DB_HSW, |
||
118 | DDI_BUF_EMP_800MV_3_5DB_HSW |
||
119 | }; |
||
120 | |||
121 | |||
122 | /* Starting with Haswell, different DDI ports can work in FDI mode for |
||
123 | * connection to the PCH-located connectors. For this, it is necessary to train |
||
124 | * both the DDI port and PCH receiver for the desired DDI buffer settings. |
||
125 | * |
||
126 | * The recommended port to work in FDI mode is DDI E, which we use here. Also, |
||
127 | * please note that when FDI mode is active on DDI E, it shares 2 lines with |
||
128 | * DDI A (which is used for eDP) |
||
129 | */ |
||
130 | |||
131 | void hsw_fdi_link_train(struct drm_crtc *crtc) |
||
132 | { |
||
133 | struct drm_device *dev = crtc->dev; |
||
134 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
135 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
136 | int pipe = intel_crtc->pipe; |
||
137 | u32 reg, temp, i; |
||
138 | |||
139 | /* Configure CPU PLL, wait for warmup */ |
||
140 | I915_WRITE(SPLL_CTL, |
||
141 | SPLL_PLL_ENABLE | |
||
142 | SPLL_PLL_FREQ_1350MHz | |
||
143 | SPLL_PLL_SCC); |
||
144 | |||
145 | /* Use SPLL to drive the output when in FDI mode */ |
||
146 | I915_WRITE(PORT_CLK_SEL(PORT_E), |
||
147 | PORT_CLK_SEL_SPLL); |
||
148 | I915_WRITE(PIPE_CLK_SEL(pipe), |
||
149 | PIPE_CLK_SEL_PORT(PORT_E)); |
||
150 | |||
151 | udelay(20); |
||
152 | |||
153 | /* Start the training iterating through available voltages and emphasis */ |
||
154 | for (i=0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values); i++) { |
||
155 | /* Configure DP_TP_CTL with auto-training */ |
||
156 | I915_WRITE(DP_TP_CTL(PORT_E), |
||
157 | DP_TP_CTL_FDI_AUTOTRAIN | |
||
158 | DP_TP_CTL_ENHANCED_FRAME_ENABLE | |
||
159 | DP_TP_CTL_LINK_TRAIN_PAT1 | |
||
160 | DP_TP_CTL_ENABLE); |
||
161 | |||
162 | /* Configure and enable DDI_BUF_CTL for DDI E with next voltage */ |
||
163 | temp = I915_READ(DDI_BUF_CTL(PORT_E)); |
||
164 | temp = (temp & ~DDI_BUF_EMP_MASK); |
||
165 | I915_WRITE(DDI_BUF_CTL(PORT_E), |
||
166 | temp | |
||
167 | DDI_BUF_CTL_ENABLE | |
||
168 | DDI_PORT_WIDTH_X2 | |
||
169 | hsw_ddi_buf_ctl_values[i]); |
||
170 | |||
171 | udelay(600); |
||
172 | |||
173 | /* We need to program FDI_RX_MISC with the default TP1 to TP2 |
||
174 | * values before enabling the receiver, and configure the delay |
||
175 | * for the FDI timing generator to 90h. Luckily, all the other |
||
176 | * bits are supposed to be zeroed, so we can write those values |
||
177 | * directly. |
||
178 | */ |
||
179 | I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 | |
||
180 | FDI_RX_FDI_DELAY_90); |
||
181 | |||
182 | /* Enable CPU FDI Receiver with auto-training */ |
||
183 | reg = FDI_RX_CTL(pipe); |
||
184 | I915_WRITE(reg, |
||
185 | I915_READ(reg) | |
||
186 | FDI_LINK_TRAIN_AUTO | |
||
187 | FDI_RX_ENABLE | |
||
188 | FDI_LINK_TRAIN_PATTERN_1_CPT | |
||
189 | FDI_RX_ENHANCE_FRAME_ENABLE | |
||
190 | FDI_PORT_WIDTH_2X_LPT | |
||
191 | FDI_RX_PLL_ENABLE); |
||
192 | POSTING_READ(reg); |
||
193 | udelay(100); |
||
194 | |||
195 | temp = I915_READ(DP_TP_STATUS(PORT_E)); |
||
196 | if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) { |
||
197 | DRM_DEBUG_DRIVER("BUF_CTL training done on %d step\n", i); |
||
198 | |||
199 | /* Enable normal pixel sending for FDI */ |
||
200 | I915_WRITE(DP_TP_CTL(PORT_E), |
||
201 | DP_TP_CTL_FDI_AUTOTRAIN | |
||
202 | DP_TP_CTL_LINK_TRAIN_NORMAL | |
||
203 | DP_TP_CTL_ENHANCED_FRAME_ENABLE | |
||
204 | DP_TP_CTL_ENABLE); |
||
205 | |||
206 | /* Enable PIPE_DDI_FUNC_CTL for the pipe to work in FDI mode */ |
||
207 | temp = I915_READ(DDI_FUNC_CTL(pipe)); |
||
208 | temp &= ~PIPE_DDI_PORT_MASK; |
||
209 | temp |= PIPE_DDI_SELECT_PORT(PORT_E) | |
||
210 | PIPE_DDI_MODE_SELECT_FDI | |
||
211 | PIPE_DDI_FUNC_ENABLE | |
||
212 | PIPE_DDI_PORT_WIDTH_X2; |
||
213 | I915_WRITE(DDI_FUNC_CTL(pipe), |
||
214 | temp); |
||
215 | break; |
||
216 | } else { |
||
217 | DRM_ERROR("Error training BUF_CTL %d\n", i); |
||
218 | |||
219 | /* Disable DP_TP_CTL and FDI_RX_CTL) and retry */ |
||
220 | I915_WRITE(DP_TP_CTL(PORT_E), |
||
221 | I915_READ(DP_TP_CTL(PORT_E)) & |
||
222 | ~DP_TP_CTL_ENABLE); |
||
223 | I915_WRITE(FDI_RX_CTL(pipe), |
||
224 | I915_READ(FDI_RX_CTL(pipe)) & |
||
225 | ~FDI_RX_PLL_ENABLE); |
||
226 | continue; |
||
227 | } |
||
228 | } |
||
229 | |||
230 | DRM_DEBUG_KMS("FDI train done.\n"); |
||
231 | } |
||
232 | |||
233 | /* For DDI connections, it is possible to support different outputs over the |
||
234 | * same DDI port, such as HDMI or DP or even VGA via FDI. So we don't know by |
||
235 | * the time the output is detected what exactly is on the other end of it. This |
||
236 | * function aims at providing support for this detection and proper output |
||
237 | * configuration. |
||
238 | */ |
||
239 | void intel_ddi_init(struct drm_device *dev, enum port port) |
||
240 | { |
||
241 | /* For now, we don't do any proper output detection and assume that we |
||
242 | * handle HDMI only */ |
||
243 | |||
244 | switch(port){ |
||
245 | case PORT_A: |
||
246 | /* We don't handle eDP and DP yet */ |
||
247 | DRM_DEBUG_DRIVER("Found digital output on DDI port A\n"); |
||
248 | break; |
||
249 | /* Assume that the ports B, C and D are working in HDMI mode for now */ |
||
250 | case PORT_B: |
||
251 | case PORT_C: |
||
252 | case PORT_D: |
||
253 | intel_hdmi_init(dev, DDI_BUF_CTL(port), port); |
||
254 | break; |
||
255 | default: |
||
256 | DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n", |
||
257 | port); |
||
258 | break; |
||
259 | } |
||
260 | } |
||
261 | |||
262 | /* WRPLL clock dividers */ |
||
263 | struct wrpll_tmds_clock { |
||
264 | u32 clock; |
||
265 | u16 p; /* Post divider */ |
||
266 | u16 n2; /* Feedback divider */ |
||
267 | u16 r2; /* Reference divider */ |
||
268 | }; |
||
269 | |||
270 | /* Table of matching values for WRPLL clocks programming for each frequency. |
||
271 | * The code assumes this table is sorted. */ |
||
272 | static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = { |
||
273 | {19750, 38, 25, 18}, |
||
274 | {20000, 48, 32, 18}, |
||
275 | {21000, 36, 21, 15}, |
||
276 | {21912, 42, 29, 17}, |
||
277 | {22000, 36, 22, 15}, |
||
278 | {23000, 36, 23, 15}, |
||
279 | {23500, 40, 40, 23}, |
||
280 | {23750, 26, 16, 14}, |
||
281 | {24000, 36, 24, 15}, |
||
282 | {25000, 36, 25, 15}, |
||
283 | {25175, 26, 40, 33}, |
||
284 | {25200, 30, 21, 15}, |
||
285 | {26000, 36, 26, 15}, |
||
286 | {27000, 30, 21, 14}, |
||
287 | {27027, 18, 100, 111}, |
||
288 | {27500, 30, 29, 19}, |
||
289 | {28000, 34, 30, 17}, |
||
290 | {28320, 26, 30, 22}, |
||
291 | {28322, 32, 42, 25}, |
||
292 | {28750, 24, 23, 18}, |
||
293 | {29000, 30, 29, 18}, |
||
294 | {29750, 32, 30, 17}, |
||
295 | {30000, 30, 25, 15}, |
||
296 | {30750, 30, 41, 24}, |
||
297 | {31000, 30, 31, 18}, |
||
298 | {31500, 30, 28, 16}, |
||
299 | {32000, 30, 32, 18}, |
||
300 | {32500, 28, 32, 19}, |
||
301 | {33000, 24, 22, 15}, |
||
302 | {34000, 28, 30, 17}, |
||
303 | {35000, 26, 32, 19}, |
||
304 | {35500, 24, 30, 19}, |
||
305 | {36000, 26, 26, 15}, |
||
306 | {36750, 26, 46, 26}, |
||
307 | {37000, 24, 23, 14}, |
||
308 | {37762, 22, 40, 26}, |
||
309 | {37800, 20, 21, 15}, |
||
310 | {38000, 24, 27, 16}, |
||
311 | {38250, 24, 34, 20}, |
||
312 | {39000, 24, 26, 15}, |
||
313 | {40000, 24, 32, 18}, |
||
314 | {40500, 20, 21, 14}, |
||
315 | {40541, 22, 147, 89}, |
||
316 | {40750, 18, 19, 14}, |
||
317 | {41000, 16, 17, 14}, |
||
318 | {41500, 22, 44, 26}, |
||
319 | {41540, 22, 44, 26}, |
||
320 | {42000, 18, 21, 15}, |
||
321 | {42500, 22, 45, 26}, |
||
322 | {43000, 20, 43, 27}, |
||
323 | {43163, 20, 24, 15}, |
||
324 | {44000, 18, 22, 15}, |
||
325 | {44900, 20, 108, 65}, |
||
326 | {45000, 20, 25, 15}, |
||
327 | {45250, 20, 52, 31}, |
||
328 | {46000, 18, 23, 15}, |
||
329 | {46750, 20, 45, 26}, |
||
330 | {47000, 20, 40, 23}, |
||
331 | {48000, 18, 24, 15}, |
||
332 | {49000, 18, 49, 30}, |
||
333 | {49500, 16, 22, 15}, |
||
334 | {50000, 18, 25, 15}, |
||
335 | {50500, 18, 32, 19}, |
||
336 | {51000, 18, 34, 20}, |
||
337 | {52000, 18, 26, 15}, |
||
338 | {52406, 14, 34, 25}, |
||
339 | {53000, 16, 22, 14}, |
||
340 | {54000, 16, 24, 15}, |
||
341 | {54054, 16, 173, 108}, |
||
342 | {54500, 14, 24, 17}, |
||
343 | {55000, 12, 22, 18}, |
||
344 | {56000, 14, 45, 31}, |
||
345 | {56250, 16, 25, 15}, |
||
346 | {56750, 14, 25, 17}, |
||
347 | {57000, 16, 27, 16}, |
||
348 | {58000, 16, 43, 25}, |
||
349 | {58250, 16, 38, 22}, |
||
350 | {58750, 16, 40, 23}, |
||
351 | {59000, 14, 26, 17}, |
||
352 | {59341, 14, 40, 26}, |
||
353 | {59400, 16, 44, 25}, |
||
354 | {60000, 16, 32, 18}, |
||
355 | {60500, 12, 39, 29}, |
||
356 | {61000, 14, 49, 31}, |
||
357 | {62000, 14, 37, 23}, |
||
358 | {62250, 14, 42, 26}, |
||
359 | {63000, 12, 21, 15}, |
||
360 | {63500, 14, 28, 17}, |
||
361 | {64000, 12, 27, 19}, |
||
362 | {65000, 14, 32, 19}, |
||
363 | {65250, 12, 29, 20}, |
||
364 | {65500, 12, 32, 22}, |
||
365 | {66000, 12, 22, 15}, |
||
366 | {66667, 14, 38, 22}, |
||
367 | {66750, 10, 21, 17}, |
||
368 | {67000, 14, 33, 19}, |
||
369 | {67750, 14, 58, 33}, |
||
370 | {68000, 14, 30, 17}, |
||
371 | {68179, 14, 46, 26}, |
||
372 | {68250, 14, 46, 26}, |
||
373 | {69000, 12, 23, 15}, |
||
374 | {70000, 12, 28, 18}, |
||
375 | {71000, 12, 30, 19}, |
||
376 | {72000, 12, 24, 15}, |
||
377 | {73000, 10, 23, 17}, |
||
378 | {74000, 12, 23, 14}, |
||
379 | {74176, 8, 100, 91}, |
||
380 | {74250, 10, 22, 16}, |
||
381 | {74481, 12, 43, 26}, |
||
382 | {74500, 10, 29, 21}, |
||
383 | {75000, 12, 25, 15}, |
||
384 | {75250, 10, 39, 28}, |
||
385 | {76000, 12, 27, 16}, |
||
386 | {77000, 12, 53, 31}, |
||
387 | {78000, 12, 26, 15}, |
||
388 | {78750, 12, 28, 16}, |
||
389 | {79000, 10, 38, 26}, |
||
390 | {79500, 10, 28, 19}, |
||
391 | {80000, 12, 32, 18}, |
||
392 | {81000, 10, 21, 14}, |
||
393 | {81081, 6, 100, 111}, |
||
394 | {81624, 8, 29, 24}, |
||
395 | {82000, 8, 17, 14}, |
||
396 | {83000, 10, 40, 26}, |
||
397 | {83950, 10, 28, 18}, |
||
398 | {84000, 10, 28, 18}, |
||
399 | {84750, 6, 16, 17}, |
||
400 | {85000, 6, 17, 18}, |
||
401 | {85250, 10, 30, 19}, |
||
402 | {85750, 10, 27, 17}, |
||
403 | {86000, 10, 43, 27}, |
||
404 | {87000, 10, 29, 18}, |
||
405 | {88000, 10, 44, 27}, |
||
406 | {88500, 10, 41, 25}, |
||
407 | {89000, 10, 28, 17}, |
||
408 | {89012, 6, 90, 91}, |
||
409 | {89100, 10, 33, 20}, |
||
410 | {90000, 10, 25, 15}, |
||
411 | {91000, 10, 32, 19}, |
||
412 | {92000, 10, 46, 27}, |
||
413 | {93000, 10, 31, 18}, |
||
414 | {94000, 10, 40, 23}, |
||
415 | {94500, 10, 28, 16}, |
||
416 | {95000, 10, 44, 25}, |
||
417 | {95654, 10, 39, 22}, |
||
418 | {95750, 10, 39, 22}, |
||
419 | {96000, 10, 32, 18}, |
||
420 | {97000, 8, 23, 16}, |
||
421 | {97750, 8, 42, 29}, |
||
422 | {98000, 8, 45, 31}, |
||
423 | {99000, 8, 22, 15}, |
||
424 | {99750, 8, 34, 23}, |
||
425 | {100000, 6, 20, 18}, |
||
426 | {100500, 6, 19, 17}, |
||
427 | {101000, 6, 37, 33}, |
||
428 | {101250, 8, 21, 14}, |
||
429 | {102000, 6, 17, 15}, |
||
430 | {102250, 6, 25, 22}, |
||
431 | {103000, 8, 29, 19}, |
||
432 | {104000, 8, 37, 24}, |
||
433 | {105000, 8, 28, 18}, |
||
434 | {106000, 8, 22, 14}, |
||
435 | {107000, 8, 46, 29}, |
||
436 | {107214, 8, 27, 17}, |
||
437 | {108000, 8, 24, 15}, |
||
438 | {108108, 8, 173, 108}, |
||
439 | {109000, 6, 23, 19}, |
||
440 | {110000, 6, 22, 18}, |
||
441 | {110013, 6, 22, 18}, |
||
442 | {110250, 8, 49, 30}, |
||
443 | {110500, 8, 36, 22}, |
||
444 | {111000, 8, 23, 14}, |
||
445 | {111264, 8, 150, 91}, |
||
446 | {111375, 8, 33, 20}, |
||
447 | {112000, 8, 63, 38}, |
||
448 | {112500, 8, 25, 15}, |
||
449 | {113100, 8, 57, 34}, |
||
450 | {113309, 8, 42, 25}, |
||
451 | {114000, 8, 27, 16}, |
||
452 | {115000, 6, 23, 18}, |
||
453 | {116000, 8, 43, 25}, |
||
454 | {117000, 8, 26, 15}, |
||
455 | {117500, 8, 40, 23}, |
||
456 | {118000, 6, 38, 29}, |
||
457 | {119000, 8, 30, 17}, |
||
458 | {119500, 8, 46, 26}, |
||
459 | {119651, 8, 39, 22}, |
||
460 | {120000, 8, 32, 18}, |
||
461 | {121000, 6, 39, 29}, |
||
462 | {121250, 6, 31, 23}, |
||
463 | {121750, 6, 23, 17}, |
||
464 | {122000, 6, 42, 31}, |
||
465 | {122614, 6, 30, 22}, |
||
466 | {123000, 6, 41, 30}, |
||
467 | {123379, 6, 37, 27}, |
||
468 | {124000, 6, 51, 37}, |
||
469 | {125000, 6, 25, 18}, |
||
470 | {125250, 4, 13, 14}, |
||
471 | {125750, 4, 27, 29}, |
||
472 | {126000, 6, 21, 15}, |
||
473 | {127000, 6, 24, 17}, |
||
474 | {127250, 6, 41, 29}, |
||
475 | {128000, 6, 27, 19}, |
||
476 | {129000, 6, 43, 30}, |
||
477 | {129859, 4, 25, 26}, |
||
478 | {130000, 6, 26, 18}, |
||
479 | {130250, 6, 42, 29}, |
||
480 | {131000, 6, 32, 22}, |
||
481 | {131500, 6, 38, 26}, |
||
482 | {131850, 6, 41, 28}, |
||
483 | {132000, 6, 22, 15}, |
||
484 | {132750, 6, 28, 19}, |
||
485 | {133000, 6, 34, 23}, |
||
486 | {133330, 6, 37, 25}, |
||
487 | {134000, 6, 61, 41}, |
||
488 | {135000, 6, 21, 14}, |
||
489 | {135250, 6, 167, 111}, |
||
490 | {136000, 6, 62, 41}, |
||
491 | {137000, 6, 35, 23}, |
||
492 | {138000, 6, 23, 15}, |
||
493 | {138500, 6, 40, 26}, |
||
494 | {138750, 6, 37, 24}, |
||
495 | {139000, 6, 34, 22}, |
||
496 | {139050, 6, 34, 22}, |
||
497 | {139054, 6, 34, 22}, |
||
498 | {140000, 6, 28, 18}, |
||
499 | {141000, 6, 36, 23}, |
||
500 | {141500, 6, 22, 14}, |
||
501 | {142000, 6, 30, 19}, |
||
502 | {143000, 6, 27, 17}, |
||
503 | {143472, 4, 17, 16}, |
||
504 | {144000, 6, 24, 15}, |
||
505 | {145000, 6, 29, 18}, |
||
506 | {146000, 6, 47, 29}, |
||
507 | {146250, 6, 26, 16}, |
||
508 | {147000, 6, 49, 30}, |
||
509 | {147891, 6, 23, 14}, |
||
510 | {148000, 6, 23, 14}, |
||
511 | {148250, 6, 28, 17}, |
||
512 | {148352, 4, 100, 91}, |
||
513 | {148500, 6, 33, 20}, |
||
514 | {149000, 6, 48, 29}, |
||
515 | {150000, 6, 25, 15}, |
||
516 | {151000, 4, 19, 17}, |
||
517 | {152000, 6, 27, 16}, |
||
518 | {152280, 6, 44, 26}, |
||
519 | {153000, 6, 34, 20}, |
||
520 | {154000, 6, 53, 31}, |
||
521 | {155000, 6, 31, 18}, |
||
522 | {155250, 6, 50, 29}, |
||
523 | {155750, 6, 45, 26}, |
||
524 | {156000, 6, 26, 15}, |
||
525 | {157000, 6, 61, 35}, |
||
526 | {157500, 6, 28, 16}, |
||
527 | {158000, 6, 65, 37}, |
||
528 | {158250, 6, 44, 25}, |
||
529 | {159000, 6, 53, 30}, |
||
530 | {159500, 6, 39, 22}, |
||
531 | {160000, 6, 32, 18}, |
||
532 | {161000, 4, 31, 26}, |
||
533 | {162000, 4, 18, 15}, |
||
534 | {162162, 4, 131, 109}, |
||
535 | {162500, 4, 53, 44}, |
||
536 | {163000, 4, 29, 24}, |
||
537 | {164000, 4, 17, 14}, |
||
538 | {165000, 4, 22, 18}, |
||
539 | {166000, 4, 32, 26}, |
||
540 | {167000, 4, 26, 21}, |
||
541 | {168000, 4, 46, 37}, |
||
542 | {169000, 4, 104, 83}, |
||
543 | {169128, 4, 64, 51}, |
||
544 | {169500, 4, 39, 31}, |
||
545 | {170000, 4, 34, 27}, |
||
546 | {171000, 4, 19, 15}, |
||
547 | {172000, 4, 51, 40}, |
||
548 | {172750, 4, 32, 25}, |
||
549 | {172800, 4, 32, 25}, |
||
550 | {173000, 4, 41, 32}, |
||
551 | {174000, 4, 49, 38}, |
||
552 | {174787, 4, 22, 17}, |
||
553 | {175000, 4, 35, 27}, |
||
554 | {176000, 4, 30, 23}, |
||
555 | {177000, 4, 38, 29}, |
||
556 | {178000, 4, 29, 22}, |
||
557 | {178500, 4, 37, 28}, |
||
558 | {179000, 4, 53, 40}, |
||
559 | {179500, 4, 73, 55}, |
||
560 | {180000, 4, 20, 15}, |
||
561 | {181000, 4, 55, 41}, |
||
562 | {182000, 4, 31, 23}, |
||
563 | {183000, 4, 42, 31}, |
||
564 | {184000, 4, 30, 22}, |
||
565 | {184750, 4, 26, 19}, |
||
566 | {185000, 4, 37, 27}, |
||
567 | {186000, 4, 51, 37}, |
||
568 | {187000, 4, 36, 26}, |
||
569 | {188000, 4, 32, 23}, |
||
570 | {189000, 4, 21, 15}, |
||
571 | {190000, 4, 38, 27}, |
||
572 | {190960, 4, 41, 29}, |
||
573 | {191000, 4, 41, 29}, |
||
574 | {192000, 4, 27, 19}, |
||
575 | {192250, 4, 37, 26}, |
||
576 | {193000, 4, 20, 14}, |
||
577 | {193250, 4, 53, 37}, |
||
578 | {194000, 4, 23, 16}, |
||
579 | {194208, 4, 23, 16}, |
||
580 | {195000, 4, 26, 18}, |
||
581 | {196000, 4, 45, 31}, |
||
582 | {197000, 4, 35, 24}, |
||
583 | {197750, 4, 41, 28}, |
||
584 | {198000, 4, 22, 15}, |
||
585 | {198500, 4, 25, 17}, |
||
586 | {199000, 4, 28, 19}, |
||
587 | {200000, 4, 37, 25}, |
||
588 | {201000, 4, 61, 41}, |
||
589 | {202000, 4, 112, 75}, |
||
590 | {202500, 4, 21, 14}, |
||
591 | {203000, 4, 146, 97}, |
||
592 | {204000, 4, 62, 41}, |
||
593 | {204750, 4, 44, 29}, |
||
594 | {205000, 4, 38, 25}, |
||
595 | {206000, 4, 29, 19}, |
||
596 | {207000, 4, 23, 15}, |
||
597 | {207500, 4, 40, 26}, |
||
598 | {208000, 4, 37, 24}, |
||
599 | {208900, 4, 48, 31}, |
||
600 | {209000, 4, 48, 31}, |
||
601 | {209250, 4, 31, 20}, |
||
602 | {210000, 4, 28, 18}, |
||
603 | {211000, 4, 25, 16}, |
||
604 | {212000, 4, 22, 14}, |
||
605 | {213000, 4, 30, 19}, |
||
606 | {213750, 4, 38, 24}, |
||
607 | {214000, 4, 46, 29}, |
||
608 | {214750, 4, 35, 22}, |
||
609 | {215000, 4, 43, 27}, |
||
610 | {216000, 4, 24, 15}, |
||
611 | {217000, 4, 37, 23}, |
||
612 | {218000, 4, 42, 26}, |
||
613 | {218250, 4, 42, 26}, |
||
614 | {218750, 4, 34, 21}, |
||
615 | {219000, 4, 47, 29}, |
||
616 | {220000, 4, 44, 27}, |
||
617 | {220640, 4, 49, 30}, |
||
618 | {220750, 4, 36, 22}, |
||
619 | {221000, 4, 36, 22}, |
||
620 | {222000, 4, 23, 14}, |
||
621 | {222525, 4, 28, 17}, |
||
622 | {222750, 4, 33, 20}, |
||
623 | {227000, 4, 37, 22}, |
||
624 | {230250, 4, 29, 17}, |
||
625 | {233500, 4, 38, 22}, |
||
626 | {235000, 4, 40, 23}, |
||
627 | {238000, 4, 30, 17}, |
||
628 | {241500, 2, 17, 19}, |
||
629 | {245250, 2, 20, 22}, |
||
630 | {247750, 2, 22, 24}, |
||
631 | {253250, 2, 15, 16}, |
||
632 | {256250, 2, 18, 19}, |
||
633 | {262500, 2, 31, 32}, |
||
634 | {267250, 2, 66, 67}, |
||
635 | {268500, 2, 94, 95}, |
||
636 | {270000, 2, 14, 14}, |
||
637 | {272500, 2, 77, 76}, |
||
638 | {273750, 2, 57, 56}, |
||
639 | {280750, 2, 24, 23}, |
||
640 | {281250, 2, 23, 22}, |
||
641 | {286000, 2, 17, 16}, |
||
642 | {291750, 2, 26, 24}, |
||
643 | {296703, 2, 56, 51}, |
||
644 | {297000, 2, 22, 20}, |
||
645 | {298000, 2, 21, 19}, |
||
646 | }; |
||
647 | |||
648 | void intel_ddi_mode_set(struct drm_encoder *encoder, |
||
649 | struct drm_display_mode *mode, |
||
650 | struct drm_display_mode *adjusted_mode) |
||
651 | { |
||
652 | struct drm_device *dev = encoder->dev; |
||
653 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
654 | struct drm_crtc *crtc = encoder->crtc; |
||
655 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
656 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
||
657 | int port = intel_hdmi->ddi_port; |
||
658 | int pipe = intel_crtc->pipe; |
||
659 | int p, n2, r2; |
||
660 | u32 temp, i; |
||
661 | |||
662 | /* On Haswell, we need to enable the clocks and prepare DDI function to |
||
663 | * work in HDMI mode for this pipe. |
||
664 | */ |
||
665 | DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe)); |
||
666 | |||
667 | for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++) |
||
668 | if (crtc->mode.clock <= wrpll_tmds_clock_table[i].clock) |
||
669 | break; |
||
670 | |||
671 | if (i == ARRAY_SIZE(wrpll_tmds_clock_table)) |
||
672 | i--; |
||
673 | |||
674 | p = wrpll_tmds_clock_table[i].p; |
||
675 | n2 = wrpll_tmds_clock_table[i].n2; |
||
676 | r2 = wrpll_tmds_clock_table[i].r2; |
||
677 | |||
678 | if (wrpll_tmds_clock_table[i].clock != crtc->mode.clock) |
||
679 | DRM_INFO("WR PLL: using settings for %dKHz on %dKHz mode\n", |
||
680 | wrpll_tmds_clock_table[i].clock, crtc->mode.clock); |
||
681 | |||
682 | DRM_DEBUG_KMS("WR PLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n", |
||
683 | crtc->mode.clock, p, n2, r2); |
||
684 | |||
685 | /* Enable LCPLL if disabled */ |
||
686 | temp = I915_READ(LCPLL_CTL); |
||
687 | if (temp & LCPLL_PLL_DISABLE) |
||
688 | I915_WRITE(LCPLL_CTL, |
||
689 | temp & ~LCPLL_PLL_DISABLE); |
||
690 | |||
691 | /* Configure WR PLL 1, program the correct divider values for |
||
692 | * the desired frequency and wait for warmup */ |
||
693 | I915_WRITE(WRPLL_CTL1, |
||
694 | WRPLL_PLL_ENABLE | |
||
695 | WRPLL_PLL_SELECT_LCPLL_2700 | |
||
696 | WRPLL_DIVIDER_REFERENCE(r2) | |
||
697 | WRPLL_DIVIDER_FEEDBACK(n2) | |
||
698 | WRPLL_DIVIDER_POST(p)); |
||
699 | |||
700 | udelay(20); |
||
701 | |||
702 | /* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use |
||
703 | * this port for connection. |
||
704 | */ |
||
705 | I915_WRITE(PORT_CLK_SEL(port), |
||
706 | PORT_CLK_SEL_WRPLL1); |
||
707 | I915_WRITE(PIPE_CLK_SEL(pipe), |
||
708 | PIPE_CLK_SEL_PORT(port)); |
||
709 | |||
710 | udelay(20); |
||
711 | |||
712 | if (intel_hdmi->has_audio) { |
||
713 | /* Proper support for digital audio needs a new logic and a new set |
||
714 | * of registers, so we leave it for future patch bombing. |
||
715 | */ |
||
716 | DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n", |
||
717 | pipe_name(intel_crtc->pipe)); |
||
718 | |||
719 | /* write eld */ |
||
720 | DRM_DEBUG_DRIVER("HDMI audio: write eld information\n"); |
||
721 | intel_write_eld(encoder, adjusted_mode); |
||
722 | } |
||
723 | |||
724 | /* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */ |
||
725 | temp = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port); |
||
726 | |||
727 | switch (intel_crtc->bpp) { |
||
728 | case 18: |
||
729 | temp |= PIPE_DDI_BPC_6; |
||
730 | break; |
||
731 | case 24: |
||
732 | temp |= PIPE_DDI_BPC_8; |
||
733 | break; |
||
734 | case 30: |
||
735 | temp |= PIPE_DDI_BPC_10; |
||
736 | break; |
||
737 | case 36: |
||
738 | temp |= PIPE_DDI_BPC_12; |
||
739 | break; |
||
740 | default: |
||
741 | WARN(1, "%d bpp unsupported by pipe DDI function\n", |
||
742 | intel_crtc->bpp); |
||
743 | } |
||
744 | |||
745 | if (intel_hdmi->has_hdmi_sink) |
||
746 | temp |= PIPE_DDI_MODE_SELECT_HDMI; |
||
747 | else |
||
748 | temp |= PIPE_DDI_MODE_SELECT_DVI; |
||
749 | |||
750 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
||
751 | temp |= PIPE_DDI_PVSYNC; |
||
752 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
||
753 | temp |= PIPE_DDI_PHSYNC; |
||
754 | |||
755 | I915_WRITE(DDI_FUNC_CTL(pipe), temp); |
||
756 | |||
757 | intel_hdmi->set_infoframes(encoder, adjusted_mode); |
||
758 | } |
||
759 | |||
760 | bool intel_ddi_get_hw_state(struct intel_encoder *encoder, |
||
761 | enum pipe *pipe) |
||
762 | { |
||
763 | struct drm_device *dev = encoder->base.dev; |
||
764 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
765 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
||
766 | u32 tmp; |
||
767 | int i; |
||
768 | |||
769 | tmp = I915_READ(DDI_BUF_CTL(intel_hdmi->ddi_port)); |
||
770 | |||
771 | if (!(tmp & DDI_BUF_CTL_ENABLE)) |
||
772 | return false; |
||
773 | |||
774 | for_each_pipe(i) { |
||
775 | tmp = I915_READ(DDI_FUNC_CTL(i)); |
||
776 | |||
777 | if ((tmp & PIPE_DDI_PORT_MASK) |
||
778 | == PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port)) { |
||
779 | *pipe = i; |
||
780 | return true; |
||
781 | } |
||
782 | } |
||
783 | |||
784 | DRM_DEBUG_KMS("No pipe for ddi port %i found\n", intel_hdmi->ddi_port); |
||
785 | |||
786 | return true; |
||
787 | } |
||
788 | |||
789 | void intel_enable_ddi(struct intel_encoder *encoder) |
||
790 | { |
||
791 | struct drm_device *dev = encoder->base.dev; |
||
792 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
793 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
||
794 | int port = intel_hdmi->ddi_port; |
||
795 | u32 temp; |
||
796 | |||
797 | temp = I915_READ(DDI_BUF_CTL(port)); |
||
798 | temp |= DDI_BUF_CTL_ENABLE; |
||
799 | |||
800 | /* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width, |
||
801 | * and swing/emphasis values are ignored so nothing special needs |
||
802 | * to be done besides enabling the port. |
||
803 | */ |
||
804 | I915_WRITE(DDI_BUF_CTL(port), temp); |
||
805 | } |
||
806 | |||
807 | void intel_disable_ddi(struct intel_encoder *encoder) |
||
808 | { |
||
809 | struct drm_device *dev = encoder->base.dev; |
||
810 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
811 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
||
812 | int port = intel_hdmi->ddi_port; |
||
813 | u32 temp; |
||
814 | |||
815 | temp = I915_READ(DDI_BUF_CTL(port)); |
||
816 | temp &= ~DDI_BUF_CTL_ENABLE; |
||
817 | |||
818 | I915_WRITE(DDI_BUF_CTL(port), temp); |
||
819 | }=>>>>> |