1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright © 2023 Intel Corporation |
4 | */ |
5 | |
6 | #include "i915_drv.h" |
7 | #include "i915_reg.h" |
8 | #include "intel_de.h" |
9 | #include "intel_display_irq.h" |
10 | #include "intel_display_types.h" |
11 | #include "intel_dp_aux.h" |
12 | #include "intel_gmbus.h" |
13 | #include "intel_hotplug.h" |
14 | #include "intel_hotplug_irq.h" |
15 | |
16 | typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val); |
17 | typedef u32 (*hotplug_enables_func)(struct intel_encoder *encoder); |
18 | typedef u32 (*hotplug_mask_func)(enum hpd_pin pin); |
19 | |
20 | static const u32 hpd_ilk[HPD_NUM_PINS] = { |
21 | [HPD_PORT_A] = DE_DP_A_HOTPLUG, |
22 | }; |
23 | |
24 | static const u32 hpd_ivb[HPD_NUM_PINS] = { |
25 | [HPD_PORT_A] = DE_DP_A_HOTPLUG_IVB, |
26 | }; |
27 | |
28 | static const u32 hpd_bdw[HPD_NUM_PINS] = { |
29 | [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), |
30 | }; |
31 | |
32 | static const u32 hpd_ibx[HPD_NUM_PINS] = { |
33 | [HPD_CRT] = SDE_CRT_HOTPLUG, |
34 | [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG, |
35 | [HPD_PORT_B] = SDE_PORTB_HOTPLUG, |
36 | [HPD_PORT_C] = SDE_PORTC_HOTPLUG, |
37 | [HPD_PORT_D] = SDE_PORTD_HOTPLUG, |
38 | }; |
39 | |
40 | static const u32 hpd_cpt[HPD_NUM_PINS] = { |
41 | [HPD_CRT] = SDE_CRT_HOTPLUG_CPT, |
42 | [HPD_SDVO_B] = SDE_SDVOB_HOTPLUG_CPT, |
43 | [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, |
44 | [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, |
45 | [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, |
46 | }; |
47 | |
48 | static const u32 hpd_spt[HPD_NUM_PINS] = { |
49 | [HPD_PORT_A] = SDE_PORTA_HOTPLUG_SPT, |
50 | [HPD_PORT_B] = SDE_PORTB_HOTPLUG_CPT, |
51 | [HPD_PORT_C] = SDE_PORTC_HOTPLUG_CPT, |
52 | [HPD_PORT_D] = SDE_PORTD_HOTPLUG_CPT, |
53 | [HPD_PORT_E] = SDE_PORTE_HOTPLUG_SPT, |
54 | }; |
55 | |
56 | static const u32 hpd_mask_i915[HPD_NUM_PINS] = { |
57 | [HPD_CRT] = CRT_HOTPLUG_INT_EN, |
58 | [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_EN, |
59 | [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_EN, |
60 | [HPD_PORT_B] = PORTB_HOTPLUG_INT_EN, |
61 | [HPD_PORT_C] = PORTC_HOTPLUG_INT_EN, |
62 | [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN, |
63 | }; |
64 | |
65 | static const u32 hpd_status_g4x[HPD_NUM_PINS] = { |
66 | [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, |
67 | [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X, |
68 | [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X, |
69 | [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, |
70 | [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, |
71 | [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS, |
72 | }; |
73 | |
74 | static const u32 hpd_status_i915[HPD_NUM_PINS] = { |
75 | [HPD_CRT] = CRT_HOTPLUG_INT_STATUS, |
76 | [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_I915, |
77 | [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_I915, |
78 | [HPD_PORT_B] = PORTB_HOTPLUG_INT_STATUS, |
79 | [HPD_PORT_C] = PORTC_HOTPLUG_INT_STATUS, |
80 | [HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS, |
81 | }; |
82 | |
83 | static const u32 hpd_bxt[HPD_NUM_PINS] = { |
84 | [HPD_PORT_A] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_A), |
85 | [HPD_PORT_B] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_B), |
86 | [HPD_PORT_C] = GEN8_DE_PORT_HOTPLUG(HPD_PORT_C), |
87 | }; |
88 | |
89 | static const u32 hpd_gen11[HPD_NUM_PINS] = { |
90 | [HPD_PORT_TC1] = GEN11_TC_HOTPLUG(HPD_PORT_TC1) | GEN11_TBT_HOTPLUG(HPD_PORT_TC1), |
91 | [HPD_PORT_TC2] = GEN11_TC_HOTPLUG(HPD_PORT_TC2) | GEN11_TBT_HOTPLUG(HPD_PORT_TC2), |
92 | [HPD_PORT_TC3] = GEN11_TC_HOTPLUG(HPD_PORT_TC3) | GEN11_TBT_HOTPLUG(HPD_PORT_TC3), |
93 | [HPD_PORT_TC4] = GEN11_TC_HOTPLUG(HPD_PORT_TC4) | GEN11_TBT_HOTPLUG(HPD_PORT_TC4), |
94 | [HPD_PORT_TC5] = GEN11_TC_HOTPLUG(HPD_PORT_TC5) | GEN11_TBT_HOTPLUG(HPD_PORT_TC5), |
95 | [HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | GEN11_TBT_HOTPLUG(HPD_PORT_TC6), |
96 | }; |
97 | |
98 | static const u32 hpd_xelpdp[HPD_NUM_PINS] = { |
99 | [HPD_PORT_TC1] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC1) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC1), |
100 | [HPD_PORT_TC2] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC2) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC2), |
101 | [HPD_PORT_TC3] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC3) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC3), |
102 | [HPD_PORT_TC4] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC4) | XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC4), |
103 | }; |
104 | |
105 | static const u32 hpd_icp[HPD_NUM_PINS] = { |
106 | [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), |
107 | [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), |
108 | [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), |
109 | [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1), |
110 | [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2), |
111 | [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3), |
112 | [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4), |
113 | [HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC5), |
114 | [HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC6), |
115 | }; |
116 | |
117 | static const u32 hpd_sde_dg1[HPD_NUM_PINS] = { |
118 | [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), |
119 | [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), |
120 | [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_C), |
121 | [HPD_PORT_D] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_D), |
122 | [HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1), |
123 | }; |
124 | |
125 | static const u32 hpd_mtp[HPD_NUM_PINS] = { |
126 | [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A), |
127 | [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B), |
128 | [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1), |
129 | [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2), |
130 | [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3), |
131 | [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4), |
132 | }; |
133 | |
134 | static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) |
135 | { |
136 | struct intel_hotplug *hpd = &dev_priv->display.hotplug; |
137 | |
138 | if (HAS_GMCH(dev_priv)) { |
139 | if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || |
140 | IS_CHERRYVIEW(dev_priv)) |
141 | hpd->hpd = hpd_status_g4x; |
142 | else |
143 | hpd->hpd = hpd_status_i915; |
144 | return; |
145 | } |
146 | |
147 | if (DISPLAY_VER(dev_priv) >= 14) |
148 | hpd->hpd = hpd_xelpdp; |
149 | else if (DISPLAY_VER(dev_priv) >= 11) |
150 | hpd->hpd = hpd_gen11; |
151 | else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) |
152 | hpd->hpd = hpd_bxt; |
153 | else if (DISPLAY_VER(dev_priv) == 9) |
154 | hpd->hpd = NULL; /* no north HPD on SKL */ |
155 | else if (DISPLAY_VER(dev_priv) >= 8) |
156 | hpd->hpd = hpd_bdw; |
157 | else if (DISPLAY_VER(dev_priv) >= 7) |
158 | hpd->hpd = hpd_ivb; |
159 | else |
160 | hpd->hpd = hpd_ilk; |
161 | |
162 | if ((INTEL_PCH_TYPE(dev_priv) < PCH_DG1) && |
163 | (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv))) |
164 | return; |
165 | |
166 | if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTL) |
167 | hpd->pch_hpd = hpd_mtp; |
168 | else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) |
169 | hpd->pch_hpd = hpd_sde_dg1; |
170 | else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) |
171 | hpd->pch_hpd = hpd_icp; |
172 | else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv)) |
173 | hpd->pch_hpd = hpd_spt; |
174 | else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_CPT(dev_priv)) |
175 | hpd->pch_hpd = hpd_cpt; |
176 | else if (HAS_PCH_IBX(dev_priv)) |
177 | hpd->pch_hpd = hpd_ibx; |
178 | else |
179 | MISSING_CASE(INTEL_PCH_TYPE(dev_priv)); |
180 | } |
181 | |
182 | /* For display hotplug interrupt */ |
183 | void i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, |
184 | u32 mask, u32 bits) |
185 | { |
186 | lockdep_assert_held(&dev_priv->irq_lock); |
187 | drm_WARN_ON(&dev_priv->drm, bits & ~mask); |
188 | |
189 | intel_uncore_rmw(uncore: &dev_priv->uncore, PORT_HOTPLUG_EN, clear: mask, set: bits); |
190 | } |
191 | |
192 | /** |
193 | * i915_hotplug_interrupt_update - update hotplug interrupt enable |
194 | * @dev_priv: driver private |
195 | * @mask: bits to update |
196 | * @bits: bits to enable |
197 | * NOTE: the HPD enable bits are modified both inside and outside |
198 | * of an interrupt context. To avoid that read-modify-write cycles |
199 | * interfer, these bits are protected by a spinlock. Since this |
200 | * function is usually not called from a context where the lock is |
201 | * held already, this function acquires the lock itself. A non-locking |
202 | * version is also available. |
203 | */ |
204 | void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, |
205 | u32 mask, |
206 | u32 bits) |
207 | { |
208 | spin_lock_irq(lock: &dev_priv->irq_lock); |
209 | i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); |
210 | spin_unlock_irq(lock: &dev_priv->irq_lock); |
211 | } |
212 | |
213 | static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) |
214 | { |
215 | switch (pin) { |
216 | case HPD_PORT_TC1: |
217 | case HPD_PORT_TC2: |
218 | case HPD_PORT_TC3: |
219 | case HPD_PORT_TC4: |
220 | case HPD_PORT_TC5: |
221 | case HPD_PORT_TC6: |
222 | return val & GEN11_HOTPLUG_CTL_LONG_DETECT(pin); |
223 | default: |
224 | return false; |
225 | } |
226 | } |
227 | |
228 | static bool bxt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) |
229 | { |
230 | switch (pin) { |
231 | case HPD_PORT_A: |
232 | return val & PORTA_HOTPLUG_LONG_DETECT; |
233 | case HPD_PORT_B: |
234 | return val & PORTB_HOTPLUG_LONG_DETECT; |
235 | case HPD_PORT_C: |
236 | return val & PORTC_HOTPLUG_LONG_DETECT; |
237 | default: |
238 | return false; |
239 | } |
240 | } |
241 | |
242 | static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) |
243 | { |
244 | switch (pin) { |
245 | case HPD_PORT_A: |
246 | case HPD_PORT_B: |
247 | case HPD_PORT_C: |
248 | case HPD_PORT_D: |
249 | return val & SHOTPLUG_CTL_DDI_HPD_LONG_DETECT(pin); |
250 | default: |
251 | return false; |
252 | } |
253 | } |
254 | |
255 | static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) |
256 | { |
257 | switch (pin) { |
258 | case HPD_PORT_TC1: |
259 | case HPD_PORT_TC2: |
260 | case HPD_PORT_TC3: |
261 | case HPD_PORT_TC4: |
262 | case HPD_PORT_TC5: |
263 | case HPD_PORT_TC6: |
264 | return val & ICP_TC_HPD_LONG_DETECT(pin); |
265 | default: |
266 | return false; |
267 | } |
268 | } |
269 | |
270 | static bool spt_port_hotplug2_long_detect(enum hpd_pin pin, u32 val) |
271 | { |
272 | switch (pin) { |
273 | case HPD_PORT_E: |
274 | return val & PORTE_HOTPLUG_LONG_DETECT; |
275 | default: |
276 | return false; |
277 | } |
278 | } |
279 | |
280 | static bool spt_port_hotplug_long_detect(enum hpd_pin pin, u32 val) |
281 | { |
282 | switch (pin) { |
283 | case HPD_PORT_A: |
284 | return val & PORTA_HOTPLUG_LONG_DETECT; |
285 | case HPD_PORT_B: |
286 | return val & PORTB_HOTPLUG_LONG_DETECT; |
287 | case HPD_PORT_C: |
288 | return val & PORTC_HOTPLUG_LONG_DETECT; |
289 | case HPD_PORT_D: |
290 | return val & PORTD_HOTPLUG_LONG_DETECT; |
291 | default: |
292 | return false; |
293 | } |
294 | } |
295 | |
296 | static bool ilk_port_hotplug_long_detect(enum hpd_pin pin, u32 val) |
297 | { |
298 | switch (pin) { |
299 | case HPD_PORT_A: |
300 | return val & DIGITAL_PORTA_HOTPLUG_LONG_DETECT; |
301 | default: |
302 | return false; |
303 | } |
304 | } |
305 | |
306 | static bool pch_port_hotplug_long_detect(enum hpd_pin pin, u32 val) |
307 | { |
308 | switch (pin) { |
309 | case HPD_PORT_B: |
310 | return val & PORTB_HOTPLUG_LONG_DETECT; |
311 | case HPD_PORT_C: |
312 | return val & PORTC_HOTPLUG_LONG_DETECT; |
313 | case HPD_PORT_D: |
314 | return val & PORTD_HOTPLUG_LONG_DETECT; |
315 | default: |
316 | return false; |
317 | } |
318 | } |
319 | |
320 | static bool i9xx_port_hotplug_long_detect(enum hpd_pin pin, u32 val) |
321 | { |
322 | switch (pin) { |
323 | case HPD_PORT_B: |
324 | return val & PORTB_HOTPLUG_INT_LONG_PULSE; |
325 | case HPD_PORT_C: |
326 | return val & PORTC_HOTPLUG_INT_LONG_PULSE; |
327 | case HPD_PORT_D: |
328 | return val & PORTD_HOTPLUG_INT_LONG_PULSE; |
329 | default: |
330 | return false; |
331 | } |
332 | } |
333 | |
334 | /* |
335 | * Get a bit mask of pins that have triggered, and which ones may be long. |
336 | * This can be called multiple times with the same masks to accumulate |
337 | * hotplug detection results from several registers. |
338 | * |
339 | * Note that the caller is expected to zero out the masks initially. |
340 | */ |
341 | static void intel_get_hpd_pins(struct drm_i915_private *dev_priv, |
342 | u32 *pin_mask, u32 *long_mask, |
343 | u32 hotplug_trigger, u32 dig_hotplug_reg, |
344 | const u32 hpd[HPD_NUM_PINS], |
345 | bool long_pulse_detect(enum hpd_pin pin, u32 val)) |
346 | { |
347 | enum hpd_pin pin; |
348 | |
349 | BUILD_BUG_ON(BITS_PER_TYPE(*pin_mask) < HPD_NUM_PINS); |
350 | |
351 | for_each_hpd_pin(pin) { |
352 | if ((hpd[pin] & hotplug_trigger) == 0) |
353 | continue; |
354 | |
355 | *pin_mask |= BIT(pin); |
356 | |
357 | if (long_pulse_detect(pin, dig_hotplug_reg)) |
358 | *long_mask |= BIT(pin); |
359 | } |
360 | |
361 | drm_dbg(&dev_priv->drm, |
362 | "hotplug event received, stat 0x%08x, dig 0x%08x, pins 0x%08x, long 0x%08x\n" , |
363 | hotplug_trigger, dig_hotplug_reg, *pin_mask, *long_mask); |
364 | } |
365 | |
366 | static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, |
367 | const u32 hpd[HPD_NUM_PINS]) |
368 | { |
369 | struct intel_encoder *encoder; |
370 | u32 enabled_irqs = 0; |
371 | |
372 | for_each_intel_encoder(&dev_priv->drm, encoder) |
373 | if (dev_priv->display.hotplug.stats[encoder->hpd_pin].state == HPD_ENABLED) |
374 | enabled_irqs |= hpd[encoder->hpd_pin]; |
375 | |
376 | return enabled_irqs; |
377 | } |
378 | |
379 | static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv, |
380 | const u32 hpd[HPD_NUM_PINS]) |
381 | { |
382 | struct intel_encoder *encoder; |
383 | u32 hotplug_irqs = 0; |
384 | |
385 | for_each_intel_encoder(&dev_priv->drm, encoder) |
386 | hotplug_irqs |= hpd[encoder->hpd_pin]; |
387 | |
388 | return hotplug_irqs; |
389 | } |
390 | |
391 | static u32 intel_hpd_hotplug_mask(struct drm_i915_private *i915, |
392 | hotplug_mask_func hotplug_mask) |
393 | { |
394 | enum hpd_pin pin; |
395 | u32 hotplug = 0; |
396 | |
397 | for_each_hpd_pin(pin) |
398 | hotplug |= hotplug_mask(pin); |
399 | |
400 | return hotplug; |
401 | } |
402 | |
403 | static u32 intel_hpd_hotplug_enables(struct drm_i915_private *i915, |
404 | hotplug_enables_func hotplug_enables) |
405 | { |
406 | struct intel_encoder *encoder; |
407 | u32 hotplug = 0; |
408 | |
409 | for_each_intel_encoder(&i915->drm, encoder) |
410 | hotplug |= hotplug_enables(encoder); |
411 | |
412 | return hotplug; |
413 | } |
414 | |
415 | u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) |
416 | { |
417 | u32 hotplug_status = 0, hotplug_status_mask; |
418 | int i; |
419 | |
420 | if (IS_G4X(dev_priv) || |
421 | IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
422 | hotplug_status_mask = HOTPLUG_INT_STATUS_G4X | |
423 | DP_AUX_CHANNEL_MASK_INT_STATUS_G4X; |
424 | else |
425 | hotplug_status_mask = HOTPLUG_INT_STATUS_I915; |
426 | |
427 | /* |
428 | * We absolutely have to clear all the pending interrupt |
429 | * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port |
430 | * interrupt bit won't have an edge, and the i965/g4x |
431 | * edge triggered IIR will not notice that an interrupt |
432 | * is still pending. We can't use PORT_HOTPLUG_EN to |
433 | * guarantee the edge as the act of toggling the enable |
434 | * bits can itself generate a new hotplug interrupt :( |
435 | */ |
436 | for (i = 0; i < 10; i++) { |
437 | u32 tmp = intel_uncore_read(uncore: &dev_priv->uncore, PORT_HOTPLUG_STAT) & hotplug_status_mask; |
438 | |
439 | if (tmp == 0) |
440 | return hotplug_status; |
441 | |
442 | hotplug_status |= tmp; |
443 | intel_uncore_write(uncore: &dev_priv->uncore, PORT_HOTPLUG_STAT, val: hotplug_status); |
444 | } |
445 | |
446 | drm_WARN_ONCE(&dev_priv->drm, 1, |
447 | "PORT_HOTPLUG_STAT did not clear (0x%08x)\n" , |
448 | intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT)); |
449 | |
450 | return hotplug_status; |
451 | } |
452 | |
453 | void i9xx_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_status) |
454 | { |
455 | u32 pin_mask = 0, long_mask = 0; |
456 | u32 hotplug_trigger; |
457 | |
458 | if (IS_G4X(dev_priv) || |
459 | IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
460 | hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X; |
461 | else |
462 | hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915; |
463 | |
464 | if (hotplug_trigger) { |
465 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
466 | hotplug_trigger, dig_hotplug_reg: hotplug_trigger, |
467 | hpd: dev_priv->display.hotplug.hpd, |
468 | long_pulse_detect: i9xx_port_hotplug_long_detect); |
469 | |
470 | intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); |
471 | } |
472 | |
473 | if ((IS_G4X(dev_priv) || |
474 | IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
475 | hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X) |
476 | intel_dp_aux_irq_handler(i915: dev_priv); |
477 | } |
478 | |
479 | void ibx_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger) |
480 | { |
481 | u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; |
482 | |
483 | /* |
484 | * Somehow the PCH doesn't seem to really ack the interrupt to the CPU |
485 | * unless we touch the hotplug register, even if hotplug_trigger is |
486 | * zero. Not acking leads to "The master control interrupt lied (SDE)!" |
487 | * errors. |
488 | */ |
489 | dig_hotplug_reg = intel_uncore_read(uncore: &dev_priv->uncore, PCH_PORT_HOTPLUG); |
490 | if (!hotplug_trigger) { |
491 | u32 mask = PORTA_HOTPLUG_STATUS_MASK | |
492 | PORTD_HOTPLUG_STATUS_MASK | |
493 | PORTC_HOTPLUG_STATUS_MASK | |
494 | PORTB_HOTPLUG_STATUS_MASK; |
495 | dig_hotplug_reg &= ~mask; |
496 | } |
497 | |
498 | intel_uncore_write(uncore: &dev_priv->uncore, PCH_PORT_HOTPLUG, val: dig_hotplug_reg); |
499 | if (!hotplug_trigger) |
500 | return; |
501 | |
502 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
503 | hotplug_trigger, dig_hotplug_reg, |
504 | hpd: dev_priv->display.hotplug.pch_hpd, |
505 | long_pulse_detect: pch_port_hotplug_long_detect); |
506 | |
507 | intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); |
508 | } |
509 | |
510 | void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir) |
511 | { |
512 | enum hpd_pin pin; |
513 | u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK); |
514 | u32 trigger_aux = iir & XELPDP_AUX_TC_MASK; |
515 | u32 pin_mask = 0, long_mask = 0; |
516 | |
517 | if (DISPLAY_VER(i915) >= 20) |
518 | trigger_aux |= iir & XE2LPD_AUX_DDI_MASK; |
519 | |
520 | for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) { |
521 | u32 val; |
522 | |
523 | if (!(i915->display.hotplug.hpd[pin] & hotplug_trigger)) |
524 | continue; |
525 | |
526 | pin_mask |= BIT(pin); |
527 | |
528 | val = intel_de_read(i915, XELPDP_PORT_HOTPLUG_CTL(pin)); |
529 | intel_de_write(i915, XELPDP_PORT_HOTPLUG_CTL(pin), val); |
530 | |
531 | if (val & (XELPDP_DP_ALT_HPD_LONG_DETECT | XELPDP_TBT_HPD_LONG_DETECT)) |
532 | long_mask |= BIT(pin); |
533 | } |
534 | |
535 | if (pin_mask) { |
536 | drm_dbg(&i915->drm, |
537 | "pica hotplug event received, stat 0x%08x, pins 0x%08x, long 0x%08x\n" , |
538 | hotplug_trigger, pin_mask, long_mask); |
539 | |
540 | intel_hpd_irq_handler(dev_priv: i915, pin_mask, long_mask); |
541 | } |
542 | |
543 | if (trigger_aux) |
544 | intel_dp_aux_irq_handler(i915); |
545 | |
546 | if (!pin_mask && !trigger_aux) |
547 | drm_err(&i915->drm, |
548 | "Unexpected DE HPD/AUX interrupt 0x%08x\n" , iir); |
549 | } |
550 | |
551 | void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) |
552 | { |
553 | u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP; |
554 | u32 tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_MASK_ICP; |
555 | u32 pin_mask = 0, long_mask = 0; |
556 | |
557 | if (ddi_hotplug_trigger) { |
558 | u32 dig_hotplug_reg; |
559 | |
560 | /* Locking due to DSI native GPIO sequences */ |
561 | spin_lock(lock: &dev_priv->irq_lock); |
562 | dig_hotplug_reg = intel_uncore_rmw(uncore: &dev_priv->uncore, SHOTPLUG_CTL_DDI, clear: 0, set: 0); |
563 | spin_unlock(lock: &dev_priv->irq_lock); |
564 | |
565 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
566 | hotplug_trigger: ddi_hotplug_trigger, dig_hotplug_reg, |
567 | hpd: dev_priv->display.hotplug.pch_hpd, |
568 | long_pulse_detect: icp_ddi_port_hotplug_long_detect); |
569 | } |
570 | |
571 | if (tc_hotplug_trigger) { |
572 | u32 dig_hotplug_reg; |
573 | |
574 | dig_hotplug_reg = intel_uncore_rmw(uncore: &dev_priv->uncore, SHOTPLUG_CTL_TC, clear: 0, set: 0); |
575 | |
576 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
577 | hotplug_trigger: tc_hotplug_trigger, dig_hotplug_reg, |
578 | hpd: dev_priv->display.hotplug.pch_hpd, |
579 | long_pulse_detect: icp_tc_port_hotplug_long_detect); |
580 | } |
581 | |
582 | if (pin_mask) |
583 | intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); |
584 | |
585 | if (pch_iir & SDE_GMBUS_ICP) |
586 | intel_gmbus_irq_handler(i915: dev_priv); |
587 | } |
588 | |
589 | void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) |
590 | { |
591 | u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_SPT & |
592 | ~SDE_PORTE_HOTPLUG_SPT; |
593 | u32 hotplug2_trigger = pch_iir & SDE_PORTE_HOTPLUG_SPT; |
594 | u32 pin_mask = 0, long_mask = 0; |
595 | |
596 | if (hotplug_trigger) { |
597 | u32 dig_hotplug_reg; |
598 | |
599 | dig_hotplug_reg = intel_uncore_rmw(uncore: &dev_priv->uncore, PCH_PORT_HOTPLUG, clear: 0, set: 0); |
600 | |
601 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
602 | hotplug_trigger, dig_hotplug_reg, |
603 | hpd: dev_priv->display.hotplug.pch_hpd, |
604 | long_pulse_detect: spt_port_hotplug_long_detect); |
605 | } |
606 | |
607 | if (hotplug2_trigger) { |
608 | u32 dig_hotplug_reg; |
609 | |
610 | dig_hotplug_reg = intel_uncore_rmw(uncore: &dev_priv->uncore, PCH_PORT_HOTPLUG2, clear: 0, set: 0); |
611 | |
612 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
613 | hotplug_trigger: hotplug2_trigger, dig_hotplug_reg, |
614 | hpd: dev_priv->display.hotplug.pch_hpd, |
615 | long_pulse_detect: spt_port_hotplug2_long_detect); |
616 | } |
617 | |
618 | if (pin_mask) |
619 | intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); |
620 | |
621 | if (pch_iir & SDE_GMBUS_CPT) |
622 | intel_gmbus_irq_handler(i915: dev_priv); |
623 | } |
624 | |
625 | void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger) |
626 | { |
627 | u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; |
628 | |
629 | dig_hotplug_reg = intel_uncore_rmw(uncore: &dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, clear: 0, set: 0); |
630 | |
631 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
632 | hotplug_trigger, dig_hotplug_reg, |
633 | hpd: dev_priv->display.hotplug.hpd, |
634 | long_pulse_detect: ilk_port_hotplug_long_detect); |
635 | |
636 | intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); |
637 | } |
638 | |
639 | void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 hotplug_trigger) |
640 | { |
641 | u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0; |
642 | |
643 | dig_hotplug_reg = intel_uncore_rmw(uncore: &dev_priv->uncore, PCH_PORT_HOTPLUG, clear: 0, set: 0); |
644 | |
645 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
646 | hotplug_trigger, dig_hotplug_reg, |
647 | hpd: dev_priv->display.hotplug.hpd, |
648 | long_pulse_detect: bxt_port_hotplug_long_detect); |
649 | |
650 | intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); |
651 | } |
652 | |
653 | void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) |
654 | { |
655 | u32 pin_mask = 0, long_mask = 0; |
656 | u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK; |
657 | u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK; |
658 | |
659 | if (trigger_tc) { |
660 | u32 dig_hotplug_reg; |
661 | |
662 | dig_hotplug_reg = intel_uncore_rmw(uncore: &dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, clear: 0, set: 0); |
663 | |
664 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
665 | hotplug_trigger: trigger_tc, dig_hotplug_reg, |
666 | hpd: dev_priv->display.hotplug.hpd, |
667 | long_pulse_detect: gen11_port_hotplug_long_detect); |
668 | } |
669 | |
670 | if (trigger_tbt) { |
671 | u32 dig_hotplug_reg; |
672 | |
673 | dig_hotplug_reg = intel_uncore_rmw(uncore: &dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, clear: 0, set: 0); |
674 | |
675 | intel_get_hpd_pins(dev_priv, pin_mask: &pin_mask, long_mask: &long_mask, |
676 | hotplug_trigger: trigger_tbt, dig_hotplug_reg, |
677 | hpd: dev_priv->display.hotplug.hpd, |
678 | long_pulse_detect: gen11_port_hotplug_long_detect); |
679 | } |
680 | |
681 | if (pin_mask) |
682 | intel_hpd_irq_handler(dev_priv, pin_mask, long_mask); |
683 | else |
684 | drm_err(&dev_priv->drm, |
685 | "Unexpected DE HPD interrupt 0x%08x\n" , iir); |
686 | } |
687 | |
688 | static u32 ibx_hotplug_mask(enum hpd_pin hpd_pin) |
689 | { |
690 | switch (hpd_pin) { |
691 | case HPD_PORT_A: |
692 | return PORTA_HOTPLUG_ENABLE; |
693 | case HPD_PORT_B: |
694 | return PORTB_HOTPLUG_ENABLE | PORTB_PULSE_DURATION_MASK; |
695 | case HPD_PORT_C: |
696 | return PORTC_HOTPLUG_ENABLE | PORTC_PULSE_DURATION_MASK; |
697 | case HPD_PORT_D: |
698 | return PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_MASK; |
699 | default: |
700 | return 0; |
701 | } |
702 | } |
703 | |
704 | static u32 ibx_hotplug_enables(struct intel_encoder *encoder) |
705 | { |
706 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
707 | |
708 | switch (encoder->hpd_pin) { |
709 | case HPD_PORT_A: |
710 | /* |
711 | * When CPU and PCH are on the same package, port A |
712 | * HPD must be enabled in both north and south. |
713 | */ |
714 | return HAS_PCH_LPT_LP(i915) ? |
715 | PORTA_HOTPLUG_ENABLE : 0; |
716 | case HPD_PORT_B: |
717 | return PORTB_HOTPLUG_ENABLE | |
718 | PORTB_PULSE_DURATION_2ms; |
719 | case HPD_PORT_C: |
720 | return PORTC_HOTPLUG_ENABLE | |
721 | PORTC_PULSE_DURATION_2ms; |
722 | case HPD_PORT_D: |
723 | return PORTD_HOTPLUG_ENABLE | |
724 | PORTD_PULSE_DURATION_2ms; |
725 | default: |
726 | return 0; |
727 | } |
728 | } |
729 | |
730 | static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) |
731 | { |
732 | /* |
733 | * Enable digital hotplug on the PCH, and configure the DP short pulse |
734 | * duration to 2ms (which is the minimum in the Display Port spec). |
735 | * The pulse duration bits are reserved on LPT+. |
736 | */ |
737 | intel_uncore_rmw(uncore: &dev_priv->uncore, PCH_PORT_HOTPLUG, |
738 | clear: intel_hpd_hotplug_mask(i915: dev_priv, hotplug_mask: ibx_hotplug_mask), |
739 | set: intel_hpd_hotplug_enables(i915: dev_priv, hotplug_enables: ibx_hotplug_enables)); |
740 | } |
741 | |
742 | static void ibx_hpd_enable_detection(struct intel_encoder *encoder) |
743 | { |
744 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
745 | |
746 | intel_uncore_rmw(uncore: &i915->uncore, PCH_PORT_HOTPLUG, |
747 | clear: ibx_hotplug_mask(hpd_pin: encoder->hpd_pin), |
748 | set: ibx_hotplug_enables(encoder)); |
749 | } |
750 | |
751 | static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) |
752 | { |
753 | u32 hotplug_irqs, enabled_irqs; |
754 | |
755 | enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd: dev_priv->display.hotplug.pch_hpd); |
756 | hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, hpd: dev_priv->display.hotplug.pch_hpd); |
757 | |
758 | ibx_display_interrupt_update(i915: dev_priv, interrupt_mask: hotplug_irqs, enabled_irq_mask: enabled_irqs); |
759 | |
760 | ibx_hpd_detection_setup(dev_priv); |
761 | } |
762 | |
763 | static u32 icp_ddi_hotplug_mask(enum hpd_pin hpd_pin) |
764 | { |
765 | switch (hpd_pin) { |
766 | case HPD_PORT_A: |
767 | case HPD_PORT_B: |
768 | case HPD_PORT_C: |
769 | case HPD_PORT_D: |
770 | return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin); |
771 | default: |
772 | return 0; |
773 | } |
774 | } |
775 | |
776 | static u32 icp_ddi_hotplug_enables(struct intel_encoder *encoder) |
777 | { |
778 | return icp_ddi_hotplug_mask(hpd_pin: encoder->hpd_pin); |
779 | } |
780 | |
781 | static u32 icp_tc_hotplug_mask(enum hpd_pin hpd_pin) |
782 | { |
783 | switch (hpd_pin) { |
784 | case HPD_PORT_TC1: |
785 | case HPD_PORT_TC2: |
786 | case HPD_PORT_TC3: |
787 | case HPD_PORT_TC4: |
788 | case HPD_PORT_TC5: |
789 | case HPD_PORT_TC6: |
790 | return ICP_TC_HPD_ENABLE(hpd_pin); |
791 | default: |
792 | return 0; |
793 | } |
794 | } |
795 | |
796 | static u32 icp_tc_hotplug_enables(struct intel_encoder *encoder) |
797 | { |
798 | return icp_tc_hotplug_mask(hpd_pin: encoder->hpd_pin); |
799 | } |
800 | |
801 | static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv) |
802 | { |
803 | intel_uncore_rmw(uncore: &dev_priv->uncore, SHOTPLUG_CTL_DDI, |
804 | clear: intel_hpd_hotplug_mask(i915: dev_priv, hotplug_mask: icp_ddi_hotplug_mask), |
805 | set: intel_hpd_hotplug_enables(i915: dev_priv, hotplug_enables: icp_ddi_hotplug_enables)); |
806 | } |
807 | |
808 | static void icp_ddi_hpd_enable_detection(struct intel_encoder *encoder) |
809 | { |
810 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
811 | |
812 | intel_uncore_rmw(uncore: &i915->uncore, SHOTPLUG_CTL_DDI, |
813 | clear: icp_ddi_hotplug_mask(hpd_pin: encoder->hpd_pin), |
814 | set: icp_ddi_hotplug_enables(encoder)); |
815 | } |
816 | |
817 | static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) |
818 | { |
819 | intel_uncore_rmw(uncore: &dev_priv->uncore, SHOTPLUG_CTL_TC, |
820 | clear: intel_hpd_hotplug_mask(i915: dev_priv, hotplug_mask: icp_tc_hotplug_mask), |
821 | set: intel_hpd_hotplug_enables(i915: dev_priv, hotplug_enables: icp_tc_hotplug_enables)); |
822 | } |
823 | |
824 | static void icp_tc_hpd_enable_detection(struct intel_encoder *encoder) |
825 | { |
826 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
827 | |
828 | intel_uncore_rmw(uncore: &i915->uncore, SHOTPLUG_CTL_TC, |
829 | clear: icp_tc_hotplug_mask(hpd_pin: encoder->hpd_pin), |
830 | set: icp_tc_hotplug_enables(encoder)); |
831 | } |
832 | |
833 | static void icp_hpd_enable_detection(struct intel_encoder *encoder) |
834 | { |
835 | icp_ddi_hpd_enable_detection(encoder); |
836 | icp_tc_hpd_enable_detection(encoder); |
837 | } |
838 | |
839 | static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv) |
840 | { |
841 | u32 hotplug_irqs, enabled_irqs; |
842 | |
843 | enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd: dev_priv->display.hotplug.pch_hpd); |
844 | hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, hpd: dev_priv->display.hotplug.pch_hpd); |
845 | |
846 | if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP) |
847 | intel_uncore_write(uncore: &dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); |
848 | else |
849 | intel_uncore_write(uncore: &dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_250); |
850 | |
851 | ibx_display_interrupt_update(i915: dev_priv, interrupt_mask: hotplug_irqs, enabled_irq_mask: enabled_irqs); |
852 | |
853 | icp_ddi_hpd_detection_setup(dev_priv); |
854 | icp_tc_hpd_detection_setup(dev_priv); |
855 | } |
856 | |
857 | static u32 gen11_hotplug_mask(enum hpd_pin hpd_pin) |
858 | { |
859 | switch (hpd_pin) { |
860 | case HPD_PORT_TC1: |
861 | case HPD_PORT_TC2: |
862 | case HPD_PORT_TC3: |
863 | case HPD_PORT_TC4: |
864 | case HPD_PORT_TC5: |
865 | case HPD_PORT_TC6: |
866 | return GEN11_HOTPLUG_CTL_ENABLE(hpd_pin); |
867 | default: |
868 | return 0; |
869 | } |
870 | } |
871 | |
872 | static u32 gen11_hotplug_enables(struct intel_encoder *encoder) |
873 | { |
874 | return gen11_hotplug_mask(hpd_pin: encoder->hpd_pin); |
875 | } |
876 | |
877 | static void dg1_hpd_invert(struct drm_i915_private *i915) |
878 | { |
879 | u32 val = (INVERT_DDIA_HPD | |
880 | INVERT_DDIB_HPD | |
881 | INVERT_DDIC_HPD | |
882 | INVERT_DDID_HPD); |
883 | intel_uncore_rmw(uncore: &i915->uncore, SOUTH_CHICKEN1, clear: 0, set: val); |
884 | } |
885 | |
886 | static void dg1_hpd_enable_detection(struct intel_encoder *encoder) |
887 | { |
888 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
889 | |
890 | dg1_hpd_invert(i915); |
891 | icp_hpd_enable_detection(encoder); |
892 | } |
893 | |
894 | static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv) |
895 | { |
896 | dg1_hpd_invert(i915: dev_priv); |
897 | icp_hpd_irq_setup(dev_priv); |
898 | } |
899 | |
900 | static void gen11_tc_hpd_detection_setup(struct drm_i915_private *dev_priv) |
901 | { |
902 | intel_uncore_rmw(uncore: &dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, |
903 | clear: intel_hpd_hotplug_mask(i915: dev_priv, hotplug_mask: gen11_hotplug_mask), |
904 | set: intel_hpd_hotplug_enables(i915: dev_priv, hotplug_enables: gen11_hotplug_enables)); |
905 | } |
906 | |
907 | static void gen11_tc_hpd_enable_detection(struct intel_encoder *encoder) |
908 | { |
909 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
910 | |
911 | intel_uncore_rmw(uncore: &i915->uncore, GEN11_TC_HOTPLUG_CTL, |
912 | clear: gen11_hotplug_mask(hpd_pin: encoder->hpd_pin), |
913 | set: gen11_hotplug_enables(encoder)); |
914 | } |
915 | |
916 | static void gen11_tbt_hpd_detection_setup(struct drm_i915_private *dev_priv) |
917 | { |
918 | intel_uncore_rmw(uncore: &dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, |
919 | clear: intel_hpd_hotplug_mask(i915: dev_priv, hotplug_mask: gen11_hotplug_mask), |
920 | set: intel_hpd_hotplug_enables(i915: dev_priv, hotplug_enables: gen11_hotplug_enables)); |
921 | } |
922 | |
923 | static void gen11_tbt_hpd_enable_detection(struct intel_encoder *encoder) |
924 | { |
925 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
926 | |
927 | intel_uncore_rmw(uncore: &i915->uncore, GEN11_TBT_HOTPLUG_CTL, |
928 | clear: gen11_hotplug_mask(hpd_pin: encoder->hpd_pin), |
929 | set: gen11_hotplug_enables(encoder)); |
930 | } |
931 | |
932 | static void gen11_hpd_enable_detection(struct intel_encoder *encoder) |
933 | { |
934 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
935 | |
936 | gen11_tc_hpd_enable_detection(encoder); |
937 | gen11_tbt_hpd_enable_detection(encoder); |
938 | |
939 | if (INTEL_PCH_TYPE(i915) >= PCH_ICP) |
940 | icp_hpd_enable_detection(encoder); |
941 | } |
942 | |
943 | static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) |
944 | { |
945 | u32 hotplug_irqs, enabled_irqs; |
946 | |
947 | enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd: dev_priv->display.hotplug.hpd); |
948 | hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, hpd: dev_priv->display.hotplug.hpd); |
949 | |
950 | intel_uncore_rmw(uncore: &dev_priv->uncore, GEN11_DE_HPD_IMR, clear: hotplug_irqs, |
951 | set: ~enabled_irqs & hotplug_irqs); |
952 | intel_uncore_posting_read(&dev_priv->uncore, GEN11_DE_HPD_IMR); |
953 | |
954 | gen11_tc_hpd_detection_setup(dev_priv); |
955 | gen11_tbt_hpd_detection_setup(dev_priv); |
956 | |
957 | if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) |
958 | icp_hpd_irq_setup(dev_priv); |
959 | } |
960 | |
961 | static u32 mtp_ddi_hotplug_mask(enum hpd_pin hpd_pin) |
962 | { |
963 | switch (hpd_pin) { |
964 | case HPD_PORT_A: |
965 | case HPD_PORT_B: |
966 | return SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin); |
967 | default: |
968 | return 0; |
969 | } |
970 | } |
971 | |
972 | static u32 mtp_ddi_hotplug_enables(struct intel_encoder *encoder) |
973 | { |
974 | return mtp_ddi_hotplug_mask(hpd_pin: encoder->hpd_pin); |
975 | } |
976 | |
977 | static u32 mtp_tc_hotplug_mask(enum hpd_pin hpd_pin) |
978 | { |
979 | switch (hpd_pin) { |
980 | case HPD_PORT_TC1: |
981 | case HPD_PORT_TC2: |
982 | case HPD_PORT_TC3: |
983 | case HPD_PORT_TC4: |
984 | return ICP_TC_HPD_ENABLE(hpd_pin); |
985 | default: |
986 | return 0; |
987 | } |
988 | } |
989 | |
990 | static u32 mtp_tc_hotplug_enables(struct intel_encoder *encoder) |
991 | { |
992 | return mtp_tc_hotplug_mask(hpd_pin: encoder->hpd_pin); |
993 | } |
994 | |
995 | static void mtp_ddi_hpd_detection_setup(struct drm_i915_private *i915) |
996 | { |
997 | intel_de_rmw(i915, SHOTPLUG_CTL_DDI, |
998 | clear: intel_hpd_hotplug_mask(i915, hotplug_mask: mtp_ddi_hotplug_mask), |
999 | set: intel_hpd_hotplug_enables(i915, hotplug_enables: mtp_ddi_hotplug_enables)); |
1000 | } |
1001 | |
1002 | static void mtp_ddi_hpd_enable_detection(struct intel_encoder *encoder) |
1003 | { |
1004 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
1005 | |
1006 | intel_de_rmw(i915, SHOTPLUG_CTL_DDI, |
1007 | clear: mtp_ddi_hotplug_mask(hpd_pin: encoder->hpd_pin), |
1008 | set: mtp_ddi_hotplug_enables(encoder)); |
1009 | } |
1010 | |
1011 | static void mtp_tc_hpd_detection_setup(struct drm_i915_private *i915) |
1012 | { |
1013 | intel_de_rmw(i915, SHOTPLUG_CTL_TC, |
1014 | clear: intel_hpd_hotplug_mask(i915, hotplug_mask: mtp_tc_hotplug_mask), |
1015 | set: intel_hpd_hotplug_enables(i915, hotplug_enables: mtp_tc_hotplug_enables)); |
1016 | } |
1017 | |
1018 | static void mtp_tc_hpd_enable_detection(struct intel_encoder *encoder) |
1019 | { |
1020 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
1021 | |
1022 | intel_de_rmw(i915, SHOTPLUG_CTL_DDI, |
1023 | clear: mtp_tc_hotplug_mask(hpd_pin: encoder->hpd_pin), |
1024 | set: mtp_tc_hotplug_enables(encoder)); |
1025 | } |
1026 | |
1027 | static void mtp_hpd_invert(struct drm_i915_private *i915) |
1028 | { |
1029 | u32 val = (INVERT_DDIA_HPD | |
1030 | INVERT_DDIB_HPD | |
1031 | INVERT_DDIC_HPD | |
1032 | INVERT_TC1_HPD | |
1033 | INVERT_TC2_HPD | |
1034 | INVERT_TC3_HPD | |
1035 | INVERT_TC4_HPD | |
1036 | INVERT_DDID_HPD_MTP | |
1037 | INVERT_DDIE_HPD); |
1038 | intel_de_rmw(i915, SOUTH_CHICKEN1, clear: 0, set: val); |
1039 | } |
1040 | |
1041 | static void mtp_hpd_enable_detection(struct intel_encoder *encoder) |
1042 | { |
1043 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
1044 | |
1045 | mtp_hpd_invert(i915); |
1046 | mtp_ddi_hpd_enable_detection(encoder); |
1047 | mtp_tc_hpd_enable_detection(encoder); |
1048 | } |
1049 | |
1050 | static void mtp_hpd_irq_setup(struct drm_i915_private *i915) |
1051 | { |
1052 | u32 hotplug_irqs, enabled_irqs; |
1053 | |
1054 | enabled_irqs = intel_hpd_enabled_irqs(dev_priv: i915, hpd: i915->display.hotplug.pch_hpd); |
1055 | hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv: i915, hpd: i915->display.hotplug.pch_hpd); |
1056 | |
1057 | intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_250); |
1058 | |
1059 | mtp_hpd_invert(i915); |
1060 | ibx_display_interrupt_update(i915, interrupt_mask: hotplug_irqs, enabled_irq_mask: enabled_irqs); |
1061 | |
1062 | mtp_ddi_hpd_detection_setup(i915); |
1063 | mtp_tc_hpd_detection_setup(i915); |
1064 | } |
1065 | |
1066 | static void xe2lpd_sde_hpd_irq_setup(struct drm_i915_private *i915) |
1067 | { |
1068 | u32 hotplug_irqs, enabled_irqs; |
1069 | |
1070 | enabled_irqs = intel_hpd_enabled_irqs(dev_priv: i915, hpd: i915->display.hotplug.pch_hpd); |
1071 | hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv: i915, hpd: i915->display.hotplug.pch_hpd); |
1072 | |
1073 | ibx_display_interrupt_update(i915, interrupt_mask: hotplug_irqs, enabled_irq_mask: enabled_irqs); |
1074 | |
1075 | mtp_ddi_hpd_detection_setup(i915); |
1076 | mtp_tc_hpd_detection_setup(i915); |
1077 | } |
1078 | |
1079 | static bool is_xelpdp_pica_hpd_pin(enum hpd_pin hpd_pin) |
1080 | { |
1081 | return hpd_pin >= HPD_PORT_TC1 && hpd_pin <= HPD_PORT_TC4; |
1082 | } |
1083 | |
1084 | static void _xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915, |
1085 | enum hpd_pin hpd_pin, bool enable) |
1086 | { |
1087 | u32 mask = XELPDP_TBT_HOTPLUG_ENABLE | |
1088 | XELPDP_DP_ALT_HOTPLUG_ENABLE; |
1089 | |
1090 | if (!is_xelpdp_pica_hpd_pin(hpd_pin)) |
1091 | return; |
1092 | |
1093 | intel_de_rmw(i915, XELPDP_PORT_HOTPLUG_CTL(hpd_pin), |
1094 | clear: mask, set: enable ? mask : 0); |
1095 | } |
1096 | |
1097 | static void xelpdp_pica_hpd_enable_detection(struct intel_encoder *encoder) |
1098 | { |
1099 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
1100 | |
1101 | _xelpdp_pica_hpd_detection_setup(i915, hpd_pin: encoder->hpd_pin, enable: true); |
1102 | } |
1103 | |
1104 | static void xelpdp_pica_hpd_detection_setup(struct drm_i915_private *i915) |
1105 | { |
1106 | struct intel_encoder *encoder; |
1107 | u32 available_pins = 0; |
1108 | enum hpd_pin pin; |
1109 | |
1110 | BUILD_BUG_ON(BITS_PER_TYPE(available_pins) < HPD_NUM_PINS); |
1111 | |
1112 | for_each_intel_encoder(&i915->drm, encoder) |
1113 | available_pins |= BIT(encoder->hpd_pin); |
1114 | |
1115 | for_each_hpd_pin(pin) |
1116 | _xelpdp_pica_hpd_detection_setup(i915, hpd_pin: pin, enable: available_pins & BIT(pin)); |
1117 | } |
1118 | |
1119 | static void xelpdp_hpd_enable_detection(struct intel_encoder *encoder) |
1120 | { |
1121 | xelpdp_pica_hpd_enable_detection(encoder); |
1122 | mtp_hpd_enable_detection(encoder); |
1123 | } |
1124 | |
1125 | static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915) |
1126 | { |
1127 | u32 hotplug_irqs, enabled_irqs; |
1128 | |
1129 | enabled_irqs = intel_hpd_enabled_irqs(dev_priv: i915, hpd: i915->display.hotplug.hpd); |
1130 | hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv: i915, hpd: i915->display.hotplug.hpd); |
1131 | |
1132 | intel_de_rmw(i915, PICAINTERRUPT_IMR, clear: hotplug_irqs, |
1133 | set: ~enabled_irqs & hotplug_irqs); |
1134 | intel_uncore_posting_read(&i915->uncore, PICAINTERRUPT_IMR); |
1135 | |
1136 | xelpdp_pica_hpd_detection_setup(i915); |
1137 | |
1138 | if (INTEL_PCH_TYPE(i915) >= PCH_LNL) |
1139 | xe2lpd_sde_hpd_irq_setup(i915); |
1140 | else if (INTEL_PCH_TYPE(i915) >= PCH_MTL) |
1141 | mtp_hpd_irq_setup(i915); |
1142 | } |
1143 | |
1144 | static u32 spt_hotplug_mask(enum hpd_pin hpd_pin) |
1145 | { |
1146 | switch (hpd_pin) { |
1147 | case HPD_PORT_A: |
1148 | return PORTA_HOTPLUG_ENABLE; |
1149 | case HPD_PORT_B: |
1150 | return PORTB_HOTPLUG_ENABLE; |
1151 | case HPD_PORT_C: |
1152 | return PORTC_HOTPLUG_ENABLE; |
1153 | case HPD_PORT_D: |
1154 | return PORTD_HOTPLUG_ENABLE; |
1155 | default: |
1156 | return 0; |
1157 | } |
1158 | } |
1159 | |
1160 | static u32 spt_hotplug_enables(struct intel_encoder *encoder) |
1161 | { |
1162 | return spt_hotplug_mask(hpd_pin: encoder->hpd_pin); |
1163 | } |
1164 | |
1165 | static u32 spt_hotplug2_mask(enum hpd_pin hpd_pin) |
1166 | { |
1167 | switch (hpd_pin) { |
1168 | case HPD_PORT_E: |
1169 | return PORTE_HOTPLUG_ENABLE; |
1170 | default: |
1171 | return 0; |
1172 | } |
1173 | } |
1174 | |
1175 | static u32 spt_hotplug2_enables(struct intel_encoder *encoder) |
1176 | { |
1177 | return spt_hotplug2_mask(hpd_pin: encoder->hpd_pin); |
1178 | } |
1179 | |
1180 | static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) |
1181 | { |
1182 | /* Display WA #1179 WaHardHangonHotPlug: cnp */ |
1183 | if (HAS_PCH_CNP(dev_priv)) { |
1184 | intel_uncore_rmw(uncore: &dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK, |
1185 | CHASSIS_CLK_REQ_DURATION(0xf)); |
1186 | } |
1187 | |
1188 | /* Enable digital hotplug on the PCH */ |
1189 | intel_uncore_rmw(uncore: &dev_priv->uncore, PCH_PORT_HOTPLUG, |
1190 | clear: intel_hpd_hotplug_mask(i915: dev_priv, hotplug_mask: spt_hotplug_mask), |
1191 | set: intel_hpd_hotplug_enables(i915: dev_priv, hotplug_enables: spt_hotplug_enables)); |
1192 | |
1193 | intel_uncore_rmw(uncore: &dev_priv->uncore, PCH_PORT_HOTPLUG2, |
1194 | clear: intel_hpd_hotplug_mask(i915: dev_priv, hotplug_mask: spt_hotplug2_mask), |
1195 | set: intel_hpd_hotplug_enables(i915: dev_priv, hotplug_enables: spt_hotplug2_enables)); |
1196 | } |
1197 | |
1198 | static void spt_hpd_enable_detection(struct intel_encoder *encoder) |
1199 | { |
1200 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
1201 | |
1202 | /* Display WA #1179 WaHardHangonHotPlug: cnp */ |
1203 | if (HAS_PCH_CNP(i915)) { |
1204 | intel_uncore_rmw(uncore: &i915->uncore, SOUTH_CHICKEN1, |
1205 | CHASSIS_CLK_REQ_DURATION_MASK, |
1206 | CHASSIS_CLK_REQ_DURATION(0xf)); |
1207 | } |
1208 | |
1209 | intel_uncore_rmw(uncore: &i915->uncore, PCH_PORT_HOTPLUG, |
1210 | clear: spt_hotplug_mask(hpd_pin: encoder->hpd_pin), |
1211 | set: spt_hotplug_enables(encoder)); |
1212 | |
1213 | intel_uncore_rmw(uncore: &i915->uncore, PCH_PORT_HOTPLUG2, |
1214 | clear: spt_hotplug2_mask(hpd_pin: encoder->hpd_pin), |
1215 | set: spt_hotplug2_enables(encoder)); |
1216 | } |
1217 | |
1218 | static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) |
1219 | { |
1220 | u32 hotplug_irqs, enabled_irqs; |
1221 | |
1222 | if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) |
1223 | intel_uncore_write(uncore: &dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); |
1224 | |
1225 | enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd: dev_priv->display.hotplug.pch_hpd); |
1226 | hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, hpd: dev_priv->display.hotplug.pch_hpd); |
1227 | |
1228 | ibx_display_interrupt_update(i915: dev_priv, interrupt_mask: hotplug_irqs, enabled_irq_mask: enabled_irqs); |
1229 | |
1230 | spt_hpd_detection_setup(dev_priv); |
1231 | } |
1232 | |
1233 | static u32 ilk_hotplug_mask(enum hpd_pin hpd_pin) |
1234 | { |
1235 | switch (hpd_pin) { |
1236 | case HPD_PORT_A: |
1237 | return DIGITAL_PORTA_HOTPLUG_ENABLE | |
1238 | DIGITAL_PORTA_PULSE_DURATION_MASK; |
1239 | default: |
1240 | return 0; |
1241 | } |
1242 | } |
1243 | |
1244 | static u32 ilk_hotplug_enables(struct intel_encoder *encoder) |
1245 | { |
1246 | switch (encoder->hpd_pin) { |
1247 | case HPD_PORT_A: |
1248 | return DIGITAL_PORTA_HOTPLUG_ENABLE | |
1249 | DIGITAL_PORTA_PULSE_DURATION_2ms; |
1250 | default: |
1251 | return 0; |
1252 | } |
1253 | } |
1254 | |
1255 | static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv) |
1256 | { |
1257 | /* |
1258 | * Enable digital hotplug on the CPU, and configure the DP short pulse |
1259 | * duration to 2ms (which is the minimum in the Display Port spec) |
1260 | * The pulse duration bits are reserved on HSW+. |
1261 | */ |
1262 | intel_uncore_rmw(uncore: &dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, |
1263 | clear: intel_hpd_hotplug_mask(i915: dev_priv, hotplug_mask: ilk_hotplug_mask), |
1264 | set: intel_hpd_hotplug_enables(i915: dev_priv, hotplug_enables: ilk_hotplug_enables)); |
1265 | } |
1266 | |
1267 | static void ilk_hpd_enable_detection(struct intel_encoder *encoder) |
1268 | { |
1269 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
1270 | |
1271 | intel_uncore_rmw(uncore: &i915->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, |
1272 | clear: ilk_hotplug_mask(hpd_pin: encoder->hpd_pin), |
1273 | set: ilk_hotplug_enables(encoder)); |
1274 | |
1275 | ibx_hpd_enable_detection(encoder); |
1276 | } |
1277 | |
1278 | static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) |
1279 | { |
1280 | u32 hotplug_irqs, enabled_irqs; |
1281 | |
1282 | enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd: dev_priv->display.hotplug.hpd); |
1283 | hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, hpd: dev_priv->display.hotplug.hpd); |
1284 | |
1285 | if (DISPLAY_VER(dev_priv) >= 8) |
1286 | bdw_update_port_irq(i915: dev_priv, interrupt_mask: hotplug_irqs, enabled_irq_mask: enabled_irqs); |
1287 | else |
1288 | ilk_update_display_irq(i915: dev_priv, interrupt_mask: hotplug_irqs, enabled_irq_mask: enabled_irqs); |
1289 | |
1290 | ilk_hpd_detection_setup(dev_priv); |
1291 | |
1292 | ibx_hpd_irq_setup(dev_priv); |
1293 | } |
1294 | |
1295 | static u32 bxt_hotplug_mask(enum hpd_pin hpd_pin) |
1296 | { |
1297 | switch (hpd_pin) { |
1298 | case HPD_PORT_A: |
1299 | return PORTA_HOTPLUG_ENABLE | BXT_DDIA_HPD_INVERT; |
1300 | case HPD_PORT_B: |
1301 | return PORTB_HOTPLUG_ENABLE | BXT_DDIB_HPD_INVERT; |
1302 | case HPD_PORT_C: |
1303 | return PORTC_HOTPLUG_ENABLE | BXT_DDIC_HPD_INVERT; |
1304 | default: |
1305 | return 0; |
1306 | } |
1307 | } |
1308 | |
1309 | static u32 bxt_hotplug_enables(struct intel_encoder *encoder) |
1310 | { |
1311 | u32 hotplug; |
1312 | |
1313 | switch (encoder->hpd_pin) { |
1314 | case HPD_PORT_A: |
1315 | hotplug = PORTA_HOTPLUG_ENABLE; |
1316 | if (intel_bios_encoder_hpd_invert(devdata: encoder->devdata)) |
1317 | hotplug |= BXT_DDIA_HPD_INVERT; |
1318 | return hotplug; |
1319 | case HPD_PORT_B: |
1320 | hotplug = PORTB_HOTPLUG_ENABLE; |
1321 | if (intel_bios_encoder_hpd_invert(devdata: encoder->devdata)) |
1322 | hotplug |= BXT_DDIB_HPD_INVERT; |
1323 | return hotplug; |
1324 | case HPD_PORT_C: |
1325 | hotplug = PORTC_HOTPLUG_ENABLE; |
1326 | if (intel_bios_encoder_hpd_invert(devdata: encoder->devdata)) |
1327 | hotplug |= BXT_DDIC_HPD_INVERT; |
1328 | return hotplug; |
1329 | default: |
1330 | return 0; |
1331 | } |
1332 | } |
1333 | |
1334 | static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv) |
1335 | { |
1336 | intel_uncore_rmw(uncore: &dev_priv->uncore, PCH_PORT_HOTPLUG, |
1337 | clear: intel_hpd_hotplug_mask(i915: dev_priv, hotplug_mask: bxt_hotplug_mask), |
1338 | set: intel_hpd_hotplug_enables(i915: dev_priv, hotplug_enables: bxt_hotplug_enables)); |
1339 | } |
1340 | |
1341 | static void bxt_hpd_enable_detection(struct intel_encoder *encoder) |
1342 | { |
1343 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
1344 | |
1345 | intel_uncore_rmw(uncore: &i915->uncore, PCH_PORT_HOTPLUG, |
1346 | clear: bxt_hotplug_mask(hpd_pin: encoder->hpd_pin), |
1347 | set: bxt_hotplug_enables(encoder)); |
1348 | } |
1349 | |
1350 | static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) |
1351 | { |
1352 | u32 hotplug_irqs, enabled_irqs; |
1353 | |
1354 | enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd: dev_priv->display.hotplug.hpd); |
1355 | hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, hpd: dev_priv->display.hotplug.hpd); |
1356 | |
1357 | bdw_update_port_irq(i915: dev_priv, interrupt_mask: hotplug_irqs, enabled_irq_mask: enabled_irqs); |
1358 | |
1359 | bxt_hpd_detection_setup(dev_priv); |
1360 | } |
1361 | |
1362 | static void g45_hpd_peg_band_gap_wa(struct drm_i915_private *i915) |
1363 | { |
1364 | /* |
1365 | * For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written |
1366 | * 0xd. Failure to do so will result in spurious interrupts being |
1367 | * generated on the port when a cable is not attached. |
1368 | */ |
1369 | intel_de_rmw(i915, PEG_BAND_GAP_DATA, clear: 0xf, set: 0xd); |
1370 | } |
1371 | |
1372 | static void i915_hpd_enable_detection(struct intel_encoder *encoder) |
1373 | { |
1374 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
1375 | u32 hotplug_en = hpd_mask_i915[encoder->hpd_pin]; |
1376 | |
1377 | if (IS_G45(i915)) |
1378 | g45_hpd_peg_band_gap_wa(i915); |
1379 | |
1380 | /* HPD sense and interrupt enable are one and the same */ |
1381 | i915_hotplug_interrupt_update(dev_priv: i915, mask: hotplug_en, bits: hotplug_en); |
1382 | } |
1383 | |
1384 | static void i915_hpd_irq_setup(struct drm_i915_private *dev_priv) |
1385 | { |
1386 | u32 hotplug_en; |
1387 | |
1388 | lockdep_assert_held(&dev_priv->irq_lock); |
1389 | |
1390 | /* |
1391 | * Note HDMI and DP share hotplug bits. Enable bits are the same for all |
1392 | * generations. |
1393 | */ |
1394 | hotplug_en = intel_hpd_enabled_irqs(dev_priv, hpd: hpd_mask_i915); |
1395 | /* |
1396 | * Programming the CRT detection parameters tends to generate a spurious |
1397 | * hotplug event about three seconds later. So just do it once. |
1398 | */ |
1399 | if (IS_G4X(dev_priv)) |
1400 | hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; |
1401 | hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; |
1402 | |
1403 | if (IS_G45(dev_priv)) |
1404 | g45_hpd_peg_band_gap_wa(i915: dev_priv); |
1405 | |
1406 | /* Ignore TV since it's buggy */ |
1407 | i915_hotplug_interrupt_update_locked(dev_priv, |
1408 | HOTPLUG_INT_EN_MASK | |
1409 | CRT_HOTPLUG_VOLTAGE_COMPARE_MASK | |
1410 | CRT_HOTPLUG_ACTIVATION_PERIOD_64, |
1411 | bits: hotplug_en); |
1412 | } |
1413 | |
1414 | struct intel_hotplug_funcs { |
1415 | /* Enable HPD sense and interrupts for all present encoders */ |
1416 | void (*hpd_irq_setup)(struct drm_i915_private *i915); |
1417 | /* Enable HPD sense for a single encoder */ |
1418 | void (*hpd_enable_detection)(struct intel_encoder *encoder); |
1419 | }; |
1420 | |
1421 | #define HPD_FUNCS(platform) \ |
1422 | static const struct intel_hotplug_funcs platform##_hpd_funcs = { \ |
1423 | .hpd_irq_setup = platform##_hpd_irq_setup, \ |
1424 | .hpd_enable_detection = platform##_hpd_enable_detection, \ |
1425 | } |
1426 | |
1427 | HPD_FUNCS(i915); |
1428 | HPD_FUNCS(xelpdp); |
1429 | HPD_FUNCS(dg1); |
1430 | HPD_FUNCS(gen11); |
1431 | HPD_FUNCS(bxt); |
1432 | HPD_FUNCS(icp); |
1433 | HPD_FUNCS(spt); |
1434 | HPD_FUNCS(ilk); |
1435 | #undef HPD_FUNCS |
1436 | |
1437 | void intel_hpd_enable_detection(struct intel_encoder *encoder) |
1438 | { |
1439 | struct drm_i915_private *i915 = to_i915(dev: encoder->base.dev); |
1440 | |
1441 | if (i915->display.funcs.hotplug) |
1442 | i915->display.funcs.hotplug->hpd_enable_detection(encoder); |
1443 | } |
1444 | |
1445 | void intel_hpd_irq_setup(struct drm_i915_private *i915) |
1446 | { |
1447 | if (i915->display_irqs_enabled && i915->display.funcs.hotplug) |
1448 | i915->display.funcs.hotplug->hpd_irq_setup(i915); |
1449 | } |
1450 | |
1451 | void intel_hotplug_irq_init(struct drm_i915_private *i915) |
1452 | { |
1453 | intel_hpd_init_pins(dev_priv: i915); |
1454 | |
1455 | intel_hpd_init_early(i915); |
1456 | |
1457 | if (HAS_GMCH(i915)) { |
1458 | if (I915_HAS_HOTPLUG(i915)) |
1459 | i915->display.funcs.hotplug = &i915_hpd_funcs; |
1460 | } else { |
1461 | if (HAS_PCH_DG2(i915)) |
1462 | i915->display.funcs.hotplug = &icp_hpd_funcs; |
1463 | else if (HAS_PCH_DG1(i915)) |
1464 | i915->display.funcs.hotplug = &dg1_hpd_funcs; |
1465 | else if (DISPLAY_VER(i915) >= 14) |
1466 | i915->display.funcs.hotplug = &xelpdp_hpd_funcs; |
1467 | else if (DISPLAY_VER(i915) >= 11) |
1468 | i915->display.funcs.hotplug = &gen11_hpd_funcs; |
1469 | else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) |
1470 | i915->display.funcs.hotplug = &bxt_hpd_funcs; |
1471 | else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) |
1472 | i915->display.funcs.hotplug = &icp_hpd_funcs; |
1473 | else if (INTEL_PCH_TYPE(i915) >= PCH_SPT) |
1474 | i915->display.funcs.hotplug = &spt_hpd_funcs; |
1475 | else |
1476 | i915->display.funcs.hotplug = &ilk_hpd_funcs; |
1477 | } |
1478 | } |
1479 | |