mga_irq.c revision 152909
1152909Sanholt/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- 2152909Sanholt */ 3139749Simp/*- 4112015Sanholt * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. 5145132Sanholt * 6112015Sanholt * The Weather Channel (TM) funded Tungsten Graphics to develop the 7112015Sanholt * initial release of the Radeon 8500 driver under the XFree86 license. 8112015Sanholt * This notice must be preserved. 9112015Sanholt * 10112015Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 11112015Sanholt * copy of this software and associated documentation files (the "Software"), 12112015Sanholt * to deal in the Software without restriction, including without limitation 13112015Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14112015Sanholt * and/or sell copies of the Software, and to permit persons to whom the 15112015Sanholt * Software is furnished to do so, subject to the following conditions: 16112015Sanholt * 17112015Sanholt * The above copyright notice and this permission notice (including the next 18112015Sanholt * paragraph) shall be included in all copies or substantial portions of the 19112015Sanholt * Software. 20112015Sanholt * 21112015Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22112015Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23112015Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24112015Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25112015Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26112015Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27112015Sanholt * DEALINGS IN THE SOFTWARE. 28112015Sanholt * 29112015Sanholt * Authors: 30112015Sanholt * Keith Whitwell <keith@tungstengraphics.com> 31112015Sanholt * Eric Anholt <anholt@FreeBSD.org> 32112015Sanholt */ 33112015Sanholt 34152909Sanholt#include <sys/cdefs.h> 35152909Sanholt__FBSDID("$FreeBSD: head/sys/dev/drm/mga_irq.c 152909 2005-11-28 23:13:57Z anholt $"); 36152909Sanholt 37112015Sanholt#include "dev/drm/drmP.h" 38112015Sanholt#include "dev/drm/drm.h" 39112015Sanholt#include "dev/drm/mga_drm.h" 40112015Sanholt#include "dev/drm/mga_drv.h" 41112015Sanholt 42145132Sanholtirqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS) 43112015Sanholt{ 44112015Sanholt drm_device_t *dev = (drm_device_t *) arg; 45145132Sanholt drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; 46112015Sanholt int status; 47152909Sanholt int handled = 0; 48112015Sanholt 49145132Sanholt status = MGA_READ(MGA_STATUS); 50145132Sanholt 51112015Sanholt /* VBLANK interrupt */ 52145132Sanholt if (status & MGA_VLINEPEN) { 53145132Sanholt MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); 54112015Sanholt atomic_inc(&dev->vbl_received); 55112015Sanholt DRM_WAKEUP(&dev->vbl_queue); 56145132Sanholt drm_vbl_send_signals(dev); 57152909Sanholt handled = 1; 58152909Sanholt } 59152909Sanholt 60152909Sanholt /* SOFTRAP interrupt */ 61152909Sanholt if (status & MGA_SOFTRAPEN) { 62152909Sanholt const u32 prim_start = MGA_READ(MGA_PRIMADDRESS); 63152909Sanholt const u32 prim_end = MGA_READ(MGA_PRIMEND); 64152909Sanholt 65152909Sanholt 66152909Sanholt MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR); 67152909Sanholt 68152909Sanholt /* In addition to clearing the interrupt-pending bit, we 69152909Sanholt * have to write to MGA_PRIMEND to re-start the DMA operation. 70152909Sanholt */ 71152909Sanholt if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) { 72152909Sanholt MGA_WRITE(MGA_PRIMEND, prim_end); 73152909Sanholt } 74152909Sanholt 75152909Sanholt atomic_inc(&dev_priv->last_fence_retired); 76152909Sanholt DRM_WAKEUP(&dev_priv->fence_queue); 77152909Sanholt handled = 1; 78152909Sanholt } 79152909Sanholt 80152909Sanholt if ( handled ) { 81119098Sanholt return IRQ_HANDLED; 82112015Sanholt } 83119098Sanholt return IRQ_NONE; 84112015Sanholt} 85112015Sanholt 86145132Sanholtint mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) 87112015Sanholt{ 88112015Sanholt unsigned int cur_vblank; 89112015Sanholt int ret = 0; 90112015Sanholt 91112015Sanholt /* Assume that the user has missed the current sequence number 92112015Sanholt * by about a day rather than she wants to wait for years 93145132Sanholt * using vertical blanks... 94112015Sanholt */ 95145132Sanholt DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, 96145132Sanholt (((cur_vblank = atomic_read(&dev->vbl_received)) 97145132Sanholt - *sequence) <= (1 << 23))); 98112015Sanholt 99112015Sanholt *sequence = cur_vblank; 100112015Sanholt 101112015Sanholt return ret; 102112015Sanholt} 103112015Sanholt 104152909Sanholtint mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence) 105152909Sanholt{ 106152909Sanholt drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; 107152909Sanholt unsigned int cur_fence; 108152909Sanholt int ret = 0; 109152909Sanholt 110152909Sanholt /* Assume that the user has missed the current sequence number 111152909Sanholt * by about a day rather than she wants to wait for years 112152909Sanholt * using fences. 113152909Sanholt */ 114152909Sanholt DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ, 115152909Sanholt (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) 116152909Sanholt - *sequence) <= (1 << 23))); 117152909Sanholt 118152909Sanholt *sequence = cur_fence; 119152909Sanholt 120152909Sanholt return ret; 121152909Sanholt} 122152909Sanholt 123145132Sanholtvoid mga_driver_irq_preinstall(drm_device_t * dev) 124145132Sanholt{ 125145132Sanholt drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; 126112015Sanholt 127112015Sanholt /* Disable *all* interrupts */ 128145132Sanholt MGA_WRITE(MGA_IEN, 0); 129112015Sanholt /* Clear bits if they're already high */ 130145132Sanholt MGA_WRITE(MGA_ICLEAR, ~0); 131112015Sanholt} 132112015Sanholt 133145132Sanholtvoid mga_driver_irq_postinstall(drm_device_t * dev) 134145132Sanholt{ 135145132Sanholt drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; 136112015Sanholt 137152909Sanholt DRM_INIT_WAITQUEUE( &dev_priv->fence_queue ); 138152909Sanholt 139152909Sanholt /* Turn on vertical blank interrupt and soft trap interrupt. */ 140152909Sanholt MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); 141112015Sanholt} 142112015Sanholt 143145132Sanholtvoid mga_driver_irq_uninstall(drm_device_t * dev) 144145132Sanholt{ 145145132Sanholt drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; 146119098Sanholt if (!dev_priv) 147119098Sanholt return; 148119098Sanholt 149119098Sanholt /* Disable *all* interrupts */ 150145132Sanholt MGA_WRITE(MGA_IEN, 0); 151152909Sanholt 152152909Sanholt dev->irq_enabled = 0; 153112015Sanholt} 154