1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright © 2021 Intel Corporation |
4 | */ |
5 | |
6 | #include "g4x_dp.h" |
7 | #include "i915_reg.h" |
8 | #include "intel_crt.h" |
9 | #include "intel_de.h" |
10 | #include "intel_display_types.h" |
11 | #include "intel_dpll.h" |
12 | #include "intel_fdi.h" |
13 | #include "intel_fdi_regs.h" |
14 | #include "intel_lvds.h" |
15 | #include "intel_lvds_regs.h" |
16 | #include "intel_pch_display.h" |
17 | #include "intel_pch_refclk.h" |
18 | #include "intel_pps.h" |
19 | #include "intel_sdvo.h" |
20 | |
21 | bool intel_has_pch_trancoder(struct drm_i915_private *i915, |
22 | enum pipe pch_transcoder) |
23 | { |
24 | return HAS_PCH_IBX(i915) || HAS_PCH_CPT(i915) || |
25 | (HAS_PCH_LPT_H(i915) && pch_transcoder == PIPE_A); |
26 | } |
27 | |
28 | enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) |
29 | { |
30 | struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev); |
31 | |
32 | if (HAS_PCH_LPT(i915)) |
33 | return PIPE_A; |
34 | else |
35 | return crtc->pipe; |
36 | } |
37 | |
38 | static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, |
39 | enum pipe pipe, enum port port, |
40 | i915_reg_t dp_reg) |
41 | { |
42 | enum pipe port_pipe; |
43 | bool state; |
44 | |
45 | state = g4x_dp_port_enabled(dev_priv, dp_reg, port, pipe: &port_pipe); |
46 | |
47 | I915_STATE_WARN(dev_priv, state && port_pipe == pipe, |
48 | "PCH DP %c enabled on transcoder %c, should be disabled\n" , |
49 | port_name(port), pipe_name(pipe)); |
50 | |
51 | I915_STATE_WARN(dev_priv, |
52 | HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, |
53 | "IBX PCH DP %c still using transcoder B\n" , |
54 | port_name(port)); |
55 | } |
56 | |
57 | static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, |
58 | enum pipe pipe, enum port port, |
59 | i915_reg_t hdmi_reg) |
60 | { |
61 | enum pipe port_pipe; |
62 | bool state; |
63 | |
64 | state = intel_sdvo_port_enabled(dev_priv, sdvo_reg: hdmi_reg, pipe: &port_pipe); |
65 | |
66 | I915_STATE_WARN(dev_priv, state && port_pipe == pipe, |
67 | "PCH HDMI %c enabled on transcoder %c, should be disabled\n" , |
68 | port_name(port), pipe_name(pipe)); |
69 | |
70 | I915_STATE_WARN(dev_priv, |
71 | HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B, |
72 | "IBX PCH HDMI %c still using transcoder B\n" , |
73 | port_name(port)); |
74 | } |
75 | |
76 | static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, |
77 | enum pipe pipe) |
78 | { |
79 | enum pipe port_pipe; |
80 | |
81 | assert_pch_dp_disabled(dev_priv, pipe, port: PORT_B, PCH_DP_B); |
82 | assert_pch_dp_disabled(dev_priv, pipe, port: PORT_C, PCH_DP_C); |
83 | assert_pch_dp_disabled(dev_priv, pipe, port: PORT_D, PCH_DP_D); |
84 | |
85 | I915_STATE_WARN(dev_priv, |
86 | intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) && port_pipe == pipe, |
87 | "PCH VGA enabled on transcoder %c, should be disabled\n" , |
88 | pipe_name(pipe)); |
89 | |
90 | I915_STATE_WARN(dev_priv, |
91 | intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) && port_pipe == pipe, |
92 | "PCH LVDS enabled on transcoder %c, should be disabled\n" , |
93 | pipe_name(pipe)); |
94 | |
95 | /* PCH SDVOB multiplex with HDMIB */ |
96 | assert_pch_hdmi_disabled(dev_priv, pipe, port: PORT_B, PCH_HDMIB); |
97 | assert_pch_hdmi_disabled(dev_priv, pipe, port: PORT_C, PCH_HDMIC); |
98 | assert_pch_hdmi_disabled(dev_priv, pipe, port: PORT_D, PCH_HDMID); |
99 | } |
100 | |
101 | static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, |
102 | enum pipe pipe) |
103 | { |
104 | u32 val; |
105 | bool enabled; |
106 | |
107 | val = intel_de_read(i915: dev_priv, PCH_TRANSCONF(pipe)); |
108 | enabled = !!(val & TRANS_ENABLE); |
109 | I915_STATE_WARN(dev_priv, enabled, |
110 | "transcoder assertion failed, should be off on pipe %c but is still active\n" , |
111 | pipe_name(pipe)); |
112 | } |
113 | |
114 | static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv, |
115 | enum port port, i915_reg_t hdmi_reg) |
116 | { |
117 | u32 val = intel_de_read(i915: dev_priv, reg: hdmi_reg); |
118 | |
119 | if (val & SDVO_ENABLE || |
120 | (val & SDVO_PIPE_SEL_MASK) == SDVO_PIPE_SEL(PIPE_A)) |
121 | return; |
122 | |
123 | drm_dbg_kms(&dev_priv->drm, |
124 | "Sanitizing transcoder select for HDMI %c\n" , |
125 | port_name(port)); |
126 | |
127 | val &= ~SDVO_PIPE_SEL_MASK; |
128 | val |= SDVO_PIPE_SEL(PIPE_A); |
129 | |
130 | intel_de_write(i915: dev_priv, reg: hdmi_reg, val); |
131 | } |
132 | |
133 | static void ibx_sanitize_pch_dp_port(struct drm_i915_private *dev_priv, |
134 | enum port port, i915_reg_t dp_reg) |
135 | { |
136 | u32 val = intel_de_read(i915: dev_priv, reg: dp_reg); |
137 | |
138 | if (val & DP_PORT_EN || |
139 | (val & DP_PIPE_SEL_MASK) == DP_PIPE_SEL(PIPE_A)) |
140 | return; |
141 | |
142 | drm_dbg_kms(&dev_priv->drm, |
143 | "Sanitizing transcoder select for DP %c\n" , |
144 | port_name(port)); |
145 | |
146 | val &= ~DP_PIPE_SEL_MASK; |
147 | val |= DP_PIPE_SEL(PIPE_A); |
148 | |
149 | intel_de_write(i915: dev_priv, reg: dp_reg, val); |
150 | } |
151 | |
152 | static void ibx_sanitize_pch_ports(struct drm_i915_private *dev_priv) |
153 | { |
154 | /* |
155 | * The BIOS may select transcoder B on some of the PCH |
156 | * ports even it doesn't enable the port. This would trip |
157 | * assert_pch_dp_disabled() and assert_pch_hdmi_disabled(). |
158 | * Sanitize the transcoder select bits to prevent that. We |
159 | * assume that the BIOS never actually enabled the port, |
160 | * because if it did we'd actually have to toggle the port |
161 | * on and back off to make the transcoder A select stick |
162 | * (see. intel_dp_link_down(), intel_disable_hdmi(), |
163 | * intel_disable_sdvo()). |
164 | */ |
165 | ibx_sanitize_pch_dp_port(dev_priv, port: PORT_B, PCH_DP_B); |
166 | ibx_sanitize_pch_dp_port(dev_priv, port: PORT_C, PCH_DP_C); |
167 | ibx_sanitize_pch_dp_port(dev_priv, port: PORT_D, PCH_DP_D); |
168 | |
169 | /* PCH SDVOB multiplex with HDMIB */ |
170 | ibx_sanitize_pch_hdmi_port(dev_priv, port: PORT_B, PCH_HDMIB); |
171 | ibx_sanitize_pch_hdmi_port(dev_priv, port: PORT_C, PCH_HDMIC); |
172 | ibx_sanitize_pch_hdmi_port(dev_priv, port: PORT_D, PCH_HDMID); |
173 | } |
174 | |
175 | static void intel_pch_transcoder_set_m1_n1(struct intel_crtc *crtc, |
176 | const struct intel_link_m_n *m_n) |
177 | { |
178 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
179 | enum pipe pipe = crtc->pipe; |
180 | |
181 | intel_set_m_n(i915: dev_priv, m_n, |
182 | PCH_TRANS_DATA_M1(pipe), PCH_TRANS_DATA_N1(pipe), |
183 | PCH_TRANS_LINK_M1(pipe), PCH_TRANS_LINK_N1(pipe)); |
184 | } |
185 | |
186 | static void intel_pch_transcoder_set_m2_n2(struct intel_crtc *crtc, |
187 | const struct intel_link_m_n *m_n) |
188 | { |
189 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
190 | enum pipe pipe = crtc->pipe; |
191 | |
192 | intel_set_m_n(i915: dev_priv, m_n, |
193 | PCH_TRANS_DATA_M2(pipe), PCH_TRANS_DATA_N2(pipe), |
194 | PCH_TRANS_LINK_M2(pipe), PCH_TRANS_LINK_N2(pipe)); |
195 | } |
196 | |
197 | void intel_pch_transcoder_get_m1_n1(struct intel_crtc *crtc, |
198 | struct intel_link_m_n *m_n) |
199 | { |
200 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
201 | enum pipe pipe = crtc->pipe; |
202 | |
203 | intel_get_m_n(i915: dev_priv, m_n, |
204 | PCH_TRANS_DATA_M1(pipe), PCH_TRANS_DATA_N1(pipe), |
205 | PCH_TRANS_LINK_M1(pipe), PCH_TRANS_LINK_N1(pipe)); |
206 | } |
207 | |
208 | void intel_pch_transcoder_get_m2_n2(struct intel_crtc *crtc, |
209 | struct intel_link_m_n *m_n) |
210 | { |
211 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
212 | enum pipe pipe = crtc->pipe; |
213 | |
214 | intel_get_m_n(i915: dev_priv, m_n, |
215 | PCH_TRANS_DATA_M2(pipe), PCH_TRANS_DATA_N2(pipe), |
216 | PCH_TRANS_LINK_M2(pipe), PCH_TRANS_LINK_N2(pipe)); |
217 | } |
218 | |
219 | static void ilk_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state, |
220 | enum pipe pch_transcoder) |
221 | { |
222 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
223 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
224 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
225 | |
226 | intel_de_write(i915: dev_priv, PCH_TRANS_HTOTAL(pch_transcoder), |
227 | val: intel_de_read(i915: dev_priv, TRANS_HTOTAL(cpu_transcoder))); |
228 | intel_de_write(i915: dev_priv, PCH_TRANS_HBLANK(pch_transcoder), |
229 | val: intel_de_read(i915: dev_priv, TRANS_HBLANK(cpu_transcoder))); |
230 | intel_de_write(i915: dev_priv, PCH_TRANS_HSYNC(pch_transcoder), |
231 | val: intel_de_read(i915: dev_priv, TRANS_HSYNC(cpu_transcoder))); |
232 | |
233 | intel_de_write(i915: dev_priv, PCH_TRANS_VTOTAL(pch_transcoder), |
234 | val: intel_de_read(i915: dev_priv, TRANS_VTOTAL(cpu_transcoder))); |
235 | intel_de_write(i915: dev_priv, PCH_TRANS_VBLANK(pch_transcoder), |
236 | val: intel_de_read(i915: dev_priv, TRANS_VBLANK(cpu_transcoder))); |
237 | intel_de_write(i915: dev_priv, PCH_TRANS_VSYNC(pch_transcoder), |
238 | val: intel_de_read(i915: dev_priv, TRANS_VSYNC(cpu_transcoder))); |
239 | intel_de_write(i915: dev_priv, PCH_TRANS_VSYNCSHIFT(pch_transcoder), |
240 | val: intel_de_read(i915: dev_priv, TRANS_VSYNCSHIFT(cpu_transcoder))); |
241 | } |
242 | |
243 | static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) |
244 | { |
245 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
246 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
247 | enum pipe pipe = crtc->pipe; |
248 | i915_reg_t reg; |
249 | u32 val, pipeconf_val; |
250 | |
251 | /* Make sure PCH DPLL is enabled */ |
252 | assert_shared_dpll_enabled(dev_priv, crtc_state->shared_dpll); |
253 | |
254 | /* FDI must be feeding us bits for PCH ports */ |
255 | assert_fdi_tx_enabled(i915: dev_priv, pipe); |
256 | assert_fdi_rx_enabled(i915: dev_priv, pipe); |
257 | |
258 | if (HAS_PCH_CPT(dev_priv)) { |
259 | reg = TRANS_CHICKEN2(pipe); |
260 | val = intel_de_read(i915: dev_priv, reg); |
261 | /* |
262 | * Workaround: Set the timing override bit |
263 | * before enabling the pch transcoder. |
264 | */ |
265 | val |= TRANS_CHICKEN2_TIMING_OVERRIDE; |
266 | /* Configure frame start delay to match the CPU */ |
267 | val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; |
268 | val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1); |
269 | intel_de_write(i915: dev_priv, reg, val); |
270 | } |
271 | |
272 | reg = PCH_TRANSCONF(pipe); |
273 | val = intel_de_read(i915: dev_priv, reg); |
274 | pipeconf_val = intel_de_read(i915: dev_priv, TRANSCONF(pipe)); |
275 | |
276 | if (HAS_PCH_IBX(dev_priv)) { |
277 | /* Configure frame start delay to match the CPU */ |
278 | val &= ~TRANS_FRAME_START_DELAY_MASK; |
279 | val |= TRANS_FRAME_START_DELAY(crtc_state->framestart_delay - 1); |
280 | |
281 | /* |
282 | * Make the BPC in transcoder be consistent with |
283 | * that in pipeconf reg. For HDMI we must use 8bpc |
284 | * here for both 8bpc and 12bpc. |
285 | */ |
286 | val &= ~TRANSCONF_BPC_MASK; |
287 | if (intel_crtc_has_type(crtc_state, type: INTEL_OUTPUT_HDMI)) |
288 | val |= TRANSCONF_BPC_8; |
289 | else |
290 | val |= pipeconf_val & TRANSCONF_BPC_MASK; |
291 | } |
292 | |
293 | val &= ~TRANS_INTERLACE_MASK; |
294 | if ((pipeconf_val & TRANSCONF_INTERLACE_MASK_ILK) == TRANSCONF_INTERLACE_IF_ID_ILK) { |
295 | if (HAS_PCH_IBX(dev_priv) && |
296 | intel_crtc_has_type(crtc_state, type: INTEL_OUTPUT_SDVO)) |
297 | val |= TRANS_INTERLACE_LEGACY_VSYNC_IBX; |
298 | else |
299 | val |= TRANS_INTERLACE_INTERLACED; |
300 | } else { |
301 | val |= TRANS_INTERLACE_PROGRESSIVE; |
302 | } |
303 | |
304 | intel_de_write(i915: dev_priv, reg, val: val | TRANS_ENABLE); |
305 | if (intel_de_wait_for_set(i915: dev_priv, reg, TRANS_STATE_ENABLE, timeout: 100)) |
306 | drm_err(&dev_priv->drm, "failed to enable transcoder %c\n" , |
307 | pipe_name(pipe)); |
308 | } |
309 | |
310 | static void ilk_disable_pch_transcoder(struct intel_crtc *crtc) |
311 | { |
312 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
313 | enum pipe pipe = crtc->pipe; |
314 | i915_reg_t reg; |
315 | |
316 | /* FDI relies on the transcoder */ |
317 | assert_fdi_tx_disabled(i915: dev_priv, pipe); |
318 | assert_fdi_rx_disabled(i915: dev_priv, pipe); |
319 | |
320 | /* Ports must be off as well */ |
321 | assert_pch_ports_disabled(dev_priv, pipe); |
322 | |
323 | reg = PCH_TRANSCONF(pipe); |
324 | intel_de_rmw(i915: dev_priv, reg, TRANS_ENABLE, set: 0); |
325 | /* wait for PCH transcoder off, transcoder state */ |
326 | if (intel_de_wait_for_clear(i915: dev_priv, reg, TRANS_STATE_ENABLE, timeout: 50)) |
327 | drm_err(&dev_priv->drm, "failed to disable transcoder %c\n" , |
328 | pipe_name(pipe)); |
329 | |
330 | if (HAS_PCH_CPT(dev_priv)) |
331 | /* Workaround: Clear the timing override chicken bit again. */ |
332 | intel_de_rmw(i915: dev_priv, TRANS_CHICKEN2(pipe), |
333 | TRANS_CHICKEN2_TIMING_OVERRIDE, set: 0); |
334 | } |
335 | |
336 | void ilk_pch_pre_enable(struct intel_atomic_state *state, |
337 | struct intel_crtc *crtc) |
338 | { |
339 | const struct intel_crtc_state *crtc_state = |
340 | intel_atomic_get_new_crtc_state(state, crtc); |
341 | |
342 | /* |
343 | * Note: FDI PLL enabling _must_ be done before we enable the |
344 | * cpu pipes, hence this is separate from all the other fdi/pch |
345 | * enabling. |
346 | */ |
347 | ilk_fdi_pll_enable(crtc_state); |
348 | } |
349 | |
350 | /* |
351 | * Enable PCH resources required for PCH ports: |
352 | * - PCH PLLs |
353 | * - FDI training & RX/TX |
354 | * - update transcoder timings |
355 | * - DP transcoding bits |
356 | * - transcoder |
357 | */ |
358 | void ilk_pch_enable(struct intel_atomic_state *state, |
359 | struct intel_crtc *crtc) |
360 | { |
361 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
362 | const struct intel_crtc_state *crtc_state = |
363 | intel_atomic_get_new_crtc_state(state, crtc); |
364 | enum pipe pipe = crtc->pipe; |
365 | u32 temp; |
366 | |
367 | assert_pch_transcoder_disabled(dev_priv, pipe); |
368 | |
369 | /* For PCH output, training FDI link */ |
370 | intel_fdi_link_train(crtc, crtc_state); |
371 | |
372 | /* |
373 | * We need to program the right clock selection |
374 | * before writing the pixel multiplier into the DPLL. |
375 | */ |
376 | if (HAS_PCH_CPT(dev_priv)) { |
377 | u32 sel; |
378 | |
379 | temp = intel_de_read(i915: dev_priv, PCH_DPLL_SEL); |
380 | temp |= TRANS_DPLL_ENABLE(pipe); |
381 | sel = TRANS_DPLLB_SEL(pipe); |
382 | if (crtc_state->shared_dpll == |
383 | intel_get_shared_dpll_by_id(i915: dev_priv, id: DPLL_ID_PCH_PLL_B)) |
384 | temp |= sel; |
385 | else |
386 | temp &= ~sel; |
387 | intel_de_write(i915: dev_priv, PCH_DPLL_SEL, val: temp); |
388 | } |
389 | |
390 | /* |
391 | * XXX: pch pll's can be enabled any time before we enable the PCH |
392 | * transcoder, and we actually should do this to not upset any PCH |
393 | * transcoder that already use the clock when we share it. |
394 | * |
395 | * Note that enable_shared_dpll tries to do the right thing, but |
396 | * get_shared_dpll unconditionally resets the pll - we need that |
397 | * to have the right LVDS enable sequence. |
398 | */ |
399 | intel_enable_shared_dpll(crtc_state); |
400 | |
401 | /* set transcoder timing, panel must allow it */ |
402 | assert_pps_unlocked(i915: dev_priv, pipe); |
403 | if (intel_crtc_has_dp_encoder(crtc_state)) { |
404 | intel_pch_transcoder_set_m1_n1(crtc, m_n: &crtc_state->dp_m_n); |
405 | intel_pch_transcoder_set_m2_n2(crtc, m_n: &crtc_state->dp_m2_n2); |
406 | } |
407 | ilk_pch_transcoder_set_timings(crtc_state, pch_transcoder: pipe); |
408 | |
409 | intel_fdi_normal_train(crtc); |
410 | |
411 | /* For PCH DP, enable TRANS_DP_CTL */ |
412 | if (HAS_PCH_CPT(dev_priv) && |
413 | intel_crtc_has_dp_encoder(crtc_state)) { |
414 | const struct drm_display_mode *adjusted_mode = |
415 | &crtc_state->hw.adjusted_mode; |
416 | u32 bpc = (intel_de_read(i915: dev_priv, TRANSCONF(pipe)) & TRANSCONF_BPC_MASK) >> 5; |
417 | i915_reg_t reg = TRANS_DP_CTL(pipe); |
418 | enum port port; |
419 | |
420 | temp = intel_de_read(i915: dev_priv, reg); |
421 | temp &= ~(TRANS_DP_PORT_SEL_MASK | |
422 | TRANS_DP_VSYNC_ACTIVE_HIGH | |
423 | TRANS_DP_HSYNC_ACTIVE_HIGH | |
424 | TRANS_DP_BPC_MASK); |
425 | temp |= TRANS_DP_OUTPUT_ENABLE; |
426 | temp |= bpc << 9; /* same format but at 11:9 */ |
427 | |
428 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
429 | temp |= TRANS_DP_HSYNC_ACTIVE_HIGH; |
430 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
431 | temp |= TRANS_DP_VSYNC_ACTIVE_HIGH; |
432 | |
433 | port = intel_get_crtc_new_encoder(state, crtc_state)->port; |
434 | drm_WARN_ON(&dev_priv->drm, port < PORT_B || port > PORT_D); |
435 | temp |= TRANS_DP_PORT_SEL(port); |
436 | |
437 | intel_de_write(i915: dev_priv, reg, val: temp); |
438 | } |
439 | |
440 | ilk_enable_pch_transcoder(crtc_state); |
441 | } |
442 | |
443 | void ilk_pch_disable(struct intel_atomic_state *state, |
444 | struct intel_crtc *crtc) |
445 | { |
446 | ilk_fdi_disable(crtc); |
447 | } |
448 | |
449 | void ilk_pch_post_disable(struct intel_atomic_state *state, |
450 | struct intel_crtc *crtc) |
451 | { |
452 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
453 | enum pipe pipe = crtc->pipe; |
454 | |
455 | ilk_disable_pch_transcoder(crtc); |
456 | |
457 | if (HAS_PCH_CPT(dev_priv)) { |
458 | /* disable TRANS_DP_CTL */ |
459 | intel_de_rmw(i915: dev_priv, TRANS_DP_CTL(pipe), |
460 | TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK, |
461 | TRANS_DP_PORT_SEL_NONE); |
462 | |
463 | /* disable DPLL_SEL */ |
464 | intel_de_rmw(i915: dev_priv, PCH_DPLL_SEL, |
465 | TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe), set: 0); |
466 | } |
467 | |
468 | ilk_fdi_pll_disable(intel_crtc: crtc); |
469 | } |
470 | |
471 | static void ilk_pch_clock_get(struct intel_crtc_state *crtc_state) |
472 | { |
473 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
474 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
475 | |
476 | /* read out port_clock from the DPLL */ |
477 | i9xx_crtc_clock_get(crtc, pipe_config: crtc_state); |
478 | |
479 | /* |
480 | * In case there is an active pipe without active ports, |
481 | * we may need some idea for the dotclock anyway. |
482 | * Calculate one based on the FDI configuration. |
483 | */ |
484 | crtc_state->hw.adjusted_mode.crtc_clock = |
485 | intel_dotclock_calculate(link_freq: intel_fdi_link_freq(i915: dev_priv, pipe_config: crtc_state), |
486 | m_n: &crtc_state->fdi_m_n); |
487 | } |
488 | |
489 | void ilk_pch_get_config(struct intel_crtc_state *crtc_state) |
490 | { |
491 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
492 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
493 | struct intel_shared_dpll *pll; |
494 | enum pipe pipe = crtc->pipe; |
495 | enum intel_dpll_id pll_id; |
496 | bool pll_active; |
497 | u32 tmp; |
498 | |
499 | if ((intel_de_read(i915: dev_priv, PCH_TRANSCONF(pipe)) & TRANS_ENABLE) == 0) |
500 | return; |
501 | |
502 | crtc_state->has_pch_encoder = true; |
503 | |
504 | tmp = intel_de_read(i915: dev_priv, FDI_RX_CTL(pipe)); |
505 | crtc_state->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >> |
506 | FDI_DP_PORT_WIDTH_SHIFT) + 1; |
507 | |
508 | intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder: crtc_state->cpu_transcoder, |
509 | m_n: &crtc_state->fdi_m_n); |
510 | |
511 | if (HAS_PCH_IBX(dev_priv)) { |
512 | /* |
513 | * The pipe->pch transcoder and pch transcoder->pll |
514 | * mapping is fixed. |
515 | */ |
516 | pll_id = (enum intel_dpll_id) pipe; |
517 | } else { |
518 | tmp = intel_de_read(i915: dev_priv, PCH_DPLL_SEL); |
519 | if (tmp & TRANS_DPLLB_SEL(pipe)) |
520 | pll_id = DPLL_ID_PCH_PLL_B; |
521 | else |
522 | pll_id = DPLL_ID_PCH_PLL_A; |
523 | } |
524 | |
525 | crtc_state->shared_dpll = intel_get_shared_dpll_by_id(i915: dev_priv, id: pll_id); |
526 | pll = crtc_state->shared_dpll; |
527 | |
528 | pll_active = intel_dpll_get_hw_state(i915: dev_priv, pll, |
529 | hw_state: &crtc_state->dpll_hw_state); |
530 | drm_WARN_ON(&dev_priv->drm, !pll_active); |
531 | |
532 | tmp = crtc_state->dpll_hw_state.dpll; |
533 | crtc_state->pixel_multiplier = |
534 | ((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) |
535 | >> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1; |
536 | |
537 | ilk_pch_clock_get(crtc_state); |
538 | } |
539 | |
540 | static void lpt_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) |
541 | { |
542 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
543 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
544 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
545 | u32 val, pipeconf_val; |
546 | |
547 | /* FDI must be feeding us bits for PCH ports */ |
548 | assert_fdi_tx_enabled(i915: dev_priv, pipe: (enum pipe) cpu_transcoder); |
549 | assert_fdi_rx_enabled(i915: dev_priv, pipe: PIPE_A); |
550 | |
551 | val = intel_de_read(i915: dev_priv, TRANS_CHICKEN2(PIPE_A)); |
552 | /* Workaround: set timing override bit. */ |
553 | val |= TRANS_CHICKEN2_TIMING_OVERRIDE; |
554 | /* Configure frame start delay to match the CPU */ |
555 | val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; |
556 | val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1); |
557 | intel_de_write(i915: dev_priv, TRANS_CHICKEN2(PIPE_A), val); |
558 | |
559 | val = TRANS_ENABLE; |
560 | pipeconf_val = intel_de_read(i915: dev_priv, TRANSCONF(cpu_transcoder)); |
561 | |
562 | if ((pipeconf_val & TRANSCONF_INTERLACE_MASK_HSW) == TRANSCONF_INTERLACE_IF_ID_ILK) |
563 | val |= TRANS_INTERLACE_INTERLACED; |
564 | else |
565 | val |= TRANS_INTERLACE_PROGRESSIVE; |
566 | |
567 | intel_de_write(i915: dev_priv, LPT_TRANSCONF, val); |
568 | if (intel_de_wait_for_set(i915: dev_priv, LPT_TRANSCONF, |
569 | TRANS_STATE_ENABLE, timeout: 100)) |
570 | drm_err(&dev_priv->drm, "Failed to enable PCH transcoder\n" ); |
571 | } |
572 | |
573 | static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) |
574 | { |
575 | intel_de_rmw(i915: dev_priv, LPT_TRANSCONF, TRANS_ENABLE, set: 0); |
576 | /* wait for PCH transcoder off, transcoder state */ |
577 | if (intel_de_wait_for_clear(i915: dev_priv, LPT_TRANSCONF, |
578 | TRANS_STATE_ENABLE, timeout: 50)) |
579 | drm_err(&dev_priv->drm, "Failed to disable PCH transcoder\n" ); |
580 | |
581 | /* Workaround: clear timing override bit. */ |
582 | intel_de_rmw(i915: dev_priv, TRANS_CHICKEN2(PIPE_A), TRANS_CHICKEN2_TIMING_OVERRIDE, set: 0); |
583 | } |
584 | |
585 | void lpt_pch_enable(struct intel_atomic_state *state, |
586 | struct intel_crtc *crtc) |
587 | { |
588 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
589 | const struct intel_crtc_state *crtc_state = |
590 | intel_atomic_get_new_crtc_state(state, crtc); |
591 | |
592 | assert_pch_transcoder_disabled(dev_priv, pipe: PIPE_A); |
593 | |
594 | lpt_program_iclkip(crtc_state); |
595 | |
596 | /* Set transcoder timing. */ |
597 | ilk_pch_transcoder_set_timings(crtc_state, pch_transcoder: PIPE_A); |
598 | |
599 | lpt_enable_pch_transcoder(crtc_state); |
600 | } |
601 | |
602 | void lpt_pch_disable(struct intel_atomic_state *state, |
603 | struct intel_crtc *crtc) |
604 | { |
605 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
606 | |
607 | lpt_disable_pch_transcoder(dev_priv); |
608 | |
609 | lpt_disable_iclkip(dev_priv); |
610 | } |
611 | |
612 | void lpt_pch_get_config(struct intel_crtc_state *crtc_state) |
613 | { |
614 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
615 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
616 | u32 tmp; |
617 | |
618 | if ((intel_de_read(i915: dev_priv, LPT_TRANSCONF) & TRANS_ENABLE) == 0) |
619 | return; |
620 | |
621 | crtc_state->has_pch_encoder = true; |
622 | |
623 | tmp = intel_de_read(i915: dev_priv, FDI_RX_CTL(PIPE_A)); |
624 | crtc_state->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >> |
625 | FDI_DP_PORT_WIDTH_SHIFT) + 1; |
626 | |
627 | intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder: crtc_state->cpu_transcoder, |
628 | m_n: &crtc_state->fdi_m_n); |
629 | |
630 | crtc_state->hw.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv); |
631 | } |
632 | |
633 | void intel_pch_sanitize(struct drm_i915_private *i915) |
634 | { |
635 | if (HAS_PCH_IBX(i915)) |
636 | ibx_sanitize_pch_ports(dev_priv: i915); |
637 | } |
638 | |