Home | History | Annotate | Line # | Download | only in via
      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