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 "mga_drv.h"
35
36u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
37{
38 const drm_mga_private_t *const dev_priv =
39 (drm_mga_private_t *) dev->dev_private;
40
41 if (pipe != 0)
42 return 0;
43
44 return atomic_read(&dev_priv->vbl_received);
45}
46
47
48irqreturn_t mga_driver_irq_handler(int irq, void *arg)
49{
50 struct drm_device *dev = (struct drm_device *) arg;
51 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
52 int status;
53 int handled = 0;
54
55 status = MGA_READ(MGA_STATUS);
56
57
58 if (status & MGA_VLINEPEN) {
59 MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
60 atomic_inc(&dev_priv->vbl_received);
61 drm_handle_vblank(dev, 0);
62 handled = 1;
63 }
64
65
66 if (status & MGA_SOFTRAPEN) {
67 const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
68 const u32 prim_end = MGA_READ(MGA_PRIMEND);
69
70
71 MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
72
73
74
75
76 if ((prim_start & ~0x03) != (prim_end & ~0x03))
77 MGA_WRITE(MGA_PRIMEND, prim_end);
78
79 atomic_inc(&dev_priv->last_fence_retired);
80 wake_up(&dev_priv->fence_queue);
81 handled = 1;
82 }
83
84 if (handled)
85 return IRQ_HANDLED;
86 return IRQ_NONE;
87}
88
89int mga_enable_vblank(struct drm_device *dev, unsigned int pipe)
90{
91 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
92
93 if (pipe != 0) {
94 DRM_ERROR("tried to enable vblank on non-existent crtc %u\n",
95 pipe);
96 return 0;
97 }
98
99 MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
100 return 0;
101}
102
103
104void mga_disable_vblank(struct drm_device *dev, unsigned int pipe)
105{
106 if (pipe != 0) {
107 DRM_ERROR("tried to disable vblank on non-existent crtc %u\n",
108 pipe);
109 }
110
111
112
113
114
115
116
117}
118
119void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence)
120{
121 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
122 unsigned int cur_fence;
123
124
125
126
127
128 wait_event_timeout(dev_priv->fence_queue,
129 (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
130 - *sequence) <= (1 << 23)),
131 msecs_to_jiffies(3000));
132
133 *sequence = cur_fence;
134}
135
136void mga_driver_irq_preinstall(struct drm_device *dev)
137{
138 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
139
140
141 MGA_WRITE(MGA_IEN, 0);
142
143 MGA_WRITE(MGA_ICLEAR, ~0);
144}
145
146int mga_driver_irq_postinstall(struct drm_device *dev)
147{
148 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
149
150 init_waitqueue_head(&dev_priv->fence_queue);
151
152
153
154
155 MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
156 return 0;
157}
158
159void mga_driver_irq_uninstall(struct drm_device *dev)
160{
161 drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
162 if (!dev_priv)
163 return;
164
165
166 MGA_WRITE(MGA_IEN, 0);
167
168 dev->irq_enabled = false;
169}
170