1 | /* |
2 | * Copyright © 2006-2007 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 |
21 | * DEALINGS IN THE SOFTWARE. |
22 | * |
23 | * Authors: |
24 | * Eric Anholt <eric@anholt.net> |
25 | */ |
26 | |
27 | #include <linux/dmi.h> |
28 | #include <linux/i2c.h> |
29 | #include <linux/slab.h> |
30 | |
31 | #include <drm/drm_atomic_helper.h> |
32 | #include <drm/drm_crtc.h> |
33 | #include <drm/drm_edid.h> |
34 | #include <drm/drm_probe_helper.h> |
35 | |
36 | #include "i915_drv.h" |
37 | #include "i915_irq.h" |
38 | #include "i915_reg.h" |
39 | #include "intel_connector.h" |
40 | #include "intel_crt.h" |
41 | #include "intel_crtc.h" |
42 | #include "intel_ddi.h" |
43 | #include "intel_ddi_buf_trans.h" |
44 | #include "intel_de.h" |
45 | #include "intel_display_driver.h" |
46 | #include "intel_display_types.h" |
47 | #include "intel_fdi.h" |
48 | #include "intel_fdi_regs.h" |
49 | #include "intel_fifo_underrun.h" |
50 | #include "intel_gmbus.h" |
51 | #include "intel_hotplug.h" |
52 | #include "intel_hotplug_irq.h" |
53 | #include "intel_load_detect.h" |
54 | #include "intel_pch_display.h" |
55 | #include "intel_pch_refclk.h" |
56 | |
57 | /* Here's the desired hotplug mode */ |
58 | #define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \ |
59 | ADPA_CRT_HOTPLUG_WARMUP_10MS | \ |
60 | ADPA_CRT_HOTPLUG_SAMPLE_4S | \ |
61 | ADPA_CRT_HOTPLUG_VOLTAGE_50 | \ |
62 | ADPA_CRT_HOTPLUG_VOLREF_325MV | \ |
63 | ADPA_CRT_HOTPLUG_ENABLE) |
64 | |
65 | struct intel_crt { |
66 | struct intel_encoder base; |
67 | /* DPMS state is stored in the connector, which we need in the |
68 | * encoder's enable/disable callbacks */ |
69 | struct intel_connector *connector; |
70 | bool force_hotplug_required; |
71 | i915_reg_t adpa_reg; |
72 | }; |
73 | |
74 | static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder) |
75 | { |
76 | return container_of(encoder, struct intel_crt, base); |
77 | } |
78 | |
79 | static struct intel_crt *intel_attached_crt(struct intel_connector *connector) |
80 | { |
81 | return intel_encoder_to_crt(encoder: intel_attached_encoder(connector)); |
82 | } |
83 | |
84 | bool intel_crt_port_enabled(struct drm_i915_private *dev_priv, |
85 | i915_reg_t adpa_reg, enum pipe *pipe) |
86 | { |
87 | u32 val; |
88 | |
89 | val = intel_de_read(i915: dev_priv, reg: adpa_reg); |
90 | |
91 | /* asserts want to know the pipe even if the port is disabled */ |
92 | if (HAS_PCH_CPT(dev_priv)) |
93 | *pipe = (val & ADPA_PIPE_SEL_MASK_CPT) >> ADPA_PIPE_SEL_SHIFT_CPT; |
94 | else |
95 | *pipe = (val & ADPA_PIPE_SEL_MASK) >> ADPA_PIPE_SEL_SHIFT; |
96 | |
97 | return val & ADPA_DAC_ENABLE; |
98 | } |
99 | |
100 | static bool intel_crt_get_hw_state(struct intel_encoder *encoder, |
101 | enum pipe *pipe) |
102 | { |
103 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
104 | struct intel_crt *crt = intel_encoder_to_crt(encoder); |
105 | intel_wakeref_t wakeref; |
106 | bool ret; |
107 | |
108 | wakeref = intel_display_power_get_if_enabled(dev_priv, |
109 | domain: encoder->power_domain); |
110 | if (!wakeref) |
111 | return false; |
112 | |
113 | ret = intel_crt_port_enabled(dev_priv, adpa_reg: crt->adpa_reg, pipe); |
114 | |
115 | intel_display_power_put(dev_priv, domain: encoder->power_domain, wakeref); |
116 | |
117 | return ret; |
118 | } |
119 | |
120 | static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) |
121 | { |
122 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
123 | struct intel_crt *crt = intel_encoder_to_crt(encoder); |
124 | u32 tmp, flags = 0; |
125 | |
126 | tmp = intel_de_read(i915: dev_priv, reg: crt->adpa_reg); |
127 | |
128 | if (tmp & ADPA_HSYNC_ACTIVE_HIGH) |
129 | flags |= DRM_MODE_FLAG_PHSYNC; |
130 | else |
131 | flags |= DRM_MODE_FLAG_NHSYNC; |
132 | |
133 | if (tmp & ADPA_VSYNC_ACTIVE_HIGH) |
134 | flags |= DRM_MODE_FLAG_PVSYNC; |
135 | else |
136 | flags |= DRM_MODE_FLAG_NVSYNC; |
137 | |
138 | return flags; |
139 | } |
140 | |
141 | static void intel_crt_get_config(struct intel_encoder *encoder, |
142 | struct intel_crtc_state *pipe_config) |
143 | { |
144 | pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG); |
145 | |
146 | pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder); |
147 | |
148 | pipe_config->hw.adjusted_mode.crtc_clock = pipe_config->port_clock; |
149 | } |
150 | |
151 | static void hsw_crt_get_config(struct intel_encoder *encoder, |
152 | struct intel_crtc_state *pipe_config) |
153 | { |
154 | lpt_pch_get_config(crtc_state: pipe_config); |
155 | |
156 | hsw_ddi_get_config(encoder, crtc_state: pipe_config); |
157 | |
158 | pipe_config->hw.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | |
159 | DRM_MODE_FLAG_NHSYNC | |
160 | DRM_MODE_FLAG_PVSYNC | |
161 | DRM_MODE_FLAG_NVSYNC); |
162 | pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder); |
163 | } |
164 | |
165 | /* Note: The caller is required to filter out dpms modes not supported by the |
166 | * platform. */ |
167 | static void intel_crt_set_dpms(struct intel_encoder *encoder, |
168 | const struct intel_crtc_state *crtc_state, |
169 | int mode) |
170 | { |
171 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
172 | struct intel_crt *crt = intel_encoder_to_crt(encoder); |
173 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
174 | const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; |
175 | u32 adpa; |
176 | |
177 | if (DISPLAY_VER(dev_priv) >= 5) |
178 | adpa = ADPA_HOTPLUG_BITS; |
179 | else |
180 | adpa = 0; |
181 | |
182 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
183 | adpa |= ADPA_HSYNC_ACTIVE_HIGH; |
184 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
185 | adpa |= ADPA_VSYNC_ACTIVE_HIGH; |
186 | |
187 | /* For CPT allow 3 pipe config, for others just use A or B */ |
188 | if (HAS_PCH_LPT(dev_priv)) |
189 | ; /* Those bits don't exist here */ |
190 | else if (HAS_PCH_CPT(dev_priv)) |
191 | adpa |= ADPA_PIPE_SEL_CPT(crtc->pipe); |
192 | else |
193 | adpa |= ADPA_PIPE_SEL(crtc->pipe); |
194 | |
195 | if (!HAS_PCH_SPLIT(dev_priv)) |
196 | intel_de_write(i915: dev_priv, BCLRPAT(crtc->pipe), val: 0); |
197 | |
198 | switch (mode) { |
199 | case DRM_MODE_DPMS_ON: |
200 | adpa |= ADPA_DAC_ENABLE; |
201 | break; |
202 | case DRM_MODE_DPMS_STANDBY: |
203 | adpa |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE; |
204 | break; |
205 | case DRM_MODE_DPMS_SUSPEND: |
206 | adpa |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE; |
207 | break; |
208 | case DRM_MODE_DPMS_OFF: |
209 | adpa |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; |
210 | break; |
211 | } |
212 | |
213 | intel_de_write(i915: dev_priv, reg: crt->adpa_reg, val: adpa); |
214 | } |
215 | |
216 | static void intel_disable_crt(struct intel_atomic_state *state, |
217 | struct intel_encoder *encoder, |
218 | const struct intel_crtc_state *old_crtc_state, |
219 | const struct drm_connector_state *old_conn_state) |
220 | { |
221 | intel_crt_set_dpms(encoder, crtc_state: old_crtc_state, DRM_MODE_DPMS_OFF); |
222 | } |
223 | |
224 | static void pch_disable_crt(struct intel_atomic_state *state, |
225 | struct intel_encoder *encoder, |
226 | const struct intel_crtc_state *old_crtc_state, |
227 | const struct drm_connector_state *old_conn_state) |
228 | { |
229 | } |
230 | |
231 | static void pch_post_disable_crt(struct intel_atomic_state *state, |
232 | struct intel_encoder *encoder, |
233 | const struct intel_crtc_state *old_crtc_state, |
234 | const struct drm_connector_state *old_conn_state) |
235 | { |
236 | intel_disable_crt(state, encoder, old_crtc_state, old_conn_state); |
237 | } |
238 | |
239 | static void hsw_disable_crt(struct intel_atomic_state *state, |
240 | struct intel_encoder *encoder, |
241 | const struct intel_crtc_state *old_crtc_state, |
242 | const struct drm_connector_state *old_conn_state) |
243 | { |
244 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
245 | |
246 | drm_WARN_ON(&dev_priv->drm, !old_crtc_state->has_pch_encoder); |
247 | |
248 | intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder: PIPE_A, enable: false); |
249 | } |
250 | |
251 | static void hsw_post_disable_crt(struct intel_atomic_state *state, |
252 | struct intel_encoder *encoder, |
253 | const struct intel_crtc_state *old_crtc_state, |
254 | const struct drm_connector_state *old_conn_state) |
255 | { |
256 | struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); |
257 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
258 | |
259 | intel_crtc_vblank_off(crtc_state: old_crtc_state); |
260 | |
261 | intel_disable_transcoder(old_crtc_state); |
262 | |
263 | intel_ddi_disable_transcoder_func(crtc_state: old_crtc_state); |
264 | |
265 | ilk_pfit_disable(old_crtc_state); |
266 | |
267 | intel_ddi_disable_transcoder_clock(crtc_state: old_crtc_state); |
268 | |
269 | pch_post_disable_crt(state, encoder, old_crtc_state, old_conn_state); |
270 | |
271 | lpt_pch_disable(state, crtc); |
272 | |
273 | hsw_fdi_disable(encoder); |
274 | |
275 | drm_WARN_ON(&dev_priv->drm, !old_crtc_state->has_pch_encoder); |
276 | |
277 | intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder: PIPE_A, enable: true); |
278 | } |
279 | |
280 | static void hsw_pre_pll_enable_crt(struct intel_atomic_state *state, |
281 | struct intel_encoder *encoder, |
282 | const struct intel_crtc_state *crtc_state, |
283 | const struct drm_connector_state *conn_state) |
284 | { |
285 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
286 | |
287 | drm_WARN_ON(&dev_priv->drm, !crtc_state->has_pch_encoder); |
288 | |
289 | intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder: PIPE_A, enable: false); |
290 | } |
291 | |
292 | static void hsw_pre_enable_crt(struct intel_atomic_state *state, |
293 | struct intel_encoder *encoder, |
294 | const struct intel_crtc_state *crtc_state, |
295 | const struct drm_connector_state *conn_state) |
296 | { |
297 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
298 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
299 | enum pipe pipe = crtc->pipe; |
300 | |
301 | drm_WARN_ON(&dev_priv->drm, !crtc_state->has_pch_encoder); |
302 | |
303 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, enable: false); |
304 | |
305 | hsw_fdi_link_train(encoder, crtc_state); |
306 | |
307 | intel_ddi_enable_transcoder_clock(encoder, crtc_state); |
308 | } |
309 | |
310 | static void hsw_enable_crt(struct intel_atomic_state *state, |
311 | struct intel_encoder *encoder, |
312 | const struct intel_crtc_state *crtc_state, |
313 | const struct drm_connector_state *conn_state) |
314 | { |
315 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
316 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
317 | enum pipe pipe = crtc->pipe; |
318 | |
319 | drm_WARN_ON(&dev_priv->drm, !crtc_state->has_pch_encoder); |
320 | |
321 | intel_ddi_enable_transcoder_func(encoder, crtc_state); |
322 | |
323 | intel_enable_transcoder(new_crtc_state: crtc_state); |
324 | |
325 | lpt_pch_enable(state, crtc); |
326 | |
327 | intel_crtc_vblank_on(crtc_state); |
328 | |
329 | intel_crt_set_dpms(encoder, crtc_state, DRM_MODE_DPMS_ON); |
330 | |
331 | intel_crtc_wait_for_next_vblank(crtc); |
332 | intel_crtc_wait_for_next_vblank(crtc); |
333 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, enable: true); |
334 | intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder: PIPE_A, enable: true); |
335 | } |
336 | |
337 | static void intel_enable_crt(struct intel_atomic_state *state, |
338 | struct intel_encoder *encoder, |
339 | const struct intel_crtc_state *crtc_state, |
340 | const struct drm_connector_state *conn_state) |
341 | { |
342 | intel_crt_set_dpms(encoder, crtc_state, DRM_MODE_DPMS_ON); |
343 | } |
344 | |
345 | static enum drm_mode_status |
346 | intel_crt_mode_valid(struct drm_connector *connector, |
347 | struct drm_display_mode *mode) |
348 | { |
349 | struct drm_device *dev = connector->dev; |
350 | struct drm_i915_private *dev_priv = to_i915(dev); |
351 | int max_dotclk = dev_priv->max_dotclk_freq; |
352 | enum drm_mode_status status; |
353 | int max_clock; |
354 | |
355 | status = intel_cpu_transcoder_mode_valid(i915: dev_priv, mode); |
356 | if (status != MODE_OK) |
357 | return status; |
358 | |
359 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
360 | return MODE_NO_DBLESCAN; |
361 | |
362 | if (mode->clock < 25000) |
363 | return MODE_CLOCK_LOW; |
364 | |
365 | if (HAS_PCH_LPT(dev_priv)) |
366 | max_clock = 180000; |
367 | else if (IS_VALLEYVIEW(dev_priv)) |
368 | /* |
369 | * 270 MHz due to current DPLL limits, |
370 | * DAC limit supposedly 355 MHz. |
371 | */ |
372 | max_clock = 270000; |
373 | else if (IS_DISPLAY_VER(dev_priv, 3, 4)) |
374 | max_clock = 400000; |
375 | else |
376 | max_clock = 350000; |
377 | if (mode->clock > max_clock) |
378 | return MODE_CLOCK_HIGH; |
379 | |
380 | if (mode->clock > max_dotclk) |
381 | return MODE_CLOCK_HIGH; |
382 | |
383 | /* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */ |
384 | if (HAS_PCH_LPT(dev_priv) && |
385 | ilk_get_lanes_required(target_clock: mode->clock, link_bw: 270000, bpp: 24) > 2) |
386 | return MODE_CLOCK_HIGH; |
387 | |
388 | /* HSW/BDW FDI limited to 4k */ |
389 | if (mode->hdisplay > 4096) |
390 | return MODE_H_ILLEGAL; |
391 | |
392 | return MODE_OK; |
393 | } |
394 | |
395 | static int intel_crt_compute_config(struct intel_encoder *encoder, |
396 | struct intel_crtc_state *pipe_config, |
397 | struct drm_connector_state *conn_state) |
398 | { |
399 | struct drm_display_mode *adjusted_mode = |
400 | &pipe_config->hw.adjusted_mode; |
401 | |
402 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) |
403 | return -EINVAL; |
404 | |
405 | pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB; |
406 | pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; |
407 | |
408 | return 0; |
409 | } |
410 | |
411 | static int pch_crt_compute_config(struct intel_encoder *encoder, |
412 | struct intel_crtc_state *pipe_config, |
413 | struct drm_connector_state *conn_state) |
414 | { |
415 | struct drm_display_mode *adjusted_mode = |
416 | &pipe_config->hw.adjusted_mode; |
417 | |
418 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) |
419 | return -EINVAL; |
420 | |
421 | pipe_config->has_pch_encoder = true; |
422 | if (!intel_fdi_compute_pipe_bpp(crtc_state: pipe_config)) |
423 | return -EINVAL; |
424 | |
425 | pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; |
426 | |
427 | return 0; |
428 | } |
429 | |
430 | static int hsw_crt_compute_config(struct intel_encoder *encoder, |
431 | struct intel_crtc_state *pipe_config, |
432 | struct drm_connector_state *conn_state) |
433 | { |
434 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
435 | struct drm_display_mode *adjusted_mode = |
436 | &pipe_config->hw.adjusted_mode; |
437 | |
438 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) |
439 | return -EINVAL; |
440 | |
441 | /* HSW/BDW FDI limited to 4k */ |
442 | if (adjusted_mode->crtc_hdisplay > 4096 || |
443 | adjusted_mode->crtc_hblank_start > 4096) |
444 | return -EINVAL; |
445 | |
446 | pipe_config->has_pch_encoder = true; |
447 | if (!intel_fdi_compute_pipe_bpp(crtc_state: pipe_config)) |
448 | return -EINVAL; |
449 | |
450 | pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; |
451 | |
452 | /* LPT FDI RX only supports 8bpc. */ |
453 | if (HAS_PCH_LPT(dev_priv)) { |
454 | /* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */ |
455 | if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) { |
456 | drm_dbg_kms(&dev_priv->drm, |
457 | "LPT only supports 24bpp\n" ); |
458 | return -EINVAL; |
459 | } |
460 | |
461 | pipe_config->pipe_bpp = 24; |
462 | } |
463 | |
464 | /* FDI must always be 2.7 GHz */ |
465 | pipe_config->port_clock = 135000 * 2; |
466 | |
467 | pipe_config->enhanced_framing = true; |
468 | |
469 | adjusted_mode->crtc_clock = lpt_iclkip(crtc_state: pipe_config); |
470 | |
471 | return 0; |
472 | } |
473 | |
474 | static bool ilk_crt_detect_hotplug(struct drm_connector *connector) |
475 | { |
476 | struct drm_device *dev = connector->dev; |
477 | struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector)); |
478 | struct drm_i915_private *dev_priv = to_i915(dev); |
479 | u32 adpa; |
480 | bool ret; |
481 | |
482 | /* The first time through, trigger an explicit detection cycle */ |
483 | if (crt->force_hotplug_required) { |
484 | bool turn_off_dac = HAS_PCH_SPLIT(dev_priv); |
485 | u32 save_adpa; |
486 | |
487 | crt->force_hotplug_required = false; |
488 | |
489 | save_adpa = adpa = intel_de_read(i915: dev_priv, reg: crt->adpa_reg); |
490 | drm_dbg_kms(&dev_priv->drm, |
491 | "trigger hotplug detect cycle: adpa=0x%x\n" , adpa); |
492 | |
493 | adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; |
494 | if (turn_off_dac) |
495 | adpa &= ~ADPA_DAC_ENABLE; |
496 | |
497 | intel_de_write(i915: dev_priv, reg: crt->adpa_reg, val: adpa); |
498 | |
499 | if (intel_de_wait_for_clear(i915: dev_priv, |
500 | reg: crt->adpa_reg, |
501 | ADPA_CRT_HOTPLUG_FORCE_TRIGGER, |
502 | timeout: 1000)) |
503 | drm_dbg_kms(&dev_priv->drm, |
504 | "timed out waiting for FORCE_TRIGGER" ); |
505 | |
506 | if (turn_off_dac) { |
507 | intel_de_write(i915: dev_priv, reg: crt->adpa_reg, val: save_adpa); |
508 | intel_de_posting_read(i915: dev_priv, reg: crt->adpa_reg); |
509 | } |
510 | } |
511 | |
512 | /* Check the status to see if both blue and green are on now */ |
513 | adpa = intel_de_read(i915: dev_priv, reg: crt->adpa_reg); |
514 | if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0) |
515 | ret = true; |
516 | else |
517 | ret = false; |
518 | drm_dbg_kms(&dev_priv->drm, "ironlake hotplug adpa=0x%x, result %d\n" , |
519 | adpa, ret); |
520 | |
521 | return ret; |
522 | } |
523 | |
524 | static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) |
525 | { |
526 | struct drm_device *dev = connector->dev; |
527 | struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector)); |
528 | struct drm_i915_private *dev_priv = to_i915(dev); |
529 | bool reenable_hpd; |
530 | u32 adpa; |
531 | bool ret; |
532 | u32 save_adpa; |
533 | |
534 | /* |
535 | * Doing a force trigger causes a hpd interrupt to get sent, which can |
536 | * get us stuck in a loop if we're polling: |
537 | * - We enable power wells and reset the ADPA |
538 | * - output_poll_exec does force probe on VGA, triggering a hpd |
539 | * - HPD handler waits for poll to unlock dev->mode_config.mutex |
540 | * - output_poll_exec shuts off the ADPA, unlocks |
541 | * dev->mode_config.mutex |
542 | * - HPD handler runs, resets ADPA and brings us back to the start |
543 | * |
544 | * Just disable HPD interrupts here to prevent this |
545 | */ |
546 | reenable_hpd = intel_hpd_disable(dev_priv, pin: crt->base.hpd_pin); |
547 | |
548 | save_adpa = adpa = intel_de_read(i915: dev_priv, reg: crt->adpa_reg); |
549 | drm_dbg_kms(&dev_priv->drm, |
550 | "trigger hotplug detect cycle: adpa=0x%x\n" , adpa); |
551 | |
552 | adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; |
553 | |
554 | intel_de_write(i915: dev_priv, reg: crt->adpa_reg, val: adpa); |
555 | |
556 | if (intel_de_wait_for_clear(i915: dev_priv, reg: crt->adpa_reg, |
557 | ADPA_CRT_HOTPLUG_FORCE_TRIGGER, timeout: 1000)) { |
558 | drm_dbg_kms(&dev_priv->drm, |
559 | "timed out waiting for FORCE_TRIGGER" ); |
560 | intel_de_write(i915: dev_priv, reg: crt->adpa_reg, val: save_adpa); |
561 | } |
562 | |
563 | /* Check the status to see if both blue and green are on now */ |
564 | adpa = intel_de_read(i915: dev_priv, reg: crt->adpa_reg); |
565 | if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0) |
566 | ret = true; |
567 | else |
568 | ret = false; |
569 | |
570 | drm_dbg_kms(&dev_priv->drm, |
571 | "valleyview hotplug adpa=0x%x, result %d\n" , adpa, ret); |
572 | |
573 | if (reenable_hpd) |
574 | intel_hpd_enable(dev_priv, pin: crt->base.hpd_pin); |
575 | |
576 | return ret; |
577 | } |
578 | |
579 | static bool intel_crt_detect_hotplug(struct drm_connector *connector) |
580 | { |
581 | struct drm_device *dev = connector->dev; |
582 | struct drm_i915_private *dev_priv = to_i915(dev); |
583 | u32 stat; |
584 | bool ret = false; |
585 | int i, tries = 0; |
586 | |
587 | if (HAS_PCH_SPLIT(dev_priv)) |
588 | return ilk_crt_detect_hotplug(connector); |
589 | |
590 | if (IS_VALLEYVIEW(dev_priv)) |
591 | return valleyview_crt_detect_hotplug(connector); |
592 | |
593 | /* |
594 | * On 4 series desktop, CRT detect sequence need to be done twice |
595 | * to get a reliable result. |
596 | */ |
597 | |
598 | if (IS_G45(dev_priv)) |
599 | tries = 2; |
600 | else |
601 | tries = 1; |
602 | |
603 | for (i = 0; i < tries ; i++) { |
604 | /* turn on the FORCE_DETECT */ |
605 | i915_hotplug_interrupt_update(i915: dev_priv, |
606 | CRT_HOTPLUG_FORCE_DETECT, |
607 | CRT_HOTPLUG_FORCE_DETECT); |
608 | /* wait for FORCE_DETECT to go off */ |
609 | if (intel_de_wait_for_clear(i915: dev_priv, PORT_HOTPLUG_EN, |
610 | CRT_HOTPLUG_FORCE_DETECT, timeout: 1000)) |
611 | drm_dbg_kms(&dev_priv->drm, |
612 | "timed out waiting for FORCE_DETECT to go off" ); |
613 | } |
614 | |
615 | stat = intel_de_read(i915: dev_priv, PORT_HOTPLUG_STAT); |
616 | if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE) |
617 | ret = true; |
618 | |
619 | /* clear the interrupt we just generated, if any */ |
620 | intel_de_write(i915: dev_priv, PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS); |
621 | |
622 | i915_hotplug_interrupt_update(i915: dev_priv, CRT_HOTPLUG_FORCE_DETECT, bits: 0); |
623 | |
624 | return ret; |
625 | } |
626 | |
627 | static const struct drm_edid *intel_crt_get_edid(struct drm_connector *connector, |
628 | struct i2c_adapter *ddc) |
629 | { |
630 | const struct drm_edid *drm_edid; |
631 | |
632 | drm_edid = drm_edid_read_ddc(connector, adapter: ddc); |
633 | |
634 | if (!drm_edid && !intel_gmbus_is_forced_bit(adapter: ddc)) { |
635 | drm_dbg_kms(connector->dev, |
636 | "CRT GMBUS EDID read failed, retry using GPIO bit-banging\n" ); |
637 | intel_gmbus_force_bit(adapter: ddc, force_bit: true); |
638 | drm_edid = drm_edid_read_ddc(connector, adapter: ddc); |
639 | intel_gmbus_force_bit(adapter: ddc, force_bit: false); |
640 | } |
641 | |
642 | return drm_edid; |
643 | } |
644 | |
645 | /* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */ |
646 | static int intel_crt_ddc_get_modes(struct drm_connector *connector, |
647 | struct i2c_adapter *ddc) |
648 | { |
649 | const struct drm_edid *drm_edid; |
650 | int ret; |
651 | |
652 | drm_edid = intel_crt_get_edid(connector, ddc); |
653 | if (!drm_edid) |
654 | return 0; |
655 | |
656 | ret = intel_connector_update_modes(connector, drm_edid); |
657 | |
658 | drm_edid_free(drm_edid); |
659 | |
660 | return ret; |
661 | } |
662 | |
663 | static bool intel_crt_detect_ddc(struct drm_connector *connector) |
664 | { |
665 | struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector)); |
666 | struct drm_i915_private *dev_priv = to_i915(dev: crt->base.base.dev); |
667 | const struct drm_edid *drm_edid; |
668 | bool ret = false; |
669 | |
670 | drm_edid = intel_crt_get_edid(connector, ddc: connector->ddc); |
671 | |
672 | if (drm_edid) { |
673 | /* |
674 | * This may be a DVI-I connector with a shared DDC |
675 | * link between analog and digital outputs, so we |
676 | * have to check the EDID input spec of the attached device. |
677 | */ |
678 | if (drm_edid_is_digital(drm_edid)) { |
679 | drm_dbg_kms(&dev_priv->drm, |
680 | "CRT not detected via DDC:0x50 [EDID reports a digital panel]\n" ); |
681 | } else { |
682 | drm_dbg_kms(&dev_priv->drm, |
683 | "CRT detected via DDC:0x50 [EDID]\n" ); |
684 | ret = true; |
685 | } |
686 | } else { |
687 | drm_dbg_kms(&dev_priv->drm, |
688 | "CRT not detected via DDC:0x50 [no valid EDID found]\n" ); |
689 | } |
690 | |
691 | drm_edid_free(drm_edid); |
692 | |
693 | return ret; |
694 | } |
695 | |
696 | static enum drm_connector_status |
697 | intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe) |
698 | { |
699 | struct drm_device *dev = crt->base.base.dev; |
700 | struct drm_i915_private *dev_priv = to_i915(dev); |
701 | enum transcoder cpu_transcoder = (enum transcoder)pipe; |
702 | u32 save_bclrpat; |
703 | u32 save_vtotal; |
704 | u32 vtotal, vactive; |
705 | u32 vsample; |
706 | u32 vblank, vblank_start, vblank_end; |
707 | u32 dsl; |
708 | u8 st00; |
709 | enum drm_connector_status status; |
710 | |
711 | drm_dbg_kms(&dev_priv->drm, "starting load-detect on CRT\n" ); |
712 | |
713 | save_bclrpat = intel_de_read(i915: dev_priv, BCLRPAT(cpu_transcoder)); |
714 | save_vtotal = intel_de_read(i915: dev_priv, TRANS_VTOTAL(cpu_transcoder)); |
715 | vblank = intel_de_read(i915: dev_priv, TRANS_VBLANK(cpu_transcoder)); |
716 | |
717 | vtotal = REG_FIELD_GET(VTOTAL_MASK, save_vtotal) + 1; |
718 | vactive = REG_FIELD_GET(VACTIVE_MASK, save_vtotal) + 1; |
719 | |
720 | vblank_start = REG_FIELD_GET(VBLANK_START_MASK, vblank) + 1; |
721 | vblank_end = REG_FIELD_GET(VBLANK_END_MASK, vblank) + 1; |
722 | |
723 | /* Set the border color to purple. */ |
724 | intel_de_write(i915: dev_priv, BCLRPAT(cpu_transcoder), val: 0x500050); |
725 | |
726 | if (DISPLAY_VER(dev_priv) != 2) { |
727 | u32 transconf = intel_de_read(i915: dev_priv, TRANSCONF(cpu_transcoder)); |
728 | |
729 | intel_de_write(i915: dev_priv, TRANSCONF(cpu_transcoder), |
730 | val: transconf | TRANSCONF_FORCE_BORDER); |
731 | intel_de_posting_read(i915: dev_priv, TRANSCONF(cpu_transcoder)); |
732 | /* Wait for next Vblank to substitue |
733 | * border color for Color info */ |
734 | intel_crtc_wait_for_next_vblank(crtc: intel_crtc_for_pipe(i915: dev_priv, pipe)); |
735 | st00 = intel_de_read8(i915: dev_priv, _VGA_MSR_WRITE); |
736 | status = ((st00 & (1 << 4)) != 0) ? |
737 | connector_status_connected : |
738 | connector_status_disconnected; |
739 | |
740 | intel_de_write(i915: dev_priv, TRANSCONF(cpu_transcoder), val: transconf); |
741 | } else { |
742 | bool restore_vblank = false; |
743 | int count, detect; |
744 | |
745 | /* |
746 | * If there isn't any border, add some. |
747 | * Yes, this will flicker |
748 | */ |
749 | if (vblank_start <= vactive && vblank_end >= vtotal) { |
750 | u32 vsync = intel_de_read(i915: dev_priv, TRANS_VSYNC(cpu_transcoder)); |
751 | u32 vsync_start = REG_FIELD_GET(VSYNC_START_MASK, vsync) + 1; |
752 | |
753 | vblank_start = vsync_start; |
754 | intel_de_write(i915: dev_priv, TRANS_VBLANK(cpu_transcoder), |
755 | VBLANK_START(vblank_start - 1) | |
756 | VBLANK_END(vblank_end - 1)); |
757 | restore_vblank = true; |
758 | } |
759 | /* sample in the vertical border, selecting the larger one */ |
760 | if (vblank_start - vactive >= vtotal - vblank_end) |
761 | vsample = (vblank_start + vactive) >> 1; |
762 | else |
763 | vsample = (vtotal + vblank_end) >> 1; |
764 | |
765 | /* |
766 | * Wait for the border to be displayed |
767 | */ |
768 | while (intel_de_read(i915: dev_priv, PIPEDSL(pipe)) >= vactive) |
769 | ; |
770 | while ((dsl = intel_de_read(i915: dev_priv, PIPEDSL(pipe))) <= vsample) |
771 | ; |
772 | /* |
773 | * Watch ST00 for an entire scanline |
774 | */ |
775 | detect = 0; |
776 | count = 0; |
777 | do { |
778 | count++; |
779 | /* Read the ST00 VGA status register */ |
780 | st00 = intel_de_read8(i915: dev_priv, _VGA_MSR_WRITE); |
781 | if (st00 & (1 << 4)) |
782 | detect++; |
783 | } while ((intel_de_read(i915: dev_priv, PIPEDSL(pipe)) == dsl)); |
784 | |
785 | /* restore vblank if necessary */ |
786 | if (restore_vblank) |
787 | intel_de_write(i915: dev_priv, TRANS_VBLANK(cpu_transcoder), val: vblank); |
788 | /* |
789 | * If more than 3/4 of the scanline detected a monitor, |
790 | * then it is assumed to be present. This works even on i830, |
791 | * where there isn't any way to force the border color across |
792 | * the screen |
793 | */ |
794 | status = detect * 4 > count * 3 ? |
795 | connector_status_connected : |
796 | connector_status_disconnected; |
797 | } |
798 | |
799 | /* Restore previous settings */ |
800 | intel_de_write(i915: dev_priv, BCLRPAT(cpu_transcoder), val: save_bclrpat); |
801 | |
802 | return status; |
803 | } |
804 | |
805 | static int intel_spurious_crt_detect_dmi_callback(const struct dmi_system_id *id) |
806 | { |
807 | DRM_DEBUG_DRIVER("Skipping CRT detection for %s\n" , id->ident); |
808 | return 1; |
809 | } |
810 | |
811 | static const struct dmi_system_id intel_spurious_crt_detect[] = { |
812 | { |
813 | .callback = intel_spurious_crt_detect_dmi_callback, |
814 | .ident = "ACER ZGB" , |
815 | .matches = { |
816 | DMI_MATCH(DMI_SYS_VENDOR, "ACER" ), |
817 | DMI_MATCH(DMI_PRODUCT_NAME, "ZGB" ), |
818 | }, |
819 | }, |
820 | { |
821 | .callback = intel_spurious_crt_detect_dmi_callback, |
822 | .ident = "Intel DZ77BH-55K" , |
823 | .matches = { |
824 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation" ), |
825 | DMI_MATCH(DMI_BOARD_NAME, "DZ77BH-55K" ), |
826 | }, |
827 | }, |
828 | { } |
829 | }; |
830 | |
831 | static int |
832 | intel_crt_detect(struct drm_connector *connector, |
833 | struct drm_modeset_acquire_ctx *ctx, |
834 | bool force) |
835 | { |
836 | struct drm_i915_private *dev_priv = to_i915(dev: connector->dev); |
837 | struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector)); |
838 | struct intel_encoder *intel_encoder = &crt->base; |
839 | struct drm_atomic_state *state; |
840 | intel_wakeref_t wakeref; |
841 | int status; |
842 | |
843 | drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] force=%d\n" , |
844 | connector->base.id, connector->name, |
845 | force); |
846 | |
847 | if (!intel_display_device_enabled(i915: dev_priv)) |
848 | return connector_status_disconnected; |
849 | |
850 | if (!intel_display_driver_check_access(i915: dev_priv)) |
851 | return connector->status; |
852 | |
853 | if (dev_priv->display.params.load_detect_test) { |
854 | wakeref = intel_display_power_get(dev_priv, |
855 | domain: intel_encoder->power_domain); |
856 | goto load_detect; |
857 | } |
858 | |
859 | /* Skip machines without VGA that falsely report hotplug events */ |
860 | if (dmi_check_system(list: intel_spurious_crt_detect)) |
861 | return connector_status_disconnected; |
862 | |
863 | wakeref = intel_display_power_get(dev_priv, |
864 | domain: intel_encoder->power_domain); |
865 | |
866 | if (I915_HAS_HOTPLUG(dev_priv)) { |
867 | /* We can not rely on the HPD pin always being correctly wired |
868 | * up, for example many KVM do not pass it through, and so |
869 | * only trust an assertion that the monitor is connected. |
870 | */ |
871 | if (intel_crt_detect_hotplug(connector)) { |
872 | drm_dbg_kms(&dev_priv->drm, |
873 | "CRT detected via hotplug\n" ); |
874 | status = connector_status_connected; |
875 | goto out; |
876 | } else |
877 | drm_dbg_kms(&dev_priv->drm, |
878 | "CRT not detected via hotplug\n" ); |
879 | } |
880 | |
881 | if (intel_crt_detect_ddc(connector)) { |
882 | status = connector_status_connected; |
883 | goto out; |
884 | } |
885 | |
886 | /* Load detection is broken on HPD capable machines. Whoever wants a |
887 | * broken monitor (without edid) to work behind a broken kvm (that fails |
888 | * to have the right resistors for HP detection) needs to fix this up. |
889 | * For now just bail out. */ |
890 | if (I915_HAS_HOTPLUG(dev_priv)) { |
891 | status = connector_status_disconnected; |
892 | goto out; |
893 | } |
894 | |
895 | load_detect: |
896 | if (!force) { |
897 | status = connector->status; |
898 | goto out; |
899 | } |
900 | |
901 | /* for pre-945g platforms use load detect */ |
902 | state = intel_load_detect_get_pipe(connector, ctx); |
903 | if (IS_ERR(ptr: state)) { |
904 | status = PTR_ERR(ptr: state); |
905 | } else if (!state) { |
906 | status = connector_status_unknown; |
907 | } else { |
908 | if (intel_crt_detect_ddc(connector)) |
909 | status = connector_status_connected; |
910 | else if (DISPLAY_VER(dev_priv) < 4) |
911 | status = intel_crt_load_detect(crt, |
912 | to_intel_crtc(connector->state->crtc)->pipe); |
913 | else if (dev_priv->display.params.load_detect_test) |
914 | status = connector_status_disconnected; |
915 | else |
916 | status = connector_status_unknown; |
917 | intel_load_detect_release_pipe(connector, old: state, ctx); |
918 | } |
919 | |
920 | out: |
921 | intel_display_power_put(dev_priv, domain: intel_encoder->power_domain, wakeref); |
922 | |
923 | return status; |
924 | } |
925 | |
926 | static int intel_crt_get_modes(struct drm_connector *connector) |
927 | { |
928 | struct drm_device *dev = connector->dev; |
929 | struct drm_i915_private *dev_priv = to_i915(dev); |
930 | struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector)); |
931 | struct intel_encoder *intel_encoder = &crt->base; |
932 | intel_wakeref_t wakeref; |
933 | struct i2c_adapter *ddc; |
934 | int ret; |
935 | |
936 | if (!intel_display_driver_check_access(i915: dev_priv)) |
937 | return drm_edid_connector_add_modes(connector); |
938 | |
939 | wakeref = intel_display_power_get(dev_priv, |
940 | domain: intel_encoder->power_domain); |
941 | |
942 | ret = intel_crt_ddc_get_modes(connector, ddc: connector->ddc); |
943 | if (ret || !IS_G4X(dev_priv)) |
944 | goto out; |
945 | |
946 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ |
947 | ddc = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB); |
948 | ret = intel_crt_ddc_get_modes(connector, ddc); |
949 | |
950 | out: |
951 | intel_display_power_put(dev_priv, domain: intel_encoder->power_domain, wakeref); |
952 | |
953 | return ret; |
954 | } |
955 | |
956 | void intel_crt_reset(struct drm_encoder *encoder) |
957 | { |
958 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->dev); |
959 | struct intel_crt *crt = intel_encoder_to_crt(to_intel_encoder(encoder)); |
960 | |
961 | if (DISPLAY_VER(dev_priv) >= 5) { |
962 | u32 adpa; |
963 | |
964 | adpa = intel_de_read(i915: dev_priv, reg: crt->adpa_reg); |
965 | adpa &= ~ADPA_CRT_HOTPLUG_MASK; |
966 | adpa |= ADPA_HOTPLUG_BITS; |
967 | intel_de_write(i915: dev_priv, reg: crt->adpa_reg, val: adpa); |
968 | intel_de_posting_read(i915: dev_priv, reg: crt->adpa_reg); |
969 | |
970 | drm_dbg_kms(&dev_priv->drm, "crt adpa set to 0x%x\n" , adpa); |
971 | crt->force_hotplug_required = true; |
972 | } |
973 | |
974 | } |
975 | |
976 | /* |
977 | * Routines for controlling stuff on the analog port |
978 | */ |
979 | |
980 | static const struct drm_connector_funcs intel_crt_connector_funcs = { |
981 | .fill_modes = drm_helper_probe_single_connector_modes, |
982 | .late_register = intel_connector_register, |
983 | .early_unregister = intel_connector_unregister, |
984 | .destroy = intel_connector_destroy, |
985 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
986 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
987 | }; |
988 | |
989 | static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { |
990 | .detect_ctx = intel_crt_detect, |
991 | .mode_valid = intel_crt_mode_valid, |
992 | .get_modes = intel_crt_get_modes, |
993 | }; |
994 | |
995 | static const struct drm_encoder_funcs intel_crt_enc_funcs = { |
996 | .reset = intel_crt_reset, |
997 | .destroy = intel_encoder_destroy, |
998 | }; |
999 | |
1000 | void intel_crt_init(struct drm_i915_private *dev_priv) |
1001 | { |
1002 | struct drm_connector *connector; |
1003 | struct intel_crt *crt; |
1004 | struct intel_connector *intel_connector; |
1005 | i915_reg_t adpa_reg; |
1006 | u8 ddc_pin; |
1007 | u32 adpa; |
1008 | |
1009 | if (HAS_PCH_SPLIT(dev_priv)) |
1010 | adpa_reg = PCH_ADPA; |
1011 | else if (IS_VALLEYVIEW(dev_priv)) |
1012 | adpa_reg = VLV_ADPA; |
1013 | else |
1014 | adpa_reg = ADPA; |
1015 | |
1016 | adpa = intel_de_read(i915: dev_priv, reg: adpa_reg); |
1017 | if ((adpa & ADPA_DAC_ENABLE) == 0) { |
1018 | /* |
1019 | * On some machines (some IVB at least) CRT can be |
1020 | * fused off, but there's no known fuse bit to |
1021 | * indicate that. On these machine the ADPA register |
1022 | * works normally, except the DAC enable bit won't |
1023 | * take. So the only way to tell is attempt to enable |
1024 | * it and see what happens. |
1025 | */ |
1026 | intel_de_write(i915: dev_priv, reg: adpa_reg, |
1027 | val: adpa | ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); |
1028 | if ((intel_de_read(i915: dev_priv, reg: adpa_reg) & ADPA_DAC_ENABLE) == 0) |
1029 | return; |
1030 | intel_de_write(i915: dev_priv, reg: adpa_reg, val: adpa); |
1031 | } |
1032 | |
1033 | crt = kzalloc(size: sizeof(struct intel_crt), GFP_KERNEL); |
1034 | if (!crt) |
1035 | return; |
1036 | |
1037 | intel_connector = intel_connector_alloc(); |
1038 | if (!intel_connector) { |
1039 | kfree(objp: crt); |
1040 | return; |
1041 | } |
1042 | |
1043 | ddc_pin = dev_priv->display.vbt.crt_ddc_pin; |
1044 | |
1045 | connector = &intel_connector->base; |
1046 | crt->connector = intel_connector; |
1047 | drm_connector_init_with_ddc(dev: &dev_priv->drm, connector, |
1048 | funcs: &intel_crt_connector_funcs, |
1049 | DRM_MODE_CONNECTOR_VGA, |
1050 | ddc: intel_gmbus_get_adapter(dev_priv, pin: ddc_pin)); |
1051 | |
1052 | drm_encoder_init(dev: &dev_priv->drm, encoder: &crt->base.base, funcs: &intel_crt_enc_funcs, |
1053 | DRM_MODE_ENCODER_DAC, name: "CRT" ); |
1054 | |
1055 | intel_connector_attach_encoder(connector: intel_connector, encoder: &crt->base); |
1056 | |
1057 | crt->base.type = INTEL_OUTPUT_ANALOG; |
1058 | crt->base.cloneable = BIT(INTEL_OUTPUT_DVO) | BIT(INTEL_OUTPUT_HDMI); |
1059 | if (IS_I830(dev_priv)) |
1060 | crt->base.pipe_mask = BIT(PIPE_A); |
1061 | else |
1062 | crt->base.pipe_mask = ~0; |
1063 | |
1064 | if (DISPLAY_VER(dev_priv) != 2) |
1065 | connector->interlace_allowed = true; |
1066 | |
1067 | crt->adpa_reg = adpa_reg; |
1068 | |
1069 | crt->base.power_domain = POWER_DOMAIN_PORT_CRT; |
1070 | |
1071 | if (I915_HAS_HOTPLUG(dev_priv) && |
1072 | !dmi_check_system(list: intel_spurious_crt_detect)) { |
1073 | crt->base.hpd_pin = HPD_CRT; |
1074 | crt->base.hotplug = intel_encoder_hotplug; |
1075 | intel_connector->polled = DRM_CONNECTOR_POLL_HPD; |
1076 | } else { |
1077 | intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
1078 | } |
1079 | intel_connector->base.polled = intel_connector->polled; |
1080 | |
1081 | if (HAS_DDI(dev_priv)) { |
1082 | assert_port_valid(i915: dev_priv, port: PORT_E); |
1083 | |
1084 | crt->base.port = PORT_E; |
1085 | crt->base.get_config = hsw_crt_get_config; |
1086 | crt->base.get_hw_state = intel_ddi_get_hw_state; |
1087 | crt->base.compute_config = hsw_crt_compute_config; |
1088 | crt->base.pre_pll_enable = hsw_pre_pll_enable_crt; |
1089 | crt->base.pre_enable = hsw_pre_enable_crt; |
1090 | crt->base.enable = hsw_enable_crt; |
1091 | crt->base.disable = hsw_disable_crt; |
1092 | crt->base.post_disable = hsw_post_disable_crt; |
1093 | crt->base.enable_clock = hsw_ddi_enable_clock; |
1094 | crt->base.disable_clock = hsw_ddi_disable_clock; |
1095 | crt->base.is_clock_enabled = hsw_ddi_is_clock_enabled; |
1096 | |
1097 | intel_ddi_buf_trans_init(encoder: &crt->base); |
1098 | } else { |
1099 | if (HAS_PCH_SPLIT(dev_priv)) { |
1100 | crt->base.compute_config = pch_crt_compute_config; |
1101 | crt->base.disable = pch_disable_crt; |
1102 | crt->base.post_disable = pch_post_disable_crt; |
1103 | } else { |
1104 | crt->base.compute_config = intel_crt_compute_config; |
1105 | crt->base.disable = intel_disable_crt; |
1106 | } |
1107 | crt->base.port = PORT_NONE; |
1108 | crt->base.get_config = intel_crt_get_config; |
1109 | crt->base.get_hw_state = intel_crt_get_hw_state; |
1110 | crt->base.enable = intel_enable_crt; |
1111 | } |
1112 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
1113 | |
1114 | drm_connector_helper_add(connector, funcs: &intel_crt_connector_helper_funcs); |
1115 | |
1116 | /* |
1117 | * TODO: find a proper way to discover whether we need to set the the |
1118 | * polarity and link reversal bits or not, instead of relying on the |
1119 | * BIOS. |
1120 | */ |
1121 | if (HAS_PCH_LPT(dev_priv)) { |
1122 | u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT | |
1123 | FDI_RX_LINK_REVERSAL_OVERRIDE; |
1124 | |
1125 | dev_priv->display.fdi.rx_config = intel_de_read(i915: dev_priv, |
1126 | FDI_RX_CTL(PIPE_A)) & fdi_config; |
1127 | } |
1128 | |
1129 | intel_crt_reset(encoder: &crt->base.base); |
1130 | } |
1131 | |