8622ab107590c4b50d086f2833199744f651dd80
[cascardo/linux.git] / drivers / gpu / drm / i915 / intel_fifo_underrun.c
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 "intel_drv.h"
30
31 static bool ivb_can_enable_err_int(struct drm_device *dev)
32 {
33         struct drm_i915_private *dev_priv = dev->dev_private;
34         struct intel_crtc *crtc;
35         enum pipe pipe;
36
37         assert_spin_locked(&dev_priv->irq_lock);
38
39         for_each_pipe(dev_priv, pipe) {
40                 crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
41
42                 if (crtc->cpu_fifo_underrun_disabled)
43                         return false;
44         }
45
46         return true;
47 }
48
49 static bool cpt_can_enable_serr_int(struct drm_device *dev)
50 {
51         struct drm_i915_private *dev_priv = dev->dev_private;
52         enum pipe pipe;
53         struct intel_crtc *crtc;
54
55         assert_spin_locked(&dev_priv->irq_lock);
56
57         for_each_pipe(dev_priv, pipe) {
58                 crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
59
60                 if (crtc->pch_fifo_underrun_disabled)
61                         return false;
62         }
63
64         return true;
65 }
66
67 void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv)
68 {
69         struct intel_crtc *crtc;
70
71         spin_lock_irq(&dev_priv->irq_lock);
72
73         for_each_intel_crtc(dev_priv->dev, crtc) {
74                 u32 reg = PIPESTAT(crtc->pipe);
75                 u32 pipestat;
76
77                 if (crtc->cpu_fifo_underrun_disabled)
78                         continue;
79
80                 pipestat = I915_READ(reg) & 0xffff0000;
81                 if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0)
82                         continue;
83
84                 I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
85                 POSTING_READ(reg);
86
87                 DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
88         }
89
90         spin_unlock_irq(&dev_priv->irq_lock);
91 }
92
93 static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
94                                              enum pipe pipe,
95                                              bool enable, bool old)
96 {
97         struct drm_i915_private *dev_priv = dev->dev_private;
98         u32 reg = PIPESTAT(pipe);
99         u32 pipestat = I915_READ(reg) & 0xffff0000;
100
101         assert_spin_locked(&dev_priv->irq_lock);
102
103         if (enable) {
104                 I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
105                 POSTING_READ(reg);
106         } else {
107                 if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS)
108                         DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
109         }
110 }
111
112 static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
113                                                  enum pipe pipe, bool enable)
114 {
115         struct drm_i915_private *dev_priv = dev->dev_private;
116         uint32_t bit = (pipe == PIPE_A) ? DE_PIPEA_FIFO_UNDERRUN :
117                                           DE_PIPEB_FIFO_UNDERRUN;
118
119         if (enable)
120                 ironlake_enable_display_irq(dev_priv, bit);
121         else
122                 ironlake_disable_display_irq(dev_priv, bit);
123 }
124
125 static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
126                                                   enum pipe pipe,
127                                                   bool enable, bool old)
128 {
129         struct drm_i915_private *dev_priv = dev->dev_private;
130         if (enable) {
131                 I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
132
133                 if (!ivb_can_enable_err_int(dev))
134                         return;
135
136                 ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
137         } else {
138                 ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
139
140                 if (old &&
141                     I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
142                         DRM_ERROR("uncleared fifo underrun on pipe %c\n",
143                                   pipe_name(pipe));
144                 }
145         }
146 }
147
148 static void broadwell_set_fifo_underrun_reporting(struct drm_device *dev,
149                                                   enum pipe pipe, bool enable)
150 {
151         struct drm_i915_private *dev_priv = dev->dev_private;
152
153         assert_spin_locked(&dev_priv->irq_lock);
154
155         if (enable)
156                 dev_priv->de_irq_mask[pipe] &= ~GEN8_PIPE_FIFO_UNDERRUN;
157         else
158                 dev_priv->de_irq_mask[pipe] |= GEN8_PIPE_FIFO_UNDERRUN;
159         I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
160         POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
161 }
162
163 static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
164                                             enum transcoder pch_transcoder,
165                                             bool enable)
166 {
167         struct drm_i915_private *dev_priv = dev->dev_private;
168         uint32_t bit = (pch_transcoder == TRANSCODER_A) ?
169                        SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
170
171         if (enable)
172                 ibx_enable_display_interrupt(dev_priv, bit);
173         else
174                 ibx_disable_display_interrupt(dev_priv, bit);
175 }
176
177 static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
178                                             enum transcoder pch_transcoder,
179                                             bool enable, bool old)
180 {
181         struct drm_i915_private *dev_priv = dev->dev_private;
182
183         if (enable) {
184                 I915_WRITE(SERR_INT,
185                            SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
186
187                 if (!cpt_can_enable_serr_int(dev))
188                         return;
189
190                 ibx_enable_display_interrupt(dev_priv, SDE_ERROR_CPT);
191         } else {
192                 ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
193
194                 if (old && I915_READ(SERR_INT) &
195                     SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
196                         DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
197                                   transcoder_name(pch_transcoder));
198                 }
199         }
200 }
201
202 /**
203  * intel_set_cpu_fifo_underrun_reporting - enable/disable FIFO underrun messages
204  * @dev: drm device
205  * @pipe: pipe
206  * @enable: true if we want to report FIFO underrun errors, false otherwise
207  *
208  * This function makes us disable or enable CPU fifo underruns for a specific
209  * pipe. Notice that on some Gens (e.g. IVB, HSW), disabling FIFO underrun
210  * reporting for one pipe may also disable all the other CPU error interruts for
211  * the other pipes, due to the fact that there's just one interrupt mask/enable
212  * bit for all the pipes.
213  *
214  * Returns the previous state of underrun reporting.
215  */
216 static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
217                                                     enum pipe pipe, bool enable)
218 {
219         struct drm_i915_private *dev_priv = dev->dev_private;
220         struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
221         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
222         bool old;
223
224         assert_spin_locked(&dev_priv->irq_lock);
225
226         old = !intel_crtc->cpu_fifo_underrun_disabled;
227         intel_crtc->cpu_fifo_underrun_disabled = !enable;
228
229         if (HAS_GMCH_DISPLAY(dev))
230                 i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
231         else if (IS_GEN5(dev) || IS_GEN6(dev))
232                 ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
233         else if (IS_GEN7(dev))
234                 ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old);
235         else if (IS_GEN8(dev) || IS_GEN9(dev))
236                 broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
237
238         return old;
239 }
240
241 bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
242                                            enum pipe pipe, bool enable)
243 {
244         unsigned long flags;
245         bool ret;
246
247         spin_lock_irqsave(&dev_priv->irq_lock, flags);
248         ret = __intel_set_cpu_fifo_underrun_reporting(dev_priv->dev, pipe,
249                                                       enable);
250         spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
251
252         return ret;
253 }
254
255 static bool
256 __cpu_fifo_underrun_reporting_enabled(struct drm_i915_private *dev_priv,
257                                       enum pipe pipe)
258 {
259         struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
260         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
261
262         return !intel_crtc->cpu_fifo_underrun_disabled;
263 }
264
265 /**
266  * intel_set_pch_fifo_underrun_reporting - enable/disable FIFO underrun messages
267  * @dev: drm device
268  * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
269  * @enable: true if we want to report FIFO underrun errors, false otherwise
270  *
271  * This function makes us disable or enable PCH fifo underruns for a specific
272  * PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO
273  * underrun reporting for one transcoder may also disable all the other PCH
274  * error interruts for the other transcoders, due to the fact that there's just
275  * one interrupt mask/enable bit for all the transcoders.
276  *
277  * Returns the previous state of underrun reporting.
278  */
279 bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
280                                            enum transcoder pch_transcoder,
281                                            bool enable)
282 {
283         struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
284         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
285         unsigned long flags;
286         bool old;
287
288         /*
289          * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
290          * has only one pch transcoder A that all pipes can use. To avoid racy
291          * pch transcoder -> pipe lookups from interrupt code simply store the
292          * underrun statistics in crtc A. Since we never expose this anywhere
293          * nor use it outside of the fifo underrun code here using the "wrong"
294          * crtc on LPT won't cause issues.
295          */
296
297         spin_lock_irqsave(&dev_priv->irq_lock, flags);
298
299         old = !intel_crtc->pch_fifo_underrun_disabled;
300         intel_crtc->pch_fifo_underrun_disabled = !enable;
301
302         if (HAS_PCH_IBX(dev_priv->dev))
303                 ibx_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
304                                                 enable);
305         else
306                 cpt_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
307                                                 enable, old);
308
309         spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
310         return old;
311 }
312
313 void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
314                                          enum pipe pipe)
315 {
316         /* GMCH can't disable fifo underruns, filter them. */
317         if (HAS_GMCH_DISPLAY(dev_priv->dev) &&
318             !__cpu_fifo_underrun_reporting_enabled(dev_priv, pipe))
319                 return;
320
321         if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false))
322                 DRM_ERROR("CPU pipe %c FIFO underrun\n",
323                           pipe_name(pipe));
324 }
325
326 void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
327                                          enum transcoder pch_transcoder)
328 {
329         if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
330                                                   false))
331                 DRM_ERROR("PCH transcoder %c FIFO underrun\n",
332                           transcoder_name(pch_transcoder));
333 }