xref: /openbmc/linux/drivers/gpu/drm/tidss/tidss_irq.c (revision 32a1795f57eecc3974901760400618571c9d357f)
1*32a1795fSJyri Sarha // SPDX-License-Identifier: GPL-2.0
2*32a1795fSJyri Sarha /*
3*32a1795fSJyri Sarha  * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
4*32a1795fSJyri Sarha  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
5*32a1795fSJyri Sarha  */
6*32a1795fSJyri Sarha 
7*32a1795fSJyri Sarha #include <drm/drm_print.h>
8*32a1795fSJyri Sarha 
9*32a1795fSJyri Sarha #include "tidss_crtc.h"
10*32a1795fSJyri Sarha #include "tidss_dispc.h"
11*32a1795fSJyri Sarha #include "tidss_drv.h"
12*32a1795fSJyri Sarha #include "tidss_irq.h"
13*32a1795fSJyri Sarha #include "tidss_plane.h"
14*32a1795fSJyri Sarha 
15*32a1795fSJyri Sarha /* call with wait_lock and dispc runtime held */
16*32a1795fSJyri Sarha static void tidss_irq_update(struct tidss_device *tidss)
17*32a1795fSJyri Sarha {
18*32a1795fSJyri Sarha 	assert_spin_locked(&tidss->wait_lock);
19*32a1795fSJyri Sarha 
20*32a1795fSJyri Sarha 	dispc_set_irqenable(tidss->dispc, tidss->irq_mask);
21*32a1795fSJyri Sarha }
22*32a1795fSJyri Sarha 
23*32a1795fSJyri Sarha void tidss_irq_enable_vblank(struct drm_crtc *crtc)
24*32a1795fSJyri Sarha {
25*32a1795fSJyri Sarha 	struct drm_device *ddev = crtc->dev;
26*32a1795fSJyri Sarha 	struct tidss_device *tidss = ddev->dev_private;
27*32a1795fSJyri Sarha 	struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
28*32a1795fSJyri Sarha 	u32 hw_videoport = tcrtc->hw_videoport;
29*32a1795fSJyri Sarha 	unsigned long flags;
30*32a1795fSJyri Sarha 
31*32a1795fSJyri Sarha 	spin_lock_irqsave(&tidss->wait_lock, flags);
32*32a1795fSJyri Sarha 	tidss->irq_mask |= DSS_IRQ_VP_VSYNC_EVEN(hw_videoport) |
33*32a1795fSJyri Sarha 			   DSS_IRQ_VP_VSYNC_ODD(hw_videoport);
34*32a1795fSJyri Sarha 	tidss_irq_update(tidss);
35*32a1795fSJyri Sarha 	spin_unlock_irqrestore(&tidss->wait_lock, flags);
36*32a1795fSJyri Sarha }
37*32a1795fSJyri Sarha 
38*32a1795fSJyri Sarha void tidss_irq_disable_vblank(struct drm_crtc *crtc)
39*32a1795fSJyri Sarha {
40*32a1795fSJyri Sarha 	struct drm_device *ddev = crtc->dev;
41*32a1795fSJyri Sarha 	struct tidss_device *tidss = ddev->dev_private;
42*32a1795fSJyri Sarha 	struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
43*32a1795fSJyri Sarha 	u32 hw_videoport = tcrtc->hw_videoport;
44*32a1795fSJyri Sarha 	unsigned long flags;
45*32a1795fSJyri Sarha 
46*32a1795fSJyri Sarha 	spin_lock_irqsave(&tidss->wait_lock, flags);
47*32a1795fSJyri Sarha 	tidss->irq_mask &= ~(DSS_IRQ_VP_VSYNC_EVEN(hw_videoport) |
48*32a1795fSJyri Sarha 			     DSS_IRQ_VP_VSYNC_ODD(hw_videoport));
49*32a1795fSJyri Sarha 	tidss_irq_update(tidss);
50*32a1795fSJyri Sarha 	spin_unlock_irqrestore(&tidss->wait_lock, flags);
51*32a1795fSJyri Sarha }
52*32a1795fSJyri Sarha 
53*32a1795fSJyri Sarha irqreturn_t tidss_irq_handler(int irq, void *arg)
54*32a1795fSJyri Sarha {
55*32a1795fSJyri Sarha 	struct drm_device *ddev = (struct drm_device *)arg;
56*32a1795fSJyri Sarha 	struct tidss_device *tidss = ddev->dev_private;
57*32a1795fSJyri Sarha 	unsigned int id;
58*32a1795fSJyri Sarha 	dispc_irq_t irqstatus;
59*32a1795fSJyri Sarha 
60*32a1795fSJyri Sarha 	if (WARN_ON(!ddev->irq_enabled))
61*32a1795fSJyri Sarha 		return IRQ_NONE;
62*32a1795fSJyri Sarha 
63*32a1795fSJyri Sarha 	irqstatus = dispc_read_and_clear_irqstatus(tidss->dispc);
64*32a1795fSJyri Sarha 
65*32a1795fSJyri Sarha 	for (id = 0; id < tidss->num_crtcs; id++) {
66*32a1795fSJyri Sarha 		struct drm_crtc *crtc = tidss->crtcs[id];
67*32a1795fSJyri Sarha 		struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
68*32a1795fSJyri Sarha 		u32 hw_videoport = tcrtc->hw_videoport;
69*32a1795fSJyri Sarha 
70*32a1795fSJyri Sarha 		if (irqstatus & (DSS_IRQ_VP_VSYNC_EVEN(hw_videoport) |
71*32a1795fSJyri Sarha 				 DSS_IRQ_VP_VSYNC_ODD(hw_videoport)))
72*32a1795fSJyri Sarha 			tidss_crtc_vblank_irq(crtc);
73*32a1795fSJyri Sarha 
74*32a1795fSJyri Sarha 		if (irqstatus & (DSS_IRQ_VP_FRAME_DONE(hw_videoport)))
75*32a1795fSJyri Sarha 			tidss_crtc_framedone_irq(crtc);
76*32a1795fSJyri Sarha 
77*32a1795fSJyri Sarha 		if (irqstatus & DSS_IRQ_VP_SYNC_LOST(hw_videoport))
78*32a1795fSJyri Sarha 			tidss_crtc_error_irq(crtc, irqstatus);
79*32a1795fSJyri Sarha 	}
80*32a1795fSJyri Sarha 
81*32a1795fSJyri Sarha 	if (irqstatus & DSS_IRQ_DEVICE_OCP_ERR)
82*32a1795fSJyri Sarha 		dev_err_ratelimited(tidss->dev, "OCP error\n");
83*32a1795fSJyri Sarha 
84*32a1795fSJyri Sarha 	return IRQ_HANDLED;
85*32a1795fSJyri Sarha }
86*32a1795fSJyri Sarha 
87*32a1795fSJyri Sarha void tidss_irq_resume(struct tidss_device *tidss)
88*32a1795fSJyri Sarha {
89*32a1795fSJyri Sarha 	unsigned long flags;
90*32a1795fSJyri Sarha 
91*32a1795fSJyri Sarha 	spin_lock_irqsave(&tidss->wait_lock, flags);
92*32a1795fSJyri Sarha 	tidss_irq_update(tidss);
93*32a1795fSJyri Sarha 	spin_unlock_irqrestore(&tidss->wait_lock, flags);
94*32a1795fSJyri Sarha }
95*32a1795fSJyri Sarha 
96*32a1795fSJyri Sarha void tidss_irq_preinstall(struct drm_device *ddev)
97*32a1795fSJyri Sarha {
98*32a1795fSJyri Sarha 	struct tidss_device *tidss = ddev->dev_private;
99*32a1795fSJyri Sarha 
100*32a1795fSJyri Sarha 	spin_lock_init(&tidss->wait_lock);
101*32a1795fSJyri Sarha 
102*32a1795fSJyri Sarha 	tidss_runtime_get(tidss);
103*32a1795fSJyri Sarha 
104*32a1795fSJyri Sarha 	dispc_set_irqenable(tidss->dispc, 0);
105*32a1795fSJyri Sarha 	dispc_read_and_clear_irqstatus(tidss->dispc);
106*32a1795fSJyri Sarha 
107*32a1795fSJyri Sarha 	tidss_runtime_put(tidss);
108*32a1795fSJyri Sarha }
109*32a1795fSJyri Sarha 
110*32a1795fSJyri Sarha int tidss_irq_postinstall(struct drm_device *ddev)
111*32a1795fSJyri Sarha {
112*32a1795fSJyri Sarha 	struct tidss_device *tidss = ddev->dev_private;
113*32a1795fSJyri Sarha 	unsigned long flags;
114*32a1795fSJyri Sarha 	unsigned int i;
115*32a1795fSJyri Sarha 
116*32a1795fSJyri Sarha 	tidss_runtime_get(tidss);
117*32a1795fSJyri Sarha 
118*32a1795fSJyri Sarha 	spin_lock_irqsave(&tidss->wait_lock, flags);
119*32a1795fSJyri Sarha 
120*32a1795fSJyri Sarha 	tidss->irq_mask = DSS_IRQ_DEVICE_OCP_ERR;
121*32a1795fSJyri Sarha 
122*32a1795fSJyri Sarha 	for (i = 0; i < tidss->num_crtcs; ++i) {
123*32a1795fSJyri Sarha 		struct tidss_crtc *tcrtc = to_tidss_crtc(tidss->crtcs[i]);
124*32a1795fSJyri Sarha 
125*32a1795fSJyri Sarha 		tidss->irq_mask |= DSS_IRQ_VP_SYNC_LOST(tcrtc->hw_videoport);
126*32a1795fSJyri Sarha 
127*32a1795fSJyri Sarha 		tidss->irq_mask |= DSS_IRQ_VP_FRAME_DONE(tcrtc->hw_videoport);
128*32a1795fSJyri Sarha 	}
129*32a1795fSJyri Sarha 
130*32a1795fSJyri Sarha 	tidss_irq_update(tidss);
131*32a1795fSJyri Sarha 
132*32a1795fSJyri Sarha 	spin_unlock_irqrestore(&tidss->wait_lock, flags);
133*32a1795fSJyri Sarha 
134*32a1795fSJyri Sarha 	tidss_runtime_put(tidss);
135*32a1795fSJyri Sarha 
136*32a1795fSJyri Sarha 	return 0;
137*32a1795fSJyri Sarha }
138*32a1795fSJyri Sarha 
139*32a1795fSJyri Sarha void tidss_irq_uninstall(struct drm_device *ddev)
140*32a1795fSJyri Sarha {
141*32a1795fSJyri Sarha 	struct tidss_device *tidss = ddev->dev_private;
142*32a1795fSJyri Sarha 
143*32a1795fSJyri Sarha 	tidss_runtime_get(tidss);
144*32a1795fSJyri Sarha 	dispc_set_irqenable(tidss->dispc, 0);
145*32a1795fSJyri Sarha 	tidss_runtime_put(tidss);
146*32a1795fSJyri Sarha }
147