aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/via_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm/via_irq.c')
-rw-r--r--drivers/char/drm/via_irq.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index d023add1929b..56d7e3daea12 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -50,6 +50,15 @@
50#define VIA_IRQ_HQV1_ENABLE (1 << 25) 50#define VIA_IRQ_HQV1_ENABLE (1 << 25)
51#define VIA_IRQ_HQV0_PENDING (1 << 9) 51#define VIA_IRQ_HQV0_PENDING (1 << 9)
52#define VIA_IRQ_HQV1_PENDING (1 << 10) 52#define VIA_IRQ_HQV1_PENDING (1 << 10)
53#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20)
54#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21)
55#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22)
56#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23)
57#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
58#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
59#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
60#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
61
53 62
54/* 63/*
55 * Device-specific IRQs go here. This type might need to be extended with 64 * Device-specific IRQs go here. This type might need to be extended with
@@ -61,13 +70,24 @@ static maskarray_t via_pro_group_a_irqs[] = {
61 {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, 70 {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
62 0x00000000}, 71 0x00000000},
63 {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, 72 {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
64 0x00000000} 73 0x00000000},
74 {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
75 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
76 {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
77 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
65}; 78};
66static int via_num_pro_group_a = 79static int via_num_pro_group_a =
67 sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t); 80 sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
81static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
68 82
69static maskarray_t via_unichrome_irqs[] = { }; 83static maskarray_t via_unichrome_irqs[] = {
84 {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
85 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
86 {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
87 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
88};
70static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t); 89static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
90static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
71 91
72static unsigned time_diff(struct timeval *now, struct timeval *then) 92static unsigned time_diff(struct timeval *now, struct timeval *then)
73{ 93{
@@ -113,6 +133,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
113 atomic_inc(&cur_irq->irq_received); 133 atomic_inc(&cur_irq->irq_received);
114 DRM_WAKEUP(&cur_irq->irq_queue); 134 DRM_WAKEUP(&cur_irq->irq_queue);
115 handled = 1; 135 handled = 1;
136 if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) {
137 via_dmablit_handler(dev, 0, 1);
138 } else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) {
139 via_dmablit_handler(dev, 1, 1);
140 }
116 } 141 }
117 cur_irq++; 142 cur_irq++;
118 } 143 }
@@ -165,7 +190,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
165 return ret; 190 return ret;
166} 191}
167 192
168static int 193int
169via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, 194via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
170 unsigned int *sequence) 195 unsigned int *sequence)
171{ 196{
@@ -174,6 +199,7 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
174 drm_via_irq_t *cur_irq = dev_priv->via_irqs; 199 drm_via_irq_t *cur_irq = dev_priv->via_irqs;
175 int ret = 0; 200 int ret = 0;
176 maskarray_t *masks = dev_priv->irq_masks; 201 maskarray_t *masks = dev_priv->irq_masks;
202 int real_irq;
177 203
178 DRM_DEBUG("%s\n", __FUNCTION__); 204 DRM_DEBUG("%s\n", __FUNCTION__);
179 205
@@ -182,15 +208,23 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
182 return DRM_ERR(EINVAL); 208 return DRM_ERR(EINVAL);
183 } 209 }
184 210
185 if (irq >= dev_priv->num_irqs) { 211 if (irq >= drm_via_irq_num) {
186 DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, 212 DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
187 irq); 213 irq);
188 return DRM_ERR(EINVAL); 214 return DRM_ERR(EINVAL);
189 } 215 }
190 216
191 cur_irq += irq; 217 real_irq = dev_priv->irq_map[irq];
218
219 if (real_irq < 0) {
220 DRM_ERROR("%s Video IRQ %d not available on this hardware.\n",
221 __FUNCTION__, irq);
222 return DRM_ERR(EINVAL);
223 }
224
225 cur_irq += real_irq;
192 226
193 if (masks[irq][2] && !force_sequence) { 227 if (masks[real_irq][2] && !force_sequence) {
194 DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ, 228 DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
195 ((VIA_READ(masks[irq][2]) & masks[irq][3]) == 229 ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
196 masks[irq][4])); 230 masks[irq][4]));
@@ -226,6 +260,8 @@ void via_driver_irq_preinstall(drm_device_t * dev)
226 via_pro_group_a_irqs : via_unichrome_irqs; 260 via_pro_group_a_irqs : via_unichrome_irqs;
227 dev_priv->num_irqs = (dev_priv->pro_group_a) ? 261 dev_priv->num_irqs = (dev_priv->pro_group_a) ?
228 via_num_pro_group_a : via_num_unichrome; 262 via_num_pro_group_a : via_num_unichrome;
263 dev_priv->irq_map = (dev_priv->pro_group_a) ?
264 via_irqmap_pro_group_a : via_irqmap_unichrome;
229 265
230 for (i = 0; i < dev_priv->num_irqs; ++i) { 266 for (i = 0; i < dev_priv->num_irqs; ++i) {
231 atomic_set(&cur_irq->irq_received, 0); 267 atomic_set(&cur_irq->irq_received, 0);
@@ -241,7 +277,7 @@ void via_driver_irq_preinstall(drm_device_t * dev)
241 277
242 dev_priv->last_vblank_valid = 0; 278 dev_priv->last_vblank_valid = 0;
243 279
244 // Clear VSync interrupt regs 280 /* Clear VSync interrupt regs */
245 status = VIA_READ(VIA_REG_INTERRUPT); 281 status = VIA_READ(VIA_REG_INTERRUPT);
246 VIA_WRITE(VIA_REG_INTERRUPT, status & 282 VIA_WRITE(VIA_REG_INTERRUPT, status &
247 ~(dev_priv->irq_enable_mask)); 283 ~(dev_priv->irq_enable_mask));
@@ -291,8 +327,7 @@ void via_driver_irq_uninstall(drm_device_t * dev)
291 327
292int via_wait_irq(DRM_IOCTL_ARGS) 328int via_wait_irq(DRM_IOCTL_ARGS)
293{ 329{
294 drm_file_t *priv = filp->private_data; 330 DRM_DEVICE;
295 drm_device_t *dev = priv->head->dev;
296 drm_via_irqwait_t __user *argp = (void __user *)data; 331 drm_via_irqwait_t __user *argp = (void __user *)data;
297 drm_via_irqwait_t irqwait; 332 drm_via_irqwait_t irqwait;
298 struct timeval now; 333 struct timeval now;