Rev 3746 | Rev 4280 | 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 | */ |
||
4104 | Serge | 87 | static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) |
3031 | serge | 88 | { |
89 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
90 | u32 reg; |
||
91 | int i; |
||
4104 | Serge | 92 | const u32 *ddi_translations = (port == PORT_E) ? |
3031 | serge | 93 | hsw_ddi_translations_fdi : |
4104 | Serge | 94 | hsw_ddi_translations_dp; |
3031 | serge | 95 | |
4104 | Serge | 96 | for (i = 0, reg = DDI_BUF_TRANS(port); |
97 | i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) { |
||
3031 | serge | 98 | I915_WRITE(reg, ddi_translations[i]); |
99 | reg += 4; |
||
100 | } |
||
101 | } |
||
102 | |||
103 | /* Program DDI buffers translations for DP. By default, program ports A-D in DP |
||
104 | * mode and port E for FDI. |
||
105 | */ |
||
106 | void intel_prepare_ddi(struct drm_device *dev) |
||
107 | { |
||
108 | int port; |
||
109 | |||
3480 | Serge | 110 | if (!HAS_DDI(dev)) |
111 | return; |
||
112 | |||
4104 | Serge | 113 | for (port = PORT_A; port <= PORT_E; port++) |
114 | intel_prepare_ddi_buffers(dev, port); |
||
3031 | serge | 115 | } |
116 | |||
117 | static const long hsw_ddi_buf_ctl_values[] = { |
||
118 | DDI_BUF_EMP_400MV_0DB_HSW, |
||
119 | DDI_BUF_EMP_400MV_3_5DB_HSW, |
||
120 | DDI_BUF_EMP_400MV_6DB_HSW, |
||
121 | DDI_BUF_EMP_400MV_9_5DB_HSW, |
||
122 | DDI_BUF_EMP_600MV_0DB_HSW, |
||
123 | DDI_BUF_EMP_600MV_3_5DB_HSW, |
||
124 | DDI_BUF_EMP_600MV_6DB_HSW, |
||
125 | DDI_BUF_EMP_800MV_0DB_HSW, |
||
126 | DDI_BUF_EMP_800MV_3_5DB_HSW |
||
127 | }; |
||
128 | |||
3243 | Serge | 129 | static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, |
130 | enum port port) |
||
131 | { |
||
132 | uint32_t reg = DDI_BUF_CTL(port); |
||
133 | int i; |
||
3031 | serge | 134 | |
3243 | Serge | 135 | for (i = 0; i < 8; i++) { |
136 | udelay(1); |
||
137 | if (I915_READ(reg) & DDI_BUF_IS_IDLE) |
||
138 | return; |
||
139 | } |
||
140 | DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port)); |
||
141 | } |
||
142 | |||
3031 | serge | 143 | /* Starting with Haswell, different DDI ports can work in FDI mode for |
144 | * connection to the PCH-located connectors. For this, it is necessary to train |
||
145 | * both the DDI port and PCH receiver for the desired DDI buffer settings. |
||
146 | * |
||
147 | * The recommended port to work in FDI mode is DDI E, which we use here. Also, |
||
148 | * please note that when FDI mode is active on DDI E, it shares 2 lines with |
||
149 | * DDI A (which is used for eDP) |
||
150 | */ |
||
151 | |||
152 | void hsw_fdi_link_train(struct drm_crtc *crtc) |
||
153 | { |
||
154 | struct drm_device *dev = crtc->dev; |
||
155 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
156 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
3243 | Serge | 157 | u32 temp, i, rx_ctl_val; |
3031 | serge | 158 | |
3243 | Serge | 159 | /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the |
160 | * mode set "sequence for CRT port" document: |
||
161 | * - TP1 to TP2 time with the default value |
||
162 | * - FDI delay to 90h |
||
4104 | Serge | 163 | * |
164 | * WaFDIAutoLinkSetTimingOverrride:hsw |
||
3243 | Serge | 165 | */ |
166 | I915_WRITE(_FDI_RXA_MISC, FDI_RX_PWRDN_LANE1_VAL(2) | |
||
167 | FDI_RX_PWRDN_LANE0_VAL(2) | |
||
168 | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90); |
||
3031 | serge | 169 | |
3243 | Serge | 170 | /* Enable the PCH Receiver FDI PLL */ |
3480 | Serge | 171 | rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE | |
4104 | Serge | 172 | FDI_RX_PLL_ENABLE | |
173 | FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes); |
||
3243 | Serge | 174 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
175 | POSTING_READ(_FDI_RXA_CTL); |
||
176 | udelay(220); |
||
3031 | serge | 177 | |
3243 | Serge | 178 | /* Switch from Rawclk to PCDclk */ |
179 | rx_ctl_val |= FDI_PCDCLK; |
||
180 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
3031 | serge | 181 | |
3243 | Serge | 182 | /* Configure Port Clock Select */ |
183 | I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->ddi_pll_sel); |
||
184 | |||
185 | /* Start the training iterating through available voltages and emphasis, |
||
186 | * testing each value twice. */ |
||
187 | for (i = 0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values) * 2; i++) { |
||
3031 | serge | 188 | /* Configure DP_TP_CTL with auto-training */ |
189 | I915_WRITE(DP_TP_CTL(PORT_E), |
||
190 | DP_TP_CTL_FDI_AUTOTRAIN | |
||
191 | DP_TP_CTL_ENHANCED_FRAME_ENABLE | |
||
192 | DP_TP_CTL_LINK_TRAIN_PAT1 | |
||
193 | DP_TP_CTL_ENABLE); |
||
194 | |||
3480 | Serge | 195 | /* Configure and enable DDI_BUF_CTL for DDI E with next voltage. |
196 | * DDI E does not support port reversal, the functionality is |
||
197 | * achieved on the PCH side in FDI_RX_CTL, so no need to set the |
||
198 | * port reversal bit */ |
||
3031 | serge | 199 | I915_WRITE(DDI_BUF_CTL(PORT_E), |
200 | DDI_BUF_CTL_ENABLE | |
||
4104 | Serge | 201 | ((intel_crtc->config.fdi_lanes - 1) << 1) | |
3243 | Serge | 202 | hsw_ddi_buf_ctl_values[i / 2]); |
203 | POSTING_READ(DDI_BUF_CTL(PORT_E)); |
||
3031 | serge | 204 | |
205 | udelay(600); |
||
206 | |||
3243 | Serge | 207 | /* Program PCH FDI Receiver TU */ |
208 | I915_WRITE(_FDI_RXA_TUSIZE1, TU_SIZE(64)); |
||
3031 | serge | 209 | |
3243 | Serge | 210 | /* Enable PCH FDI Receiver with auto-training */ |
211 | rx_ctl_val |= FDI_RX_ENABLE | FDI_LINK_TRAIN_AUTO; |
||
212 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
213 | POSTING_READ(_FDI_RXA_CTL); |
||
3031 | serge | 214 | |
3243 | Serge | 215 | /* Wait for FDI receiver lane calibration */ |
216 | udelay(30); |
||
217 | |||
218 | /* Unset FDI_RX_MISC pwrdn lanes */ |
||
219 | temp = I915_READ(_FDI_RXA_MISC); |
||
220 | temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); |
||
221 | I915_WRITE(_FDI_RXA_MISC, temp); |
||
222 | POSTING_READ(_FDI_RXA_MISC); |
||
223 | |||
224 | /* Wait for FDI auto training time */ |
||
225 | udelay(5); |
||
226 | |||
3031 | serge | 227 | temp = I915_READ(DP_TP_STATUS(PORT_E)); |
228 | if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) { |
||
3243 | Serge | 229 | DRM_DEBUG_KMS("FDI link training done on step %d\n", i); |
3031 | serge | 230 | |
231 | /* Enable normal pixel sending for FDI */ |
||
232 | I915_WRITE(DP_TP_CTL(PORT_E), |
||
233 | DP_TP_CTL_FDI_AUTOTRAIN | |
||
234 | DP_TP_CTL_LINK_TRAIN_NORMAL | |
||
235 | DP_TP_CTL_ENHANCED_FRAME_ENABLE | |
||
236 | DP_TP_CTL_ENABLE); |
||
237 | |||
3243 | Serge | 238 | return; |
3031 | serge | 239 | } |
240 | |||
3243 | Serge | 241 | temp = I915_READ(DDI_BUF_CTL(PORT_E)); |
242 | temp &= ~DDI_BUF_CTL_ENABLE; |
||
243 | I915_WRITE(DDI_BUF_CTL(PORT_E), temp); |
||
244 | POSTING_READ(DDI_BUF_CTL(PORT_E)); |
||
3031 | serge | 245 | |
3243 | Serge | 246 | /* Disable DP_TP_CTL and FDI_RX_CTL and retry */ |
247 | temp = I915_READ(DP_TP_CTL(PORT_E)); |
||
248 | temp &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); |
||
249 | temp |= DP_TP_CTL_LINK_TRAIN_PAT1; |
||
250 | I915_WRITE(DP_TP_CTL(PORT_E), temp); |
||
251 | POSTING_READ(DP_TP_CTL(PORT_E)); |
||
3031 | serge | 252 | |
3243 | Serge | 253 | intel_wait_ddi_buf_idle(dev_priv, PORT_E); |
254 | |||
255 | rx_ctl_val &= ~FDI_RX_ENABLE; |
||
256 | I915_WRITE(_FDI_RXA_CTL, rx_ctl_val); |
||
257 | POSTING_READ(_FDI_RXA_CTL); |
||
258 | |||
259 | /* Reset FDI_RX_MISC pwrdn lanes */ |
||
260 | temp = I915_READ(_FDI_RXA_MISC); |
||
261 | temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); |
||
262 | temp |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); |
||
263 | I915_WRITE(_FDI_RXA_MISC, temp); |
||
264 | POSTING_READ(_FDI_RXA_MISC); |
||
3031 | serge | 265 | } |
3243 | Serge | 266 | |
267 | DRM_ERROR("FDI link training failed!\n"); |
||
3031 | serge | 268 | } |
269 | |||
4104 | Serge | 270 | static void intel_ddi_mode_set(struct intel_encoder *encoder) |
3031 | serge | 271 | { |
4104 | Serge | 272 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
273 | int port = intel_ddi_get_encoder_port(encoder); |
||
274 | int pipe = crtc->pipe; |
||
275 | int type = encoder->type; |
||
276 | struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode; |
||
3031 | serge | 277 | |
4104 | Serge | 278 | DRM_DEBUG_KMS("Preparing DDI mode on port %c, pipe %c\n", |
3243 | Serge | 279 | port_name(port), pipe_name(pipe)); |
3031 | serge | 280 | |
4104 | Serge | 281 | crtc->eld_vld = false; |
3243 | Serge | 282 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
4104 | Serge | 283 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
3480 | Serge | 284 | struct intel_digital_port *intel_dig_port = |
4104 | Serge | 285 | enc_to_dig_port(&encoder->base); |
3243 | Serge | 286 | |
4104 | Serge | 287 | intel_dp->DP = intel_dig_port->saved_port_bits | |
3480 | Serge | 288 | DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW; |
4104 | Serge | 289 | intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count); |
3243 | Serge | 290 | |
291 | if (intel_dp->has_audio) { |
||
292 | DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n", |
||
4104 | Serge | 293 | pipe_name(crtc->pipe)); |
3243 | Serge | 294 | |
295 | /* write eld */ |
||
296 | DRM_DEBUG_DRIVER("DP audio: write eld information\n"); |
||
4104 | Serge | 297 | intel_write_eld(&encoder->base, adjusted_mode); |
3243 | Serge | 298 | } |
299 | |||
300 | intel_dp_init_link_config(intel_dp); |
||
301 | |||
302 | } else if (type == INTEL_OUTPUT_HDMI) { |
||
4104 | Serge | 303 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
3243 | Serge | 304 | |
305 | if (intel_hdmi->has_audio) { |
||
306 | /* Proper support for digital audio needs a new logic |
||
307 | * and a new set of registers, so we leave it for future |
||
308 | * patch bombing. |
||
309 | */ |
||
310 | DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n", |
||
4104 | Serge | 311 | pipe_name(crtc->pipe)); |
3243 | Serge | 312 | |
313 | /* write eld */ |
||
314 | DRM_DEBUG_DRIVER("HDMI audio: write eld information\n"); |
||
4104 | Serge | 315 | intel_write_eld(&encoder->base, adjusted_mode); |
3243 | Serge | 316 | } |
317 | |||
4104 | Serge | 318 | intel_hdmi->set_infoframes(&encoder->base, adjusted_mode); |
3243 | Serge | 319 | } |
320 | } |
||
321 | |||
322 | static struct intel_encoder * |
||
323 | intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) |
||
324 | { |
||
325 | struct drm_device *dev = crtc->dev; |
||
326 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
327 | struct intel_encoder *intel_encoder, *ret = NULL; |
||
328 | int num_encoders = 0; |
||
329 | |||
330 | for_each_encoder_on_crtc(dev, crtc, intel_encoder) { |
||
331 | ret = intel_encoder; |
||
332 | num_encoders++; |
||
333 | } |
||
334 | |||
335 | if (num_encoders != 1) |
||
4104 | Serge | 336 | WARN(1, "%d encoders on crtc for pipe %c\n", num_encoders, |
337 | pipe_name(intel_crtc->pipe)); |
||
3243 | Serge | 338 | |
339 | BUG_ON(ret == NULL); |
||
340 | return ret; |
||
341 | } |
||
342 | |||
343 | void intel_ddi_put_crtc_pll(struct drm_crtc *crtc) |
||
344 | { |
||
345 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
346 | struct intel_ddi_plls *plls = &dev_priv->ddi_plls; |
||
347 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
348 | uint32_t val; |
||
349 | |||
350 | switch (intel_crtc->ddi_pll_sel) { |
||
351 | case PORT_CLK_SEL_SPLL: |
||
352 | plls->spll_refcount--; |
||
353 | if (plls->spll_refcount == 0) { |
||
354 | DRM_DEBUG_KMS("Disabling SPLL\n"); |
||
355 | val = I915_READ(SPLL_CTL); |
||
356 | WARN_ON(!(val & SPLL_PLL_ENABLE)); |
||
357 | I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE); |
||
358 | POSTING_READ(SPLL_CTL); |
||
359 | } |
||
360 | break; |
||
361 | case PORT_CLK_SEL_WRPLL1: |
||
362 | plls->wrpll1_refcount--; |
||
363 | if (plls->wrpll1_refcount == 0) { |
||
364 | DRM_DEBUG_KMS("Disabling WRPLL 1\n"); |
||
365 | val = I915_READ(WRPLL_CTL1); |
||
366 | WARN_ON(!(val & WRPLL_PLL_ENABLE)); |
||
367 | I915_WRITE(WRPLL_CTL1, val & ~WRPLL_PLL_ENABLE); |
||
368 | POSTING_READ(WRPLL_CTL1); |
||
369 | } |
||
370 | break; |
||
371 | case PORT_CLK_SEL_WRPLL2: |
||
372 | plls->wrpll2_refcount--; |
||
373 | if (plls->wrpll2_refcount == 0) { |
||
374 | DRM_DEBUG_KMS("Disabling WRPLL 2\n"); |
||
375 | val = I915_READ(WRPLL_CTL2); |
||
376 | WARN_ON(!(val & WRPLL_PLL_ENABLE)); |
||
377 | I915_WRITE(WRPLL_CTL2, val & ~WRPLL_PLL_ENABLE); |
||
378 | POSTING_READ(WRPLL_CTL2); |
||
379 | } |
||
380 | break; |
||
381 | } |
||
382 | |||
383 | WARN(plls->spll_refcount < 0, "Invalid SPLL refcount\n"); |
||
384 | WARN(plls->wrpll1_refcount < 0, "Invalid WRPLL1 refcount\n"); |
||
385 | WARN(plls->wrpll2_refcount < 0, "Invalid WRPLL2 refcount\n"); |
||
386 | |||
387 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE; |
||
388 | } |
||
389 | |||
4104 | Serge | 390 | #define LC_FREQ 2700 |
391 | #define LC_FREQ_2K (LC_FREQ * 2000) |
||
392 | |||
393 | #define P_MIN 2 |
||
394 | #define P_MAX 64 |
||
395 | #define P_INC 2 |
||
396 | |||
397 | /* Constraints for PLL good behavior */ |
||
398 | #define REF_MIN 48 |
||
399 | #define REF_MAX 400 |
||
400 | #define VCO_MIN 2400 |
||
401 | #define VCO_MAX 4800 |
||
402 | |||
403 | #define ABS_DIFF(a, b) ((a > b) ? (a - b) : (b - a)) |
||
404 | |||
405 | struct wrpll_rnp { |
||
406 | unsigned p, n2, r2; |
||
407 | }; |
||
408 | |||
409 | static unsigned wrpll_get_budget_for_freq(int clock) |
||
3243 | Serge | 410 | { |
4104 | Serge | 411 | unsigned budget; |
3243 | Serge | 412 | |
4104 | Serge | 413 | switch (clock) { |
414 | case 25175000: |
||
415 | case 25200000: |
||
416 | case 27000000: |
||
417 | case 27027000: |
||
418 | case 37762500: |
||
419 | case 37800000: |
||
420 | case 40500000: |
||
421 | case 40541000: |
||
422 | case 54000000: |
||
423 | case 54054000: |
||
424 | case 59341000: |
||
425 | case 59400000: |
||
426 | case 72000000: |
||
427 | case 74176000: |
||
428 | case 74250000: |
||
429 | case 81000000: |
||
430 | case 81081000: |
||
431 | case 89012000: |
||
432 | case 89100000: |
||
433 | case 108000000: |
||
434 | case 108108000: |
||
435 | case 111264000: |
||
436 | case 111375000: |
||
437 | case 148352000: |
||
438 | case 148500000: |
||
439 | case 162000000: |
||
440 | case 162162000: |
||
441 | case 222525000: |
||
442 | case 222750000: |
||
443 | case 296703000: |
||
444 | case 297000000: |
||
445 | budget = 0; |
||
446 | break; |
||
447 | case 233500000: |
||
448 | case 245250000: |
||
449 | case 247750000: |
||
450 | case 253250000: |
||
451 | case 298000000: |
||
452 | budget = 1500; |
||
453 | break; |
||
454 | case 169128000: |
||
455 | case 169500000: |
||
456 | case 179500000: |
||
457 | case 202000000: |
||
458 | budget = 2000; |
||
459 | break; |
||
460 | case 256250000: |
||
461 | case 262500000: |
||
462 | case 270000000: |
||
463 | case 272500000: |
||
464 | case 273750000: |
||
465 | case 280750000: |
||
466 | case 281250000: |
||
467 | case 286000000: |
||
468 | case 291750000: |
||
469 | budget = 4000; |
||
470 | break; |
||
471 | case 267250000: |
||
472 | case 268500000: |
||
473 | budget = 5000; |
||
3031 | serge | 474 | break; |
4104 | Serge | 475 | default: |
476 | budget = 1000; |
||
477 | break; |
||
478 | } |
||
3031 | serge | 479 | |
4104 | Serge | 480 | return budget; |
481 | } |
||
3031 | serge | 482 | |
4104 | Serge | 483 | static void wrpll_update_rnp(uint64_t freq2k, unsigned budget, |
484 | unsigned r2, unsigned n2, unsigned p, |
||
485 | struct wrpll_rnp *best) |
||
486 | { |
||
487 | uint64_t a, b, c, d, diff, diff_best; |
||
3031 | serge | 488 | |
4104 | Serge | 489 | /* No best (r,n,p) yet */ |
490 | if (best->p == 0) { |
||
491 | best->p = p; |
||
492 | best->n2 = n2; |
||
493 | best->r2 = r2; |
||
494 | return; |
||
495 | } |
||
3031 | serge | 496 | |
4104 | Serge | 497 | /* |
498 | * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to |
||
499 | * freq2k. |
||
500 | * |
||
501 | * delta = 1e6 * |
||
502 | * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) / |
||
503 | * freq2k; |
||
504 | * |
||
505 | * and we would like delta <= budget. |
||
506 | * |
||
507 | * If the discrepancy is above the PPM-based budget, always prefer to |
||
508 | * improve upon the previous solution. However, if you're within the |
||
509 | * budget, try to maximize Ref * VCO, that is N / (P * R^2). |
||
510 | */ |
||
511 | a = freq2k * budget * p * r2; |
||
512 | b = freq2k * budget * best->p * best->r2; |
||
513 | diff = ABS_DIFF((freq2k * p * r2), (LC_FREQ_2K * n2)); |
||
514 | diff_best = ABS_DIFF((freq2k * best->p * best->r2), |
||
515 | (LC_FREQ_2K * best->n2)); |
||
516 | c = 1000000 * diff; |
||
517 | d = 1000000 * diff_best; |
||
518 | |||
519 | if (a < c && b < d) { |
||
520 | /* If both are above the budget, pick the closer */ |
||
521 | if (best->p * best->r2 * diff < p * r2 * diff_best) { |
||
522 | best->p = p; |
||
523 | best->n2 = n2; |
||
524 | best->r2 = r2; |
||
525 | } |
||
526 | } else if (a >= c && b < d) { |
||
527 | /* If A is below the threshold but B is above it? Update. */ |
||
528 | best->p = p; |
||
529 | best->n2 = n2; |
||
530 | best->r2 = r2; |
||
531 | } else if (a >= c && b >= d) { |
||
532 | /* Both are below the limit, so pick the higher n2/(r2*r2) */ |
||
533 | if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) { |
||
534 | best->p = p; |
||
535 | best->n2 = n2; |
||
536 | best->r2 = r2; |
||
537 | } |
||
538 | } |
||
539 | /* Otherwise a < c && b >= d, do nothing */ |
||
3243 | Serge | 540 | } |
3031 | serge | 541 | |
4104 | Serge | 542 | static void |
543 | intel_ddi_calculate_wrpll(int clock /* in Hz */, |
||
544 | unsigned *r2_out, unsigned *n2_out, unsigned *p_out) |
||
3243 | Serge | 545 | { |
4104 | Serge | 546 | uint64_t freq2k; |
547 | unsigned p, n2, r2; |
||
548 | struct wrpll_rnp best = { 0, 0, 0 }; |
||
549 | unsigned budget; |
||
550 | |||
551 | freq2k = clock / 100; |
||
552 | |||
553 | budget = wrpll_get_budget_for_freq(clock); |
||
554 | |||
555 | /* Special case handling for 540 pixel clock: bypass WR PLL entirely |
||
556 | * and directly pass the LC PLL to it. */ |
||
557 | if (freq2k == 5400000) { |
||
558 | *n2_out = 2; |
||
559 | *p_out = 1; |
||
560 | *r2_out = 2; |
||
561 | return; |
||
562 | } |
||
563 | |||
564 | /* |
||
565 | * Ref = LC_FREQ / R, where Ref is the actual reference input seen by |
||
566 | * the WR PLL. |
||
567 | * |
||
568 | * We want R so that REF_MIN <= Ref <= REF_MAX. |
||
569 | * Injecting R2 = 2 * R gives: |
||
570 | * REF_MAX * r2 > LC_FREQ * 2 and |
||
571 | * REF_MIN * r2 < LC_FREQ * 2 |
||
572 | * |
||
573 | * Which means the desired boundaries for r2 are: |
||
574 | * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN |
||
575 | * |
||
576 | */ |
||
577 | for (r2 = LC_FREQ * 2 / REF_MAX + 1; |
||
578 | r2 <= LC_FREQ * 2 / REF_MIN; |
||
579 | r2++) { |
||
580 | |||
581 | /* |
||
582 | * VCO = N * Ref, that is: VCO = N * LC_FREQ / R |
||
583 | * |
||
584 | * Once again we want VCO_MIN <= VCO <= VCO_MAX. |
||
585 | * Injecting R2 = 2 * R and N2 = 2 * N, we get: |
||
586 | * VCO_MAX * r2 > n2 * LC_FREQ and |
||
587 | * VCO_MIN * r2 < n2 * LC_FREQ) |
||
588 | * |
||
589 | * Which means the desired boundaries for n2 are: |
||
590 | * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ |
||
591 | */ |
||
592 | for (n2 = VCO_MIN * r2 / LC_FREQ + 1; |
||
593 | n2 <= VCO_MAX * r2 / LC_FREQ; |
||
594 | n2++) { |
||
595 | |||
596 | for (p = P_MIN; p <= P_MAX; p += P_INC) |
||
597 | wrpll_update_rnp(freq2k, budget, |
||
598 | r2, n2, p, &best); |
||
599 | } |
||
600 | } |
||
601 | |||
602 | *n2_out = best.n2; |
||
603 | *p_out = best.p; |
||
604 | *r2_out = best.r2; |
||
605 | |||
606 | DRM_DEBUG_KMS("WRPLL: %dHz refresh rate with p=%d, n2=%d r2=%d\n", |
||
607 | clock, *p_out, *n2_out, *r2_out); |
||
608 | } |
||
609 | |||
610 | bool intel_ddi_pll_mode_set(struct drm_crtc *crtc) |
||
611 | { |
||
3243 | Serge | 612 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
613 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
614 | struct drm_encoder *encoder = &intel_encoder->base; |
||
615 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
616 | struct intel_ddi_plls *plls = &dev_priv->ddi_plls; |
||
617 | int type = intel_encoder->type; |
||
618 | enum pipe pipe = intel_crtc->pipe; |
||
619 | uint32_t reg, val; |
||
4104 | Serge | 620 | int clock = intel_crtc->config.port_clock; |
3031 | serge | 621 | |
3243 | Serge | 622 | /* TODO: reuse PLLs when possible (compare values) */ |
3031 | serge | 623 | |
3243 | Serge | 624 | intel_ddi_put_crtc_pll(crtc); |
3031 | serge | 625 | |
3243 | Serge | 626 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
627 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
3031 | serge | 628 | |
3243 | Serge | 629 | switch (intel_dp->link_bw) { |
630 | case DP_LINK_BW_1_62: |
||
631 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810; |
||
632 | break; |
||
633 | case DP_LINK_BW_2_7: |
||
634 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350; |
||
635 | break; |
||
636 | case DP_LINK_BW_5_4: |
||
637 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700; |
||
638 | break; |
||
639 | default: |
||
640 | DRM_ERROR("Link bandwidth %d unsupported\n", |
||
641 | intel_dp->link_bw); |
||
642 | return false; |
||
643 | } |
||
644 | |||
645 | /* We don't need to turn any PLL on because we'll use LCPLL. */ |
||
646 | return true; |
||
647 | |||
648 | } else if (type == INTEL_OUTPUT_HDMI) { |
||
4104 | Serge | 649 | unsigned p, n2, r2; |
3243 | Serge | 650 | |
651 | if (plls->wrpll1_refcount == 0) { |
||
652 | DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n", |
||
653 | pipe_name(pipe)); |
||
654 | plls->wrpll1_refcount++; |
||
655 | reg = WRPLL_CTL1; |
||
656 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1; |
||
657 | } else if (plls->wrpll2_refcount == 0) { |
||
658 | DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n", |
||
659 | pipe_name(pipe)); |
||
660 | plls->wrpll2_refcount++; |
||
661 | reg = WRPLL_CTL2; |
||
662 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2; |
||
663 | } else { |
||
664 | DRM_ERROR("No WRPLLs available!\n"); |
||
665 | return false; |
||
666 | } |
||
667 | |||
668 | WARN(I915_READ(reg) & WRPLL_PLL_ENABLE, |
||
669 | "WRPLL already enabled\n"); |
||
670 | |||
4104 | Serge | 671 | intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); |
3243 | Serge | 672 | |
673 | val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 | |
||
674 | WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | |
||
675 | WRPLL_DIVIDER_POST(p); |
||
676 | |||
677 | } else if (type == INTEL_OUTPUT_ANALOG) { |
||
678 | if (plls->spll_refcount == 0) { |
||
679 | DRM_DEBUG_KMS("Using SPLL on pipe %c\n", |
||
680 | pipe_name(pipe)); |
||
681 | plls->spll_refcount++; |
||
682 | reg = SPLL_CTL; |
||
683 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL; |
||
3746 | Serge | 684 | } else { |
685 | DRM_ERROR("SPLL already in use\n"); |
||
686 | return false; |
||
3243 | Serge | 687 | } |
688 | |||
689 | WARN(I915_READ(reg) & SPLL_PLL_ENABLE, |
||
690 | "SPLL already enabled\n"); |
||
691 | |||
692 | val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC; |
||
693 | |||
694 | } else { |
||
695 | WARN(1, "Invalid DDI encoder type %d\n", type); |
||
696 | return false; |
||
697 | } |
||
698 | |||
699 | I915_WRITE(reg, val); |
||
3031 | serge | 700 | udelay(20); |
701 | |||
3243 | Serge | 702 | return true; |
703 | } |
||
3031 | serge | 704 | |
3243 | Serge | 705 | void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) |
706 | { |
||
707 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
708 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
709 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
3746 | Serge | 710 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
3243 | Serge | 711 | int type = intel_encoder->type; |
712 | uint32_t temp; |
||
713 | |||
714 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
||
715 | |||
716 | temp = TRANS_MSA_SYNC_CLK; |
||
3746 | Serge | 717 | switch (intel_crtc->config.pipe_bpp) { |
3243 | Serge | 718 | case 18: |
719 | temp |= TRANS_MSA_6_BPC; |
||
720 | break; |
||
721 | case 24: |
||
722 | temp |= TRANS_MSA_8_BPC; |
||
723 | break; |
||
724 | case 30: |
||
725 | temp |= TRANS_MSA_10_BPC; |
||
726 | break; |
||
727 | case 36: |
||
728 | temp |= TRANS_MSA_12_BPC; |
||
729 | break; |
||
730 | default: |
||
3746 | Serge | 731 | BUG(); |
3031 | serge | 732 | } |
3243 | Serge | 733 | I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp); |
734 | } |
||
735 | } |
||
3031 | serge | 736 | |
3746 | Serge | 737 | void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) |
3243 | Serge | 738 | { |
739 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
740 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
741 | struct drm_encoder *encoder = &intel_encoder->base; |
||
742 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
743 | enum pipe pipe = intel_crtc->pipe; |
||
3746 | Serge | 744 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
3243 | Serge | 745 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
746 | int type = intel_encoder->type; |
||
747 | uint32_t temp; |
||
3031 | serge | 748 | |
3243 | Serge | 749 | /* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */ |
750 | temp = TRANS_DDI_FUNC_ENABLE; |
||
751 | temp |= TRANS_DDI_SELECT_PORT(port); |
||
752 | |||
3746 | Serge | 753 | switch (intel_crtc->config.pipe_bpp) { |
3031 | serge | 754 | case 18: |
3243 | Serge | 755 | temp |= TRANS_DDI_BPC_6; |
3031 | serge | 756 | break; |
757 | case 24: |
||
3243 | Serge | 758 | temp |= TRANS_DDI_BPC_8; |
3031 | serge | 759 | break; |
760 | case 30: |
||
3243 | Serge | 761 | temp |= TRANS_DDI_BPC_10; |
3031 | serge | 762 | break; |
763 | case 36: |
||
3243 | Serge | 764 | temp |= TRANS_DDI_BPC_12; |
3031 | serge | 765 | break; |
766 | default: |
||
3746 | Serge | 767 | BUG(); |
3031 | serge | 768 | } |
769 | |||
3243 | Serge | 770 | if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC) |
771 | temp |= TRANS_DDI_PVSYNC; |
||
772 | if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC) |
||
773 | temp |= TRANS_DDI_PHSYNC; |
||
774 | |||
775 | if (cpu_transcoder == TRANSCODER_EDP) { |
||
776 | switch (pipe) { |
||
777 | case PIPE_A: |
||
3480 | Serge | 778 | /* Can only use the always-on power well for eDP when |
779 | * not using the panel fitter, and when not using motion |
||
780 | * blur mitigation (which we don't support). */ |
||
4104 | Serge | 781 | if (intel_crtc->config.pch_pfit.enabled) |
3243 | Serge | 782 | temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; |
3480 | Serge | 783 | else |
784 | temp |= TRANS_DDI_EDP_INPUT_A_ON; |
||
3243 | Serge | 785 | break; |
786 | case PIPE_B: |
||
787 | temp |= TRANS_DDI_EDP_INPUT_B_ONOFF; |
||
788 | break; |
||
789 | case PIPE_C: |
||
790 | temp |= TRANS_DDI_EDP_INPUT_C_ONOFF; |
||
791 | break; |
||
792 | default: |
||
793 | BUG(); |
||
794 | break; |
||
795 | } |
||
796 | } |
||
797 | |||
798 | if (type == INTEL_OUTPUT_HDMI) { |
||
799 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
||
800 | |||
3031 | serge | 801 | if (intel_hdmi->has_hdmi_sink) |
3243 | Serge | 802 | temp |= TRANS_DDI_MODE_SELECT_HDMI; |
3031 | serge | 803 | else |
3243 | Serge | 804 | temp |= TRANS_DDI_MODE_SELECT_DVI; |
3031 | serge | 805 | |
3243 | Serge | 806 | } else if (type == INTEL_OUTPUT_ANALOG) { |
807 | temp |= TRANS_DDI_MODE_SELECT_FDI; |
||
4104 | Serge | 808 | temp |= (intel_crtc->config.fdi_lanes - 1) << 1; |
3031 | serge | 809 | |
3243 | Serge | 810 | } else if (type == INTEL_OUTPUT_DISPLAYPORT || |
811 | type == INTEL_OUTPUT_EDP) { |
||
812 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
3031 | serge | 813 | |
3243 | Serge | 814 | temp |= TRANS_DDI_MODE_SELECT_DP_SST; |
815 | |||
4104 | Serge | 816 | temp |= DDI_PORT_WIDTH(intel_dp->lane_count); |
3243 | Serge | 817 | } else { |
4104 | Serge | 818 | WARN(1, "Invalid encoder type %d for pipe %c\n", |
819 | intel_encoder->type, pipe_name(pipe)); |
||
3243 | Serge | 820 | } |
821 | |||
822 | I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp); |
||
3031 | serge | 823 | } |
824 | |||
3243 | Serge | 825 | void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, |
826 | enum transcoder cpu_transcoder) |
||
827 | { |
||
828 | uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder); |
||
829 | uint32_t val = I915_READ(reg); |
||
830 | |||
831 | val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK); |
||
832 | val |= TRANS_DDI_PORT_NONE; |
||
833 | I915_WRITE(reg, val); |
||
834 | } |
||
835 | |||
836 | bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector) |
||
837 | { |
||
838 | struct drm_device *dev = intel_connector->base.dev; |
||
839 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
840 | struct intel_encoder *intel_encoder = intel_connector->encoder; |
||
841 | int type = intel_connector->base.connector_type; |
||
842 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
843 | enum pipe pipe = 0; |
||
844 | enum transcoder cpu_transcoder; |
||
845 | uint32_t tmp; |
||
846 | |||
847 | if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) |
||
848 | return false; |
||
849 | |||
850 | if (port == PORT_A) |
||
851 | cpu_transcoder = TRANSCODER_EDP; |
||
852 | else |
||
3480 | Serge | 853 | cpu_transcoder = (enum transcoder) pipe; |
3243 | Serge | 854 | |
855 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
||
856 | |||
857 | switch (tmp & TRANS_DDI_MODE_SELECT_MASK) { |
||
858 | case TRANS_DDI_MODE_SELECT_HDMI: |
||
859 | case TRANS_DDI_MODE_SELECT_DVI: |
||
860 | return (type == DRM_MODE_CONNECTOR_HDMIA); |
||
861 | |||
862 | case TRANS_DDI_MODE_SELECT_DP_SST: |
||
863 | if (type == DRM_MODE_CONNECTOR_eDP) |
||
864 | return true; |
||
865 | case TRANS_DDI_MODE_SELECT_DP_MST: |
||
866 | return (type == DRM_MODE_CONNECTOR_DisplayPort); |
||
867 | |||
868 | case TRANS_DDI_MODE_SELECT_FDI: |
||
869 | return (type == DRM_MODE_CONNECTOR_VGA); |
||
870 | |||
871 | default: |
||
872 | return false; |
||
873 | } |
||
874 | } |
||
875 | |||
3031 | serge | 876 | bool intel_ddi_get_hw_state(struct intel_encoder *encoder, |
877 | enum pipe *pipe) |
||
878 | { |
||
879 | struct drm_device *dev = encoder->base.dev; |
||
880 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
3243 | Serge | 881 | enum port port = intel_ddi_get_encoder_port(encoder); |
3031 | serge | 882 | u32 tmp; |
883 | int i; |
||
884 | |||
3243 | Serge | 885 | tmp = I915_READ(DDI_BUF_CTL(port)); |
3031 | serge | 886 | |
887 | if (!(tmp & DDI_BUF_CTL_ENABLE)) |
||
888 | return false; |
||
889 | |||
3243 | Serge | 890 | if (port == PORT_A) { |
891 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); |
||
3031 | serge | 892 | |
3243 | Serge | 893 | switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { |
894 | case TRANS_DDI_EDP_INPUT_A_ON: |
||
895 | case TRANS_DDI_EDP_INPUT_A_ONOFF: |
||
896 | *pipe = PIPE_A; |
||
897 | break; |
||
898 | case TRANS_DDI_EDP_INPUT_B_ONOFF: |
||
899 | *pipe = PIPE_B; |
||
900 | break; |
||
901 | case TRANS_DDI_EDP_INPUT_C_ONOFF: |
||
902 | *pipe = PIPE_C; |
||
903 | break; |
||
904 | } |
||
905 | |||
906 | return true; |
||
907 | } else { |
||
908 | for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) { |
||
909 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(i)); |
||
910 | |||
911 | if ((tmp & TRANS_DDI_PORT_MASK) |
||
912 | == TRANS_DDI_SELECT_PORT(port)) { |
||
3031 | serge | 913 | *pipe = i; |
914 | return true; |
||
915 | } |
||
916 | } |
||
3243 | Serge | 917 | } |
3031 | serge | 918 | |
4104 | Serge | 919 | DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port)); |
3031 | serge | 920 | |
3746 | Serge | 921 | return false; |
3031 | serge | 922 | } |
923 | |||
3243 | Serge | 924 | static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv, |
925 | enum pipe pipe) |
||
3031 | serge | 926 | { |
3243 | Serge | 927 | uint32_t temp, ret; |
3746 | Serge | 928 | enum port port = I915_MAX_PORTS; |
3243 | Serge | 929 | enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, |
930 | pipe); |
||
931 | int i; |
||
932 | |||
933 | if (cpu_transcoder == TRANSCODER_EDP) { |
||
934 | port = PORT_A; |
||
935 | } else { |
||
936 | temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
||
937 | temp &= TRANS_DDI_PORT_MASK; |
||
938 | |||
939 | for (i = PORT_B; i <= PORT_E; i++) |
||
940 | if (temp == TRANS_DDI_SELECT_PORT(i)) |
||
941 | port = i; |
||
942 | } |
||
943 | |||
3746 | Serge | 944 | if (port == I915_MAX_PORTS) { |
945 | WARN(1, "Pipe %c enabled on an unknown port\n", |
||
946 | pipe_name(pipe)); |
||
947 | ret = PORT_CLK_SEL_NONE; |
||
948 | } else { |
||
3243 | Serge | 949 | ret = I915_READ(PORT_CLK_SEL(port)); |
3746 | Serge | 950 | DRM_DEBUG_KMS("Pipe %c connected to port %c using clock " |
951 | "0x%08x\n", pipe_name(pipe), port_name(port), |
||
952 | ret); |
||
953 | } |
||
3243 | Serge | 954 | |
955 | return ret; |
||
956 | } |
||
957 | |||
958 | void intel_ddi_setup_hw_pll_state(struct drm_device *dev) |
||
959 | { |
||
3031 | serge | 960 | struct drm_i915_private *dev_priv = dev->dev_private; |
3243 | Serge | 961 | enum pipe pipe; |
962 | struct intel_crtc *intel_crtc; |
||
3031 | serge | 963 | |
3243 | Serge | 964 | for_each_pipe(pipe) { |
965 | intel_crtc = |
||
966 | to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
||
3031 | serge | 967 | |
3243 | Serge | 968 | if (!intel_crtc->active) |
969 | continue; |
||
970 | |||
971 | intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv, |
||
972 | pipe); |
||
973 | |||
974 | switch (intel_crtc->ddi_pll_sel) { |
||
975 | case PORT_CLK_SEL_SPLL: |
||
976 | dev_priv->ddi_plls.spll_refcount++; |
||
977 | break; |
||
978 | case PORT_CLK_SEL_WRPLL1: |
||
979 | dev_priv->ddi_plls.wrpll1_refcount++; |
||
980 | break; |
||
981 | case PORT_CLK_SEL_WRPLL2: |
||
982 | dev_priv->ddi_plls.wrpll2_refcount++; |
||
983 | break; |
||
984 | } |
||
985 | } |
||
3031 | serge | 986 | } |
987 | |||
3243 | Serge | 988 | void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc) |
3031 | serge | 989 | { |
3243 | Serge | 990 | struct drm_crtc *crtc = &intel_crtc->base; |
991 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
992 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
993 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
3746 | Serge | 994 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
3243 | Serge | 995 | |
996 | if (cpu_transcoder != TRANSCODER_EDP) |
||
997 | I915_WRITE(TRANS_CLK_SEL(cpu_transcoder), |
||
998 | TRANS_CLK_SEL_PORT(port)); |
||
999 | } |
||
1000 | |||
1001 | void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) |
||
1002 | { |
||
1003 | struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; |
||
3746 | Serge | 1004 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
3243 | Serge | 1005 | |
1006 | if (cpu_transcoder != TRANSCODER_EDP) |
||
1007 | I915_WRITE(TRANS_CLK_SEL(cpu_transcoder), |
||
1008 | TRANS_CLK_SEL_DISABLED); |
||
1009 | } |
||
1010 | |||
1011 | static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) |
||
1012 | { |
||
1013 | struct drm_encoder *encoder = &intel_encoder->base; |
||
1014 | struct drm_crtc *crtc = encoder->crtc; |
||
1015 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
||
1016 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
1017 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
1018 | int type = intel_encoder->type; |
||
1019 | |||
1020 | if (type == INTEL_OUTPUT_EDP) { |
||
1021 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1022 | ironlake_edp_panel_vdd_on(intel_dp); |
||
1023 | ironlake_edp_panel_on(intel_dp); |
||
1024 | ironlake_edp_panel_vdd_off(intel_dp, true); |
||
1025 | } |
||
1026 | |||
1027 | WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE); |
||
1028 | I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel); |
||
1029 | |||
1030 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) { |
||
1031 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1032 | |||
1033 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); |
||
1034 | intel_dp_start_link_train(intel_dp); |
||
1035 | intel_dp_complete_link_train(intel_dp); |
||
3746 | Serge | 1036 | if (port != PORT_A) |
1037 | intel_dp_stop_link_train(intel_dp); |
||
3243 | Serge | 1038 | } |
1039 | } |
||
1040 | |||
1041 | static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) |
||
1042 | { |
||
1043 | struct drm_encoder *encoder = &intel_encoder->base; |
||
1044 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
||
1045 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
||
1046 | int type = intel_encoder->type; |
||
1047 | uint32_t val; |
||
1048 | bool wait = false; |
||
1049 | |||
1050 | val = I915_READ(DDI_BUF_CTL(port)); |
||
1051 | if (val & DDI_BUF_CTL_ENABLE) { |
||
1052 | val &= ~DDI_BUF_CTL_ENABLE; |
||
1053 | I915_WRITE(DDI_BUF_CTL(port), val); |
||
1054 | wait = true; |
||
1055 | } |
||
1056 | |||
1057 | val = I915_READ(DP_TP_CTL(port)); |
||
1058 | val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); |
||
1059 | val |= DP_TP_CTL_LINK_TRAIN_PAT1; |
||
1060 | I915_WRITE(DP_TP_CTL(port), val); |
||
1061 | |||
1062 | if (wait) |
||
1063 | intel_wait_ddi_buf_idle(dev_priv, port); |
||
1064 | |||
1065 | if (type == INTEL_OUTPUT_EDP) { |
||
1066 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1067 | ironlake_edp_panel_vdd_on(intel_dp); |
||
1068 | ironlake_edp_panel_off(intel_dp); |
||
1069 | } |
||
1070 | |||
1071 | I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); |
||
1072 | } |
||
1073 | |||
1074 | static void intel_enable_ddi(struct intel_encoder *intel_encoder) |
||
1075 | { |
||
1076 | struct drm_encoder *encoder = &intel_encoder->base; |
||
3480 | Serge | 1077 | struct drm_crtc *crtc = encoder->crtc; |
1078 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
1079 | int pipe = intel_crtc->pipe; |
||
3243 | Serge | 1080 | struct drm_device *dev = encoder->dev; |
3031 | serge | 1081 | struct drm_i915_private *dev_priv = dev->dev_private; |
3243 | Serge | 1082 | enum port port = intel_ddi_get_encoder_port(intel_encoder); |
1083 | int type = intel_encoder->type; |
||
3480 | Serge | 1084 | uint32_t tmp; |
3031 | serge | 1085 | |
3243 | Serge | 1086 | if (type == INTEL_OUTPUT_HDMI) { |
3480 | Serge | 1087 | struct intel_digital_port *intel_dig_port = |
1088 | enc_to_dig_port(encoder); |
||
1089 | |||
3243 | Serge | 1090 | /* In HDMI/DVI mode, the port width, and swing/emphasis values |
1091 | * are ignored so nothing special needs to be done besides |
||
1092 | * enabling the port. |
||
1093 | */ |
||
3480 | Serge | 1094 | I915_WRITE(DDI_BUF_CTL(port), |
4104 | Serge | 1095 | intel_dig_port->saved_port_bits | |
1096 | DDI_BUF_CTL_ENABLE); |
||
3243 | Serge | 1097 | } else if (type == INTEL_OUTPUT_EDP) { |
1098 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
3031 | serge | 1099 | |
3746 | Serge | 1100 | if (port == PORT_A) |
1101 | intel_dp_stop_link_train(intel_dp); |
||
1102 | |||
3243 | Serge | 1103 | ironlake_edp_backlight_on(intel_dp); |
4104 | Serge | 1104 | intel_edp_psr_enable(intel_dp); |
3243 | Serge | 1105 | } |
3480 | Serge | 1106 | |
4104 | Serge | 1107 | if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) { |
3480 | Serge | 1108 | tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); |
1109 | tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4)); |
||
1110 | I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); |
||
1111 | } |
||
3031 | serge | 1112 | } |
3243 | Serge | 1113 | |
1114 | static void intel_disable_ddi(struct intel_encoder *intel_encoder) |
||
1115 | { |
||
1116 | struct drm_encoder *encoder = &intel_encoder->base; |
||
3480 | Serge | 1117 | struct drm_crtc *crtc = encoder->crtc; |
1118 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
||
1119 | int pipe = intel_crtc->pipe; |
||
3243 | Serge | 1120 | int type = intel_encoder->type; |
3480 | Serge | 1121 | struct drm_device *dev = encoder->dev; |
1122 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
1123 | uint32_t tmp; |
||
3243 | Serge | 1124 | |
4104 | Serge | 1125 | if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) { |
3746 | Serge | 1126 | tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); |
4104 | Serge | 1127 | tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << |
1128 | (pipe * 4)); |
||
3746 | Serge | 1129 | I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); |
4104 | Serge | 1130 | } |
3746 | Serge | 1131 | |
3243 | Serge | 1132 | if (type == INTEL_OUTPUT_EDP) { |
1133 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
||
1134 | |||
4104 | Serge | 1135 | intel_edp_psr_disable(intel_dp); |
3243 | Serge | 1136 | ironlake_edp_backlight_off(intel_dp); |
1137 | } |
||
1138 | } |
||
1139 | |||
1140 | int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) |
||
1141 | { |
||
4104 | Serge | 1142 | uint32_t lcpll = I915_READ(LCPLL_CTL); |
1143 | |||
1144 | if (lcpll & LCPLL_CD_SOURCE_FCLK) |
||
1145 | return 800000; |
||
1146 | else if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT) |
||
1147 | return 450000; |
||
1148 | else if ((lcpll & LCPLL_CLK_FREQ_MASK) == LCPLL_CLK_FREQ_450) |
||
1149 | return 450000; |
||
3243 | Serge | 1150 | else if (IS_ULT(dev_priv->dev)) |
4104 | Serge | 1151 | return 337500; |
3243 | Serge | 1152 | else |
4104 | Serge | 1153 | return 540000; |
3243 | Serge | 1154 | } |
1155 | |||
1156 | void intel_ddi_pll_init(struct drm_device *dev) |
||
1157 | { |
||
1158 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
1159 | uint32_t val = I915_READ(LCPLL_CTL); |
||
1160 | |||
1161 | /* The LCPLL register should be turned on by the BIOS. For now let's |
||
1162 | * just check its state and print errors in case something is wrong. |
||
1163 | * Don't even try to turn it on. |
||
1164 | */ |
||
1165 | |||
4104 | Serge | 1166 | DRM_DEBUG_KMS("CDCLK running at %dKHz\n", |
3243 | Serge | 1167 | intel_ddi_get_cdclk_freq(dev_priv)); |
1168 | |||
1169 | if (val & LCPLL_CD_SOURCE_FCLK) |
||
1170 | DRM_ERROR("CDCLK source is not LCPLL\n"); |
||
1171 | |||
1172 | if (val & LCPLL_PLL_DISABLE) |
||
1173 | DRM_ERROR("LCPLL is disabled\n"); |
||
1174 | } |
||
1175 | |||
1176 | void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder) |
||
1177 | { |
||
1178 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
||
1179 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
||
1180 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
||
1181 | enum port port = intel_dig_port->port; |
||
1182 | uint32_t val; |
||
3480 | Serge | 1183 | bool wait = false; |
3243 | Serge | 1184 | |
1185 | if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) { |
||
1186 | val = I915_READ(DDI_BUF_CTL(port)); |
||
1187 | if (val & DDI_BUF_CTL_ENABLE) { |
||
1188 | val &= ~DDI_BUF_CTL_ENABLE; |
||
1189 | I915_WRITE(DDI_BUF_CTL(port), val); |
||
1190 | wait = true; |
||
1191 | } |
||
1192 | |||
1193 | val = I915_READ(DP_TP_CTL(port)); |
||
1194 | val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); |
||
1195 | val |= DP_TP_CTL_LINK_TRAIN_PAT1; |
||
1196 | I915_WRITE(DP_TP_CTL(port), val); |
||
1197 | POSTING_READ(DP_TP_CTL(port)); |
||
1198 | |||
1199 | if (wait) |
||
1200 | intel_wait_ddi_buf_idle(dev_priv, port); |
||
1201 | } |
||
1202 | |||
1203 | val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST | |
||
1204 | DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; |
||
1205 | if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) |
||
1206 | val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; |
||
1207 | I915_WRITE(DP_TP_CTL(port), val); |
||
1208 | POSTING_READ(DP_TP_CTL(port)); |
||
1209 | |||
1210 | intel_dp->DP |= DDI_BUF_CTL_ENABLE; |
||
1211 | I915_WRITE(DDI_BUF_CTL(port), intel_dp->DP); |
||
1212 | POSTING_READ(DDI_BUF_CTL(port)); |
||
1213 | |||
1214 | udelay(600); |
||
1215 | } |
||
1216 | |||
1217 | void intel_ddi_fdi_disable(struct drm_crtc *crtc) |
||
1218 | { |
||
1219 | struct drm_i915_private *dev_priv = crtc->dev->dev_private; |
||
1220 | struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); |
||
1221 | uint32_t val; |
||
1222 | |||
1223 | intel_ddi_post_disable(intel_encoder); |
||
1224 | |||
1225 | val = I915_READ(_FDI_RXA_CTL); |
||
1226 | val &= ~FDI_RX_ENABLE; |
||
1227 | I915_WRITE(_FDI_RXA_CTL, val); |
||
1228 | |||
1229 | val = I915_READ(_FDI_RXA_MISC); |
||
1230 | val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); |
||
1231 | val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); |
||
1232 | I915_WRITE(_FDI_RXA_MISC, val); |
||
1233 | |||
1234 | val = I915_READ(_FDI_RXA_CTL); |
||
1235 | val &= ~FDI_PCDCLK; |
||
1236 | I915_WRITE(_FDI_RXA_CTL, val); |
||
1237 | |||
1238 | val = I915_READ(_FDI_RXA_CTL); |
||
1239 | val &= ~FDI_RX_PLL_ENABLE; |
||
1240 | I915_WRITE(_FDI_RXA_CTL, val); |
||
1241 | } |
||
1242 | |||
1243 | static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) |
||
1244 | { |
||
1245 | struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); |
||
1246 | int type = intel_encoder->type; |
||
1247 | |||
1248 | if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) |
||
1249 | intel_dp_check_link_status(intel_dp); |
||
1250 | } |
||
1251 | |||
4104 | Serge | 1252 | static void intel_ddi_get_config(struct intel_encoder *encoder, |
1253 | struct intel_crtc_config *pipe_config) |
||
1254 | { |
||
1255 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
||
1256 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
||
1257 | enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; |
||
1258 | u32 temp, flags = 0; |
||
1259 | |||
1260 | temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); |
||
1261 | if (temp & TRANS_DDI_PHSYNC) |
||
1262 | flags |= DRM_MODE_FLAG_PHSYNC; |
||
1263 | else |
||
1264 | flags |= DRM_MODE_FLAG_NHSYNC; |
||
1265 | if (temp & TRANS_DDI_PVSYNC) |
||
1266 | flags |= DRM_MODE_FLAG_PVSYNC; |
||
1267 | else |
||
1268 | flags |= DRM_MODE_FLAG_NVSYNC; |
||
1269 | |||
1270 | pipe_config->adjusted_mode.flags |= flags; |
||
1271 | } |
||
1272 | |||
3243 | Serge | 1273 | static void intel_ddi_destroy(struct drm_encoder *encoder) |
1274 | { |
||
1275 | /* HDMI has nothing special to destroy, so we can go with this. */ |
||
1276 | intel_dp_encoder_destroy(encoder); |
||
1277 | } |
||
1278 | |||
3746 | Serge | 1279 | static bool intel_ddi_compute_config(struct intel_encoder *encoder, |
1280 | struct intel_crtc_config *pipe_config) |
||
3243 | Serge | 1281 | { |
3746 | Serge | 1282 | int type = encoder->type; |
4104 | Serge | 1283 | int port = intel_ddi_get_encoder_port(encoder); |
3243 | Serge | 1284 | |
3746 | Serge | 1285 | WARN(type == INTEL_OUTPUT_UNKNOWN, "compute_config() on unknown output!\n"); |
3243 | Serge | 1286 | |
4104 | Serge | 1287 | if (port == PORT_A) |
1288 | pipe_config->cpu_transcoder = TRANSCODER_EDP; |
||
1289 | |||
3243 | Serge | 1290 | if (type == INTEL_OUTPUT_HDMI) |
3746 | Serge | 1291 | return intel_hdmi_compute_config(encoder, pipe_config); |
3243 | Serge | 1292 | else |
3746 | Serge | 1293 | return intel_dp_compute_config(encoder, pipe_config); |
3243 | Serge | 1294 | } |
1295 | |||
1296 | static const struct drm_encoder_funcs intel_ddi_funcs = { |
||
1297 | .destroy = intel_ddi_destroy, |
||
1298 | }; |
||
1299 | |||
1300 | void intel_ddi_init(struct drm_device *dev, enum port port) |
||
1301 | { |
||
3480 | Serge | 1302 | struct drm_i915_private *dev_priv = dev->dev_private; |
3243 | Serge | 1303 | struct intel_digital_port *intel_dig_port; |
1304 | struct intel_encoder *intel_encoder; |
||
1305 | struct drm_encoder *encoder; |
||
1306 | struct intel_connector *hdmi_connector = NULL; |
||
1307 | struct intel_connector *dp_connector = NULL; |
||
1308 | |||
1309 | intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); |
||
1310 | if (!intel_dig_port) |
||
1311 | return; |
||
1312 | |||
1313 | dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
||
1314 | if (!dp_connector) { |
||
1315 | kfree(intel_dig_port); |
||
1316 | return; |
||
1317 | } |
||
1318 | |||
1319 | intel_encoder = &intel_dig_port->base; |
||
1320 | encoder = &intel_encoder->base; |
||
1321 | |||
1322 | drm_encoder_init(dev, encoder, &intel_ddi_funcs, |
||
1323 | DRM_MODE_ENCODER_TMDS); |
||
1324 | |||
3746 | Serge | 1325 | intel_encoder->compute_config = intel_ddi_compute_config; |
4104 | Serge | 1326 | intel_encoder->mode_set = intel_ddi_mode_set; |
3243 | Serge | 1327 | intel_encoder->enable = intel_enable_ddi; |
1328 | intel_encoder->pre_enable = intel_ddi_pre_enable; |
||
1329 | intel_encoder->disable = intel_disable_ddi; |
||
1330 | intel_encoder->post_disable = intel_ddi_post_disable; |
||
1331 | intel_encoder->get_hw_state = intel_ddi_get_hw_state; |
||
4104 | Serge | 1332 | intel_encoder->get_config = intel_ddi_get_config; |
3243 | Serge | 1333 | |
1334 | intel_dig_port->port = port; |
||
4104 | Serge | 1335 | intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & |
1336 | (DDI_BUF_PORT_REVERSAL | |
||
1337 | DDI_A_4_LANES); |
||
3243 | Serge | 1338 | intel_dig_port->dp.output_reg = DDI_BUF_CTL(port); |
1339 | |||
1340 | intel_encoder->type = INTEL_OUTPUT_UNKNOWN; |
||
1341 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
||
1342 | intel_encoder->cloneable = false; |
||
1343 | intel_encoder->hot_plug = intel_ddi_hot_plug; |
||
1344 | |||
4104 | Serge | 1345 | if (!intel_dp_init_connector(intel_dig_port, dp_connector)) { |
1346 | drm_encoder_cleanup(encoder); |
||
1347 | kfree(intel_dig_port); |
||
1348 | kfree(dp_connector); |
||
1349 | return; |
||
1350 | } |
||
1351 | |||
1352 | if (intel_encoder->type != INTEL_OUTPUT_EDP) { |
||
1353 | hdmi_connector = kzalloc(sizeof(struct intel_connector), |
||
1354 | GFP_KERNEL); |
||
1355 | if (!hdmi_connector) { |
||
1356 | return; |
||
1357 | } |
||
1358 | |||
1359 | intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); |
||
3243 | Serge | 1360 | intel_hdmi_init_connector(intel_dig_port, hdmi_connector); |
4104 | Serge | 1361 | } |
3243 | Serge | 1362 | }><>><>><> |