diff options
author | Eric Anholt <anholt@freebsd.org> | 2002-10-30 06:10:34 +0000 |
---|---|---|
committer | Eric Anholt <anholt@freebsd.org> | 2002-10-30 06:10:34 +0000 |
commit | e656655a361acf73c5652fcef8cf6ba61dfe7a50 (patch) | |
tree | 96775fd22bd84a7030a114b108235ca07e12934c /shared-core | |
parent | 344c7f6b412c19c963c33709f0d4a3a7205e1d79 (diff) |
Kernel support for vblank syncing on Rage 128 and Matrox.
Diffstat (limited to 'shared-core')
-rw-r--r-- | shared-core/mga_drm.h | 11 | ||||
-rw-r--r-- | shared-core/mga_drv.h | 12 | ||||
-rw-r--r-- | shared-core/mga_irq.c | 99 | ||||
-rw-r--r-- | shared-core/mga_state.c | 33 | ||||
-rw-r--r-- | shared-core/r128_drm.h | 11 | ||||
-rw-r--r-- | shared-core/r128_drv.h | 6 | ||||
-rw-r--r-- | shared-core/r128_irq.c | 99 | ||||
-rw-r--r-- | shared-core/r128_state.c | 33 |
8 files changed, 304 insertions, 0 deletions
diff --git a/shared-core/mga_drm.h b/shared-core/mga_drm.h index c259814d..b19bc011 100644 --- a/shared-core/mga_drm.h +++ b/shared-core/mga_drm.h @@ -239,6 +239,7 @@ typedef struct _drm_mga_sarea { #define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) #define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x47, drm_mga_iload_t) #define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x48, drm_mga_blit_t) +#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(0x49, drm_mga_getparam_t) typedef struct _drm_mga_warp_index { int installed; @@ -322,4 +323,14 @@ typedef struct _drm_mga_blit { int source_pitch, dest_pitch; } drm_mga_blit_t; +/* 3.1: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define MGA_PARAM_IRQ_NR 1 + +typedef struct drm_mga_getparam { + int param; + int *value; +} drm_mga_getparam_t; + #endif diff --git a/shared-core/mga_drv.h b/shared-core/mga_drv.h index b5f16ae2..a5085b06 100644 --- a/shared-core/mga_drv.h +++ b/shared-core/mga_drv.h @@ -125,6 +125,7 @@ extern int mga_dma_vertex( DRM_IOCTL_ARGS ); extern int mga_dma_indices( DRM_IOCTL_ARGS ); extern int mga_dma_iload( DRM_IOCTL_ARGS ); extern int mga_dma_blit( DRM_IOCTL_ARGS ); +extern int mga_getparam( DRM_IOCTL_ARGS ); /* mga_warp.c */ extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv ); @@ -141,6 +142,7 @@ extern int mga_warp_init( drm_mga_private_t *dev_priv ); #ifdef __alpha__ #define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg))) +#define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg))) #define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0) #define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0) @@ -152,6 +154,7 @@ static inline u32 _MGA_READ(u32 *addr) #else #define MGA_READ( reg ) MGA_DEREF( reg ) +#define MGA_READ8( reg ) MGA_DEREF8( reg ) #define MGA_WRITE( reg, val ) do { MGA_DEREF( reg ) = val; } while (0) #define MGA_WRITE8( reg, val ) do { MGA_DEREF8( reg ) = val; } while (0) #endif @@ -345,6 +348,11 @@ do { \ /* A reduced set of the mga registers. */ #define MGA_CRTC_INDEX 0x1fd4 +#define MGA_CRTC_DATA 0x1fd5 + +/* CRTC11 */ +#define MGA_VINTCLR (1 << 4) +#define MGA_VINTEN (1 << 5) #define MGA_ALPHACTRL 0x2c7c #define MGA_AR0 0x1c60 @@ -416,8 +424,10 @@ do { \ #define MGA_ICLEAR 0x1e18 # define MGA_SOFTRAPICLR (1 << 0) +# define MGA_VLINEICLR (1 << 5) #define MGA_IEN 0x1e1c # define MGA_SOFTRAPIEN (1 << 0) +# define MGA_VLINEIEN (1 << 5) #define MGA_LEN 0x1c5c @@ -456,6 +466,8 @@ do { \ # define MGA_SRCACC_AGP (1 << 1) #define MGA_STATUS 0x1e14 # define MGA_SOFTRAPEN (1 << 0) +# define MGA_VSYNCPEN (1 << 4) +# define MGA_VLINEPEN (1 << 5) # define MGA_DWGENGSTS (1 << 16) # define MGA_ENDPRDMASTS (1 << 17) #define MGA_STENCIL 0x2cc8 diff --git a/shared-core/mga_irq.c b/shared-core/mga_irq.c new file mode 100644 index 00000000..568d193f --- /dev/null +++ b/shared-core/mga_irq.c @@ -0,0 +1,99 @@ +/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Eric Anholt <anholt@FreeBSD.org> + */ + +#include "mga.h" +#include "drmP.h" +#include "drm.h" +#include "mga_drm.h" +#include "mga_drv.h" + +void mga_dma_service( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + int status; + + status = MGA_READ( MGA_STATUS ); + + /* VBLANK interrupt */ + if ( status & MGA_VLINEPEN ) { + MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR ); + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + } +} + +int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence) +{ + unsigned int cur_vblank; + int ret = 0; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... + */ + DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, + ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) + + ~*sequence + 1 ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + +void mga_driver_irq_preinstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + MGA_WRITE( MGA_IEN, 0 ); + /* Clear bits if they're already high */ + MGA_WRITE( MGA_ICLEAR, ~0 ); +} + +void mga_driver_irq_postinstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + + /* Turn on VBL interrupt */ + MGA_WRITE( MGA_IEN, MGA_VLINEIEN ); +} + +void mga_driver_irq_uninstall( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = + (drm_mga_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + MGA_WRITE( MGA_IEN, 0 ); + } +} diff --git a/shared-core/mga_state.c b/shared-core/mga_state.c index 26ea3e7f..61077220 100644 --- a/shared-core/mga_state.c +++ b/shared-core/mga_state.c @@ -1075,3 +1075,36 @@ int mga_dma_blit( DRM_IOCTL_ARGS ) return 0; } + +int mga_getparam( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_mga_private_t *dev_priv = dev->dev_private; + drm_mga_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); + + switch( param.param ) { + case MGA_PARAM_IRQ_NR: + value = dev->irq; + break; + default: + return DRM_ERR(EINVAL); + } + + if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} diff --git a/shared-core/r128_drm.h b/shared-core/r128_drm.h index a8d23008..bbb1a93b 100644 --- a/shared-core/r128_drm.h +++ b/shared-core/r128_drm.h @@ -190,6 +190,7 @@ typedef struct drm_r128_sarea { #define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t) #define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t) #define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t) +#define DRM_IOCTL_R128_GETPARAM DRM_IOW( 0x52, drm_r128_getparam_t) typedef struct drm_r128_init { enum { @@ -305,4 +306,14 @@ typedef struct drm_r128_fullscreen { } func; } drm_r128_fullscreen_t; +/* 2.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define R128_PARAM_IRQ_NR 1 + +typedef struct drm_r128_getparam { + int param; + int *value; +} drm_r128_getparam_t; + #endif diff --git a/shared-core/r128_drv.h b/shared-core/r128_drv.h index aeb73e08..763fcb3a 100644 --- a/shared-core/r128_drv.h +++ b/shared-core/r128_drv.h @@ -124,6 +124,7 @@ extern int r128_cce_idle( DRM_IOCTL_ARGS ); extern int r128_engine_reset( DRM_IOCTL_ARGS ); extern int r128_fullscreen( DRM_IOCTL_ARGS ); extern int r128_cce_buffers( DRM_IOCTL_ARGS ); +extern int r128_getparam( DRM_IOCTL_ARGS ); extern void r128_freelist_reset( drm_device_t *dev ); extern drm_buf_t *r128_freelist_get( drm_device_t *dev ); @@ -213,6 +214,11 @@ extern int r128_cce_indirect( DRM_IOCTL_ARGS ); #define R128_DST_PITCH_OFFSET_C 0x1c80 # define R128_DST_TILE (1 << 31) +#define R128_GEN_INT_CNTL 0x0040 +# define R128_CRTC_VBLANK_INT_EN (1 << 0) +#define R128_GEN_INT_STATUS 0x0044 +# define R128_CRTC_VBLANK_INT (1 << 0) +# define R128_CRTC_VBLANK_INT_AK (1 << 0) #define R128_GEN_RESET_CNTL 0x00f0 # define R128_SOFT_RESET_GUI (1 << 0) diff --git a/shared-core/r128_irq.c b/shared-core/r128_irq.c new file mode 100644 index 00000000..a29a81b5 --- /dev/null +++ b/shared-core/r128_irq.c @@ -0,0 +1,99 @@ +/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- + * + * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + * + * The Weather Channel (TM) funded Tungsten Graphics to develop the + * initial release of the Radeon 8500 driver under the XFree86 license. + * This notice must be preserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Eric Anholt <anholt@FreeBSD.org> + */ + +#include "r128.h" +#include "drmP.h" +#include "drm.h" +#include "r128_drm.h" +#include "r128_drv.h" + +void r128_dma_service( DRM_IRQ_ARGS ) +{ + drm_device_t *dev = (drm_device_t *) arg; + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + int status; + + status = R128_READ( R128_GEN_INT_STATUS ); + + /* VBLANK interrupt */ + if ( status & R128_CRTC_VBLANK_INT ) { + R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK ); + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + } +} + +int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) +{ + unsigned int cur_vblank; + int ret = 0; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... + */ + DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, + ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) + + ~*sequence + 1 ) <= (1<<23) ) ); + + *sequence = cur_vblank; + + return ret; +} + +void r128_driver_irq_preinstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + + /* Disable *all* interrupts */ + R128_WRITE( R128_GEN_INT_CNTL, 0 ); + /* Clear vblank bit if it's already high */ + R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK ); +} + +void r128_driver_irq_postinstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + + /* Turn on VBL interrupt */ + R128_WRITE( R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN ); +} + +void r128_driver_irq_uninstall( drm_device_t *dev ) { + drm_r128_private_t *dev_priv = + (drm_r128_private_t *)dev->dev_private; + if ( dev_priv ) { + /* Disable *all* interrupts */ + R128_WRITE( R128_GEN_INT_CNTL, 0 ); + } +} diff --git a/shared-core/r128_state.c b/shared-core/r128_state.c index 6ae58639..68f73061 100644 --- a/shared-core/r128_state.c +++ b/shared-core/r128_state.c @@ -1564,3 +1564,36 @@ int r128_cce_indirect( DRM_IOCTL_ARGS ) return 0; } + +int r128_getparam( DRM_IOCTL_ARGS ) +{ + DRM_DEVICE; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_getparam_t param; + int value; + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t *)data, + sizeof(param) ); + + DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); + + switch( param.param ) { + case R128_PARAM_IRQ_NR: + value = dev->irq; + break; + default: + return DRM_ERR(EINVAL); + } + + if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { + DRM_ERROR( "copy_to_user\n" ); + return DRM_ERR(EFAULT); + } + + return 0; +} |