radeon_irq.c revision 119098
1193323Sed/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- 2193323Sed * 3193323Sed * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. 4193323Sed * 5193323Sed * The Weather Channel (TM) funded Tungsten Graphics to develop the 6193323Sed * initial release of the Radeon 8500 driver under the XFree86 license. 7193323Sed * This notice must be preserved. 8193323Sed * 9193323Sed * Permission is hereby granted, free of charge, to any person obtaining a 10193323Sed * copy of this software and associated documentation files (the "Software"), 11193323Sed * to deal in the Software without restriction, including without limitation 12193323Sed * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13193323Sed * and/or sell copies of the Software, and to permit persons to whom the 14193323Sed * Software is furnished to do so, subject to the following conditions: 15193323Sed * 16193323Sed * The above copyright notice and this permission notice (including the next 17193323Sed * paragraph) shall be included in all copies or substantial portions of the 18193323Sed * Software. 19193323Sed * 20193323Sed * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21193323Sed * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22193323Sed * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23193323Sed * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24193323Sed * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25193323Sed * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26193323Sed * DEALINGS IN THE SOFTWARE. 27193323Sed * 28193323Sed * Authors: 29193323Sed * Keith Whitwell <keith@tungstengraphics.com> 30193323Sed * Michel D�nzer <michel@daenzer.net> 31193323Sed * 32193323Sed * $FreeBSD: head/sys/dev/drm/radeon_irq.c 119098 2003-08-19 02:57:31Z anholt $ 33193323Sed */ 34193323Sed 35193323Sed#include "dev/drm/radeon.h" 36193323Sed#include "dev/drm/drmP.h" 37193323Sed#include "dev/drm/drm.h" 38193323Sed#include "dev/drm/radeon_drm.h" 39193323Sed#include "dev/drm/radeon_drv.h" 40193323Sed 41193323Sed/* Interrupts - Used for device synchronization and flushing in the 42193323Sed * following circumstances: 43193323Sed * 44193323Sed * - Exclusive FB access with hw idle: 45193323Sed * - Wait for GUI Idle (?) interrupt, then do normal flush. 46193323Sed * 47193323Sed * - Frame throttling, NV_fence: 48193323Sed * - Drop marker irq's into command stream ahead of time. 49193323Sed * - Wait on irq's with lock *not held* 50193323Sed * - Check each for termination condition 51193323Sed * 52193323Sed * - Internally in cp_getbuffer, etc: 53193323Sed * - as above, but wait with lock held??? 54193323Sed * 55193323Sed * NOTE: These functions are misleadingly named -- the irq's aren't 56193323Sed * tied to dma at all, this is just a hangover from dri prehistory. 57193323Sed */ 58193323Sed 59193323Sedirqreturn_t DRM(dma_service)( DRM_IRQ_ARGS ) 60193323Sed{ 61193323Sed drm_device_t *dev = (drm_device_t *) arg; 62193323Sed drm_radeon_private_t *dev_priv = 63193323Sed (drm_radeon_private_t *)dev->dev_private; 64193323Sed u32 stat; 65193323Sed 66193323Sed /* Only consider the bits we're interested in - others could be used 67193323Sed * outside the DRM 68193323Sed */ 69193323Sed stat = RADEON_READ(RADEON_GEN_INT_STATUS) 70193323Sed & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); 71193323Sed if (!stat) 72193323Sed return IRQ_NONE; 73193323Sed 74193323Sed /* SW interrupt */ 75193323Sed if (stat & RADEON_SW_INT_TEST) { 76193323Sed DRM_WAKEUP( &dev_priv->swi_queue ); 77193323Sed } 78193323Sed 79193323Sed /* VBLANK interrupt */ 80193323Sed if (stat & RADEON_CRTC_VBLANK_STAT) { 81193323Sed atomic_inc(&dev->vbl_received); 82193323Sed DRM_WAKEUP(&dev->vbl_queue); 83193323Sed DRM(vbl_send_signals)( dev ); 84193323Sed } 85193323Sed 86193323Sed /* Acknowledge interrupts we handle */ 87193323Sed RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); 88193323Sed return IRQ_HANDLED; 89193323Sed} 90193323Sed 91193323Sedstatic __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) 92193323Sed{ 93193323Sed u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS ) 94193323Sed & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT); 95193323Sed if (tmp) 96193323Sed RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); 97193323Sed} 98193323Sed 99193323Sedint radeon_emit_irq(drm_device_t *dev) 100193323Sed{ 101193323Sed drm_radeon_private_t *dev_priv = dev->dev_private; 102193323Sed unsigned int ret; 103193323Sed RING_LOCALS; 104193323Sed 105193323Sed atomic_inc(&dev_priv->swi_emitted); 106193323Sed ret = atomic_read(&dev_priv->swi_emitted); 107193323Sed 108193323Sed BEGIN_RING( 4 ); 109193323Sed OUT_RING_REG( RADEON_LAST_SWI_REG, ret ); 110193323Sed OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE ); 111193323Sed ADVANCE_RING(); 112193323Sed COMMIT_RING(); 113193323Sed 114193323Sed return ret; 115193323Sed} 116193323Sed 117193323Sed 118193323Sedint radeon_wait_irq(drm_device_t *dev, int swi_nr) 119193323Sed{ 120193323Sed drm_radeon_private_t *dev_priv = 121193323Sed (drm_radeon_private_t *)dev->dev_private; 122193323Sed int ret = 0; 123193323Sed 124193323Sed if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) 125193323Sed return 0; 126193323Sed 127193323Sed dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 128193323Sed 129193323Sed /* This is a hack to work around mysterious freezes on certain 130193323Sed * systems: 131193323Sed */ 132193323Sed radeon_acknowledge_irqs( dev_priv ); 133193323Sed 134193323Sed DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ, 135193323Sed RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr ); 136193323Sed 137193323Sed return ret; 138193323Sed} 139193323Sed 140193323Sedint radeon_emit_and_wait_irq(drm_device_t *dev) 141193323Sed{ 142193323Sed return radeon_wait_irq( dev, radeon_emit_irq(dev) ); 143193323Sed} 144193323Sed 145193323Sed 146193323Sedint DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) 147193323Sed{ 148193323Sed drm_radeon_private_t *dev_priv = 149193323Sed (drm_radeon_private_t *)dev->dev_private; 150193323Sed unsigned int cur_vblank; 151193323Sed int ret = 0; 152193323Sed 153193323Sed if ( !dev_priv ) { 154193323Sed DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); 155193323Sed return DRM_ERR(EINVAL); 156193323Sed } 157193323Sed 158193323Sed radeon_acknowledge_irqs( dev_priv ); 159193323Sed 160193323Sed dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 161193323Sed 162195340Sed /* Assume that the user has missed the current sequence number 163193323Sed * by about a day rather than she wants to wait for years 164193323Sed * using vertical blanks... 165193323Sed */ 166193323Sed DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, 167193323Sed ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) 168193323Sed - *sequence ) <= (1<<23) ) ); 169193323Sed 170193323Sed *sequence = cur_vblank; 171193323Sed 172193323Sed return ret; 173193323Sed} 174193323Sed 175193323Sed 176193323Sed/* Needs the lock as it touches the ring. 177193323Sed */ 178193323Sedint radeon_irq_emit( DRM_IOCTL_ARGS ) 179193323Sed{ 180193323Sed DRM_DEVICE; 181193323Sed drm_radeon_private_t *dev_priv = dev->dev_private; 182193323Sed drm_radeon_irq_emit_t emit; 183193323Sed int result; 184193323Sed 185193323Sed LOCK_TEST_WITH_RETURN( dev, filp ); 186193323Sed 187193323Sed if ( !dev_priv ) { 188193323Sed DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); 189193323Sed return DRM_ERR(EINVAL); 190193323Sed } 191193323Sed 192193323Sed DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t *)data, 193193323Sed sizeof(emit) ); 194193323Sed 195193323Sed result = radeon_emit_irq( dev ); 196193323Sed 197193323Sed if ( DRM_COPY_TO_USER( emit.irq_seq, &result, sizeof(int) ) ) { 198193323Sed DRM_ERROR( "copy_to_user\n" ); 199193323Sed return DRM_ERR(EFAULT); 200193323Sed } 201193323Sed 202193323Sed return 0; 203193323Sed} 204193323Sed 205193323Sed 206193323Sed/* Doesn't need the hardware lock. 207193323Sed */ 208193323Sedint radeon_irq_wait( DRM_IOCTL_ARGS ) 209193323Sed{ 210193323Sed DRM_DEVICE; 211193323Sed drm_radeon_private_t *dev_priv = dev->dev_private; 212193323Sed drm_radeon_irq_wait_t irqwait; 213193323Sed 214193323Sed if ( !dev_priv ) { 215193323Sed DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); 216193323Sed return DRM_ERR(EINVAL); 217193323Sed } 218193323Sed 219193323Sed DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t *)data, 220193323Sed sizeof(irqwait) ); 221193323Sed 222193323Sed return radeon_wait_irq( dev, irqwait.irq_seq ); 223193323Sed} 224193323Sed 225193323Sed 226193323Sed/* drm_dma.h hooks 227193323Sed*/ 228193323Sedvoid DRM(driver_irq_preinstall)( drm_device_t *dev ) { 229193323Sed drm_radeon_private_t *dev_priv = 230193323Sed (drm_radeon_private_t *)dev->dev_private; 231193323Sed 232193323Sed /* Disable *all* interrupts */ 233193323Sed RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); 234193323Sed 235193323Sed /* Clear bits if they're already high */ 236193323Sed radeon_acknowledge_irqs( dev_priv ); 237193323Sed} 238193323Sed 239193323Sedvoid DRM(driver_irq_postinstall)( drm_device_t *dev ) { 240193323Sed drm_radeon_private_t *dev_priv = 241193323Sed (drm_radeon_private_t *)dev->dev_private; 242193323Sed 243193323Sed atomic_set(&dev_priv->swi_emitted, 0); 244193323Sed DRM_INIT_WAITQUEUE( &dev_priv->swi_queue ); 245193323Sed 246193323Sed /* Turn on SW and VBL ints */ 247193323Sed RADEON_WRITE( RADEON_GEN_INT_CNTL, 248193323Sed RADEON_CRTC_VBLANK_MASK | 249193323Sed RADEON_SW_INT_ENABLE ); 250193323Sed} 251193323Sed 252193323Sedvoid DRM(driver_irq_uninstall)( drm_device_t *dev ) { 253193323Sed drm_radeon_private_t *dev_priv = 254193323Sed (drm_radeon_private_t *)dev->dev_private; 255193323Sed if (!dev_priv) 256193323Sed return; 257193323Sed 258193323Sed /* Disable *all* interrupts */ 259193323Sed RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); 260193323Sed} 261193323Sed