1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <drm/drmP.h>
18
19#include "xylon_drv.h"
20#include "xylon_crtc.h"
21#include "xylon_irq.h"
22
23irqreturn_t xylon_drm_irq_handler(int irq, void *arg)
24{
25 struct drm_device *dev = (struct drm_device *)arg;
26 struct xylon_drm_device *xdev;
27
28 if (!dev)
29 return IRQ_NONE;
30
31 xdev = dev->dev_private;
32
33 xylon_drm_crtc_int_handle(xdev->crtc);
34
35 return IRQ_HANDLED;
36}
37
38void xylon_drm_irq_preinst(struct drm_device *dev)
39{
40 struct xylon_drm_device *xdev = dev->dev_private;
41
42 xylon_drm_crtc_int_hw_disable(xdev->crtc);
43}
44
45int xylon_drm_irq_postinst(struct drm_device *dev)
46{
47 return 0;
48}
49
50void xylon_drm_irq_uninst(struct drm_device *dev)
51{
52 struct xylon_drm_device *xdev = dev->dev_private;
53
54 xylon_drm_crtc_int_hw_disable(xdev->crtc);
55}
56
57int xylon_drm_irq_install(struct drm_device *dev)
58{
59 struct xylon_drm_device *xdev = dev->dev_private;
60 unsigned long irq_flags;
61 int ret;
62
63 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
64 return -EINVAL;
65
66 mutex_lock(&dev->struct_mutex);
67 if (dev->irq_enabled)
68 return -EBUSY;
69 mutex_unlock(&dev->struct_mutex);
70
71 if (dev->driver->irq_preinstall)
72 dev->driver->irq_preinstall(dev);
73
74 if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
75 irq_flags = IRQF_SHARED;
76 else
77 irq_flags = 0;
78
79 ret = xylon_drm_crtc_int_request(xdev->crtc, irq_flags,
80 xylon_drm_irq_handler, dev);
81 if (ret < 0)
82 return ret;
83
84 if (dev->driver->irq_postinstall)
85 ret = dev->driver->irq_postinstall(dev);
86
87 if (ret < 0) {
88 xylon_drm_crtc_int_free(xdev->crtc, dev);
89 return ret;
90 }
91
92 mutex_lock(&dev->struct_mutex);
93 dev->irq_enabled = 1;
94 mutex_unlock(&dev->struct_mutex);
95
96 return ret;
97}
98
99int xylon_drm_irq_uninstall(struct drm_device *dev)
100{
101 struct xylon_drm_device *xdev = dev->dev_private;
102 unsigned long irqflags;
103 int i, irq_enabled;
104
105 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
106 return -EINVAL;
107
108 mutex_lock(&dev->struct_mutex);
109 irq_enabled = dev->irq_enabled;
110 dev->irq_enabled = 0;
111 mutex_unlock(&dev->struct_mutex);
112
113 if (dev->num_crtcs) {
114 spin_lock_irqsave(&dev->vbl_lock, irqflags);
115 for (i = 0; i < dev->num_crtcs; i++) {
116 wake_up(&dev->vblank[i].queue);
117 dev->vblank[i].enabled = 0;
118 dev->vblank[i].last =
119 dev->driver->get_vblank_counter(dev, i);
120 }
121 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
122 }
123
124 if (!irq_enabled)
125 return -EINVAL;
126
127 if (dev->driver->irq_uninstall)
128 dev->driver->irq_uninstall(dev);
129
130 xylon_drm_crtc_int_free(xdev->crtc, dev);
131
132 return 0;
133}
134