1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <drm/drmP.h>
35#include <drm/mga_drm.h>
36#include "mga_drv.h"
37
38u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
39{
40 const drm_mga_private_t *const dev_priv =
41 (drm_mga_private_t *) dev->dev_private;
42
43 if (crtc != 0)
44 return 0;
45
46 return atomic_read(&dev_priv->vbl_received);
47}
48
49
50irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
51{
52 struct drm_device *dev = (struct drm_device *) arg;
53 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
54 int status;
55 int handled = 0;
56
57 status = MGA_READ(MGA_STATUS);
58
59
60 if (status & MGA_VLINEPEN) {
61 MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
62 atomic_inc(&dev_priv->vbl_received);
63 drm_handle_vblank(dev, 0);
64 handled = 1;
65 }
66
67
68 if (status & MGA_SOFTRAPEN) {
69 const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
70 const u32 prim_end = MGA_READ(MGA_PRIMEND);
71
72
73 MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
74
75
76
77
78 if ((prim_start & ~0x03) != (prim_end & ~0x03))
79 MGA_WRITE(MGA_PRIMEND, prim_end);
80
81 atomic_inc(&dev_priv->last_fence_retired);
82 DRM_WAKEUP(&dev_priv->fence_queue);
83 handled = 1;
84 }
85
86 if (handled)
87 return IRQ_HANDLED;
88 return IRQ_NONE;
89}
90
91int mga_enable_vblank(struct drm_device *dev, int crtc)
92{
93 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
94
95 if (crtc != 0) {
96 DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
97 crtc);
98 return 0;
99 }
100
101 MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
102 return 0;
103}
104
105
106void mga_disable_vblank(struct drm_device *dev, int crtc)
107{
108 if (crtc != 0) {
109 DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
110 crtc);
111 }
112
113
114
115
116
117
118
119}
120
121int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence)
122{
123 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
124 unsigned int cur_fence;
125 int ret = 0;
126
127
128
129
130
131 DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
132 (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
133 - *sequence) <= (1 << 23)));
134
135 *sequence = cur_fence;
136
137 return ret;
138}
139
140void mga_driver_irq_preinstall(struct drm_device *dev)
141{
142 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
143
144
145 MGA_WRITE(MGA_IEN, 0);
146
147 MGA_WRITE(MGA_ICLEAR, ~0);
148}
149
150int mga_driver_irq_postinstall(struct drm_device *dev)
151{
152 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
153
154 DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
155
156
157
158
159 MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
160 return 0;
161}
162
163void mga_driver_irq_uninstall(struct drm_device *dev)
164{
165 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
166 if (!dev_priv)
167 return;
168
169
170 MGA_WRITE(MGA_IEN, 0);
171
172 dev->irq_enabled = 0;
173}
174