aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_irq.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2015-05-27 17:21:29 -0400
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2016-12-19 04:24:56 -0500
commit728ae8dd696a483355b593487eba73f4c64f1152 (patch)
tree71f69575be8ded505985561a294b9b3b64908c33 /drivers/gpu/drm/omapdrm/omap_irq.c
parenta078a3ddc7209474e8dd827743390e9ed4bc6881 (diff)
drm: omapdrm: Handle FIFO underflow IRQs internally
As the FIFO underflow IRQ handler just prints an error message to the kernel log, simplify the code by not registering one IRQ handler per plane but print the messages directly from the main IRQ handler. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_irq.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_irq.c67
1 files changed, 64 insertions, 3 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 60e1e8016708..57a2de7e0d7b 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -32,7 +32,7 @@ static void omap_irq_update(struct drm_device *dev)
32{ 32{
33 struct omap_drm_private *priv = dev->dev_private; 33 struct omap_drm_private *priv = dev->dev_private;
34 struct omap_drm_irq *irq; 34 struct omap_drm_irq *irq;
35 uint32_t irqmask = priv->vblank_mask; 35 uint32_t irqmask = priv->irq_mask;
36 36
37 assert_spin_locked(&list_lock); 37 assert_spin_locked(&list_lock);
38 38
@@ -153,7 +153,7 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe)
153 DBG("dev=%p, crtc=%u", dev, pipe); 153 DBG("dev=%p, crtc=%u", dev, pipe);
154 154
155 spin_lock_irqsave(&list_lock, flags); 155 spin_lock_irqsave(&list_lock, flags);
156 priv->vblank_mask |= pipe2vbl(crtc); 156 priv->irq_mask |= pipe2vbl(crtc);
157 omap_irq_update(dev); 157 omap_irq_update(dev);
158 spin_unlock_irqrestore(&list_lock, flags); 158 spin_unlock_irqrestore(&list_lock, flags);
159 159
@@ -178,11 +178,52 @@ void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe)
178 DBG("dev=%p, crtc=%u", dev, pipe); 178 DBG("dev=%p, crtc=%u", dev, pipe);
179 179
180 spin_lock_irqsave(&list_lock, flags); 180 spin_lock_irqsave(&list_lock, flags);
181 priv->vblank_mask &= ~pipe2vbl(crtc); 181 priv->irq_mask &= ~pipe2vbl(crtc);
182 omap_irq_update(dev); 182 omap_irq_update(dev);
183 spin_unlock_irqrestore(&list_lock, flags); 183 spin_unlock_irqrestore(&list_lock, flags);
184} 184}
185 185
186static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
187 u32 irqstatus)
188{
189 static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
190 DEFAULT_RATELIMIT_BURST);
191 static const struct {
192 const char *name;
193 u32 mask;
194 } sources[] = {
195 { "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW },
196 { "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW },
197 { "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW },
198 { "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW },
199 };
200
201 const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW
202 | DISPC_IRQ_VID1_FIFO_UNDERFLOW
203 | DISPC_IRQ_VID2_FIFO_UNDERFLOW
204 | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
205 unsigned int i;
206
207 spin_lock(&list_lock);
208 irqstatus &= priv->irq_mask & mask;
209 spin_unlock(&list_lock);
210
211 if (!irqstatus)
212 return;
213
214 if (!__ratelimit(&_rs))
215 return;
216
217 DRM_ERROR("FIFO underflow on ");
218
219 for (i = 0; i < ARRAY_SIZE(sources); ++i) {
220 if (sources[i].mask & irqstatus)
221 pr_cont("%s ", sources[i].name);
222 }
223
224 pr_cont("(0x%08x)\n", irqstatus);
225}
226
186static irqreturn_t omap_irq_handler(int irq, void *arg) 227static irqreturn_t omap_irq_handler(int irq, void *arg)
187{ 228{
188 struct drm_device *dev = (struct drm_device *) arg; 229 struct drm_device *dev = (struct drm_device *) arg;
@@ -205,6 +246,8 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
205 drm_handle_vblank(dev, id); 246 drm_handle_vblank(dev, id);
206 } 247 }
207 248
249 omap_irq_fifo_underflow(priv, irqstatus);
250
208 spin_lock_irqsave(&list_lock, flags); 251 spin_lock_irqsave(&list_lock, flags);
209 list_for_each_entry_safe(handler, n, &priv->irq_list, node) { 252 list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
210 if (handler->irqmask & irqstatus) { 253 if (handler->irqmask & irqstatus) {
@@ -218,6 +261,13 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
218 return IRQ_HANDLED; 261 return IRQ_HANDLED;
219} 262}
220 263
264static const u32 omap_underflow_irqs[] = {
265 [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
266 [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
267 [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
268 [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
269};
270
221/* 271/*
222 * We need a special version, instead of just using drm_irq_install(), 272 * We need a special version, instead of just using drm_irq_install(),
223 * because we need to register the irq via omapdss. Once omapdss and 273 * because we need to register the irq via omapdss. Once omapdss and
@@ -229,10 +279,21 @@ int omap_drm_irq_install(struct drm_device *dev)
229{ 279{
230 struct omap_drm_private *priv = dev->dev_private; 280 struct omap_drm_private *priv = dev->dev_private;
231 struct omap_drm_irq *error_handler = &priv->error_handler; 281 struct omap_drm_irq *error_handler = &priv->error_handler;
282 unsigned int max_planes;
283 unsigned int i;
232 int ret; 284 int ret;
233 285
234 INIT_LIST_HEAD(&priv->irq_list); 286 INIT_LIST_HEAD(&priv->irq_list);
235 287
288 priv->irq_mask = 0;
289
290 max_planes = min(ARRAY_SIZE(priv->planes),
291 ARRAY_SIZE(omap_underflow_irqs));
292 for (i = 0; i < max_planes; ++i) {
293 if (priv->planes[i])
294 priv->irq_mask |= omap_underflow_irqs[i];
295 }
296
236 dispc_runtime_get(); 297 dispc_runtime_get();
237 dispc_clear_irqstatus(0xffffffff); 298 dispc_clear_irqstatus(0xffffffff);
238 dispc_runtime_put(); 299 dispc_runtime_put();