diff options
| author | Dave Airlie <airlied@linux.ie> | 2007-05-08 01:19:23 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@linux.ie> | 2007-05-08 01:19:23 -0400 |
| commit | f2b04cd219e5c0f1214c0eeeec814ddd08a12c1b (patch) | |
| tree | fa114ea7f96b5985e10c7f8696d635b074649bab | |
| parent | 5b94f675f57e4ff16c8fda09088d7480a84dcd91 (diff) | |
drm/radeon: upgrade to 1.27 - make PCI GART more flexible
radeon: make PCI GART aperture size variable, but making table size variable
This is precursor to getting a TTM backend for this stuff, and also
allows the PCI table to be allocated at fb 0
radeon: add support for reverse engineered xpress200m
The IGPGART setup code was traced using mmio-trace on fglrx by myself
and Phillip Ezolt <phillipezolt@gmail.com> on dri-devel.
This code doesn't let the 3D driver work properly as the card has no
vertex shader support.
Thanks to Matthew Garrett + Ubuntu for providing me some hardware to do this
work on.
Signed-off-by: Dave Airlie <airlied@linux.ie>
| -rw-r--r-- | drivers/char/drm/ati_pcigart.c | 84 | ||||
| -rw-r--r-- | drivers/char/drm/drmP.h | 7 | ||||
| -rw-r--r-- | drivers/char/drm/drm_pciids.h | 1 | ||||
| -rw-r--r-- | drivers/char/drm/r128_cce.c | 3 | ||||
| -rw-r--r-- | drivers/char/drm/r128_drv.h | 2 | ||||
| -rw-r--r-- | drivers/char/drm/radeon_cp.c | 71 | ||||
| -rw-r--r-- | drivers/char/drm/radeon_drm.h | 1 | ||||
| -rw-r--r-- | drivers/char/drm/radeon_drv.h | 23 | ||||
| -rw-r--r-- | drivers/char/drm/radeon_state.c | 6 |
9 files changed, 150 insertions, 48 deletions
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index bd7be09ea53d..5b91bc04ea4e 100644 --- a/drivers/char/drm/ati_pcigart.c +++ b/drivers/char/drm/ati_pcigart.c | |||
| @@ -33,59 +33,44 @@ | |||
| 33 | 33 | ||
| 34 | #include "drmP.h" | 34 | #include "drmP.h" |
| 35 | 35 | ||
| 36 | #if PAGE_SIZE == 65536 | ||
| 37 | # define ATI_PCIGART_TABLE_ORDER 0 | ||
| 38 | # define ATI_PCIGART_TABLE_PAGES (1 << 0) | ||
| 39 | #elif PAGE_SIZE == 16384 | ||
| 40 | # define ATI_PCIGART_TABLE_ORDER 1 | ||
| 41 | # define ATI_PCIGART_TABLE_PAGES (1 << 1) | ||
| 42 | #elif PAGE_SIZE == 8192 | ||
| 43 | # define ATI_PCIGART_TABLE_ORDER 2 | ||
| 44 | # define ATI_PCIGART_TABLE_PAGES (1 << 2) | ||
| 45 | #elif PAGE_SIZE == 4096 | ||
| 46 | # define ATI_PCIGART_TABLE_ORDER 3 | ||
| 47 | # define ATI_PCIGART_TABLE_PAGES (1 << 3) | ||
| 48 | #else | ||
| 49 | # error - PAGE_SIZE not 64K, 16K, 8K or 4K | ||
| 50 | #endif | ||
| 51 | |||
| 52 | # define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */ | ||
| 53 | # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ | 36 | # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ |
| 54 | 37 | ||
| 55 | static void *drm_ati_alloc_pcigart_table(void) | 38 | static void *drm_ati_alloc_pcigart_table(int order) |
| 56 | { | 39 | { |
| 57 | unsigned long address; | 40 | unsigned long address; |
| 58 | struct page *page; | 41 | struct page *page; |
| 59 | int i; | 42 | int i; |
| 60 | DRM_DEBUG("%s\n", __FUNCTION__); | 43 | |
| 44 | DRM_DEBUG("%s: alloc %d order\n", __FUNCTION__, order); | ||
| 61 | 45 | ||
| 62 | address = __get_free_pages(GFP_KERNEL | __GFP_COMP, | 46 | address = __get_free_pages(GFP_KERNEL | __GFP_COMP, |
| 63 | ATI_PCIGART_TABLE_ORDER); | 47 | order); |
| 64 | if (address == 0UL) { | 48 | if (address == 0UL) { |
| 65 | return NULL; | 49 | return NULL; |
| 66 | } | 50 | } |
| 67 | 51 | ||
| 68 | page = virt_to_page(address); | 52 | page = virt_to_page(address); |
| 69 | 53 | ||
| 70 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) | 54 | for (i = 0; i < order; i++, page++) |
| 71 | SetPageReserved(page); | 55 | SetPageReserved(page); |
| 72 | 56 | ||
| 73 | DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); | 57 | DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); |
| 74 | return (void *)address; | 58 | return (void *)address; |
| 75 | } | 59 | } |
| 76 | 60 | ||
| 77 | static void drm_ati_free_pcigart_table(void *address) | 61 | static void drm_ati_free_pcigart_table(void *address, int order) |
| 78 | { | 62 | { |
| 79 | struct page *page; | 63 | struct page *page; |
| 80 | int i; | 64 | int i; |
| 65 | int num_pages = 1 << order; | ||
| 81 | DRM_DEBUG("%s\n", __FUNCTION__); | 66 | DRM_DEBUG("%s\n", __FUNCTION__); |
| 82 | 67 | ||
| 83 | page = virt_to_page((unsigned long)address); | 68 | page = virt_to_page((unsigned long)address); |
| 84 | 69 | ||
| 85 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) | 70 | for (i = 0; i < num_pages; i++, page++) |
| 86 | ClearPageReserved(page); | 71 | ClearPageReserved(page); |
| 87 | 72 | ||
| 88 | free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER); | 73 | free_pages((unsigned long)address, order); |
| 89 | } | 74 | } |
| 90 | 75 | ||
| 91 | int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | 76 | int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) |
| @@ -93,6 +78,8 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
| 93 | drm_sg_mem_t *entry = dev->sg; | 78 | drm_sg_mem_t *entry = dev->sg; |
| 94 | unsigned long pages; | 79 | unsigned long pages; |
| 95 | int i; | 80 | int i; |
| 81 | int order; | ||
| 82 | int num_pages, max_pages; | ||
| 96 | 83 | ||
| 97 | /* we need to support large memory configurations */ | 84 | /* we need to support large memory configurations */ |
| 98 | if (!entry) { | 85 | if (!entry) { |
| @@ -100,15 +87,19 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
| 100 | return 0; | 87 | return 0; |
| 101 | } | 88 | } |
| 102 | 89 | ||
| 90 | order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE); | ||
| 91 | num_pages = 1 << order; | ||
| 92 | |||
| 103 | if (gart_info->bus_addr) { | 93 | if (gart_info->bus_addr) { |
| 104 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { | 94 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { |
| 105 | pci_unmap_single(dev->pdev, gart_info->bus_addr, | 95 | pci_unmap_single(dev->pdev, gart_info->bus_addr, |
| 106 | ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, | 96 | num_pages * PAGE_SIZE, |
| 107 | PCI_DMA_TODEVICE); | 97 | PCI_DMA_TODEVICE); |
| 108 | } | 98 | } |
| 109 | 99 | ||
| 110 | pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) | 100 | max_pages = (gart_info->table_size / sizeof(u32)); |
| 111 | ? entry->pages : ATI_MAX_PCIGART_PAGES; | 101 | pages = (entry->pages <= max_pages) |
| 102 | ? entry->pages : max_pages; | ||
| 112 | 103 | ||
| 113 | for (i = 0; i < pages; i++) { | 104 | for (i = 0; i < pages; i++) { |
| 114 | if (!entry->busaddr[i]) | 105 | if (!entry->busaddr[i]) |
| @@ -123,13 +114,12 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
| 123 | 114 | ||
| 124 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN | 115 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN |
| 125 | && gart_info->addr) { | 116 | && gart_info->addr) { |
| 126 | drm_ati_free_pcigart_table(gart_info->addr); | 117 | drm_ati_free_pcigart_table(gart_info->addr, order); |
| 127 | gart_info->addr = NULL; | 118 | gart_info->addr = NULL; |
| 128 | } | 119 | } |
| 129 | 120 | ||
| 130 | return 1; | 121 | return 1; |
| 131 | } | 122 | } |
| 132 | |||
| 133 | EXPORT_SYMBOL(drm_ati_pcigart_cleanup); | 123 | EXPORT_SYMBOL(drm_ati_pcigart_cleanup); |
| 134 | 124 | ||
| 135 | int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | 125 | int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) |
| @@ -139,6 +129,9 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
| 139 | unsigned long pages; | 129 | unsigned long pages; |
| 140 | u32 *pci_gart, page_base, bus_address = 0; | 130 | u32 *pci_gart, page_base, bus_address = 0; |
| 141 | int i, j, ret = 0; | 131 | int i, j, ret = 0; |
| 132 | int order; | ||
| 133 | int max_pages; | ||
| 134 | int num_pages; | ||
| 142 | 135 | ||
| 143 | if (!entry) { | 136 | if (!entry) { |
| 144 | DRM_ERROR("no scatter/gather memory!\n"); | 137 | DRM_ERROR("no scatter/gather memory!\n"); |
| @@ -148,7 +141,10 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
| 148 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { | 141 | if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { |
| 149 | DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); | 142 | DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); |
| 150 | 143 | ||
| 151 | address = drm_ati_alloc_pcigart_table(); | 144 | order = drm_order((gart_info->table_size + |
| 145 | (PAGE_SIZE-1)) / PAGE_SIZE); | ||
| 146 | num_pages = 1 << order; | ||
| 147 | address = drm_ati_alloc_pcigart_table(order); | ||
| 152 | if (!address) { | 148 | if (!address) { |
| 153 | DRM_ERROR("cannot allocate PCI GART page!\n"); | 149 | DRM_ERROR("cannot allocate PCI GART page!\n"); |
| 154 | goto done; | 150 | goto done; |
| @@ -160,11 +156,13 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) | |||
| 160 | } | 156 | } |
| 161 | 157 | ||
| 162 | bus_address = pci_map_single(dev->pdev, address, | 158 | bus_address = pci_map_single(dev->pdev, address, |
