2 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
3 * Author: Rob Clark <rob.clark@linaro.org>
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.
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
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/>.
20 struct omap_irq_wait
{
21 struct list_head node
;
27 /* call with wait_lock and dispc runtime held */
28 static void omap_irq_update(struct drm_device
*dev
)
30 struct omap_drm_private
*priv
= dev
->dev_private
;
31 struct omap_irq_wait
*wait
;
32 u32 irqmask
= priv
->irq_mask
;
34 assert_spin_locked(&priv
->wait_lock
);
36 list_for_each_entry(wait
, &priv
->wait_list
, node
)
37 irqmask
|= wait
->irqmask
;
39 DBG("irqmask=%08x", irqmask
);
41 priv
->dispc_ops
->write_irqenable(priv
->dispc
, irqmask
);
44 static void omap_irq_wait_handler(struct omap_irq_wait
*wait
)
50 struct omap_irq_wait
* omap_irq_wait_init(struct drm_device
*dev
,
51 u32 irqmask
, int count
)
53 struct omap_drm_private
*priv
= dev
->dev_private
;
54 struct omap_irq_wait
*wait
= kzalloc(sizeof(*wait
), GFP_KERNEL
);
57 init_waitqueue_head(&wait
->wq
);
58 wait
->irqmask
= irqmask
;
61 spin_lock_irqsave(&priv
->wait_lock
, flags
);
62 list_add(&wait
->node
, &priv
->wait_list
);
64 spin_unlock_irqrestore(&priv
->wait_lock
, flags
);
69 int omap_irq_wait(struct drm_device
*dev
, struct omap_irq_wait
*wait
,
70 unsigned long timeout
)
72 struct omap_drm_private
*priv
= dev
->dev_private
;
76 ret
= wait_event_timeout(wait
->wq
, (wait
->count
<= 0), timeout
);
78 spin_lock_irqsave(&priv
->wait_lock
, flags
);
79 list_del(&wait
->node
);
81 spin_unlock_irqrestore(&priv
->wait_lock
, flags
);
85 return ret
== 0 ? -1 : 0;
89 * enable_vblank - enable vblank interrupt events
91 * @pipe: which irq to enable
93 * Enable vblank interrupts for @crtc. If the device doesn't have
94 * a hardware vblank counter, this routine should be a no-op, since
95 * interrupts will have to stay on to keep the count accurate.
98 * Zero on success, appropriate errno if the given @crtc's vblank
99 * interrupt cannot be enabled.
101 int omap_irq_enable_vblank(struct drm_crtc
*crtc
)
103 struct drm_device
*dev
= crtc
->dev
;
104 struct omap_drm_private
*priv
= dev
->dev_private
;
106 enum omap_channel channel
= omap_crtc_channel(crtc
);
108 DBG("dev=%p, crtc=%u", dev
, channel
);
110 spin_lock_irqsave(&priv
->wait_lock
, flags
);
111 priv
->irq_mask
|= priv
->dispc_ops
->mgr_get_vsync_irq(priv
->dispc
,
113 omap_irq_update(dev
);
114 spin_unlock_irqrestore(&priv
->wait_lock
, flags
);
120 * disable_vblank - disable vblank interrupt events
122 * @pipe: which irq to enable
124 * Disable vblank interrupts for @crtc. If the device doesn't have
125 * a hardware vblank counter, this routine should be a no-op, since
126 * interrupts will have to stay on to keep the count accurate.
128 void omap_irq_disable_vblank(struct drm_crtc
*crtc
)
130 struct drm_device
*dev
= crtc
->dev
;
131 struct omap_drm_private
*priv
= dev
->dev_private
;
133 enum omap_channel channel
= omap_crtc_channel(crtc
);
135 DBG("dev=%p, crtc=%u", dev
, channel
);
137 spin_lock_irqsave(&priv
->wait_lock
, flags
);
138 priv
->irq_mask
&= ~priv
->dispc_ops
->mgr_get_vsync_irq(priv
->dispc
,
140 omap_irq_update(dev
);
141 spin_unlock_irqrestore(&priv
->wait_lock
, flags
);
144 static void omap_irq_fifo_underflow(struct omap_drm_private
*priv
,
147 static DEFINE_RATELIMIT_STATE(_rs
, DEFAULT_RATELIMIT_INTERVAL
,
148 DEFAULT_RATELIMIT_BURST
);
149 static const struct {
153 { "gfx", DISPC_IRQ_GFX_FIFO_UNDERFLOW
},
154 { "vid1", DISPC_IRQ_VID1_FIFO_UNDERFLOW
},
155 { "vid2", DISPC_IRQ_VID2_FIFO_UNDERFLOW
},
156 { "vid3", DISPC_IRQ_VID3_FIFO_UNDERFLOW
},
159 const u32 mask
= DISPC_IRQ_GFX_FIFO_UNDERFLOW
160 | DISPC_IRQ_VID1_FIFO_UNDERFLOW
161 | DISPC_IRQ_VID2_FIFO_UNDERFLOW
162 | DISPC_IRQ_VID3_FIFO_UNDERFLOW
;
165 spin_lock(&priv
->wait_lock
);
166 irqstatus
&= priv
->irq_mask
& mask
;
167 spin_unlock(&priv
->wait_lock
);
172 if (!__ratelimit(&_rs
))
175 DRM_ERROR("FIFO underflow on ");
177 for (i
= 0; i
< ARRAY_SIZE(sources
); ++i
) {
178 if (sources
[i
].mask
& irqstatus
)
179 pr_cont("%s ", sources
[i
].name
);
182 pr_cont("(0x%08x)\n", irqstatus
);
185 static void omap_irq_ocp_error_handler(struct drm_device
*dev
,
188 if (!(irqstatus
& DISPC_IRQ_OCP_ERR
))
191 dev_err_ratelimited(dev
->dev
, "OCP error\n");
194 static irqreturn_t
omap_irq_handler(int irq
, void *arg
)
196 struct drm_device
*dev
= (struct drm_device
*) arg
;
197 struct omap_drm_private
*priv
= dev
->dev_private
;
198 struct omap_irq_wait
*wait
, *n
;
203 irqstatus
= priv
->dispc_ops
->read_irqstatus(priv
->dispc
);
204 priv
->dispc_ops
->clear_irqstatus(priv
->dispc
, irqstatus
);
205 priv
->dispc_ops
->read_irqstatus(priv
->dispc
); /* flush posted write */
207 VERB("irqs: %08x", irqstatus
);
209 for (id
= 0; id
< priv
->num_crtcs
; id
++) {
210 struct drm_crtc
*crtc
= priv
->crtcs
[id
];
211 enum omap_channel channel
= omap_crtc_channel(crtc
);
213 if (irqstatus
& priv
->dispc_ops
->mgr_get_vsync_irq(priv
->dispc
, channel
)) {
214 drm_handle_vblank(dev
, id
);
215 omap_crtc_vblank_irq(crtc
);
218 if (irqstatus
& priv
->dispc_ops
->mgr_get_sync_lost_irq(priv
->dispc
, channel
))
219 omap_crtc_error_irq(crtc
, irqstatus
);
222 omap_irq_ocp_error_handler(dev
, irqstatus
);
223 omap_irq_fifo_underflow(priv
, irqstatus
);
225 spin_lock_irqsave(&priv
->wait_lock
, flags
);
226 list_for_each_entry_safe(wait
, n
, &priv
->wait_list
, node
) {
227 if (wait
->irqmask
& irqstatus
)
228 omap_irq_wait_handler(wait
);
230 spin_unlock_irqrestore(&priv
->wait_lock
, flags
);
235 static const u32 omap_underflow_irqs
[] = {
236 [OMAP_DSS_GFX
] = DISPC_IRQ_GFX_FIFO_UNDERFLOW
,
237 [OMAP_DSS_VIDEO1
] = DISPC_IRQ_VID1_FIFO_UNDERFLOW
,
238 [OMAP_DSS_VIDEO2
] = DISPC_IRQ_VID2_FIFO_UNDERFLOW
,
239 [OMAP_DSS_VIDEO3
] = DISPC_IRQ_VID3_FIFO_UNDERFLOW
,
243 * We need a special version, instead of just using drm_irq_install(),
244 * because we need to register the irq via omapdss. Once omapdss and
245 * omapdrm are merged together we can assign the dispc hwmod data to
246 * ourselves and drop these and just use drm_irq_{install,uninstall}()
249 int omap_drm_irq_install(struct drm_device
*dev
)
251 struct omap_drm_private
*priv
= dev
->dev_private
;
252 unsigned int num_mgrs
= priv
->dispc_ops
->get_num_mgrs(priv
->dispc
);
253 unsigned int max_planes
;
257 spin_lock_init(&priv
->wait_lock
);
258 INIT_LIST_HEAD(&priv
->wait_list
);
260 priv
->irq_mask
= DISPC_IRQ_OCP_ERR
;
262 max_planes
= min(ARRAY_SIZE(priv
->planes
),
263 ARRAY_SIZE(omap_underflow_irqs
));
264 for (i
= 0; i
< max_planes
; ++i
) {
266 priv
->irq_mask
|= omap_underflow_irqs
[i
];
269 for (i
= 0; i
< num_mgrs
; ++i
)
270 priv
->irq_mask
|= priv
->dispc_ops
->mgr_get_sync_lost_irq(priv
->dispc
, i
);
272 priv
->dispc_ops
->runtime_get(priv
->dispc
);
273 priv
->dispc_ops
->clear_irqstatus(priv
->dispc
, 0xffffffff);
274 priv
->dispc_ops
->runtime_put(priv
->dispc
);
276 ret
= priv
->dispc_ops
->request_irq(priv
->dispc
, omap_irq_handler
, dev
);
280 dev
->irq_enabled
= true;
285 void omap_drm_irq_uninstall(struct drm_device
*dev
)
287 struct omap_drm_private
*priv
= dev
->dev_private
;
289 if (!dev
->irq_enabled
)
292 dev
->irq_enabled
= false;
294 priv
->dispc_ops
->free_irq(priv
->dispc
, dev
);