diff options
author | Dave Airlie <airlied@starflyer.(none)> | 2005-09-11 06:28:11 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2005-09-11 06:28:11 -0400 |
commit | ea98a92ff18c03bf7f4d21536986cbbcb4c10cd9 (patch) | |
tree | fbff15aaacf19824083c9edb8d37548031636580 /drivers/char/drm/ati_pcigart.c | |
parent | 9d17601c4e132eee9fe450191f6866fb9fb5a762 (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.c | 82 |
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 ) | |||
91 | free_pages( address, ATI_PCIGART_TABLE_ORDER ); | 91 | free_pages( address, ATI_PCIGART_TABLE_ORDER ); |
92 | } | 92 | } |
93 | 93 | ||
94 | int drm_ati_pcigart_cleanup( drm_device_t *dev, | 94 | int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) |
95 | unsigned long addr, | ||
96 | dma_addr_t bus_addr) | ||
97 | { | 95 | { |
98 | drm_sg_mem_t *entry = dev->sg; | 96 | drm_sg_mem_t *entry = dev->sg; |
99 | unsigned long pages; | 97 | unsigned long pages; |
@@ -105,10 +103,12 @@ int drm_ati_pcigart_cleanup( drm_device_t *dev, | |||
105 | return 0; | 103 | return 0; |
106 | } | 104 | } |
107 | 105 | ||
108 | if ( bus_addr ) { | 106 | if (gart_info->bus_addr) { |
109 | pci_unmap_single(dev->pdev, bus_addr, | 107 | if (gart_info->gart_table_location==DRM_ATI_GART_MAIN) { |
110 | ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, | 108 | pci_unmap_single(dev->pdev, gart_info->bus_addr, |
111 | PCI_DMA_TODEVICE); | 109 | ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, |
110 | PCI_DMA_TODEVICE); | ||
111 | } | ||
112 | 112 | ||
113 | pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) | 113 | pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES ) |
114 | ? entry->pages : ATI_MAX_PCIGART_PAGES; | 114 | ? entry->pages : ATI_MAX_PCIGART_PAGES; |
@@ -118,19 +118,21 @@ int drm_ati_pcigart_cleanup( drm_device_t *dev, | |||
118 | pci_unmap_single(dev->pdev, entry->busaddr[i], | 118 | pci_unmap_single(dev->pdev, entry->busaddr[i], |
119 | PAGE_SIZE, PCI_DMA_TODEVICE); | 119 | PAGE_SIZE, PCI_DMA_TODEVICE); |
120 | } | 120 | } |
121 | |||
122 | if (gart_info->gart_table_location==DRM_ATI_GART_MAIN) | ||
123 | gart_info->bus_addr=0; | ||
121 | } | 124 | } |
122 | 125 | ||
123 | if ( addr ) { | 126 | if (gart_info->gart_table_location==DRM_ATI_GART_MAIN && gart_info->addr) { |
124 | drm_ati_free_pcigart_table( addr ); | 127 | drm_ati_free_pcigart_table(gart_info->addr); |
128 | gart_info->addr=0; | ||
125 | } | 129 | } |
126 | 130 | ||
127 | return 1; | 131 | return 1; |
128 | } | 132 | } |
129 | EXPORT_SYMBOL(drm_ati_pcigart_cleanup); | 133 | EXPORT_SYMBOL(drm_ati_pcigart_cleanup); |
130 | 134 | ||
131 | int drm_ati_pcigart_init( drm_device_t *dev, | 135 | int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) |
132 | unsigned long *addr, | ||
133 | dma_addr_t *bus_addr) | ||
134 | { | 136 | { |
135 | drm_sg_mem_t *entry = dev->sg; | 137 | drm_sg_mem_t *entry = dev->sg; |
136 | unsigned long address = 0; | 138 | unsigned long address = 0; |
@@ -143,25 +145,36 @@ int drm_ati_pcigart_init( drm_device_t *dev, | |||
143 | goto done; | 145 | goto done; |
144 | } | 146 | } |
145 | 147 | ||
146 | address = drm_ati_alloc_pcigart_table(); | 148 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) |
147 | if ( !address ) { | 149 | { |
148 | DRM_ERROR( "cannot allocate PCI GART page!\n" ); | 150 | DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); |
149 | goto done; | 151 | |
150 | } | 152 | address = drm_ati_alloc_pcigart_table(); |
153 | if ( !address ) { | ||
154 | DRM_ERROR( "cannot allocate PCI GART page!\n" ); | ||
155 | goto done; | ||
156 | } | ||
157 | |||
158 | if ( !dev->pdev ) { | ||
159 | DRM_ERROR( "PCI device unknown!\n" ); | ||
160 | goto done; | ||
161 | } | ||
151 | 162 | ||
152 | if ( !dev->pdev ) { | 163 | bus_address = pci_map_single(dev->pdev, (void *)address, |
153 | DRM_ERROR( "PCI device unknown!\n" ); | 164 | ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, |
154 | goto done; | 165 | PCI_DMA_TODEVICE); |
166 | if (bus_address == 0) { | ||
167 | DRM_ERROR( "unable to map PCIGART pages!\n" ); | ||
168 | drm_ati_free_pcigart_table( address ); | ||
169 | address = 0; | ||
170 | goto done; | ||
171 | } | ||
155 | } | 172 | } |
156 | 173 | else | |
157 | bus_address = pci_map_single(dev->pdev, (void *)address, | 174 | { |
158 | ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, | 175 | address = gart_info->addr; |
159 | PCI_DMA_TODEVICE); | 176 | bus_address = gart_info->bus_addr; |
160 | if (bus_address == 0) { | 177 | DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n", bus_address, address); |
161 | DRM_ERROR( "unable to map PCIGART pages!\n" ); | ||
162 | drm_ati_free_pcigart_table( address ); | ||
163 | address = 0; | ||
164 | goto done; | ||
165 | } | 178 | } |
166 | 179 | ||
167 | pci_gart = (u32 *)address; | 180 | pci_gart = (u32 *)address; |
@@ -179,7 +192,7 @@ int drm_ati_pcigart_init( drm_device_t *dev, | |||
179 | PCI_DMA_TODEVICE); | 192 | PCI_DMA_TODEVICE); |
180 | if (entry->busaddr[i] == 0) { | 193 | if (entry->busaddr[i] == 0) { |
181 | DRM_ERROR( "unable to map PCIGART pages!\n" ); | 194 | DRM_ERROR( "unable to map PCIGART pages!\n" ); |
182 | drm_ati_pcigart_cleanup( dev, address, bus_address ); | 195 | drm_ati_pcigart_cleanup(dev, gart_info); |
183 | address = 0; | 196 | address = 0; |
184 | bus_address = 0; | 197 | bus_address = 0; |
185 | goto done; | 198 | goto done; |
@@ -187,7 +200,10 @@ int drm_ati_pcigart_init( drm_device_t *dev, | |||
187 | page_base = (u32) entry->busaddr[i]; | 200 | page_base = (u32) entry->busaddr[i]; |
188 | 201 | ||
189 | for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { | 202 | for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { |
190 | *pci_gart++ = cpu_to_le32( page_base ); | 203 | if (gart_info->is_pcie) |
204 | *pci_gart = (cpu_to_le32(page_base)>>8) | 0xc; | ||
205 | else | ||
206 | *pci_gart++ = cpu_to_le32( page_base ); | ||
191 | page_base += ATI_PCIGART_PAGE_SIZE; | 207 | page_base += ATI_PCIGART_PAGE_SIZE; |
192 | } | 208 | } |
193 | } | 209 | } |
@@ -201,8 +217,8 @@ int drm_ati_pcigart_init( drm_device_t *dev, | |||
201 | #endif | 217 | #endif |
202 | 218 | ||
203 | done: | 219 | done: |
204 | *addr = address; | 220 | gart_info->addr = address; |
205 | *bus_addr = bus_address; | 221 | gart_info->bus_addr = bus_address; |
206 | return ret; | 222 | return ret; |
207 | } | 223 | } |
208 | EXPORT_SYMBOL(drm_ati_pcigart_init); | 224 | EXPORT_SYMBOL(drm_ati_pcigart_init); |