]> Git Repo - linux.git/blob - drivers/gpu/drm/omapdrm/omap_irq.c
drm: Add Grain Media GM12U320 driver v2
[linux.git] / drivers / gpu / drm / omapdrm / omap_irq.c
1 /*
2  * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
3  * Author: Rob Clark <[email protected]>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <drm/drm_vblank.h>
19
20 #include "omap_drv.h"
21
22 struct omap_irq_wait {
23         struct list_head node;
24         wait_queue_head_t wq;
25         u32 irqmask;
26         int count;
27 };
28
29 /* call with wait_lock and dispc runtime held */
30 static void omap_irq_update(struct drm_device *dev)
31 {
32         struct omap_drm_private *priv = dev->dev_private;
33         struct omap_irq_wait *wait;
34         u32 irqmask = priv->irq_mask;
35
36         assert_spin_locked(&priv->wait_lock);
37
38         list_for_each_entry(wait, &priv->wait_list, node)
39                 irqmask |= wait->irqmask;
40
41         DBG("irqmask=%08x", irqmask);
42
43         priv->dispc_ops->write_irqenable(priv->dispc, irqmask);
44 }
45
46 static void omap_irq_wait_handler(struct omap_irq_wait *wait)
47 {
48         wait->count--;
49         wake_up(&wait->wq);
50 }
51
52 struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
53                 u32 irqmask, int count)
54 {
55         struct omap_drm_private *priv = dev->dev_private;
56         struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
57         unsigned long flags;
58
59         init_waitqueue_head(&wait->wq);
60         wait->irqmask = irqmask;
61         wait->count = count;
62
63         spin_lock_irqsave(&priv->wait_lock, flags);
64         list_add(&wait->node, &priv->wait_list);
65         omap_irq_update(dev);
66         spin_unlock_irqrestore(&priv->wait_lock, flags);
67
68         return wait;
69 }
70
71 int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
72                 unsigned long timeout)
73 {
74         struct omap_drm_private *priv = dev->dev_private;
75         unsigned long flags;
76         int ret;
77
78         ret = wait_event_timeout(wait->wq, (wait->count <= 0), timeout);
79
80         spin_lock_irqsave(&priv->wait_lock, flags);
81         list_del(&wait->node);
82         omap_irq_update(dev);
83         spin_unlock_irqrestore(&priv->wait_lock, flags);
84
85         kfree(wait);
86
87         return ret == 0 ? -1 : 0;
88 }
89
90 int omap_irq_enable_framedone(struct drm_crtc *crtc, bool enable)
91 {
92         struct drm_device *dev = crtc->dev;
93         struct omap_drm_private *priv = dev->dev_private;
94         unsigned long flags;
95         enum omap_channel channel = omap_crtc_channel(crtc);
96         int framedone_irq =
97                 priv->dispc_ops->mgr_get_framedone_irq(priv->dispc, channel);
98
99         DBG("dev=%p, crtc=%u, enable=%d", dev, channel, enable);
100
101         spin_lock_irqsave(&priv->wait_lock, flags);
102         if (enable)
103                 priv->irq_mask |= framedone_irq;
104         else
105                 priv->irq_mask &= ~framedone_irq;
106         omap_irq_update(dev);
107         spin_unlock_irqrestore(&priv->wait_lock, flags);
108
109         return 0;
110 }
111
112 /**
113  * enable_vblank - enable vblank interrupt events
114  * @dev: DRM device
115  * @pipe: which irq to enable
116  *
117  * Enable vblank interrupts for @crtc.  If the device doesn't have
118  * a hardware vblank counter, this routine should be a no-op, since
119  * interrupts will have to stay on to keep the count accurate.
120  *
121  * RETURNS
122  * Zero on success, appropriate errno if the given @crtc's vblank
123  * interrupt cannot be enabled.
124  */
125 int omap_irq_enable_vblank(struct drm_crtc *crtc)
126 {
127         struct drm_device *dev = crtc->dev;
128         struct omap_drm_private *priv = dev->dev_private;
129         unsigned long flags;
130         enum omap_channel channel = omap_crtc_channel(crtc);
131
132         DBG("dev=%p, crtc=%u", dev, channel);
133
134         spin_lock_irqsave(&priv->wait_lock, flags);
135         priv->irq_mask |= priv->dispc_ops->mgr_get_vsync_irq(priv->dispc,
136                                                              channel);
137         omap_irq_update(dev);
138         spin_unlock_irqrestore(&priv->wait_lock, flags);
139
140         return 0;
141 }
142
143 /**
144  * disable_vblank - disable vblank interrupt events
145  * @dev: DRM device
146  * @pipe: which irq to enable
147  *
148  * Disable vblank interrupts for @crtc.  If the device doesn't have
149  * a hardware vblank counter, this routine should be a no-op, since
150  * interrupts will have to stay on to keep the count accurate.
151  */
152 void omap_irq_disable_vblank(struct drm_crtc *crtc)
153 {
154         struct drm_device *dev = crtc->dev;
155         struct omap_drm_private *priv = dev->dev_private;
156         unsigned long flags;
157         enum omap_channel channel = omap_crtc_channel(crtc);
158
159         DBG("dev=%p, crtc=%u", dev, channel);
160
161         spin_lock_irqsave(&priv->wait_lock, flags);
162         priv->irq_mask &= ~priv->dispc_ops->mgr_get_vsync_irq(priv->dispc,
163                                                               channel);
164         omap_irq_update(dev);
165         spin_unlock_irqrestore(&priv->wait_lock, flags);
166 }
167
168 static void omap_irq_fifo_underflow(struct omap_drm_private *priv,
169                                     u32 irqstatus)
170 {
171         static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
172                                       DEFAULT_RATELIMIT_BURST);
173         static const struct {
174                 const char *name;
175                 u32 mask;
176         } sources[] = {
177                 { "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW },
178                 { "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW },
179                 { "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW },
180                 { "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW },
181         };
182
183         const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW
184                        | DISPC_IRQ_VID1_FIFO_UNDERFLOW
185                        | DISPC_IRQ_VID2_FIFO_UNDERFLOW
186                        | DISPC_IRQ_VID3_FIFO_UNDERFLOW;
187         unsigned int i;
188
189         spin_lock(&priv->wait_lock);
190         irqstatus &= priv->irq_mask & mask;
191         spin_unlock(&priv->wait_lock);
192
193         if (!irqstatus)
194                 return;
195
196         if (!__ratelimit(&_rs))
197                 return;
198
199         DRM_ERROR("FIFO underflow on ");
200
201         for (i = 0; i < ARRAY_SIZE(sources); ++i) {
202                 if (sources[i].mask & irqstatus)
203                         pr_cont("%s ", sources[i].name);
204         }
205
206         pr_cont("(0x%08x)\n", irqstatus);
207 }
208
209 static void omap_irq_ocp_error_handler(struct drm_device *dev,
210         u32 irqstatus)
211 {
212         if (!(irqstatus & DISPC_IRQ_OCP_ERR))
213                 return;
214
215         dev_err_ratelimited(dev->dev, "OCP error\n");
216 }
217
218 static irqreturn_t omap_irq_handler(int irq, void *arg)
219 {
220         struct drm_device *dev = (struct drm_device *) arg;
221         struct omap_drm_private *priv = dev->dev_private;
222         struct omap_irq_wait *wait, *n;
223         unsigned long flags;
224         unsigned int id;
225         u32 irqstatus;
226
227         irqstatus = priv->dispc_ops->read_irqstatus(priv->dispc);
228         priv->dispc_ops->clear_irqstatus(priv->dispc, irqstatus);
229         priv->dispc_ops->read_irqstatus(priv->dispc);   /* flush posted write */
230
231         VERB("irqs: %08x", irqstatus);
232
233         for (id = 0; id < priv->num_pipes; id++) {
234                 struct drm_crtc *crtc = priv->pipes[id].crtc;
235                 enum omap_channel channel = omap_crtc_channel(crtc);
236
237                 if (irqstatus & priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, channel)) {
238                         drm_handle_vblank(dev, id);
239                         omap_crtc_vblank_irq(crtc);
240                 }
241
242                 if (irqstatus & priv->dispc_ops->mgr_get_sync_lost_irq(priv->dispc, channel))
243                         omap_crtc_error_irq(crtc, irqstatus);
244
245                 if (irqstatus & priv->dispc_ops->mgr_get_framedone_irq(priv->dispc, channel))
246                         omap_crtc_framedone_irq(crtc, irqstatus);
247         }
248
249         omap_irq_ocp_error_handler(dev, irqstatus);
250         omap_irq_fifo_underflow(priv, irqstatus);
251
252         spin_lock_irqsave(&priv->wait_lock, flags);
253         list_for_each_entry_safe(wait, n, &priv->wait_list, node) {
254                 if (wait->irqmask & irqstatus)
255                         omap_irq_wait_handler(wait);
256         }
257         spin_unlock_irqrestore(&priv->wait_lock, flags);
258
259         return IRQ_HANDLED;
260 }
261
262 static const u32 omap_underflow_irqs[] = {
263         [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
264         [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
265         [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
266         [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
267 };
268
269 /*
270  * We need a special version, instead of just using drm_irq_install(),
271  * because we need to register the irq via omapdss.  Once omapdss and
272  * omapdrm are merged together we can assign the dispc hwmod data to
273  * ourselves and drop these and just use drm_irq_{install,uninstall}()
274  */
275
276 int omap_drm_irq_install(struct drm_device *dev)
277 {
278         struct omap_drm_private *priv = dev->dev_private;
279         unsigned int num_mgrs = priv->dispc_ops->get_num_mgrs(priv->dispc);
280         unsigned int max_planes;
281         unsigned int i;
282         int ret;
283
284         spin_lock_init(&priv->wait_lock);
285         INIT_LIST_HEAD(&priv->wait_list);
286
287         priv->irq_mask = DISPC_IRQ_OCP_ERR;
288
289         max_planes = min(ARRAY_SIZE(priv->planes),
290                          ARRAY_SIZE(omap_underflow_irqs));
291         for (i = 0; i < max_planes; ++i) {
292                 if (priv->planes[i])
293                         priv->irq_mask |= omap_underflow_irqs[i];
294         }
295
296         for (i = 0; i < num_mgrs; ++i)
297                 priv->irq_mask |= priv->dispc_ops->mgr_get_sync_lost_irq(priv->dispc, i);
298
299         priv->dispc_ops->runtime_get(priv->dispc);
300         priv->dispc_ops->clear_irqstatus(priv->dispc, 0xffffffff);
301         priv->dispc_ops->runtime_put(priv->dispc);
302
303         ret = priv->dispc_ops->request_irq(priv->dispc, omap_irq_handler, dev);
304         if (ret < 0)
305                 return ret;
306
307         dev->irq_enabled = true;
308
309         return 0;
310 }
311
312 void omap_drm_irq_uninstall(struct drm_device *dev)
313 {
314         struct omap_drm_private *priv = dev->dev_private;
315
316         if (!dev->irq_enabled)
317                 return;
318
319         dev->irq_enabled = false;
320
321         priv->dispc_ops->free_irq(priv->dispc, dev);
322 }
This page took 0.05178 seconds and 4 git commands to generate.