summaryrefslogtreecommitdiff
path: root/drivers/char/drm/ati_pcigart.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@starflyer.(none)>2005-09-11 20:28:11 +1000
committerDave Airlie <airlied@linux.ie>2005-09-11 20:28:11 +1000
commitea98a92ff18c03bf7f4d21536986cbbcb4c10cd9 (patch)
treefbff15aaacf19824083c9edb8d37548031636580 /drivers/char/drm/ati_pcigart.c
parent9d17601c4e132eee9fe450191f6866fb9fb5a762 (diff)
drm: add radeon PCI express support
Add support for Radeon PCI Express cards (needs a new X.org DDX) Also allows PCI GART table to be stored in VRAM for non PCIE cards Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/ati_pcigart.c')
-rw-r--r--drivers/char/drm/ati_pcigart.c82
1 files changed, 49 insertions, 33 deletions
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index 0aec5ef481b8..957596c63934 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -91,9 +91,7 @@ static void drm_ati_free_pcigart_table( unsigned long address )
free_pages( address, ATI_PCIGART_TABLE_ORDER );
}
-int drm_ati_pcigart_cleanup( drm_device_t *dev,
- unsigned long addr,
- dma_addr_t bus_addr)
+int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
{
drm_sg_mem_t *entry = dev->sg;
unsigned long pages;
@@ -105,10 +103,12 @@ int drm_ati_pcigart_cleanup( drm_device_t *dev,
return 0;
}
- if ( bus_addr ) {
- pci_unmap_single(dev->pdev, bus_addr,
- ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
- PCI_DMA_TODEVICE);
+ if (gart_info->bus_addr) {
+ if (gart_info->gart_table_location==DRM_ATI_GART_MAIN) {
+ pci_unmap_single(dev->pdev, gart_info->bus_addr,
+ ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+ PCI_DMA_TODEVICE);
+ }
pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
? entry->pages : ATI_MAX_PCIGART_PAGES;
@@ -118,19 +118,21 @@ int drm_ati_pcigart_cleanup( drm_device_t *dev,
pci_unmap_single(dev->pdev, entry->busaddr[i],
PAGE_SIZE, PCI_DMA_TODEVICE);
}
+
+ if (gart_info->gart_table_location==DRM_ATI_GART_MAIN)
+ gart_info->bus_addr=0;
}
- if ( addr ) {
- drm_ati_free_pcigart_table( addr );
+ if (gart_info->gart_table_location==DRM_ATI_GART_MAIN && gart_info->addr) {
+ drm_ati_free_pcigart_table(gart_info->addr);
+ gart_info->addr=0;
}
return 1;
}
EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
-int drm_ati_pcigart_init( drm_device_t *dev,
- unsigned long *addr,
- dma_addr_t *bus_addr)
+int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
{
drm_sg_mem_t *entry = dev->sg;
unsigned long address = 0;
@@ -143,25 +145,36 @@ int drm_ati_pcigart_init( drm_device_t *dev,
goto done;
}
- address = drm_ati_alloc_pcigart_table();
- if ( !address ) {
- DRM_ERROR( "cannot allocate PCI GART page!\n" );
- goto done;
- }
+ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
+ {
+ DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
+
+ address = drm_ati_alloc_pcigart_table();
+ if ( !address ) {
+ DRM_ERROR( "cannot allocate PCI GART page!\n" );
+ goto done;
+ }
+
+ if ( !dev->pdev ) {
+ DRM_ERROR( "PCI device unknown!\n" );
+ goto done;
+ }
- if ( !dev->pdev ) {
- DRM_ERROR( "PCI device unknown!\n" );
- goto done;
+ bus_address = pci_map_single(dev->pdev, (void *)address,
+ ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+ PCI_DMA_TODEVICE);
+ if (bus_address == 0) {
+ DRM_ERROR( "unable to map PCIGART pages!\n" );
+ drm_ati_free_pcigart_table( address );
+ address = 0;
+ goto done;
+ }
}
-
- bus_address = pci_map_single(dev->pdev, (void *)address,
- ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
- PCI_DMA_TODEVICE);
- if (bus_address == 0) {
- DRM_ERROR( "unable to map PCIGART pages!\n" );
- drm_ati_free_pcigart_table( address );
- address = 0;
- goto done;
+ else
+ {
+ address = gart_info->addr;
+ bus_address = gart_info->bus_addr;
+ DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n", bus_address, address);
}
pci_gart = (u32 *)address;
@@ -179,7 +192,7 @@ int drm_ati_pcigart_init( drm_device_t *dev,
PCI_DMA_TODEVICE);
if (entry->busaddr[i] == 0) {
DRM_ERROR( "unable to map PCIGART pages!\n" );
- drm_ati_pcigart_cleanup( dev, address, bus_address );
+ drm_ati_pcigart_cleanup(dev, gart_info);
address = 0;
bus_address = 0;
goto done;
@@ -187,7 +200,10 @@ int drm_ati_pcigart_init( drm_device_t *dev,
page_base = (u32) entry->busaddr[i];
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
- *pci_gart++ = cpu_to_le32( page_base );
+ if (gart_info->is_pcie)
+ *pci_gart = (cpu_to_le32(page_base)>>8) | 0xc;
+ else
+ *pci_gart++ = cpu_to_le32( page_base );
page_base += ATI_PCIGART_PAGE_SIZE;
}
}
@@ -201,8 +217,8 @@ int drm_ati_pcigart_init( drm_device_t *dev,
#endif
done:
- *addr = address;
- *bus_addr = bus_address;
+ gart_info->addr = address;
+ gart_info->bus_addr = bus_address;
return ret;
}
EXPORT_SYMBOL(drm_ati_pcigart_init);