1 | /* |
2 | * Copyright © 2014 Intel Corporation |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
11 | * The above copyright notice and this permission notice (including the next |
12 | * paragraph) shall be included in all copies or substantial portions of the |
13 | * Software. |
14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
21 | * IN THE SOFTWARE. |
22 | * |
23 | * Authors: |
24 | * Daniel Vetter <daniel.vetter@ffwll.ch> |
25 | * |
26 | */ |
27 | |
28 | #include "i915_drv.h" |
29 | #include "i915_reg.h" |
30 | #include "intel_de.h" |
31 | #include "intel_display_irq.h" |
32 | #include "intel_display_trace.h" |
33 | #include "intel_display_types.h" |
34 | #include "intel_fbc.h" |
35 | #include "intel_fifo_underrun.h" |
36 | #include "intel_pch_display.h" |
37 | |
38 | /** |
39 | * DOC: fifo underrun handling |
40 | * |
41 | * The i915 driver checks for display fifo underruns using the interrupt signals |
42 | * provided by the hardware. This is enabled by default and fairly useful to |
43 | * debug display issues, especially watermark settings. |
44 | * |
45 | * If an underrun is detected this is logged into dmesg. To avoid flooding logs |
46 | * and occupying the cpu underrun interrupts are disabled after the first |
47 | * occurrence until the next modeset on a given pipe. |
48 | * |
49 | * Note that underrun detection on gmch platforms is a bit more ugly since there |
50 | * is no interrupt (despite that the signalling bit is in the PIPESTAT pipe |
51 | * interrupt register). Also on some other platforms underrun interrupts are |
52 | * shared, which means that if we detect an underrun we need to disable underrun |
53 | * reporting on all pipes. |
54 | * |
55 | * The code also supports underrun detection on the PCH transcoder. |
56 | */ |
57 | |
58 | static bool ivb_can_enable_err_int(struct drm_device *dev) |
59 | { |
60 | struct drm_i915_private *dev_priv = to_i915(dev); |
61 | struct intel_crtc *crtc; |
62 | enum pipe pipe; |
63 | |
64 | lockdep_assert_held(&dev_priv->irq_lock); |
65 | |
66 | for_each_pipe(dev_priv, pipe) { |
67 | crtc = intel_crtc_for_pipe(i915: dev_priv, pipe); |
68 | |
69 | if (crtc->cpu_fifo_underrun_disabled) |
70 | return false; |
71 | } |
72 | |
73 | return true; |
74 | } |
75 | |
76 | static bool cpt_can_enable_serr_int(struct drm_device *dev) |
77 | { |
78 | struct drm_i915_private *dev_priv = to_i915(dev); |
79 | enum pipe pipe; |
80 | struct intel_crtc *crtc; |
81 | |
82 | lockdep_assert_held(&dev_priv->irq_lock); |
83 | |
84 | for_each_pipe(dev_priv, pipe) { |
85 | crtc = intel_crtc_for_pipe(i915: dev_priv, pipe); |
86 | |
87 | if (crtc->pch_fifo_underrun_disabled) |
88 | return false; |
89 | } |
90 | |
91 | return true; |
92 | } |
93 | |
94 | static void i9xx_check_fifo_underruns(struct intel_crtc *crtc) |
95 | { |
96 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
97 | i915_reg_t reg = PIPESTAT(crtc->pipe); |
98 | u32 enable_mask; |
99 | |
100 | lockdep_assert_held(&dev_priv->irq_lock); |
101 | |
102 | if ((intel_de_read(i915: dev_priv, reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0) |
103 | return; |
104 | |
105 | enable_mask = i915_pipestat_enable_mask(i915: dev_priv, pipe: crtc->pipe); |
106 | intel_de_write(i915: dev_priv, reg, val: enable_mask | PIPE_FIFO_UNDERRUN_STATUS); |
107 | intel_de_posting_read(i915: dev_priv, reg); |
108 | |
109 | trace_intel_cpu_fifo_underrun(dev_priv, pipe: crtc->pipe); |
110 | drm_err(&dev_priv->drm, "pipe %c underrun\n" , pipe_name(crtc->pipe)); |
111 | } |
112 | |
113 | static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, |
114 | enum pipe pipe, |
115 | bool enable, bool old) |
116 | { |
117 | struct drm_i915_private *dev_priv = to_i915(dev); |
118 | i915_reg_t reg = PIPESTAT(pipe); |
119 | |
120 | lockdep_assert_held(&dev_priv->irq_lock); |
121 | |
122 | if (enable) { |
123 | u32 enable_mask = i915_pipestat_enable_mask(i915: dev_priv, pipe); |
124 | |
125 | intel_de_write(i915: dev_priv, reg, |
126 | val: enable_mask | PIPE_FIFO_UNDERRUN_STATUS); |
127 | intel_de_posting_read(i915: dev_priv, reg); |
128 | } else { |
129 | if (old && intel_de_read(i915: dev_priv, reg) & PIPE_FIFO_UNDERRUN_STATUS) |
130 | drm_err(&dev_priv->drm, "pipe %c underrun\n" , |
131 | pipe_name(pipe)); |
132 | } |
133 | } |
134 | |
135 | static void ilk_set_fifo_underrun_reporting(struct drm_device *dev, |
136 | enum pipe pipe, bool enable) |
137 | { |
138 | struct drm_i915_private *dev_priv = to_i915(dev); |
139 | u32 bit = (pipe == PIPE_A) ? |
140 | DE_PIPEA_FIFO_UNDERRUN : DE_PIPEB_FIFO_UNDERRUN; |
141 | |
142 | if (enable) |
143 | ilk_enable_display_irq(i915: dev_priv, bits: bit); |
144 | else |
145 | ilk_disable_display_irq(i915: dev_priv, bits: bit); |
146 | } |
147 | |
148 | static void ivb_check_fifo_underruns(struct intel_crtc *crtc) |
149 | { |
150 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
151 | enum pipe pipe = crtc->pipe; |
152 | u32 err_int = intel_de_read(i915: dev_priv, GEN7_ERR_INT); |
153 | |
154 | lockdep_assert_held(&dev_priv->irq_lock); |
155 | |
156 | if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0) |
157 | return; |
158 | |
159 | intel_de_write(i915: dev_priv, GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe)); |
160 | intel_de_posting_read(i915: dev_priv, GEN7_ERR_INT); |
161 | |
162 | trace_intel_cpu_fifo_underrun(dev_priv, pipe); |
163 | drm_err(&dev_priv->drm, "fifo underrun on pipe %c\n" , pipe_name(pipe)); |
164 | } |
165 | |
166 | static void ivb_set_fifo_underrun_reporting(struct drm_device *dev, |
167 | enum pipe pipe, bool enable, |
168 | bool old) |
169 | { |
170 | struct drm_i915_private *dev_priv = to_i915(dev); |
171 | if (enable) { |
172 | intel_de_write(i915: dev_priv, GEN7_ERR_INT, |
173 | ERR_INT_FIFO_UNDERRUN(pipe)); |
174 | |
175 | if (!ivb_can_enable_err_int(dev)) |
176 | return; |
177 | |
178 | ilk_enable_display_irq(i915: dev_priv, DE_ERR_INT_IVB); |
179 | } else { |
180 | ilk_disable_display_irq(i915: dev_priv, DE_ERR_INT_IVB); |
181 | |
182 | if (old && |
183 | intel_de_read(i915: dev_priv, GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) { |
184 | drm_err(&dev_priv->drm, |
185 | "uncleared fifo underrun on pipe %c\n" , |
186 | pipe_name(pipe)); |
187 | } |
188 | } |
189 | } |
190 | |
191 | static u32 |
192 | icl_pipe_status_underrun_mask(struct drm_i915_private *dev_priv) |
193 | { |
194 | u32 mask = PIPE_STATUS_UNDERRUN; |
195 | |
196 | if (DISPLAY_VER(dev_priv) >= 13) |
197 | mask |= PIPE_STATUS_SOFT_UNDERRUN_XELPD | |
198 | PIPE_STATUS_HARD_UNDERRUN_XELPD | |
199 | PIPE_STATUS_PORT_UNDERRUN_XELPD; |
200 | |
201 | return mask; |
202 | } |
203 | |
204 | static void bdw_set_fifo_underrun_reporting(struct drm_device *dev, |
205 | enum pipe pipe, bool enable) |
206 | { |
207 | struct drm_i915_private *dev_priv = to_i915(dev); |
208 | u32 mask = gen8_de_pipe_underrun_mask(i915: dev_priv); |
209 | |
210 | if (enable) { |
211 | if (DISPLAY_VER(dev_priv) >= 11) |
212 | intel_de_write(i915: dev_priv, ICL_PIPESTATUS(pipe), |
213 | val: icl_pipe_status_underrun_mask(dev_priv)); |
214 | |
215 | bdw_enable_pipe_irq(i915: dev_priv, pipe, bits: mask); |
216 | } else { |
217 | bdw_disable_pipe_irq(i915: dev_priv, pipe, bits: mask); |
218 | } |
219 | } |
220 | |
221 | static void ibx_set_fifo_underrun_reporting(struct drm_device *dev, |
222 | enum pipe pch_transcoder, |
223 | bool enable) |
224 | { |
225 | struct drm_i915_private *dev_priv = to_i915(dev); |
226 | u32 bit = (pch_transcoder == PIPE_A) ? |
227 | SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER; |
228 | |
229 | if (enable) |
230 | ibx_enable_display_interrupt(i915: dev_priv, bits: bit); |
231 | else |
232 | ibx_disable_display_interrupt(i915: dev_priv, bits: bit); |
233 | } |
234 | |
235 | static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc) |
236 | { |
237 | struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev); |
238 | enum pipe pch_transcoder = crtc->pipe; |
239 | u32 serr_int = intel_de_read(i915: dev_priv, SERR_INT); |
240 | |
241 | lockdep_assert_held(&dev_priv->irq_lock); |
242 | |
243 | if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0) |
244 | return; |
245 | |
246 | intel_de_write(i915: dev_priv, SERR_INT, |
247 | SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)); |
248 | intel_de_posting_read(i915: dev_priv, SERR_INT); |
249 | |
250 | trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder); |
251 | drm_err(&dev_priv->drm, "pch fifo underrun on pch transcoder %c\n" , |
252 | pipe_name(pch_transcoder)); |
253 | } |
254 | |
255 | static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, |
256 | enum pipe pch_transcoder, |
257 | bool enable, bool old) |
258 | { |
259 | struct drm_i915_private *dev_priv = to_i915(dev); |
260 | |
261 | if (enable) { |
262 | intel_de_write(i915: dev_priv, SERR_INT, |
263 | SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)); |
264 | |
265 | if (!cpt_can_enable_serr_int(dev)) |
266 | return; |
267 | |
268 | ibx_enable_display_interrupt(i915: dev_priv, SDE_ERROR_CPT); |
269 | } else { |
270 | ibx_disable_display_interrupt(i915: dev_priv, SDE_ERROR_CPT); |
271 | |
272 | if (old && intel_de_read(i915: dev_priv, SERR_INT) & |
273 | SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) { |
274 | drm_err(&dev_priv->drm, |
275 | "uncleared pch fifo underrun on pch transcoder %c\n" , |
276 | pipe_name(pch_transcoder)); |
277 | } |
278 | } |
279 | } |
280 | |
281 | static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, |
282 | enum pipe pipe, bool enable) |
283 | { |
284 | struct drm_i915_private *dev_priv = to_i915(dev); |
285 | struct intel_crtc *crtc = intel_crtc_for_pipe(i915: dev_priv, pipe); |
286 | bool old; |
287 | |
288 | lockdep_assert_held(&dev_priv->irq_lock); |
289 | |
290 | old = !crtc->cpu_fifo_underrun_disabled; |
291 | crtc->cpu_fifo_underrun_disabled = !enable; |
292 | |
293 | if (HAS_GMCH(dev_priv)) |
294 | i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old); |
295 | else if (IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv)) |
296 | ilk_set_fifo_underrun_reporting(dev, pipe, enable); |
297 | else if (DISPLAY_VER(dev_priv) == 7) |
298 | ivb_set_fifo_underrun_reporting(dev, pipe, enable, old); |
299 | else if (DISPLAY_VER(dev_priv) >= 8) |
300 | bdw_set_fifo_underrun_reporting(dev, pipe, enable); |
301 | |
302 | return old; |
303 | } |
304 | |
305 | /** |
306 | * intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrrun reporting state |
307 | * @dev_priv: i915 device instance |
308 | * @pipe: (CPU) pipe to set state for |
309 | * @enable: whether underruns should be reported or not |
310 | * |
311 | * This function sets the fifo underrun state for @pipe. It is used in the |
312 | * modeset code to avoid false positives since on many platforms underruns are |
313 | * expected when disabling or enabling the pipe. |
314 | * |
315 | * Notice that on some platforms disabling underrun reports for one pipe |
316 | * disables for all due to shared interrupts. Actual reporting is still per-pipe |
317 | * though. |
318 | * |
319 | * Returns the previous state of underrun reporting. |
320 | */ |
321 | bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv, |
322 | enum pipe pipe, bool enable) |
323 | { |
324 | unsigned long flags; |
325 | bool ret; |
326 | |
327 | spin_lock_irqsave(&dev_priv->irq_lock, flags); |
328 | ret = __intel_set_cpu_fifo_underrun_reporting(dev: &dev_priv->drm, pipe, |
329 | enable); |
330 | spin_unlock_irqrestore(lock: &dev_priv->irq_lock, flags); |
331 | |
332 | return ret; |
333 | } |
334 | |
335 | /** |
336 | * intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state |
337 | * @dev_priv: i915 device instance |
338 | * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older) |
339 | * @enable: whether underruns should be reported or not |
340 | * |
341 | * This function makes us disable or enable PCH fifo underruns for a specific |
342 | * PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO |
343 | * underrun reporting for one transcoder may also disable all the other PCH |
344 | * error interruts for the other transcoders, due to the fact that there's just |
345 | * one interrupt mask/enable bit for all the transcoders. |
346 | * |
347 | * Returns the previous state of underrun reporting. |
348 | */ |
349 | bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv, |
350 | enum pipe pch_transcoder, |
351 | bool enable) |
352 | { |
353 | struct intel_crtc *crtc = |
354 | intel_crtc_for_pipe(i915: dev_priv, pipe: pch_transcoder); |
355 | unsigned long flags; |
356 | bool old; |
357 | |
358 | /* |
359 | * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT |
360 | * has only one pch transcoder A that all pipes can use. To avoid racy |
361 | * pch transcoder -> pipe lookups from interrupt code simply store the |
362 | * underrun statistics in crtc A. Since we never expose this anywhere |
363 | * nor use it outside of the fifo underrun code here using the "wrong" |
364 | * crtc on LPT won't cause issues. |
365 | */ |
366 | |
367 | spin_lock_irqsave(&dev_priv->irq_lock, flags); |
368 | |
369 | old = !crtc->pch_fifo_underrun_disabled; |
370 | crtc->pch_fifo_underrun_disabled = !enable; |
371 | |
372 | if (HAS_PCH_IBX(dev_priv)) |
373 | ibx_set_fifo_underrun_reporting(dev: &dev_priv->drm, |
374 | pch_transcoder, |
375 | enable); |
376 | else |
377 | cpt_set_fifo_underrun_reporting(dev: &dev_priv->drm, |
378 | pch_transcoder, |
379 | enable, old); |
380 | |
381 | spin_unlock_irqrestore(lock: &dev_priv->irq_lock, flags); |
382 | return old; |
383 | } |
384 | |
385 | /** |
386 | * intel_cpu_fifo_underrun_irq_handler - handle CPU fifo underrun interrupt |
387 | * @dev_priv: i915 device instance |
388 | * @pipe: (CPU) pipe to set state for |
389 | * |
390 | * This handles a CPU fifo underrun interrupt, generating an underrun warning |
391 | * into dmesg if underrun reporting is enabled and then disables the underrun |
392 | * interrupt to avoid an irq storm. |
393 | */ |
394 | void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, |
395 | enum pipe pipe) |
396 | { |
397 | struct intel_crtc *crtc = intel_crtc_for_pipe(i915: dev_priv, pipe); |
398 | u32 underruns = 0; |
399 | |
400 | /* We may be called too early in init, thanks BIOS! */ |
401 | if (crtc == NULL) |
402 | return; |
403 | |
404 | /* GMCH can't disable fifo underruns, filter them. */ |
405 | if (HAS_GMCH(dev_priv) && |
406 | crtc->cpu_fifo_underrun_disabled) |
407 | return; |
408 | |
409 | /* |
410 | * Starting with display version 11, the PIPE_STAT register records |
411 | * whether an underrun has happened, and on XELPD+, it will also record |
412 | * whether the underrun was soft/hard and whether it was triggered by |
413 | * the downstream port logic. We should clear these bits (which use |
414 | * write-1-to-clear logic) too. |
415 | * |
416 | * Note that although the IIR gives us the same underrun and soft/hard |
417 | * information, PIPE_STAT is the only place we can find out whether |
418 | * the underrun was caused by the downstream port. |
419 | */ |
420 | if (DISPLAY_VER(dev_priv) >= 11) { |
421 | underruns = intel_de_read(i915: dev_priv, ICL_PIPESTATUS(pipe)) & |
422 | icl_pipe_status_underrun_mask(dev_priv); |
423 | intel_de_write(i915: dev_priv, ICL_PIPESTATUS(pipe), val: underruns); |
424 | } |
425 | |
426 | if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, enable: false)) { |
427 | trace_intel_cpu_fifo_underrun(dev_priv, pipe); |
428 | |
429 | if (DISPLAY_VER(dev_priv) >= 11) |
430 | drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun: %s%s%s%s\n" , |
431 | pipe_name(pipe), |
432 | underruns & PIPE_STATUS_SOFT_UNDERRUN_XELPD ? "soft," : "" , |
433 | underruns & PIPE_STATUS_HARD_UNDERRUN_XELPD ? "hard," : "" , |
434 | underruns & PIPE_STATUS_PORT_UNDERRUN_XELPD ? "port," : "" , |
435 | underruns & PIPE_STATUS_UNDERRUN ? "transcoder," : "" ); |
436 | else |
437 | drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n" , pipe_name(pipe)); |
438 | } |
439 | |
440 | intel_fbc_handle_fifo_underrun_irq(i915: dev_priv); |
441 | } |
442 | |
443 | /** |
444 | * intel_pch_fifo_underrun_irq_handler - handle PCH fifo underrun interrupt |
445 | * @dev_priv: i915 device instance |
446 | * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older) |
447 | * |
448 | * This handles a PCH fifo underrun interrupt, generating an underrun warning |
449 | * into dmesg if underrun reporting is enabled and then disables the underrun |
450 | * interrupt to avoid an irq storm. |
451 | */ |
452 | void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, |
453 | enum pipe pch_transcoder) |
454 | { |
455 | if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, |
456 | enable: false)) { |
457 | trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder); |
458 | drm_err(&dev_priv->drm, "PCH transcoder %c FIFO underrun\n" , |
459 | pipe_name(pch_transcoder)); |
460 | } |
461 | } |
462 | |
463 | /** |
464 | * intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately |
465 | * @dev_priv: i915 device instance |
466 | * |
467 | * Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared |
468 | * error interrupt may have been disabled, and so CPU fifo underruns won't |
469 | * necessarily raise an interrupt, and on GMCH platforms where underruns never |
470 | * raise an interrupt. |
471 | */ |
472 | void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv) |
473 | { |
474 | struct intel_crtc *crtc; |
475 | |
476 | spin_lock_irq(lock: &dev_priv->irq_lock); |
477 | |
478 | for_each_intel_crtc(&dev_priv->drm, crtc) { |
479 | if (crtc->cpu_fifo_underrun_disabled) |
480 | continue; |
481 | |
482 | if (HAS_GMCH(dev_priv)) |
483 | i9xx_check_fifo_underruns(crtc); |
484 | else if (DISPLAY_VER(dev_priv) == 7) |
485 | ivb_check_fifo_underruns(crtc); |
486 | } |
487 | |
488 | spin_unlock_irq(lock: &dev_priv->irq_lock); |
489 | } |
490 | |
491 | /** |
492 | * intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately |
493 | * @dev_priv: i915 device instance |
494 | * |
495 | * Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared |
496 | * error interrupt may have been disabled, and so PCH fifo underruns won't |
497 | * necessarily raise an interrupt. |
498 | */ |
499 | void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv) |
500 | { |
501 | struct intel_crtc *crtc; |
502 | |
503 | spin_lock_irq(lock: &dev_priv->irq_lock); |
504 | |
505 | for_each_intel_crtc(&dev_priv->drm, crtc) { |
506 | if (crtc->pch_fifo_underrun_disabled) |
507 | continue; |
508 | |
509 | if (HAS_PCH_CPT(dev_priv)) |
510 | cpt_check_pch_fifo_underruns(crtc); |
511 | } |
512 | |
513 | spin_unlock_irq(lock: &dev_priv->irq_lock); |
514 | } |
515 | |
516 | void intel_init_fifo_underrun_reporting(struct drm_i915_private *i915, |
517 | struct intel_crtc *crtc, |
518 | bool enable) |
519 | { |
520 | crtc->cpu_fifo_underrun_disabled = !enable; |
521 | |
522 | /* |
523 | * We track the PCH trancoder underrun reporting state |
524 | * within the crtc. With crtc for pipe A housing the underrun |
525 | * reporting state for PCH transcoder A, crtc for pipe B housing |
526 | * it for PCH transcoder B, etc. LPT-H has only PCH transcoder A, |
527 | * and marking underrun reporting as disabled for the non-existing |
528 | * PCH transcoders B and C would prevent enabling the south |
529 | * error interrupt (see cpt_can_enable_serr_int()). |
530 | */ |
531 | if (intel_has_pch_trancoder(i915, pch_transcoder: crtc->pipe)) |
532 | crtc->pch_fifo_underrun_disabled = !enable; |
533 | } |
534 | |