diff options
-rw-r--r-- | shared-core/radeon_cp.c | 163 | ||||
-rw-r--r-- | shared-core/radeon_drm.h | 2 | ||||
-rw-r--r-- | shared-core/radeon_drv.h | 20 | ||||
-rw-r--r-- | shared/radeon.h | 4 | ||||
-rw-r--r-- | shared/radeon_cp.c | 163 | ||||
-rw-r--r-- | shared/radeon_drm.h | 2 | ||||
-rw-r--r-- | shared/radeon_drv.h | 20 |
7 files changed, 258 insertions, 116 deletions
diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index f6964908..4efb6c2a 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -859,7 +859,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, | ( dev_priv->fb_location >> 16 ) ); #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { RADEON_WRITE( RADEON_MC_AGP_LOCATION, (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & 0xffff0000) | @@ -868,7 +868,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, ring_start = (dev_priv->cp_ring->offset - dev->agp->base + dev_priv->gart_vm_start); - } else + } else #endif ring_start = (dev_priv->cp_ring->offset - dev->sg->handle @@ -886,7 +886,9 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, dev_priv->ring.tail = cur_read_ptr; #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { + /* set RADEON_AGP_BASE here instead of relying on X from user space */ + RADEON_WRITE( RADEON_AGP_BASE, (unsigned int)dev->agp->base ); RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset - dev->agp->base @@ -1003,20 +1005,11 @@ static void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on ) static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) { - drm_radeon_private_t *dev_priv; + drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); - dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); - if ( dev_priv == NULL ) - return DRM_ERR(ENOMEM); - - memset( dev_priv, 0, sizeof(drm_radeon_private_t) ); - - dev_priv->is_pci = init->is_pci; - - if ( dev_priv->is_pci && !dev->sg ) { + if ( (!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg ) { DRM_ERROR( "PCI GART memory not allocated!\n" ); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1025,7 +1018,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) if ( dev_priv->usec_timeout < 1 || dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) { DRM_DEBUG( "TIMEOUT problem!\n" ); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1041,7 +1033,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) && ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) { DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode ); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1113,7 +1104,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) if(!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1121,28 +1111,24 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); if(!dev_priv->mmio) { DRM_ERROR("could not find mmio region!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset ); if(!dev_priv->cp_ring) { DRM_ERROR("could not find cp ring region!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset ); if(!dev_priv->ring_rptr) { DRM_ERROR("could not find ring read pointer!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); if(!dev_priv->buffers) { DRM_ERROR("could not find dma buffer region!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1151,7 +1137,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_FIND_MAP( dev_priv->gart_textures, init->gart_textures_offset ); if ( !dev_priv->gart_textures ) { DRM_ERROR("could not find GART texture region!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1162,7 +1147,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) init->sarea_priv_offset); #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { DRM_IOREMAP( dev_priv->cp_ring, dev ); DRM_IOREMAP( dev_priv->ring_rptr, dev ); DRM_IOREMAP( dev_priv->buffers, dev ); @@ -1170,7 +1155,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { DRM_ERROR("could not find ioremap agp regions!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1212,7 +1196,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) + RADEON_READ( RADEON_CONFIG_APER_SIZE ); #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) + if (dev_priv->flags & CHIP_IS_AGP) dev_priv->gart_buffers_offset = (dev_priv->buffers->offset - dev->agp->base + dev_priv->gart_vm_start); @@ -1241,7 +1225,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { /* Turn off PCI GART */ radeon_set_pcigart( dev_priv, 0 ); } else @@ -1250,7 +1234,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, &dev_priv->bus_pci_gart)) { DRM_ERROR( "failed to init PCI GART!\n" ); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(ENOMEM); } @@ -1264,8 +1247,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) dev_priv->last_buf = 0; - dev->dev_private = (void *)dev_priv; - radeon_do_engine_reset( dev ); return 0; @@ -1273,6 +1254,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) int radeon_do_cleanup_cp( drm_device_t *dev ) { + drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); #if __HAVE_IRQ @@ -1283,29 +1265,26 @@ int radeon_do_cleanup_cp( drm_device_t *dev ) if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); #endif - if ( dev->dev_private ) { - drm_radeon_private_t *dev_priv = dev->dev_private; - #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { - if ( dev_priv->cp_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cp_ring, dev ); - if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); - if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers, dev ); - } else + if (dev_priv->flags & CHIP_IS_AGP) { + if ( dev_priv->cp_ring != NULL ) + DRM_IOREMAPFREE( dev_priv->cp_ring, dev ); + if ( dev_priv->ring_rptr != NULL ) + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); + if ( dev_priv->buffers != NULL ) + DRM_IOREMAPFREE( dev_priv->buffers, dev ); + } else #endif - { - if (!DRM(ati_pcigart_cleanup)( dev, - dev_priv->phys_pci_gart, - dev_priv->bus_pci_gart )) - DRM_ERROR( "failed to cleanup PCI GART!\n" ); - } - - DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), - DRM_MEM_DRIVER ); - dev->dev_private = NULL; + { + if (!DRM(ati_pcigart_cleanup)( dev, + dev_priv->phys_pci_gart, + dev_priv->bus_pci_gart )) + DRM_ERROR( "failed to cleanup PCI GART!\n" ); + } + { + int flags = dev_priv->flags; + memset(dev_priv, 0, sizeof(*dev_priv)); + dev_priv->flags = flags; } return 0; @@ -1330,7 +1309,7 @@ static int radeon_do_resume_cp( drm_device_t *dev ) DRM_DEBUG("Starting radeon_do_resume_cp()\n"); #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { /* Turn off PCI GART */ radeon_set_pcigart( dev_priv, 0 ); } else @@ -1444,8 +1423,10 @@ void radeon_do_release( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; int ret; + DRM_DEBUG("dev_priv %ptr\n", dev_priv); if (dev_priv) { + if (dev_priv->cp_running) { /* Stop the cp */ while ((ret = radeon_do_cp_idle( dev_priv )) != 0) { @@ -1461,7 +1442,8 @@ void radeon_do_release( drm_device_t *dev ) } /* Disable *all* interrupts */ - RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); + if (dev_priv->mmio) /* remove this after permanent addmaps */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); /* Free memory heap structures */ radeon_mem_takedown( &(dev_priv->gart_heap) ); @@ -1745,3 +1727,80 @@ int radeon_cp_buffers( DRM_IOCTL_ARGS ) return ret; } + +static int radeon_register_regions(struct pci_dev *pdev) { + int retcode = -EINVAL; + + /* request the mem regions */ + if (!request_mem_region (pci_resource_start( pdev, 2 ), + pci_resource_len(pdev, 2), DRIVER_NAME)) { + printk(KERN_ERR DRIVER_NAME ": cannot reserve MMIO region\n"); + return retcode; + } + if (!request_mem_region (pci_resource_start( pdev, 0 ), + pci_resource_len(pdev, 0), DRIVER_NAME)) { + printk(KERN_ERR DRIVER_NAME ": cannot reserve FB region\n"); + return retcode; + } + return 0; +} + +static void radeon_release_regions(struct pci_dev *pdev) { + release_mem_region (pci_resource_start( pdev, 2 ), pci_resource_len(pdev, 2)); + release_mem_region (pci_resource_start( pdev, 0 ), pci_resource_len(pdev, 0)); +} + +/* Always create a map record for MMIO and FB memory, done from DRIVER_POSTINIT */ +int radeon_preinit( drm_device_t *dev, unsigned long flags ) +{ + int retcode = -EINVAL; + u32 save, temp; + drm_radeon_private_t *dev_priv; + + dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); + if ( dev_priv == NULL ) + return DRM_ERR(ENOMEM); + DRM_DEBUG("dev_priv %ptr\n", dev_priv); + + memset( dev_priv, 0, sizeof(drm_radeon_private_t) ); + dev->dev_private = (void *)dev_priv; + dev_priv->flags = flags; + + /* request the mem regions */ + if (!DRM(fb_loaded)) + if ((retcode = radeon_register_regions(dev->pdev)) != 0) + return retcode; + + /* There are signatures in BIOS and PCI-SSID for a PCI card, but they are not very reliable. + Following detection method works for all cards tested so far. + Note, checking AGP_ENABLE bit after drmAgpEnable call can also give the correct result. + However, calling drmAgpEnable on a PCI card can cause some strange lockup when the server + restarts next time. + */ + pci_read_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, &save); + pci_write_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, save | RADEON_AGP_ENABLE); + pci_read_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, &temp); + if (temp & RADEON_AGP_ENABLE) + dev_priv->flags |= CHIP_IS_AGP; + DRM_DEBUG("%s card detected\n", ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI")); + pci_write_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, save); + + return 0; +} + +int radeon_postinit( drm_device_t *dev, unsigned long flags ) +{ + return 0; +} + +void radeon_postcleanup( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER ); + + if (!DRM(fb_loaded)) + radeon_release_regions(dev->pdev); + + dev->dev_private = NULL; +} diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index e447308b..207a0c00 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -433,7 +433,7 @@ typedef struct drm_radeon_init { RADEON_INIT_R200_CP = 0x03 } func; unsigned long sarea_priv_offset; - int is_pci; + int is_pci; /* not used, driver asks hardware */ int cp_mode; int gart_size; int ring_size; diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 81b9a98e..eb2d4dca 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -40,6 +40,7 @@ enum radeon_chip_flags { CHIP_IS_MOBILITY = 0x00010000UL, CHIP_IS_IGP = 0x00020000UL, CHIP_SINGLE_CRTC = 0x00040000UL, + CHIP_IS_AGP = 0x00080000UL, }; #define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) @@ -81,6 +82,9 @@ struct mem_block { }; typedef struct drm_radeon_private { + + u32 flags; /* see radeon_chip_flags */ + drm_radeon_ring_buffer_t ring; drm_radeon_sarea_t *sarea_priv; @@ -103,7 +107,6 @@ typedef struct drm_radeon_private { int is_r200; - int is_pci; unsigned long phys_pci_gart; dma_addr_t bus_pci_gart; @@ -223,13 +226,13 @@ extern void radeon_do_release(drm_device_t *dev); #define RADEON_BOX_WAIT_IDLE 0x8 #define RADEON_BOX_TEXTURE_LOAD 0x10 - - /* Register definitions, register access macros and drmAddMap constants * for Radeon kernel driver. */ - #define RADEON_AGP_COMMAND 0x0f60 +#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ +# define RADEON_AGP_ENABLE (1<<8) + #define RADEON_AUX_SCISSOR_CNTL 0x26f0 # define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24) # define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25) @@ -252,6 +255,11 @@ extern void radeon_do_release(drm_device_t *dev); #define RADEON_CRTC2_OFFSET 0x0324 #define RADEON_CRTC2_OFFSET_CNTL 0x0328 +#define RADEON_MPP_TB_CONFIG 0x01c0 +#define RADEON_MEM_CNTL 0x0140 +#define RADEON_MEM_SDRAM_MODE_REG 0x0158 +#define RADEON_AGP_BASE 0x0170 + #define RADEON_RB3D_COLOROFFSET 0x1c40 #define RADEON_RB3D_COLORPITCH 0x1c48 @@ -730,7 +738,9 @@ do { \ } while (0) extern int RADEON_READ_PLL( drm_device_t *dev, int addr ); - +extern int radeon_preinit( drm_device_t *dev, unsigned long flags ); +extern int radeon_postinit( drm_device_t *dev, unsigned long flags ); +extern void radeon_postcleanup( drm_device_t *dev ); #define CP_PACKET0( reg, n ) \ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) diff --git a/shared/radeon.h b/shared/radeon.h index eb857daf..44c4aee7 100644 --- a/shared/radeon.h +++ b/shared/radeon.h @@ -127,6 +127,10 @@ do { \ filp_priv->radeon_fb_delta = 0; \ } while( 0 ) +#define DRIVER_POSTINIT(dev, flags) radeon_postinit(dev, flags) +#define DRIVER_PREINIT(dev, flags) radeon_preinit(dev, flags) +#define DRIVER_POSTCLEANUP(dev) radeon_postcleanup(dev) + /* When a client dies: * - Check for and clean up flipped page state * - Free any alloced GART memory. diff --git a/shared/radeon_cp.c b/shared/radeon_cp.c index f6964908..4efb6c2a 100644 --- a/shared/radeon_cp.c +++ b/shared/radeon_cp.c @@ -859,7 +859,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, | ( dev_priv->fb_location >> 16 ) ); #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { RADEON_WRITE( RADEON_MC_AGP_LOCATION, (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & 0xffff0000) | @@ -868,7 +868,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, ring_start = (dev_priv->cp_ring->offset - dev->agp->base + dev_priv->gart_vm_start); - } else + } else #endif ring_start = (dev_priv->cp_ring->offset - dev->sg->handle @@ -886,7 +886,9 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev, dev_priv->ring.tail = cur_read_ptr; #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { + /* set RADEON_AGP_BASE here instead of relying on X from user space */ + RADEON_WRITE( RADEON_AGP_BASE, (unsigned int)dev->agp->base ); RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset - dev->agp->base @@ -1003,20 +1005,11 @@ static void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on ) static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) { - drm_radeon_private_t *dev_priv; + drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); - dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); - if ( dev_priv == NULL ) - return DRM_ERR(ENOMEM); - - memset( dev_priv, 0, sizeof(drm_radeon_private_t) ); - - dev_priv->is_pci = init->is_pci; - - if ( dev_priv->is_pci && !dev->sg ) { + if ( (!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg ) { DRM_ERROR( "PCI GART memory not allocated!\n" ); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1025,7 +1018,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) if ( dev_priv->usec_timeout < 1 || dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) { DRM_DEBUG( "TIMEOUT problem!\n" ); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1041,7 +1033,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) && ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) { DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode ); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1113,7 +1104,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) if(!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1121,28 +1111,24 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); if(!dev_priv->mmio) { DRM_ERROR("could not find mmio region!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset ); if(!dev_priv->cp_ring) { DRM_ERROR("could not find cp ring region!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset ); if(!dev_priv->ring_rptr) { DRM_ERROR("could not find ring read pointer!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); if(!dev_priv->buffers) { DRM_ERROR("could not find dma buffer region!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1151,7 +1137,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) DRM_FIND_MAP( dev_priv->gart_textures, init->gart_textures_offset ); if ( !dev_priv->gart_textures ) { DRM_ERROR("could not find GART texture region!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1162,7 +1147,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) init->sarea_priv_offset); #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { DRM_IOREMAP( dev_priv->cp_ring, dev ); DRM_IOREMAP( dev_priv->ring_rptr, dev ); DRM_IOREMAP( dev_priv->buffers, dev ); @@ -1170,7 +1155,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { DRM_ERROR("could not find ioremap agp regions!\n"); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } @@ -1212,7 +1196,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) + RADEON_READ( RADEON_CONFIG_APER_SIZE ); #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) + if (dev_priv->flags & CHIP_IS_AGP) dev_priv->gart_buffers_offset = (dev_priv->buffers->offset - dev->agp->base + dev_priv->gart_vm_start); @@ -1241,7 +1225,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { /* Turn off PCI GART */ radeon_set_pcigart( dev_priv, 0 ); } else @@ -1250,7 +1234,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, &dev_priv->bus_pci_gart)) { DRM_ERROR( "failed to init PCI GART!\n" ); - dev->dev_private = (void *)dev_priv; radeon_do_cleanup_cp(dev); return DRM_ERR(ENOMEM); } @@ -1264,8 +1247,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) dev_priv->last_buf = 0; - dev->dev_private = (void *)dev_priv; - radeon_do_engine_reset( dev ); return 0; @@ -1273,6 +1254,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) int radeon_do_cleanup_cp( drm_device_t *dev ) { + drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "\n" ); #if __HAVE_IRQ @@ -1283,29 +1265,26 @@ int radeon_do_cleanup_cp( drm_device_t *dev ) if ( dev->irq_enabled ) DRM(irq_uninstall)(dev); #endif - if ( dev->dev_private ) { - drm_radeon_private_t *dev_priv = dev->dev_private; - #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { - if ( dev_priv->cp_ring != NULL ) - DRM_IOREMAPFREE( dev_priv->cp_ring, dev ); - if ( dev_priv->ring_rptr != NULL ) - DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); - if ( dev_priv->buffers != NULL ) - DRM_IOREMAPFREE( dev_priv->buffers, dev ); - } else + if (dev_priv->flags & CHIP_IS_AGP) { + if ( dev_priv->cp_ring != NULL ) + DRM_IOREMAPFREE( dev_priv->cp_ring, dev ); + if ( dev_priv->ring_rptr != NULL ) + DRM_IOREMAPFREE( dev_priv->ring_rptr, dev ); + if ( dev_priv->buffers != NULL ) + DRM_IOREMAPFREE( dev_priv->buffers, dev ); + } else #endif - { - if (!DRM(ati_pcigart_cleanup)( dev, - dev_priv->phys_pci_gart, - dev_priv->bus_pci_gart )) - DRM_ERROR( "failed to cleanup PCI GART!\n" ); - } - - DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t), - DRM_MEM_DRIVER ); - dev->dev_private = NULL; + { + if (!DRM(ati_pcigart_cleanup)( dev, + dev_priv->phys_pci_gart, + dev_priv->bus_pci_gart )) + DRM_ERROR( "failed to cleanup PCI GART!\n" ); + } + { + int flags = dev_priv->flags; + memset(dev_priv, 0, sizeof(*dev_priv)); + dev_priv->flags = flags; } return 0; @@ -1330,7 +1309,7 @@ static int radeon_do_resume_cp( drm_device_t *dev ) DRM_DEBUG("Starting radeon_do_resume_cp()\n"); #if __REALLY_HAVE_AGP - if ( !dev_priv->is_pci ) { + if (dev_priv->flags & CHIP_IS_AGP) { /* Turn off PCI GART */ radeon_set_pcigart( dev_priv, 0 ); } else @@ -1444,8 +1423,10 @@ void radeon_do_release( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; int ret; + DRM_DEBUG("dev_priv %ptr\n", dev_priv); if (dev_priv) { + if (dev_priv->cp_running) { /* Stop the cp */ while ((ret = radeon_do_cp_idle( dev_priv )) != 0) { @@ -1461,7 +1442,8 @@ void radeon_do_release( drm_device_t *dev ) } /* Disable *all* interrupts */ - RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); + if (dev_priv->mmio) /* remove this after permanent addmaps */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); /* Free memory heap structures */ radeon_mem_takedown( &(dev_priv->gart_heap) ); @@ -1745,3 +1727,80 @@ int radeon_cp_buffers( DRM_IOCTL_ARGS ) return ret; } + +static int radeon_register_regions(struct pci_dev *pdev) { + int retcode = -EINVAL; + + /* request the mem regions */ + if (!request_mem_region (pci_resource_start( pdev, 2 ), + pci_resource_len(pdev, 2), DRIVER_NAME)) { + printk(KERN_ERR DRIVER_NAME ": cannot reserve MMIO region\n"); + return retcode; + } + if (!request_mem_region (pci_resource_start( pdev, 0 ), + pci_resource_len(pdev, 0), DRIVER_NAME)) { + printk(KERN_ERR DRIVER_NAME ": cannot reserve FB region\n"); + return retcode; + } + return 0; +} + +static void radeon_release_regions(struct pci_dev *pdev) { + release_mem_region (pci_resource_start( pdev, 2 ), pci_resource_len(pdev, 2)); + release_mem_region (pci_resource_start( pdev, 0 ), pci_resource_len(pdev, 0)); +} + +/* Always create a map record for MMIO and FB memory, done from DRIVER_POSTINIT */ +int radeon_preinit( drm_device_t *dev, unsigned long flags ) +{ + int retcode = -EINVAL; + u32 save, temp; + drm_radeon_private_t *dev_priv; + + dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER ); + if ( dev_priv == NULL ) + return DRM_ERR(ENOMEM); + DRM_DEBUG("dev_priv %ptr\n", dev_priv); + + memset( dev_priv, 0, sizeof(drm_radeon_private_t) ); + dev->dev_private = (void *)dev_priv; + dev_priv->flags = flags; + + /* request the mem regions */ + if (!DRM(fb_loaded)) + if ((retcode = radeon_register_regions(dev->pdev)) != 0) + return retcode; + + /* There are signatures in BIOS and PCI-SSID for a PCI card, but they are not very reliable. + Following detection method works for all cards tested so far. + Note, checking AGP_ENABLE bit after drmAgpEnable call can also give the correct result. + However, calling drmAgpEnable on a PCI card can cause some strange lockup when the server + restarts next time. + */ + pci_read_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, &save); + pci_write_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, save | RADEON_AGP_ENABLE); + pci_read_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, &temp); + if (temp & RADEON_AGP_ENABLE) + dev_priv->flags |= CHIP_IS_AGP; + DRM_DEBUG("%s card detected\n", ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI")); + pci_write_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, save); + + return 0; +} + +int radeon_postinit( drm_device_t *dev, unsigned long flags ) +{ + return 0; +} + +void radeon_postcleanup( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER ); + + if (!DRM(fb_loaded)) + radeon_release_regions(dev->pdev); + + dev->dev_private = NULL; +} diff --git a/shared/radeon_drm.h b/shared/radeon_drm.h index e447308b..207a0c00 100644 --- a/shared/radeon_drm.h +++ b/shared/radeon_drm.h @@ -433,7 +433,7 @@ typedef struct drm_radeon_init { RADEON_INIT_R200_CP = 0x03 } func; unsigned long sarea_priv_offset; - int is_pci; + int is_pci; /* not used, driver asks hardware */ int cp_mode; int gart_size; int ring_size; diff --git a/shared/radeon_drv.h b/shared/radeon_drv.h index 81b9a98e..eb2d4dca 100644 --- a/shared/radeon_drv.h +++ b/shared/radeon_drv.h @@ -40,6 +40,7 @@ enum radeon_chip_flags { CHIP_IS_MOBILITY = 0x00010000UL, CHIP_IS_IGP = 0x00020000UL, CHIP_SINGLE_CRTC = 0x00040000UL, + CHIP_IS_AGP = 0x00080000UL, }; #define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) @@ -81,6 +82,9 @@ struct mem_block { }; typedef struct drm_radeon_private { + + u32 flags; /* see radeon_chip_flags */ + drm_radeon_ring_buffer_t ring; drm_radeon_sarea_t *sarea_priv; @@ -103,7 +107,6 @@ typedef struct drm_radeon_private { int is_r200; - int is_pci; unsigned long phys_pci_gart; dma_addr_t bus_pci_gart; @@ -223,13 +226,13 @@ extern void radeon_do_release(drm_device_t *dev); #define RADEON_BOX_WAIT_IDLE 0x8 #define RADEON_BOX_TEXTURE_LOAD 0x10 - - /* Register definitions, register access macros and drmAddMap constants * for Radeon kernel driver. */ - #define RADEON_AGP_COMMAND 0x0f60 +#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ +# define RADEON_AGP_ENABLE (1<<8) + #define RADEON_AUX_SCISSOR_CNTL 0x26f0 # define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24) # define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25) @@ -252,6 +255,11 @@ extern void radeon_do_release(drm_device_t *dev); #define RADEON_CRTC2_OFFSET 0x0324 #define RADEON_CRTC2_OFFSET_CNTL 0x0328 +#define RADEON_MPP_TB_CONFIG 0x01c0 +#define RADEON_MEM_CNTL 0x0140 +#define RADEON_MEM_SDRAM_MODE_REG 0x0158 +#define RADEON_AGP_BASE 0x0170 + #define RADEON_RB3D_COLOROFFSET 0x1c40 #define RADEON_RB3D_COLORPITCH 0x1c48 @@ -730,7 +738,9 @@ do { \ } while (0) extern int RADEON_READ_PLL( drm_device_t *dev, int addr ); - +extern int radeon_preinit( drm_device_t *dev, unsigned long flags ); +extern int radeon_postinit( drm_device_t *dev, unsigned long flags ); +extern void radeon_postcleanup( drm_device_t *dev ); #define CP_PACKET0( reg, n ) \ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) |