1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright © 2020 Intel Corporation |
4 | * |
5 | * HDMI support for G4x,ILK,SNB,IVB,VLV,CHV (HSW+ handled by the DDI code). |
6 | */ |
7 | |
8 | #include "g4x_hdmi.h" |
9 | #include "i915_reg.h" |
10 | #include "intel_atomic.h" |
11 | #include "intel_audio.h" |
12 | #include "intel_connector.h" |
13 | #include "intel_crtc.h" |
14 | #include "intel_de.h" |
15 | #include "intel_display_power.h" |
16 | #include "intel_display_types.h" |
17 | #include "intel_dp_aux.h" |
18 | #include "intel_dpio_phy.h" |
19 | #include "intel_fdi.h" |
20 | #include "intel_fifo_underrun.h" |
21 | #include "intel_hdmi.h" |
22 | #include "intel_hotplug.h" |
23 | #include "intel_sdvo.h" |
24 | #include "vlv_sideband.h" |
25 | |
26 | static void intel_hdmi_prepare(struct intel_encoder *encoder, |
27 | const struct intel_crtc_state *crtc_state) |
28 | { |
29 | struct drm_device *dev = encoder->base.dev; |
30 | struct drm_i915_private *dev_priv = to_i915(dev); |
31 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
32 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
33 | const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; |
34 | u32 hdmi_val; |
35 | |
36 | intel_dp_dual_mode_set_tmds_output(hdmi: intel_hdmi, enable: true); |
37 | |
38 | hdmi_val = SDVO_ENCODING_HDMI; |
39 | if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range) |
40 | hdmi_val |= HDMI_COLOR_RANGE_16_235; |
41 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
42 | hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; |
43 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
44 | hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH; |
45 | |
46 | if (crtc_state->pipe_bpp > 24) |
47 | hdmi_val |= HDMI_COLOR_FORMAT_12bpc; |
48 | else |
49 | hdmi_val |= SDVO_COLOR_FORMAT_8bpc; |
50 | |
51 | if (crtc_state->has_hdmi_sink) |
52 | hdmi_val |= HDMI_MODE_SELECT_HDMI; |
53 | |
54 | if (HAS_PCH_CPT(dev_priv)) |
55 | hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); |
56 | else if (IS_CHERRYVIEW(dev_priv)) |
57 | hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe); |
58 | else |
59 | hdmi_val |= SDVO_PIPE_SEL(crtc->pipe); |
60 | |
61 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: hdmi_val); |
62 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
63 | } |
64 | |
65 | static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, |
66 | enum pipe *pipe) |
67 | { |
68 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
69 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
70 | intel_wakeref_t wakeref; |
71 | bool ret; |
72 | |
73 | wakeref = intel_display_power_get_if_enabled(dev_priv, |
74 | domain: encoder->power_domain); |
75 | if (!wakeref) |
76 | return false; |
77 | |
78 | ret = intel_sdvo_port_enabled(dev_priv, sdvo_reg: intel_hdmi->hdmi_reg, pipe); |
79 | |
80 | intel_display_power_put(dev_priv, domain: encoder->power_domain, wakeref); |
81 | |
82 | return ret; |
83 | } |
84 | |
85 | static bool connector_is_hdmi(struct drm_connector *connector) |
86 | { |
87 | struct intel_encoder *encoder = |
88 | intel_attached_encoder(to_intel_connector(connector)); |
89 | |
90 | return encoder && encoder->type == INTEL_OUTPUT_HDMI; |
91 | } |
92 | |
93 | static bool g4x_compute_has_hdmi_sink(struct intel_atomic_state *state, |
94 | struct intel_crtc *this_crtc) |
95 | { |
96 | const struct drm_connector_state *conn_state; |
97 | struct drm_connector *connector; |
98 | int i; |
99 | |
100 | /* |
101 | * On g4x only one HDMI port can transmit infoframes/audio at |
102 | * any given time. Select the first suitable port for this duty. |
103 | * |
104 | * See also g4x_hdmi_connector_atomic_check(). |
105 | */ |
106 | for_each_new_connector_in_state(&state->base, connector, conn_state, i) { |
107 | struct intel_encoder *encoder = to_intel_encoder(conn_state->best_encoder); |
108 | const struct intel_crtc_state *crtc_state; |
109 | struct intel_crtc *crtc; |
110 | |
111 | if (!connector_is_hdmi(connector)) |
112 | continue; |
113 | |
114 | crtc = to_intel_crtc(conn_state->crtc); |
115 | if (!crtc) |
116 | continue; |
117 | |
118 | crtc_state = intel_atomic_get_new_crtc_state(state, crtc); |
119 | |
120 | if (!intel_hdmi_compute_has_hdmi_sink(encoder, crtc_state, conn_state)) |
121 | continue; |
122 | |
123 | return crtc == this_crtc; |
124 | } |
125 | |
126 | return false; |
127 | } |
128 | |
129 | static int g4x_hdmi_compute_config(struct intel_encoder *encoder, |
130 | struct intel_crtc_state *crtc_state, |
131 | struct drm_connector_state *conn_state) |
132 | { |
133 | struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); |
134 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
135 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
136 | |
137 | if (HAS_PCH_SPLIT(i915)) { |
138 | crtc_state->has_pch_encoder = true; |
139 | if (!intel_fdi_compute_pipe_bpp(crtc_state)) |
140 | return -EINVAL; |
141 | } |
142 | |
143 | if (IS_G4X(i915)) |
144 | crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, this_crtc: crtc); |
145 | else |
146 | crtc_state->has_hdmi_sink = |
147 | intel_hdmi_compute_has_hdmi_sink(encoder, crtc_state, conn_state); |
148 | |
149 | return intel_hdmi_compute_config(encoder, pipe_config: crtc_state, conn_state); |
150 | } |
151 | |
152 | static void intel_hdmi_get_config(struct intel_encoder *encoder, |
153 | struct intel_crtc_state *pipe_config) |
154 | { |
155 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
156 | struct drm_device *dev = encoder->base.dev; |
157 | struct drm_i915_private *dev_priv = to_i915(dev); |
158 | u32 tmp, flags = 0; |
159 | int dotclock; |
160 | |
161 | pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI); |
162 | |
163 | tmp = intel_de_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
164 | |
165 | if (tmp & SDVO_HSYNC_ACTIVE_HIGH) |
166 | flags |= DRM_MODE_FLAG_PHSYNC; |
167 | else |
168 | flags |= DRM_MODE_FLAG_NHSYNC; |
169 | |
170 | if (tmp & SDVO_VSYNC_ACTIVE_HIGH) |
171 | flags |= DRM_MODE_FLAG_PVSYNC; |
172 | else |
173 | flags |= DRM_MODE_FLAG_NVSYNC; |
174 | |
175 | if (tmp & HDMI_MODE_SELECT_HDMI) |
176 | pipe_config->has_hdmi_sink = true; |
177 | |
178 | pipe_config->infoframes.enable |= |
179 | intel_hdmi_infoframes_enabled(encoder, crtc_state: pipe_config); |
180 | |
181 | if (pipe_config->infoframes.enable) |
182 | pipe_config->has_infoframe = true; |
183 | |
184 | if (tmp & HDMI_AUDIO_ENABLE) |
185 | pipe_config->has_audio = true; |
186 | |
187 | if (!HAS_PCH_SPLIT(dev_priv) && |
188 | tmp & HDMI_COLOR_RANGE_16_235) |
189 | pipe_config->limited_color_range = true; |
190 | |
191 | pipe_config->hw.adjusted_mode.flags |= flags; |
192 | |
193 | if ((tmp & SDVO_COLOR_FORMAT_MASK) == HDMI_COLOR_FORMAT_12bpc) |
194 | dotclock = DIV_ROUND_CLOSEST(pipe_config->port_clock * 2, 3); |
195 | else |
196 | dotclock = pipe_config->port_clock; |
197 | |
198 | if (pipe_config->pixel_multiplier) |
199 | dotclock /= pipe_config->pixel_multiplier; |
200 | |
201 | pipe_config->hw.adjusted_mode.crtc_clock = dotclock; |
202 | |
203 | pipe_config->lane_count = 4; |
204 | |
205 | intel_hdmi_read_gcp_infoframe(encoder, crtc_state: pipe_config); |
206 | |
207 | intel_read_infoframe(encoder, crtc_state: pipe_config, |
208 | type: HDMI_INFOFRAME_TYPE_AVI, |
209 | frame: &pipe_config->infoframes.avi); |
210 | intel_read_infoframe(encoder, crtc_state: pipe_config, |
211 | type: HDMI_INFOFRAME_TYPE_SPD, |
212 | frame: &pipe_config->infoframes.spd); |
213 | intel_read_infoframe(encoder, crtc_state: pipe_config, |
214 | type: HDMI_INFOFRAME_TYPE_VENDOR, |
215 | frame: &pipe_config->infoframes.hdmi); |
216 | |
217 | intel_audio_codec_get_config(encoder, crtc_state: pipe_config); |
218 | } |
219 | |
220 | static void g4x_hdmi_enable_port(struct intel_encoder *encoder, |
221 | const struct intel_crtc_state *pipe_config) |
222 | { |
223 | struct drm_device *dev = encoder->base.dev; |
224 | struct drm_i915_private *dev_priv = to_i915(dev); |
225 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
226 | u32 temp; |
227 | |
228 | temp = intel_de_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
229 | |
230 | temp |= SDVO_ENABLE; |
231 | |
232 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
233 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
234 | } |
235 | |
236 | static void g4x_hdmi_audio_enable(struct intel_encoder *encoder, |
237 | const struct intel_crtc_state *crtc_state, |
238 | const struct drm_connector_state *conn_state) |
239 | { |
240 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
241 | struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder); |
242 | |
243 | if (!crtc_state->has_audio) |
244 | return; |
245 | |
246 | drm_WARN_ON(&i915->drm, !crtc_state->has_hdmi_sink); |
247 | |
248 | /* Enable audio presence detect */ |
249 | intel_de_rmw(i915, reg: hdmi->hdmi_reg, clear: 0, HDMI_AUDIO_ENABLE); |
250 | |
251 | intel_audio_codec_enable(encoder, crtc_state, conn_state); |
252 | } |
253 | |
254 | static void g4x_hdmi_audio_disable(struct intel_encoder *encoder, |
255 | const struct intel_crtc_state *old_crtc_state, |
256 | const struct drm_connector_state *old_conn_state) |
257 | { |
258 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
259 | struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder); |
260 | |
261 | if (!old_crtc_state->has_audio) |
262 | return; |
263 | |
264 | intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); |
265 | |
266 | /* Disable audio presence detect */ |
267 | intel_de_rmw(i915, reg: hdmi->hdmi_reg, HDMI_AUDIO_ENABLE, set: 0); |
268 | } |
269 | |
270 | static void g4x_enable_hdmi(struct intel_atomic_state *state, |
271 | struct intel_encoder *encoder, |
272 | const struct intel_crtc_state *pipe_config, |
273 | const struct drm_connector_state *conn_state) |
274 | { |
275 | g4x_hdmi_enable_port(encoder, pipe_config); |
276 | } |
277 | |
278 | static void ibx_enable_hdmi(struct intel_atomic_state *state, |
279 | struct intel_encoder *encoder, |
280 | const struct intel_crtc_state *pipe_config, |
281 | const struct drm_connector_state *conn_state) |
282 | { |
283 | struct drm_device *dev = encoder->base.dev; |
284 | struct drm_i915_private *dev_priv = to_i915(dev); |
285 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
286 | u32 temp; |
287 | |
288 | temp = intel_de_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
289 | |
290 | temp |= SDVO_ENABLE; |
291 | |
292 | /* |
293 | * HW workaround, need to write this twice for issue |
294 | * that may result in first write getting masked. |
295 | */ |
296 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
297 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
298 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
299 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
300 | |
301 | /* |
302 | * HW workaround, need to toggle enable bit off and on |
303 | * for 12bpc with pixel repeat. |
304 | * |
305 | * FIXME: BSpec says this should be done at the end of |
306 | * the modeset sequence, so not sure if this isn't too soon. |
307 | */ |
308 | if (pipe_config->pipe_bpp > 24 && |
309 | pipe_config->pixel_multiplier > 1) { |
310 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, |
311 | val: temp & ~SDVO_ENABLE); |
312 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
313 | |
314 | /* |
315 | * HW workaround, need to write this twice for issue |
316 | * that may result in first write getting masked. |
317 | */ |
318 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
319 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
320 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
321 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
322 | } |
323 | } |
324 | |
325 | static void cpt_enable_hdmi(struct intel_atomic_state *state, |
326 | struct intel_encoder *encoder, |
327 | const struct intel_crtc_state *pipe_config, |
328 | const struct drm_connector_state *conn_state) |
329 | { |
330 | struct drm_device *dev = encoder->base.dev; |
331 | struct drm_i915_private *dev_priv = to_i915(dev); |
332 | struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); |
333 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
334 | enum pipe pipe = crtc->pipe; |
335 | u32 temp; |
336 | |
337 | temp = intel_de_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
338 | |
339 | temp |= SDVO_ENABLE; |
340 | |
341 | /* |
342 | * WaEnableHDMI8bpcBefore12bpc:snb,ivb |
343 | * |
344 | * The procedure for 12bpc is as follows: |
345 | * 1. disable HDMI clock gating |
346 | * 2. enable HDMI with 8bpc |
347 | * 3. enable HDMI with 12bpc |
348 | * 4. enable HDMI clock gating |
349 | */ |
350 | |
351 | if (pipe_config->pipe_bpp > 24) { |
352 | intel_de_rmw(i915: dev_priv, TRANS_CHICKEN1(pipe), |
353 | clear: 0, TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE); |
354 | |
355 | temp &= ~SDVO_COLOR_FORMAT_MASK; |
356 | temp |= SDVO_COLOR_FORMAT_8bpc; |
357 | } |
358 | |
359 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
360 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
361 | |
362 | if (pipe_config->pipe_bpp > 24) { |
363 | temp &= ~SDVO_COLOR_FORMAT_MASK; |
364 | temp |= HDMI_COLOR_FORMAT_12bpc; |
365 | |
366 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
367 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
368 | |
369 | intel_de_rmw(i915: dev_priv, TRANS_CHICKEN1(pipe), |
370 | TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE, set: 0); |
371 | } |
372 | } |
373 | |
374 | static void vlv_enable_hdmi(struct intel_atomic_state *state, |
375 | struct intel_encoder *encoder, |
376 | const struct intel_crtc_state *pipe_config, |
377 | const struct drm_connector_state *conn_state) |
378 | { |
379 | } |
380 | |
381 | static void intel_disable_hdmi(struct intel_atomic_state *state, |
382 | struct intel_encoder *encoder, |
383 | const struct intel_crtc_state *old_crtc_state, |
384 | const struct drm_connector_state *old_conn_state) |
385 | { |
386 | struct drm_device *dev = encoder->base.dev; |
387 | struct drm_i915_private *dev_priv = to_i915(dev); |
388 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
389 | struct intel_digital_port *dig_port = |
390 | hdmi_to_dig_port(intel_hdmi); |
391 | struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); |
392 | u32 temp; |
393 | |
394 | temp = intel_de_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
395 | |
396 | temp &= ~SDVO_ENABLE; |
397 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
398 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
399 | |
400 | /* |
401 | * HW workaround for IBX, we need to move the port |
402 | * to transcoder A after disabling it to allow the |
403 | * matching DP port to be enabled on transcoder A. |
404 | */ |
405 | if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) { |
406 | /* |
407 | * We get CPU/PCH FIFO underruns on the other pipe when |
408 | * doing the workaround. Sweep them under the rug. |
409 | */ |
410 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe: PIPE_A, enable: false); |
411 | intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder: PIPE_A, enable: false); |
412 | |
413 | temp &= ~SDVO_PIPE_SEL_MASK; |
414 | temp |= SDVO_ENABLE | SDVO_PIPE_SEL(PIPE_A); |
415 | /* |
416 | * HW workaround, need to write this twice for issue |
417 | * that may result in first write getting masked. |
418 | */ |
419 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
420 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
421 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
422 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
423 | |
424 | temp &= ~SDVO_ENABLE; |
425 | intel_de_write(i915: dev_priv, reg: intel_hdmi->hdmi_reg, val: temp); |
426 | intel_de_posting_read(i915: dev_priv, reg: intel_hdmi->hdmi_reg); |
427 | |
428 | intel_wait_for_vblank_if_active(i915: dev_priv, pipe: PIPE_A); |
429 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe: PIPE_A, enable: true); |
430 | intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder: PIPE_A, enable: true); |
431 | } |
432 | |
433 | dig_port->set_infoframes(encoder, |
434 | false, |
435 | old_crtc_state, old_conn_state); |
436 | |
437 | intel_dp_dual_mode_set_tmds_output(hdmi: intel_hdmi, enable: false); |
438 | } |
439 | |
440 | static void g4x_disable_hdmi(struct intel_atomic_state *state, |
441 | struct intel_encoder *encoder, |
442 | const struct intel_crtc_state *old_crtc_state, |
443 | const struct drm_connector_state *old_conn_state) |
444 | { |
445 | intel_disable_hdmi(state, encoder, old_crtc_state, old_conn_state); |
446 | } |
447 | |
448 | static void pch_disable_hdmi(struct intel_atomic_state *state, |
449 | struct intel_encoder *encoder, |
450 | const struct intel_crtc_state *old_crtc_state, |
451 | const struct drm_connector_state *old_conn_state) |
452 | { |
453 | } |
454 | |
455 | static void pch_post_disable_hdmi(struct intel_atomic_state *state, |
456 | struct intel_encoder *encoder, |
457 | const struct intel_crtc_state *old_crtc_state, |
458 | const struct drm_connector_state *old_conn_state) |
459 | { |
460 | intel_disable_hdmi(state, encoder, old_crtc_state, old_conn_state); |
461 | } |
462 | |
463 | static void intel_hdmi_pre_enable(struct intel_atomic_state *state, |
464 | struct intel_encoder *encoder, |
465 | const struct intel_crtc_state *pipe_config, |
466 | const struct drm_connector_state *conn_state) |
467 | { |
468 | struct intel_digital_port *dig_port = |
469 | enc_to_dig_port(encoder); |
470 | |
471 | intel_hdmi_prepare(encoder, crtc_state: pipe_config); |
472 | |
473 | dig_port->set_infoframes(encoder, |
474 | pipe_config->has_infoframe, |
475 | pipe_config, conn_state); |
476 | } |
477 | |
478 | static void vlv_hdmi_pre_enable(struct intel_atomic_state *state, |
479 | struct intel_encoder *encoder, |
480 | const struct intel_crtc_state *pipe_config, |
481 | const struct drm_connector_state *conn_state) |
482 | { |
483 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); |
484 | struct drm_i915_private *dev_priv = to_i915(dev: encoder->base.dev); |
485 | |
486 | vlv_phy_pre_encoder_enable(encoder, crtc_state: pipe_config); |
487 | |
488 | /* HDMI 1.0V-2dB */ |
489 | vlv_set_phy_signal_level(encoder, crtc_state: pipe_config, |
490 | demph_reg_value: 0x2b245f5f, preemph_reg_value: 0x00002000, |
491 | uniqtranscale_reg_value: 0x5578b83a, tx3_demph: 0x2b247878); |
492 | |
493 | dig_port->set_infoframes(encoder, |
494 | pipe_config->has_infoframe, |
495 | pipe_config, conn_state); |
496 | |
497 | g4x_hdmi_enable_port(encoder, pipe_config); |
498 | |
499 | vlv_wait_port_ready(dev_priv, dig_port, expected_mask: 0x0); |
500 | } |
501 | |
502 | static void vlv_hdmi_pre_pll_enable(struct intel_atomic_state *state, |
503 | struct intel_encoder *encoder, |
504 | const struct intel_crtc_state *pipe_config, |
505 | const struct drm_connector_state *conn_state) |
506 | { |
507 | intel_hdmi_prepare(encoder, crtc_state: pipe_config); |
508 | |
509 | vlv_phy_pre_pll_enable(encoder, crtc_state: pipe_config); |
510 | } |
511 | |
512 | static void chv_hdmi_pre_pll_enable(struct intel_atomic_state *state, |
513 | struct intel_encoder *encoder, |
514 | const struct intel_crtc_state *pipe_config, |
515 | const struct drm_connector_state *conn_state) |
516 | { |
517 | intel_hdmi_prepare(encoder, crtc_state: pipe_config); |
518 | |
519 | chv_phy_pre_pll_enable(encoder, crtc_state: pipe_config); |
520 | } |
521 | |
522 | static void chv_hdmi_post_pll_disable(struct intel_atomic_state *state, |
523 | struct intel_encoder *encoder, |
524 | const struct intel_crtc_state *old_crtc_state, |
525 | const struct drm_connector_state *old_conn_state) |
526 | { |
527 | chv_phy_post_pll_disable(encoder, old_crtc_state); |
528 | } |
529 | |
530 | static void vlv_hdmi_post_disable(struct intel_atomic_state *state, |
531 | struct intel_encoder *encoder, |
532 | const struct intel_crtc_state *old_crtc_state, |
533 | const struct drm_connector_state *old_conn_state) |
534 | { |
535 | /* Reset lanes to avoid HDMI flicker (VLV w/a) */ |
536 | vlv_phy_reset_lanes(encoder, old_crtc_state); |
537 | } |
538 | |
539 | static void chv_hdmi_post_disable(struct intel_atomic_state *state, |
540 | struct intel_encoder *encoder, |
541 | const struct intel_crtc_state *old_crtc_state, |
542 | const struct drm_connector_state *old_conn_state) |
543 | { |
544 | struct drm_device *dev = encoder->base.dev; |
545 | struct drm_i915_private *dev_priv = to_i915(dev); |
546 | |
547 | vlv_dpio_get(i915: dev_priv); |
548 | |
549 | /* Assert data lane reset */ |
550 | chv_data_lane_soft_reset(encoder, crtc_state: old_crtc_state, reset: true); |
551 | |
552 | vlv_dpio_put(i915: dev_priv); |
553 | } |
554 | |
555 | static void chv_hdmi_pre_enable(struct intel_atomic_state *state, |
556 | struct intel_encoder *encoder, |
557 | const struct intel_crtc_state *pipe_config, |
558 | const struct drm_connector_state *conn_state) |
559 | { |
560 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); |
561 | struct drm_device *dev = encoder->base.dev; |
562 | struct drm_i915_private *dev_priv = to_i915(dev); |
563 | |
564 | chv_phy_pre_encoder_enable(encoder, crtc_state: pipe_config); |
565 | |
566 | /* FIXME: Program the support xxx V-dB */ |
567 | /* Use 800mV-0dB */ |
568 | chv_set_phy_signal_level(encoder, crtc_state: pipe_config, deemph_reg_value: 128, margin_reg_value: 102, uniq_trans_scale: false); |
569 | |
570 | dig_port->set_infoframes(encoder, |
571 | pipe_config->has_infoframe, |
572 | pipe_config, conn_state); |
573 | |
574 | g4x_hdmi_enable_port(encoder, pipe_config); |
575 | |
576 | vlv_wait_port_ready(dev_priv, dig_port, expected_mask: 0x0); |
577 | |
578 | /* Second common lane will stay alive on its own now */ |
579 | chv_phy_release_cl2_override(encoder); |
580 | } |
581 | |
582 | static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { |
583 | .destroy = intel_encoder_destroy, |
584 | }; |
585 | |
586 | static enum intel_hotplug_state |
587 | intel_hdmi_hotplug(struct intel_encoder *encoder, |
588 | struct intel_connector *connector) |
589 | { |
590 | enum intel_hotplug_state state; |
591 | |
592 | state = intel_encoder_hotplug(encoder, connector); |
593 | |
594 | /* |
595 | * On many platforms the HDMI live state signal is known to be |
596 | * unreliable, so we can't use it to detect if a sink is connected or |
597 | * not. Instead we detect if it's connected based on whether we can |
598 | * read the EDID or not. That in turn has a problem during disconnect, |
599 | * since the HPD interrupt may be raised before the DDC lines get |
600 | * disconnected (due to how the required length of DDC vs. HPD |
601 | * connector pins are specified) and so we'll still be able to get a |
602 | * valid EDID. To solve this schedule another detection cycle if this |
603 | * time around we didn't detect any change in the sink's connection |
604 | * status. |
605 | */ |
606 | if (state == INTEL_HOTPLUG_UNCHANGED && !connector->hotplug_retries) |
607 | state = INTEL_HOTPLUG_RETRY; |
608 | |
609 | return state; |
610 | } |
611 | |
612 | int g4x_hdmi_connector_atomic_check(struct drm_connector *connector, |
613 | struct drm_atomic_state *state) |
614 | { |
615 | struct drm_i915_private *i915 = to_i915(dev: state->dev); |
616 | struct drm_connector_list_iter conn_iter; |
617 | struct drm_connector *conn; |
618 | int ret; |
619 | |
620 | ret = intel_digital_connector_atomic_check(conn: connector, state); |
621 | if (ret) |
622 | return ret; |
623 | |
624 | if (!IS_G4X(i915)) |
625 | return 0; |
626 | |
627 | if (!intel_connector_needs_modeset(to_intel_atomic_state(state), connector)) |
628 | return 0; |
629 | |
630 | /* |
631 | * On g4x only one HDMI port can transmit infoframes/audio |
632 | * at any given time. Make sure all enabled HDMI ports are |
633 | * included in the state so that it's possible to select |
634 | * one of them for this duty. |
635 | * |
636 | * See also g4x_compute_has_hdmi_sink(). |
637 | */ |
638 | drm_connector_list_iter_begin(dev: &i915->drm, iter: &conn_iter); |
639 | drm_for_each_connector_iter(conn, &conn_iter) { |
640 | struct drm_connector_state *conn_state; |
641 | struct drm_crtc_state *crtc_state; |
642 | struct drm_crtc *crtc; |
643 | |
644 | if (!connector_is_hdmi(connector: conn)) |
645 | continue; |
646 | |
647 | drm_dbg_kms(&i915->drm, "Adding [CONNECTOR:%d:%s]\n" , |
648 | conn->base.id, conn->name); |
649 | |
650 | conn_state = drm_atomic_get_connector_state(state, connector: conn); |
651 | if (IS_ERR(ptr: conn_state)) { |
652 | ret = PTR_ERR(ptr: conn_state); |
653 | break; |
654 | } |
655 | |
656 | crtc = conn_state->crtc; |
657 | if (!crtc) |
658 | continue; |
659 | |
660 | crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
661 | crtc_state->mode_changed = true; |
662 | |
663 | ret = drm_atomic_add_affected_planes(state, crtc); |
664 | if (ret) |
665 | break; |
666 | } |
667 | drm_connector_list_iter_end(iter: &conn_iter); |
668 | |
669 | return ret; |
670 | } |
671 | |
672 | static bool is_hdmi_port_valid(struct drm_i915_private *i915, enum port port) |
673 | { |
674 | if (IS_G4X(i915) || IS_VALLEYVIEW(i915)) |
675 | return port == PORT_B || port == PORT_C; |
676 | else |
677 | return port == PORT_B || port == PORT_C || port == PORT_D; |
678 | } |
679 | |
680 | static bool assert_hdmi_port_valid(struct drm_i915_private *i915, enum port port) |
681 | { |
682 | return !drm_WARN(&i915->drm, !is_hdmi_port_valid(i915, port), |
683 | "Platform does not support HDMI %c\n" , port_name(port)); |
684 | } |
685 | |
686 | void g4x_hdmi_init(struct drm_i915_private *dev_priv, |
687 | i915_reg_t hdmi_reg, enum port port) |
688 | { |
689 | const struct intel_bios_encoder_data *devdata; |
690 | struct intel_digital_port *dig_port; |
691 | struct intel_encoder *intel_encoder; |
692 | struct intel_connector *intel_connector; |
693 | |
694 | if (!assert_port_valid(i915: dev_priv, port)) |
695 | return; |
696 | |
697 | if (!assert_hdmi_port_valid(i915: dev_priv, port)) |
698 | return; |
699 | |
700 | devdata = intel_bios_encoder_data_lookup(i915: dev_priv, port); |
701 | |
702 | /* FIXME bail? */ |
703 | if (!devdata) |
704 | drm_dbg_kms(&dev_priv->drm, "No VBT child device for HDMI-%c\n" , |
705 | port_name(port)); |
706 | |
707 | dig_port = kzalloc(size: sizeof(*dig_port), GFP_KERNEL); |
708 | if (!dig_port) |
709 | return; |
710 | |
711 | dig_port->aux_ch = AUX_CH_NONE; |
712 | |
713 | intel_connector = intel_connector_alloc(); |
714 | if (!intel_connector) { |
715 | kfree(objp: dig_port); |
716 | return; |
717 | } |
718 | |
719 | intel_encoder = &dig_port->base; |
720 | |
721 | intel_encoder->devdata = devdata; |
722 | |
723 | mutex_init(&dig_port->hdcp_mutex); |
724 | |
725 | drm_encoder_init(dev: &dev_priv->drm, encoder: &intel_encoder->base, |
726 | funcs: &intel_hdmi_enc_funcs, DRM_MODE_ENCODER_TMDS, |
727 | name: "HDMI %c" , port_name(port)); |
728 | |
729 | intel_encoder->hotplug = intel_hdmi_hotplug; |
730 | intel_encoder->compute_config = g4x_hdmi_compute_config; |
731 | if (HAS_PCH_SPLIT(dev_priv)) { |
732 | intel_encoder->disable = pch_disable_hdmi; |
733 | intel_encoder->post_disable = pch_post_disable_hdmi; |
734 | } else { |
735 | intel_encoder->disable = g4x_disable_hdmi; |
736 | } |
737 | intel_encoder->get_hw_state = intel_hdmi_get_hw_state; |
738 | intel_encoder->get_config = intel_hdmi_get_config; |
739 | if (IS_CHERRYVIEW(dev_priv)) { |
740 | intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable; |
741 | intel_encoder->pre_enable = chv_hdmi_pre_enable; |
742 | intel_encoder->enable = vlv_enable_hdmi; |
743 | intel_encoder->post_disable = chv_hdmi_post_disable; |
744 | intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable; |
745 | } else if (IS_VALLEYVIEW(dev_priv)) { |
746 | intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; |
747 | intel_encoder->pre_enable = vlv_hdmi_pre_enable; |
748 | intel_encoder->enable = vlv_enable_hdmi; |
749 | intel_encoder->post_disable = vlv_hdmi_post_disable; |
750 | } else { |
751 | intel_encoder->pre_enable = intel_hdmi_pre_enable; |
752 | if (HAS_PCH_CPT(dev_priv)) |
753 | intel_encoder->enable = cpt_enable_hdmi; |
754 | else if (HAS_PCH_IBX(dev_priv)) |
755 | intel_encoder->enable = ibx_enable_hdmi; |
756 | else |
757 | intel_encoder->enable = g4x_enable_hdmi; |
758 | } |
759 | intel_encoder->audio_enable = g4x_hdmi_audio_enable; |
760 | intel_encoder->audio_disable = g4x_hdmi_audio_disable; |
761 | intel_encoder->shutdown = intel_hdmi_encoder_shutdown; |
762 | |
763 | intel_encoder->type = INTEL_OUTPUT_HDMI; |
764 | intel_encoder->power_domain = intel_display_power_ddi_lanes_domain(i915: dev_priv, port); |
765 | intel_encoder->port = port; |
766 | if (IS_CHERRYVIEW(dev_priv)) { |
767 | if (port == PORT_D) |
768 | intel_encoder->pipe_mask = BIT(PIPE_C); |
769 | else |
770 | intel_encoder->pipe_mask = BIT(PIPE_A) | BIT(PIPE_B); |
771 | } else { |
772 | intel_encoder->pipe_mask = ~0; |
773 | } |
774 | intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG); |
775 | intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); |
776 | /* |
777 | * BSpec is unclear about HDMI+HDMI cloning on g4x, but it seems |
778 | * to work on real hardware. And since g4x can send infoframes to |
779 | * only one port anyway, nothing is lost by allowing it. |
780 | */ |
781 | if (IS_G4X(dev_priv)) |
782 | intel_encoder->cloneable |= BIT(INTEL_OUTPUT_HDMI); |
783 | |
784 | dig_port->hdmi.hdmi_reg = hdmi_reg; |
785 | dig_port->dp.output_reg = INVALID_MMIO_REG; |
786 | dig_port->max_lanes = 4; |
787 | |
788 | intel_infoframe_init(dig_port); |
789 | |
790 | intel_hdmi_init_connector(dig_port, intel_connector); |
791 | } |
792 | |