1 1.9 riastrad /* $NetBSD: via_irq.c,v 1.9 2021/12/19 12:30:23 riastradh Exp $ */ 2 1.6 riastrad 3 1.1 riastrad /* via_irq.c 4 1.1 riastrad * 5 1.1 riastrad * Copyright 2004 BEAM Ltd. 6 1.1 riastrad * Copyright 2002 Tungsten Graphics, Inc. 7 1.1 riastrad * Copyright 2005 Thomas Hellstrom. 8 1.1 riastrad * All Rights Reserved. 9 1.1 riastrad * 10 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 11 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 12 1.1 riastrad * to deal in the Software without restriction, including without limitation 13 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 15 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 16 1.1 riastrad * 17 1.1 riastrad * The above copyright notice and this permission notice (including the next 18 1.1 riastrad * paragraph) shall be included in all copies or substantial portions of the 19 1.1 riastrad * Software. 20 1.1 riastrad * 21 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 1.1 riastrad * BEAM LTD, TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 25 1.1 riastrad * DAMAGES OR 26 1.1 riastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27 1.1 riastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 1.1 riastrad * DEALINGS IN THE SOFTWARE. 29 1.1 riastrad * 30 1.1 riastrad * Authors: 31 1.1 riastrad * Terry Barnaby <terry1 (at) beam.ltd.uk> 32 1.1 riastrad * Keith Whitwell <keith (at) tungstengraphics.com> 33 1.1 riastrad * Thomas Hellstrom <unichrome (at) shipmail.org> 34 1.1 riastrad * 35 1.1 riastrad * This code provides standard DRM access to the Via Unichrome / Pro Vertical blank 36 1.1 riastrad * interrupt, as well as an infrastructure to handle other interrupts of the chip. 37 1.1 riastrad * The refresh rate is also calculated for video playback sync purposes. 38 1.1 riastrad */ 39 1.1 riastrad 40 1.6 riastrad #include <sys/cdefs.h> 41 1.9 riastrad __KERNEL_RCSID(0, "$NetBSD: via_irq.c,v 1.9 2021/12/19 12:30:23 riastradh Exp $"); 42 1.6 riastrad 43 1.8 riastrad #include <drm/drm_device.h> 44 1.8 riastrad #include <drm/drm_vblank.h> 45 1.1 riastrad #include <drm/via_drm.h> 46 1.8 riastrad 47 1.1 riastrad #include "via_drv.h" 48 1.1 riastrad 49 1.1 riastrad #define VIA_REG_INTERRUPT 0x200 50 1.1 riastrad 51 1.1 riastrad /* VIA_REG_INTERRUPT */ 52 1.1 riastrad #define VIA_IRQ_GLOBAL (1 << 31) 53 1.1 riastrad #define VIA_IRQ_VBLANK_ENABLE (1 << 19) 54 1.1 riastrad #define VIA_IRQ_VBLANK_PENDING (1 << 3) 55 1.1 riastrad #define VIA_IRQ_HQV0_ENABLE (1 << 11) 56 1.1 riastrad #define VIA_IRQ_HQV1_ENABLE (1 << 25) 57 1.1 riastrad #define VIA_IRQ_HQV0_PENDING (1 << 9) 58 1.1 riastrad #define VIA_IRQ_HQV1_PENDING (1 << 10) 59 1.1 riastrad #define VIA_IRQ_DMA0_DD_ENABLE (1 << 20) 60 1.1 riastrad #define VIA_IRQ_DMA0_TD_ENABLE (1 << 21) 61 1.1 riastrad #define VIA_IRQ_DMA1_DD_ENABLE (1 << 22) 62 1.1 riastrad #define VIA_IRQ_DMA1_TD_ENABLE (1 << 23) 63 1.1 riastrad #define VIA_IRQ_DMA0_DD_PENDING (1 << 4) 64 1.1 riastrad #define VIA_IRQ_DMA0_TD_PENDING (1 << 5) 65 1.1 riastrad #define VIA_IRQ_DMA1_DD_PENDING (1 << 6) 66 1.1 riastrad #define VIA_IRQ_DMA1_TD_PENDING (1 << 7) 67 1.1 riastrad 68 1.1 riastrad 69 1.1 riastrad /* 70 1.1 riastrad * Device-specific IRQs go here. This type might need to be extended with 71 1.1 riastrad * the register if there are multiple IRQ control registers. 72 1.1 riastrad * Currently we activate the HQV interrupts of Unichrome Pro group A. 73 1.1 riastrad */ 74 1.1 riastrad 75 1.1 riastrad static maskarray_t via_pro_group_a_irqs[] = { 76 1.1 riastrad {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, 77 1.1 riastrad 0x00000000 }, 78 1.1 riastrad {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, 79 1.1 riastrad 0x00000000 }, 80 1.1 riastrad {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, 81 1.1 riastrad VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, 82 1.1 riastrad {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, 83 1.1 riastrad VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, 84 1.1 riastrad }; 85 1.1 riastrad static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs); 86 1.1 riastrad static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3}; 87 1.1 riastrad 88 1.1 riastrad static maskarray_t via_unichrome_irqs[] = { 89 1.1 riastrad {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, 90 1.1 riastrad VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, 91 1.1 riastrad {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, 92 1.1 riastrad VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008} 93 1.1 riastrad }; 94 1.1 riastrad static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs); 95 1.1 riastrad static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; 96 1.1 riastrad 97 1.1 riastrad 98 1.6 riastrad u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe) 99 1.1 riastrad { 100 1.1 riastrad drm_via_private_t *dev_priv = dev->dev_private; 101 1.6 riastrad 102 1.6 riastrad if (pipe != 0) 103 1.1 riastrad return 0; 104 1.1 riastrad 105 1.1 riastrad return atomic_read(&dev_priv->vbl_received); 106 1.1 riastrad } 107 1.1 riastrad 108 1.5 riastrad irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) 109 1.1 riastrad { 110 1.1 riastrad struct drm_device *dev = (struct drm_device *) arg; 111 1.1 riastrad drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 112 1.1 riastrad u32 status; 113 1.1 riastrad int handled = 0; 114 1.8 riastrad ktime_t cur_vblank; 115 1.1 riastrad drm_via_irq_t *cur_irq = dev_priv->via_irqs; 116 1.1 riastrad int i; 117 1.1 riastrad 118 1.8 riastrad status = via_read(dev_priv, VIA_REG_INTERRUPT); 119 1.1 riastrad if (status & VIA_IRQ_VBLANK_PENDING) { 120 1.1 riastrad atomic_inc(&dev_priv->vbl_received); 121 1.1 riastrad if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { 122 1.8 riastrad cur_vblank = ktime_get(); 123 1.1 riastrad if (dev_priv->last_vblank_valid) { 124 1.8 riastrad dev_priv->nsec_per_vblank = 125 1.8 riastrad ktime_sub(cur_vblank, 126 1.8 riastrad dev_priv->last_vblank) >> 4; 127 1.1 riastrad } 128 1.1 riastrad dev_priv->last_vblank = cur_vblank; 129 1.1 riastrad dev_priv->last_vblank_valid = 1; 130 1.1 riastrad } 131 1.1 riastrad if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) { 132 1.9 riastrad DRM_DEBUG("nsec per vblank is: %"PRIu64"\n", 133 1.8 riastrad ktime_to_ns(dev_priv->nsec_per_vblank)); 134 1.1 riastrad } 135 1.1 riastrad drm_handle_vblank(dev, 0); 136 1.1 riastrad handled = 1; 137 1.1 riastrad } 138 1.1 riastrad 139 1.1 riastrad for (i = 0; i < dev_priv->num_irqs; ++i) { 140 1.1 riastrad if (status & cur_irq->pending_mask) { 141 1.2 riastrad #ifdef __NetBSD__ 142 1.2 riastrad spin_lock(&cur_irq->irq_lock); 143 1.2 riastrad cur_irq->irq_received++; 144 1.2 riastrad DRM_SPIN_WAKEUP_ONE(&cur_irq->irq_queue, 145 1.2 riastrad &cur_irq->irq_lock); 146 1.2 riastrad spin_unlock(&cur_irq->irq_lock); 147 1.2 riastrad #else 148 1.1 riastrad atomic_inc(&cur_irq->irq_received); 149 1.2 riastrad wake_up(&cur_irq->irq_queue); 150 1.2 riastrad #endif 151 1.1 riastrad handled = 1; 152 1.1 riastrad if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) 153 1.1 riastrad via_dmablit_handler(dev, 0, 1); 154 1.1 riastrad else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) 155 1.1 riastrad via_dmablit_handler(dev, 1, 1); 156 1.1 riastrad } 157 1.1 riastrad cur_irq++; 158 1.1 riastrad } 159 1.1 riastrad 160 1.1 riastrad /* Acknowledge interrupts */ 161 1.8 riastrad via_write(dev_priv, VIA_REG_INTERRUPT, status); 162 1.1 riastrad 163 1.1 riastrad 164 1.1 riastrad if (handled) 165 1.1 riastrad return IRQ_HANDLED; 166 1.1 riastrad else 167 1.1 riastrad return IRQ_NONE; 168 1.1 riastrad } 169 1.1 riastrad 170 1.1 riastrad static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv) 171 1.1 riastrad { 172 1.1 riastrad u32 status; 173 1.1 riastrad 174 1.1 riastrad if (dev_priv) { 175 1.1 riastrad /* Acknowledge interrupts */ 176 1.8 riastrad status = via_read(dev_priv, VIA_REG_INTERRUPT); 177 1.8 riastrad via_write(dev_priv, VIA_REG_INTERRUPT, status | 178 1.1 riastrad dev_priv->irq_pending_mask); 179 1.1 riastrad } 180 1.1 riastrad } 181 1.1 riastrad 182 1.6 riastrad int via_enable_vblank(struct drm_device *dev, unsigned int pipe) 183 1.1 riastrad { 184 1.1 riastrad drm_via_private_t *dev_priv = dev->dev_private; 185 1.1 riastrad u32 status; 186 1.1 riastrad 187 1.6 riastrad if (pipe != 0) { 188 1.6 riastrad DRM_ERROR("%s: bad crtc %u\n", __func__, pipe); 189 1.1 riastrad return -EINVAL; 190 1.1 riastrad } 191 1.1 riastrad 192 1.8 riastrad status = via_read(dev_priv, VIA_REG_INTERRUPT); 193 1.8 riastrad via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE); 194 1.1 riastrad 195 1.8 riastrad via_write8(dev_priv, 0x83d4, 0x11); 196 1.8 riastrad via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30); 197 1.1 riastrad 198 1.1 riastrad return 0; 199 1.1 riastrad } 200 1.1 riastrad 201 1.6 riastrad void via_disable_vblank(struct drm_device *dev, unsigned int pipe) 202 1.1 riastrad { 203 1.1 riastrad drm_via_private_t *dev_priv = dev->dev_private; 204 1.1 riastrad u32 status; 205 1.1 riastrad 206 1.8 riastrad status = via_read(dev_priv, VIA_REG_INTERRUPT); 207 1.8 riastrad via_write(dev_priv, VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE); 208 1.1 riastrad 209 1.8 riastrad via_write8(dev_priv, 0x83d4, 0x11); 210 1.8 riastrad via_write8_mask(dev_priv, 0x83d5, 0x30, 0); 211 1.1 riastrad 212 1.6 riastrad if (pipe != 0) 213 1.6 riastrad DRM_ERROR("%s: bad crtc %u\n", __func__, pipe); 214 1.1 riastrad } 215 1.1 riastrad 216 1.1 riastrad static int 217 1.1 riastrad via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence, 218 1.1 riastrad unsigned int *sequence) 219 1.1 riastrad { 220 1.1 riastrad drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 221 1.1 riastrad unsigned int cur_irq_sequence; 222 1.1 riastrad drm_via_irq_t *cur_irq; 223 1.1 riastrad int ret = 0; 224 1.1 riastrad maskarray_t *masks; 225 1.1 riastrad int real_irq; 226 1.1 riastrad 227 1.1 riastrad DRM_DEBUG("\n"); 228 1.1 riastrad 229 1.1 riastrad if (!dev_priv) { 230 1.1 riastrad DRM_ERROR("called with no initialization\n"); 231 1.1 riastrad return -EINVAL; 232 1.1 riastrad } 233 1.1 riastrad 234 1.1 riastrad if (irq >= drm_via_irq_num) { 235 1.1 riastrad DRM_ERROR("Trying to wait on unknown irq %d\n", irq); 236 1.1 riastrad return -EINVAL; 237 1.1 riastrad } 238 1.1 riastrad 239 1.1 riastrad real_irq = dev_priv->irq_map[irq]; 240 1.1 riastrad 241 1.1 riastrad if (real_irq < 0) { 242 1.1 riastrad DRM_ERROR("Video IRQ %d not available on this hardware.\n", 243 1.1 riastrad irq); 244 1.1 riastrad return -EINVAL; 245 1.1 riastrad } 246 1.1 riastrad 247 1.1 riastrad masks = dev_priv->irq_masks; 248 1.1 riastrad cur_irq = dev_priv->via_irqs + real_irq; 249 1.1 riastrad 250 1.2 riastrad #ifdef __NetBSD__ 251 1.2 riastrad spin_lock(&cur_irq->irq_lock); 252 1.1 riastrad if (masks[real_irq][2] && !force_sequence) { 253 1.4 riastrad DRM_SPIN_WAIT_ON(ret, &cur_irq->irq_queue, &cur_irq->irq_lock, 254 1.7 riastrad 3 * HZ, 255 1.9 riastrad ((via_read(dev_priv, masks[irq][2]) & masks[irq][3]) == 256 1.2 riastrad masks[irq][4])); 257 1.2 riastrad cur_irq_sequence = cur_irq->irq_received; 258 1.2 riastrad } else { 259 1.4 riastrad DRM_SPIN_WAIT_ON(ret, &cur_irq->irq_queue, &cur_irq->irq_lock, 260 1.7 riastrad 3 * HZ, 261 1.2 riastrad (((cur_irq_sequence = cur_irq->irq_received) - 262 1.2 riastrad *sequence) <= (1 << 23))); 263 1.2 riastrad } 264 1.2 riastrad spin_unlock(&cur_irq->irq_lock); 265 1.2 riastrad #else 266 1.2 riastrad if (masks[real_irq][2] && !force_sequence) { 267 1.8 riastrad VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, 268 1.8 riastrad ((via_read(dev_priv, masks[irq][2]) & masks[irq][3]) == 269 1.1 riastrad masks[irq][4])); 270 1.1 riastrad cur_irq_sequence = atomic_read(&cur_irq->irq_received); 271 1.1 riastrad } else { 272 1.8 riastrad VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, 273 1.1 riastrad (((cur_irq_sequence = 274 1.1 riastrad atomic_read(&cur_irq->irq_received)) - 275 1.1 riastrad *sequence) <= (1 << 23))); 276 1.1 riastrad } 277 1.2 riastrad #endif 278 1.1 riastrad *sequence = cur_irq_sequence; 279 1.1 riastrad return ret; 280 1.1 riastrad } 281 1.1 riastrad 282 1.1 riastrad 283 1.1 riastrad /* 284 1.1 riastrad * drm_dma.h hooks 285 1.1 riastrad */ 286 1.1 riastrad 287 1.1 riastrad void via_driver_irq_preinstall(struct drm_device *dev) 288 1.1 riastrad { 289 1.1 riastrad drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 290 1.1 riastrad u32 status; 291 1.1 riastrad drm_via_irq_t *cur_irq; 292 1.1 riastrad int i; 293 1.1 riastrad 294 1.1 riastrad DRM_DEBUG("dev_priv: %p\n", dev_priv); 295 1.1 riastrad if (dev_priv) { 296 1.1 riastrad cur_irq = dev_priv->via_irqs; 297 1.1 riastrad 298 1.1 riastrad dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; 299 1.1 riastrad dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; 300 1.1 riastrad 301 1.1 riastrad if (dev_priv->chipset == VIA_PRO_GROUP_A || 302 1.1 riastrad dev_priv->chipset == VIA_DX9_0) { 303 1.1 riastrad dev_priv->irq_masks = via_pro_group_a_irqs; 304 1.1 riastrad dev_priv->num_irqs = via_num_pro_group_a; 305 1.1 riastrad dev_priv->irq_map = via_irqmap_pro_group_a; 306 1.1 riastrad } else { 307 1.1 riastrad dev_priv->irq_masks = via_unichrome_irqs; 308 1.1 riastrad dev_priv->num_irqs = via_num_unichrome; 309 1.1 riastrad dev_priv->irq_map = via_irqmap_unichrome; 310 1.1 riastrad } 311 1.1 riastrad 312 1.1 riastrad for (i = 0; i < dev_priv->num_irqs; ++i) { 313 1.2 riastrad #ifdef __NetBSD__ 314 1.2 riastrad spin_lock_init(&cur_irq->irq_lock); 315 1.2 riastrad cur_irq->irq_received = 0; 316 1.2 riastrad #else 317 1.1 riastrad atomic_set(&cur_irq->irq_received, 0); 318 1.2 riastrad #endif 319 1.1 riastrad cur_irq->enable_mask = dev_priv->irq_masks[i][0]; 320 1.1 riastrad cur_irq->pending_mask = dev_priv->irq_masks[i][1]; 321 1.2 riastrad #ifdef __NetBSD__ 322 1.2 riastrad DRM_INIT_WAITQUEUE(&cur_irq->irq_queue, "viairq"); 323 1.2 riastrad #else 324 1.2 riastrad init_waitqueue_head(&cur_irq->irq_queue); 325 1.2 riastrad #endif 326 1.1 riastrad dev_priv->irq_enable_mask |= cur_irq->enable_mask; 327 1.1 riastrad dev_priv->irq_pending_mask |= cur_irq->pending_mask; 328 1.1 riastrad cur_irq++; 329 1.1 riastrad 330 1.1 riastrad DRM_DEBUG("Initializing IRQ %d\n", i); 331 1.1 riastrad } 332 1.1 riastrad 333 1.1 riastrad dev_priv->last_vblank_valid = 0; 334 1.1 riastrad 335 1.1 riastrad /* Clear VSync interrupt regs */ 336 1.8 riastrad status = via_read(dev_priv, VIA_REG_INTERRUPT); 337 1.8 riastrad via_write(dev_priv, VIA_REG_INTERRUPT, status & 338 1.1 riastrad ~(dev_priv->irq_enable_mask)); 339 1.1 riastrad 340 1.1 riastrad /* Clear bits if they're already high */ 341 1.1 riastrad viadrv_acknowledge_irqs(dev_priv); 342 1.1 riastrad } 343 1.1 riastrad } 344 1.1 riastrad 345 1.1 riastrad int via_driver_irq_postinstall(struct drm_device *dev) 346 1.1 riastrad { 347 1.1 riastrad drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 348 1.1 riastrad u32 status; 349 1.1 riastrad 350 1.1 riastrad DRM_DEBUG("via_driver_irq_postinstall\n"); 351 1.1 riastrad if (!dev_priv) 352 1.1 riastrad return -EINVAL; 353 1.1 riastrad 354 1.8 riastrad status = via_read(dev_priv, VIA_REG_INTERRUPT); 355 1.8 riastrad via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL 356 1.1 riastrad | dev_priv->irq_enable_mask); 357 1.1 riastrad 358 1.1 riastrad /* Some magic, oh for some data sheets ! */ 359 1.8 riastrad via_write8(dev_priv, 0x83d4, 0x11); 360 1.8 riastrad via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30); 361 1.1 riastrad 362 1.1 riastrad return 0; 363 1.1 riastrad } 364 1.1 riastrad 365 1.1 riastrad void via_driver_irq_uninstall(struct drm_device *dev) 366 1.1 riastrad { 367 1.1 riastrad drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 368 1.1 riastrad u32 status; 369 1.1 riastrad 370 1.1 riastrad DRM_DEBUG("\n"); 371 1.1 riastrad if (dev_priv) { 372 1.1 riastrad 373 1.1 riastrad /* Some more magic, oh for some data sheets ! */ 374 1.1 riastrad 375 1.8 riastrad via_write8(dev_priv, 0x83d4, 0x11); 376 1.8 riastrad via_write8_mask(dev_priv, 0x83d5, 0x30, 0); 377 1.1 riastrad 378 1.8 riastrad status = via_read(dev_priv, VIA_REG_INTERRUPT); 379 1.8 riastrad via_write(dev_priv, VIA_REG_INTERRUPT, status & 380 1.1 riastrad ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask)); 381 1.2 riastrad 382 1.2 riastrad #ifdef __NetBSD__ 383 1.2 riastrad { 384 1.2 riastrad int i; 385 1.2 riastrad 386 1.2 riastrad for (i = 0; i < dev_priv->num_irqs; i++) { 387 1.2 riastrad DRM_DESTROY_WAITQUEUE(&dev_priv->via_irqs[i].irq_queue); 388 1.2 riastrad spin_lock_destroy(&dev_priv->via_irqs[i].irq_lock); 389 1.2 riastrad } 390 1.2 riastrad } 391 1.2 riastrad #endif 392 1.1 riastrad } 393 1.1 riastrad } 394 1.1 riastrad 395 1.1 riastrad int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) 396 1.1 riastrad { 397 1.1 riastrad drm_via_irqwait_t *irqwait = data; 398 1.8 riastrad struct timespec64 now; 399 1.1 riastrad int ret = 0; 400 1.1 riastrad drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 401 1.1 riastrad drm_via_irq_t *cur_irq = dev_priv->via_irqs; 402 1.1 riastrad int force_sequence; 403 1.1 riastrad 404 1.1 riastrad if (irqwait->request.irq >= dev_priv->num_irqs) { 405 1.1 riastrad DRM_ERROR("Trying to wait on unknown irq %d\n", 406 1.1 riastrad irqwait->request.irq); 407 1.1 riastrad return -EINVAL; 408 1.1 riastrad } 409 1.1 riastrad 410 1.1 riastrad cur_irq += irqwait->request.irq; 411 1.1 riastrad 412 1.1 riastrad switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) { 413 1.1 riastrad case VIA_IRQ_RELATIVE: 414 1.2 riastrad #ifdef __NetBSD__ 415 1.2 riastrad irqwait->request.sequence += cur_irq->irq_received; 416 1.2 riastrad #else 417 1.1 riastrad irqwait->request.sequence += 418 1.1 riastrad atomic_read(&cur_irq->irq_received); 419 1.2 riastrad #endif 420 1.1 riastrad irqwait->request.type &= ~_DRM_VBLANK_RELATIVE; 421 1.1 riastrad case VIA_IRQ_ABSOLUTE: 422 1.1 riastrad break; 423 1.1 riastrad default: 424 1.1 riastrad return -EINVAL; 425 1.1 riastrad } 426 1.1 riastrad 427 1.1 riastrad if (irqwait->request.type & VIA_IRQ_SIGNAL) { 428 1.1 riastrad DRM_ERROR("Signals on Via IRQs not implemented yet.\n"); 429 1.1 riastrad return -EINVAL; 430 1.1 riastrad } 431 1.1 riastrad 432 1.1 riastrad force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE); 433 1.1 riastrad 434 1.1 riastrad ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence, 435 1.1 riastrad &irqwait->request.sequence); 436 1.8 riastrad ktime_get_ts64(&now); 437 1.1 riastrad irqwait->reply.tval_sec = now.tv_sec; 438 1.8 riastrad irqwait->reply.tval_usec = now.tv_nsec / NSEC_PER_USEC; 439 1.1 riastrad 440 1.1 riastrad return ret; 441 1.1 riastrad } 442