aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:52:35 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:52:35 -0400
commit5335a40be6867eff986a31bcd8fc82a5cb1e16bb (patch)
treeb32be59c2a2679a5cc3fef172006886f7dcd2466 /drivers/char
parent393bfca19ecdce60a8d9a4d2577cac11ca924a25 (diff)
parentef68d295508d52e792abf70d4f84461104d33b9d (diff)
Merge branch 'drm-patches' of master.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-patches' of master.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6: via: Make sure we flush write-combining using a follow-up read. via: Try to improve command-buffer chaining. drm: remove old taskqueue remnant drm: rename badly named define and cleanup ioctl code spacing radeon: Don't mess up page flipping when a file descriptor is closed. drm/radeon: upgrade to 1.27 - make PCI GART more flexible
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/drm/ati_pcigart.c84
-rw-r--r--drivers/char/drm/drmP.h7
-rw-r--r--drivers/char/drm/drm_drv.c10
-rw-r--r--drivers/char/drm/drm_os_linux.h3
-rw-r--r--drivers/char/drm/drm_pciids.h1
-rw-r--r--drivers/char/drm/r128_cce.c3
-rw-r--r--drivers/char/drm/r128_drv.h2
-rw-r--r--drivers/char/drm/radeon_cp.c71
-rw-r--r--drivers/char/drm/radeon_drm.h1
-rw-r--r--drivers/char/drm/radeon_drv.h24
-rw-r--r--drivers/char/drm/radeon_state.c52
-rw-r--r--drivers/char/drm/via_dma.c111
-rw-r--r--drivers/char/drm/via_drv.h5
13 files changed, 222 insertions, 152 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
55static void *drm_ati_alloc_pcigart_table(void) 38static 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
77static void drm_ati_free_pcigart_table(void *address) 61static 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
91int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) 76int 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
133EXPORT_SYMBOL(drm_ati_pcigart_cleanup); 123EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
134 124
135int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) 125int 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,
163 ATI_PCIGART_TABLE_PAGES * 159 num_pages * PAGE_SIZE,
164 PAGE_SIZE, PCI_DMA_TODEVICE); 160 PCI_DMA_TODEVICE);
165 if (bus_address == 0) { 161 if (bus_address == 0) {
166 DRM_ERROR("unable to map PCIGART pages!\n"); 162 DRM_ERROR("unable to map PCIGART pages!\n");
167 drm_ati_free_pcigart_table(address); 163 order = drm_order((gart_info->table_size +
164 (PAGE_SIZE-1)) / PAGE_SIZE);
165 drm_ati_free_pcigart_table(address, order);
168 address = NULL; 166 address = NULL;
169 goto done; 167 goto done;
170 } 168 }
@@ -177,10 +175,11 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
177 175
178 pci_gart = (u32 *) address; 176 pci_gart = (u32 *) address;
179 177
180 pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) 178 max_pages = (gart_info->table_size / sizeof(u32));
181 ? entry->pages : ATI_MAX_PCIGART_PAGES; 179 pages = (entry->pages <= max_pages)
180 ? entry->pages : max_pages;
182 181
183 memset(pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32)); 182 memset(pci_gart, 0, max_pages * sizeof(u32));
184 183
185 for (i = 0; i < pages; i++) { 184 for (i = 0; i < pages; i++) {
186 /* we need to support large memory configurations */ 185 /* we need to support large memory configurations */
@@ -198,10 +197,18 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
198 page_base = (u32) entry->busaddr[i]; 197 page_base = (u32) entry->busaddr[i];
199 198
200 for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { 199 for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
201 if (gart_info->is_pcie) 200 switch(gart_info->gart_reg_if) {
201 case DRM_ATI_GART_IGP:
202 *pci_gart = cpu_to_le32((page_base) | 0xc);
203 break;
204 case DRM_ATI_GART_PCIE:
202 *pci_gart = cpu_to_le32((page_base >> 8) | 0xc); 205 *pci_gart = cpu_to_le32((page_base >> 8) | 0xc);
203 else 206 break;
207 default:
208 case DRM_ATI_GART_PCI:
204 *pci_gart = cpu_to_le32(page_base); 209 *pci_gart = cpu_to_le32(page_base);
210 break;
211 }
205 pci_gart++; 212 pci_gart++;
206 page_base += ATI_PCIGART_PAGE_SIZE; 213 page_base += ATI_PCIGART_PAGE_SIZE;
207 } 214 }
@@ -220,5 +227,4 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
220 gart_info->bus_addr = bus_address; 227 gart_info->bus_addr = bus_address;
221 return ret; 228 return ret;
222} 229}
223
224EXPORT_SYMBOL(drm_ati_pcigart_init); 230EXPORT_SYMBOL(drm_ati_pcigart_init);
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 80041d5b792d..d494315752a2 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -519,12 +519,17 @@ typedef struct drm_vbl_sig {
519#define DRM_ATI_GART_MAIN 1 519#define DRM_ATI_GART_MAIN 1
520#define DRM_ATI_GART_FB 2 520#define DRM_ATI_GART_FB 2
521 521
522#define DRM_ATI_GART_PCI 1
523#define DRM_ATI_GART_PCIE 2
524#define DRM_ATI_GART_IGP 3
525
522typedef struct ati_pcigart_info { 526typedef struct ati_pcigart_info {
523 int gart_table_location; 527 int gart_table_location;
524 int is_pcie; 528 int gart_reg_if;
525 void *addr; 529 void *addr;
526 dma_addr_t bus_addr; 530 dma_addr_t bus_addr;
527 drm_local_map_t mapping; 531 drm_local_map_t mapping;
532 int table_size;
528} drm_ati_pcigart_info; 533} drm_ati_pcigart_info;
529 534
530/* 535/*
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 26bec30ee86e..8e77b7ed0f44 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -15,8 +15,6 @@
15 * #define DRIVER_DESC "Matrox G200/G400" 15 * #define DRIVER_DESC "Matrox G200/G400"
16 * #define DRIVER_DATE "20001127" 16 * #define DRIVER_DATE "20001127"
17 * 17 *
18 * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
19 *
20 * #define drm_x mga_##x 18 * #define drm_x mga_##x
21 * \endcode 19 * \endcode
22 */ 20 */
@@ -120,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
120 [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, 118 [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
121}; 119};
122 120
123#define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) 121#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
124 122
125/** 123/**
126 * Take down the DRM device. 124 * Take down the DRM device.
@@ -496,11 +494,11 @@ int drm_ioctl(struct inode *inode, struct file *filp,
496 (long)old_encode_dev(priv->head->device), 494 (long)old_encode_dev(priv->head->device),
497 priv->authenticated); 495 priv->authenticated);
498 496
499 if ((nr >= DRIVER_IOCTL_COUNT) && 497 if ((nr >= DRM_CORE_IOCTL_COUNT) &&
500 ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) 498 ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
501 goto err_i1; 499 goto err_i1;
502 if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) 500 if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
503 && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) 501 (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
504 ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; 502 ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
505 else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) 503 else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE))
506 ioctl = &drm_ioctls[nr]; 504 ioctl = &drm_ioctls[nr];
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index 2908b72daa6e..0fe7b4497927 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -70,9 +70,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
70 70
71#endif 71#endif
72 72
73/** Task queue handler arguments */
74#define DRM_TASKQUEUE_ARGS void *arg
75
76/** For data going into the kernel through the ioctl argument */ 73/** For data going into the kernel through the ioctl argument */
77#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \ 74#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
78 if ( copy_from_user(&arg1, arg2, arg3) ) \ 75 if ( copy_from_user(&arg1, arg2, arg3) ) \
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 01cf482d2d00..31cdde83713b 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -102,6 +102,7 @@
102 {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ 102 {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
103 {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \ 103 {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
104 {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ 104 {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
105 {0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
105 {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ 106 {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
106 {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ 107 {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
107 {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ 108 {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
index db5a60450e68..1014602c43a7 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -560,9 +560,10 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
560 if (dev_priv->is_pci) { 560 if (dev_priv->is_pci) {
561#endif 561#endif
562 dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; 562 dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
563 dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
563 dev_priv->gart_info.addr = NULL; 564 dev_priv->gart_info.addr = NULL;
564 dev_priv->gart_info.bus_addr = 0; 565 dev_priv->gart_info.bus_addr = 0;
565 dev_priv->gart_info.is_pcie = 0; 566 dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
566 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { 567 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
567 DRM_ERROR("failed to init PCI GART!\n"); 568 DRM_ERROR("failed to init PCI GART!\n");
568 dev->dev_private = (void *)dev_priv; 569 dev->dev_private = (void *)dev_priv;
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index f1efb49de8df..9086835686dc 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -383,6 +383,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
383 383
384#define R128_PERFORMANCE_BOXES 0 384#define R128_PERFORMANCE_BOXES 0
385 385
386#define R128_PCIGART_TABLE_SIZE 32768
387
386#define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) 388#define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
387#define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) 389#define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
388#define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) 390#define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index c1850ecac302..68338389d836 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -830,6 +830,15 @@ static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
830 return RADEON_READ(RADEON_PCIE_DATA); 830 return RADEON_READ(RADEON_PCIE_DATA);
831} 831}
832 832
833static u32 RADEON_READ_IGPGART(drm_radeon_private_t *dev_priv, int addr)
834{
835 u32 ret;
836 RADEON_WRITE(RADEON_IGPGART_INDEX, addr & 0x7f);
837 ret = RADEON_READ(RADEON_IGPGART_DATA);
838 RADEON_WRITE(RADEON_IGPGART_INDEX, 0x7f);
839 return ret;
840}
841
833#if RADEON_FIFO_DEBUG 842#if RADEON_FIFO_DEBUG
834static void radeon_status(drm_radeon_private_t * dev_priv) 843static void radeon_status(drm_radeon_private_t * dev_priv)
835{ 844{
@@ -1267,7 +1276,44 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
1267 } 1276 }
1268} 1277}
1269 1278
1270/* Enable or disable PCI-E GART on the chip */ 1279/* Enable or disable IGP GART on the chip */
1280static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
1281{
1282 u32 temp, tmp;
1283
1284 tmp = RADEON_READ(RADEON_AIC_CNTL);
1285 if (on) {
1286 DRM_DEBUG("programming igpgart %08X %08lX %08X\n",
1287 dev_priv->gart_vm_start,
1288 (long)dev_priv->gart_info.bus_addr,
1289 dev_priv->gart_size);
1290
1291 RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_18, 0x1000);
1292 RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, 0x1);
1293 RADEON_WRITE_IGPGART(RADEON_IGPGART_CTRL, 0x42040800);
1294 RADEON_WRITE_IGPGART(RADEON_IGPGART_BASE_ADDR,
1295 dev_priv->gart_info.bus_addr);
1296
1297 temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_UNK_39);
1298 RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_39, temp);
1299
1300 RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev_priv->gart_vm_start);
1301 dev_priv->gart_size = 32*1024*1024;
1302 RADEON_WRITE(RADEON_MC_AGP_LOCATION,
1303 (((dev_priv->gart_vm_start - 1 +
1304 dev_priv->gart_size) & 0xffff0000) |
1305 (dev_priv->gart_vm_start >> 16)));
1306
1307 temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_ENABLE);
1308 RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, temp);
1309
1310 RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
1311 RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x1);
1312 RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
1313 RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x0);
1314 }
1315}
1316
1271static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) 1317static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
1272{ 1318{
1273 u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); 1319 u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
@@ -1302,6 +1348,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
1302{ 1348{
1303 u32 tmp; 1349 u32 tmp;
1304 1350
1351 if (dev_priv->flags & RADEON_IS_IGPGART) {
1352 radeon_set_igpgart(dev_priv, on);
1353 return;
1354 }
1355
1305 if (dev_priv->flags & RADEON_IS_PCIE) { 1356 if (dev_priv->flags & RADEON_IS_PCIE) {
1306 radeon_set_pciegart(dev_priv, on); 1357 radeon_set_pciegart(dev_priv, on);
1307 return; 1358 return;
@@ -1620,20 +1671,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1620#endif 1671#endif
1621 { 1672 {
1622 /* if we have an offset set from userspace */ 1673 /* if we have an offset set from userspace */
1623 if (dev_priv->pcigart_offset) { 1674 if (dev_priv->pcigart_offset_set) {
1624 dev_priv->gart_info.bus_addr = 1675 dev_priv->gart_info.bus_addr =
1625 dev_priv->pcigart_offset + dev_priv->fb_location; 1676 dev_priv->pcigart_offset + dev_priv->fb_location;
1626 dev_priv->gart_info.mapping.offset = 1677 dev_priv->gart_info.mapping.offset =
1627 dev_priv->gart_info.bus_addr; 1678 dev_priv->gart_info.bus_addr;
1628 dev_priv->gart_info.mapping.size = 1679 dev_priv->gart_info.mapping.size =
1629 RADEON_PCIGART_TABLE_SIZE; 1680 dev_priv->gart_info.table_size;
1630 1681
1631 drm_core_ioremap(&dev_priv->gart_info.mapping, dev); 1682 drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
1632 dev_priv->gart_info.addr = 1683 dev_priv->gart_info.addr =
1633 dev_priv->gart_info.mapping.handle; 1684 dev_priv->gart_info.mapping.handle;
1634 1685
1635 dev_priv->gart_info.is_pcie = 1686 if (dev_priv->flags & RADEON_IS_PCIE)
1636 !!(dev_priv->flags & RADEON_IS_PCIE); 1687 dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
1688 else
1689 dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
1637 dev_priv->gart_info.gart_table_location = 1690 dev_priv->gart_info.gart_table_location =
1638 DRM_ATI_GART_FB; 1691 DRM_ATI_GART_FB;
1639 1692
@@ -1641,6 +1694,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
1641 dev_priv->gart_info.addr, 1694 dev_priv->gart_info.addr,
1642 dev_priv->pcigart_offset); 1695 dev_priv->pcigart_offset);
1643 } else { 1696 } else {
1697 if (dev_priv->flags & RADEON_IS_IGPGART)
1698 dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
1699 else
1700 dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
1644 dev_priv->gart_info.gart_table_location = 1701 dev_priv->gart_info.gart_table_location =
1645 DRM_ATI_GART_MAIN; 1702 DRM_ATI_GART_MAIN;
1646 dev_priv->gart_info.addr = NULL; 1703 dev_priv->gart_info.addr = NULL;
@@ -1714,7 +1771,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
1714 if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) 1771 if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
1715 { 1772 {
1716 drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); 1773 drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
1717 dev_priv->gart_info.addr = NULL; 1774 dev_priv->gart_info.addr = 0;
1718 } 1775 }
1719 } 1776 }
1720 /* only clear to the start of flags */ 1777 /* only clear to the start of flags */
@@ -2222,6 +2279,8 @@ int radeon_driver_firstopen(struct drm_device *dev)
2222 drm_local_map_t *map; 2279 drm_local_map_t *map;
2223 drm_radeon_private_t *dev_priv = dev->dev_private; 2280 drm_radeon_private_t *dev_priv = dev->dev_private;
2224 2281
2282 dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
2283
2225 ret = drm_addmap(dev, drm_get_resource_start(dev, 2), 2284 ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
2226 drm_get_resource_len(dev, 2), _DRM_REGISTERS, 2285 drm_get_resource_len(dev, 2), _DRM_REGISTERS,
2227 _DRM_READ_ONLY, &dev_priv->mmio); 2286 _DRM_READ_ONLY, &dev_priv->mmio);
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 8d6350dd5360..66c4b6fed04f 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -707,6 +707,7 @@ typedef struct drm_radeon_setparam {
707#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ 707#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
708#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ 708#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
709#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ 709#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
710#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */
710 711
711/* 1.14: Clients can allocate/free a surface 712/* 1.14: Clients can allocate/free a surface
712 */ 713 */
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 8b105f1460a7..54f49ef4bef0 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -95,9 +95,11 @@
95 * 1.24- Add general-purpose packet for manipulating scratch registers (r300) 95 * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
96 * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, 96 * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
97 * new packet type) 97 * new packet type)
98 * 1.26- Add support for variable size PCI(E) gart aperture
99 * 1.27- Add support for IGP GART
98 */ 100 */
99#define DRIVER_MAJOR 1 101#define DRIVER_MAJOR 1
100#define DRIVER_MINOR 25 102#define DRIVER_MINOR 27
101#define DRIVER_PATCHLEVEL 0 103#define DRIVER_PATCHLEVEL 0
102 104
103/* 105/*
@@ -143,6 +145,7 @@ enum radeon_chip_flags {
143 RADEON_IS_PCIE = 0x00200000UL, 145 RADEON_IS_PCIE = 0x00200000UL,
144 RADEON_NEW_MEMMAP = 0x00400000UL, 146 RADEON_NEW_MEMMAP = 0x00400000UL,
145 RADEON_IS_PCI = 0x00800000UL, 147 RADEON_IS_PCI = 0x00800000UL,
148 RADEON_IS_IGPGART = 0x01000000UL,
146}; 149};
147 150
148#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ 151#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \
@@ -240,7 +243,6 @@ typedef struct drm_radeon_private {
240 243
241 int do_boxes; 244 int do_boxes;
242 int page_flipping; 245 int page_flipping;
243 int current_page;
244 246
245 u32 color_fmt; 247 u32 color_fmt;
246 unsigned int front_offset; 248 unsigned int front_offset;
@@ -280,6 +282,7 @@ typedef struct drm_radeon_private {
280 struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES]; 282 struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
281 283
282 unsigned long pcigart_offset; 284 unsigned long pcigart_offset;
285 unsigned int pcigart_offset_set;
283 drm_ati_pcigart_info gart_info; 286 drm_ati_pcigart_info gart_info;
284 287
285 u32 scratch_ages[5]; 288 u32 scratch_ages[5];
@@ -432,6 +435,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
432#define RADEON_PCIE_TX_GART_END_LO 0x16 435#define RADEON_PCIE_TX_GART_END_LO 0x16
433#define RADEON_PCIE_TX_GART_END_HI 0x17 436#define RADEON_PCIE_TX_GART_END_HI 0x17
434 437
438#define RADEON_IGPGART_INDEX 0x168
439#define RADEON_IGPGART_DATA 0x16c
440#define RADEON_IGPGART_UNK_18 0x18
441#define RADEON_IGPGART_CTRL 0x2b
442#define RADEON_IGPGART_BASE_ADDR 0x2c
443#define RADEON_IGPGART_FLUSH 0x2e
444#define RADEON_IGPGART_ENABLE 0x38
445#define RADEON_IGPGART_UNK_39 0x39
446
435#define RADEON_MPP_TB_CONFIG 0x01c0 447#define RADEON_MPP_TB_CONFIG 0x01c0
436#define RADEON_MEM_CNTL 0x0140 448#define RADEON_MEM_CNTL 0x0140
437#define RADEON_MEM_SDRAM_MODE_REG 0x0158 449#define RADEON_MEM_SDRAM_MODE_REG 0x0158
@@ -964,6 +976,14 @@ do { \
964 RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \ 976 RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
965} while (0) 977} while (0)
966 978
979#define RADEON_WRITE_IGPGART( addr, val ) \
980do { \
981 RADEON_WRITE( RADEON_IGPGART_INDEX, \
982 ((addr) & 0x7f) | (1 << 8)); \
983 RADEON_WRITE( RADEON_IGPGART_DATA, (val) ); \
984 RADEON_WRITE( RADEON_IGPGART_INDEX, 0x7f ); \
985} while (0)
986
967#define RADEON_WRITE_PCIE( addr, val ) \ 987#define RADEON_WRITE_PCIE( addr, val ) \
968do { \ 988do { \
969 RADEON_WRITE8( RADEON_PCIE_INDEX, \ 989 RADEON_WRITE8( RADEON_PCIE_INDEX, \
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 938eccb78cc0..98c5f1d3a8e7 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -773,7 +773,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,
773 RADEON_GMC_SRC_DATATYPE_COLOR | 773 RADEON_GMC_SRC_DATATYPE_COLOR |
774 RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); 774 RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
775 775
776 if (dev_priv->page_flipping && dev_priv->current_page == 1) { 776 if (dev_priv->sarea_priv->pfCurrentPage == 1) {
777 OUT_RING(dev_priv->front_pitch_offset); 777 OUT_RING(dev_priv->front_pitch_offset);
778 } else { 778 } else {
779 OUT_RING(dev_priv->back_pitch_offset); 779 OUT_RING(dev_priv->back_pitch_offset);
@@ -861,7 +861,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
861 861
862 dev_priv->stats.clears++; 862 dev_priv->stats.clears++;
863 863
864 if (dev_priv->page_flipping && dev_priv->current_page == 1) { 864 if (dev_priv->sarea_priv->pfCurrentPage == 1) {
865 unsigned int tmp = flags; 865 unsigned int tmp = flags;
866 866
867 flags &= ~(RADEON_FRONT | RADEON_BACK); 867 flags &= ~(RADEON_FRONT | RADEON_BACK);
@@ -1382,7 +1382,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
1382 /* Make this work even if front & back are flipped: 1382 /* Make this work even if front & back are flipped:
1383 */ 1383 */
1384 OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); 1384 OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
1385 if (dev_priv->current_page == 0) { 1385 if (dev_priv->sarea_priv->pfCurrentPage == 0) {
1386 OUT_RING(dev_priv->back_pitch_offset); 1386 OUT_RING(dev_priv->back_pitch_offset);
1387 OUT_RING(dev_priv->front_pitch_offset); 1387 OUT_RING(dev_priv->front_pitch_offset);
1388 } else { 1388 } else {
@@ -1416,12 +1416,12 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
1416{ 1416{
1417 drm_radeon_private_t *dev_priv = dev->dev_private; 1417 drm_radeon_private_t *dev_priv = dev->dev_private;
1418 drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle; 1418 drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
1419 int offset = (dev_priv->current_page == 1) 1419 int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
1420 ? dev_priv->front_offset : dev_priv->back_offset; 1420 ? dev_priv->front_offset : dev_priv->back_offset;
1421 RING_LOCALS; 1421 RING_LOCALS;
1422 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", 1422 DRM_DEBUG("%s: pfCurrentPage=%d\n",
1423 __FUNCTION__, 1423 __FUNCTION__,
1424 dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); 1424 dev_priv->sarea_priv->pfCurrentPage);
1425 1425
1426 /* Do some trivial performance monitoring... 1426 /* Do some trivial performance monitoring...
1427 */ 1427 */
@@ -1449,8 +1449,8 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
1449 * performing the swapbuffer ioctl. 1449 * performing the swapbuffer ioctl.
1450 */ 1450 */
1451 dev_priv->sarea_priv->last_frame++; 1451 dev_priv->sarea_priv->last_frame++;
1452 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = 1452 dev_priv->sarea_priv->pfCurrentPage =
1453 1 - dev_priv->current_page; 1453 1 - dev_priv->sarea_priv->pfCurrentPage;
1454 1454
1455 BEGIN_RING(2); 1455 BEGIN_RING(2);
1456 1456
@@ -2152,24 +2152,10 @@ static int radeon_do_init_pageflip(drm_device_t * dev)
2152 ADVANCE_RING(); 2152 ADVANCE_RING();
2153 2153
2154 dev_priv->page_flipping = 1; 2154 dev_priv->page_flipping = 1;
2155 dev_priv->current_page = 0;
2156 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
2157 2155
2158 return 0; 2156 if (dev_priv->sarea_priv->pfCurrentPage != 1)
2159} 2157 dev_priv->sarea_priv->pfCurrentPage = 0;
2160
2161/* Called whenever a client dies, from drm_release.
2162 * NOTE: Lock isn't necessarily held when this is called!
2163 */
2164static int radeon_do_cleanup_pageflip(drm_device_t * dev)
2165{
2166 drm_radeon_private_t *dev_priv = dev->dev_private;
2167 DRM_DEBUG("\n");
2168
2169 if (dev_priv->current_page != 0)
2170 radeon_cp_dispatch_flip(dev);
2171 2158
2172 dev_priv->page_flipping = 0;
2173 return 0; 2159 return 0;
2174} 2160}
2175 2161
@@ -3145,10 +3131,16 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
3145 break; 3131 break;
3146 case RADEON_SETPARAM_PCIGART_LOCATION: 3132 case RADEON_SETPARAM_PCIGART_LOCATION:
3147 dev_priv->pcigart_offset = sp.value; 3133 dev_priv->pcigart_offset = sp.value;
3134 dev_priv->pcigart_offset_set = 1;
3148 break; 3135 break;
3149 case RADEON_SETPARAM_NEW_MEMMAP: 3136 case RADEON_SETPARAM_NEW_MEMMAP:
3150 dev_priv->new_memmap = sp.value; 3137 dev_priv->new_memmap = sp.value;
3151 break; 3138 break;
3139 case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
3140 dev_priv->gart_info.table_size = sp.value;
3141 if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
3142 dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
3143 break;
3152 default: 3144 default:
3153 DRM_DEBUG("Invalid parameter %d\n", sp.param); 3145 DRM_DEBUG("Invalid parameter %d\n", sp.param);
3154 return DRM_ERR(EINVAL); 3146 return DRM_ERR(EINVAL);
@@ -3168,9 +3160,7 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
3168{ 3160{
3169 if (dev->dev_private) { 3161 if (dev->dev_private) {
3170 drm_radeon_private_t *dev_priv = dev->dev_private; 3162 drm_radeon_private_t *dev_priv = dev->dev_private;
3171 if (dev_priv->page_flipping) { 3163 dev_priv->page_flipping = 0;
3172 radeon_do_cleanup_pageflip(dev);
3173 }
3174 radeon_mem_release(filp, dev_priv->gart_heap); 3164 radeon_mem_release(filp, dev_priv->gart_heap);
3175 radeon_mem_release(filp, dev_priv->fb_heap); 3165 radeon_mem_release(filp, dev_priv->fb_heap);
3176 radeon_surfaces_release(filp, dev_priv); 3166 radeon_surfaces_release(filp, dev_priv);
@@ -3179,6 +3169,14 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
3179 3169
3180void radeon_driver_lastclose(drm_device_t * dev) 3170void radeon_driver_lastclose(drm_device_t * dev)
3181{ 3171{
3172 if (dev->dev_private) {
3173 drm_radeon_private_t *dev_priv = dev->dev_private;
3174
3175 if (dev_priv->sarea_priv &&
3176 dev_priv->sarea_priv->pfCurrentPage != 0)
3177 radeon_cp_dispatch_flip(dev);
3178 }
3179
3182 radeon_do_release(dev); 3180 radeon_do_release(dev);
3183} 3181}
3184 3182
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index c0539c6299cf..13a9c5ca4593 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -252,7 +252,7 @@ static int via_dma_init(DRM_IOCTL_ARGS)
252 break; 252 break;
253 case VIA_DMA_INITIALIZED: 253 case VIA_DMA_INITIALIZED:
254 retcode = (dev_priv->ring.virtual_start != NULL) ? 254 retcode = (dev_priv->ring.virtual_start != NULL) ?
255 0 : DRM_ERR(EFAULT); 255 0 : DRM_ERR(EFAULT);
256 break; 256 break;
257 default: 257 default:
258 retcode = DRM_ERR(EINVAL); 258 retcode = DRM_ERR(EINVAL);
@@ -432,56 +432,34 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
432{ 432{
433 int paused, count; 433 int paused, count;
434 volatile uint32_t *paused_at = dev_priv->last_pause_ptr; 434 volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
435 uint32_t reader,ptr;
435 436
437 paused = 0;
436 via_flush_write_combine(); 438 via_flush_write_combine();
437 while (!*(via_get_dma(dev_priv) - 1)) ; 439 (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1);
438 *dev_priv->last_pause_ptr = pause_addr_lo; 440 *paused_at = pause_addr_lo;
439 via_flush_write_combine(); 441 via_flush_write_combine();
440 442 (void) *paused_at;
441 /* 443 reader = *(dev_priv->hw_addr_ptr);
442 * The below statement is inserted to really force the flush. 444 ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
443 * Not sure it is needed. 445 dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
444 */
445
446 while (!*dev_priv->last_pause_ptr) ;
447 dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; 446 dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
448 while (!*dev_priv->last_pause_ptr) ;
449 447
450 paused = 0; 448 if ((ptr - reader) <= dev_priv->dma_diff ) {
451 count = 20; 449 count = 10000000;
452 450 while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
453 while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--) ;
454 if ((count <= 8) && (count >= 0)) {
455 uint32_t rgtr, ptr;
456 rgtr = *(dev_priv->hw_addr_ptr);
457 ptr = ((volatile char *)dev_priv->last_pause_ptr -
458 dev_priv->dma_ptr) + dev_priv->dma_offset +
459 (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE;
460 if (rgtr <= ptr) {
461 DRM_ERROR
462 ("Command regulator\npaused at count %d, address %x, "
463 "while current pause address is %x.\n"
464 "Please mail this message to "
465 "<unichrome-devel@lists.sourceforge.net>\n", count,
466 rgtr, ptr);
467 }
468 } 451 }
469 452
470 if (paused && !no_pci_fire) { 453 if (paused && !no_pci_fire) {
471 uint32_t rgtr, ptr; 454 reader = *(dev_priv->hw_addr_ptr);
472 uint32_t ptr_low; 455 if ((ptr - reader) == dev_priv->dma_diff) {
473 456
474 count = 1000000; 457 /*
475 while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) 458 * There is a concern that these writes may stall the PCI bus
476 && count--) ; 459 * if the GPU is not idle. However, idling the GPU first
460 * doesn't make a difference.
461 */
477 462
478 rgtr = *(dev_priv->hw_addr_ptr);
479 ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
480 dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
481
482 ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ?
483 ptr - 3 * CMDBUF_ALIGNMENT_SIZE : 0;
484 if (rgtr <= ptr && rgtr >= ptr_low) {
485 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); 463 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
486 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); 464 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
487 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); 465 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
@@ -494,6 +472,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
494static int via_wait_idle(drm_via_private_t * dev_priv) 472static int via_wait_idle(drm_via_private_t * dev_priv)
495{ 473{
496 int count = 10000000; 474 int count = 10000000;
475
476 while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
477
497 while (count-- && (VIA_READ(VIA_REG_STATUS) & 478 while (count-- && (VIA_READ(VIA_REG_STATUS) &
498 (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | 479 (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
499 VIA_3D_ENG_BUSY))) ; 480 VIA_3D_ENG_BUSY))) ;
@@ -537,6 +518,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
537 uint32_t end_addr, end_addr_lo; 518 uint32_t end_addr, end_addr_lo;
538 uint32_t command; 519 uint32_t command;
539 uint32_t agp_base; 520 uint32_t agp_base;
521 uint32_t ptr;
522 uint32_t reader;
523 int count;
540 524
541 dev_priv->dma_low = 0; 525 dev_priv->dma_low = 0;
542 526
@@ -554,7 +538,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
554 &pause_addr_hi, &pause_addr_lo, 1) - 1; 538 &pause_addr_hi, &pause_addr_lo, 1) - 1;
555 539
556 via_flush_write_combine(); 540 via_flush_write_combine();
557 while (!*dev_priv->last_pause_ptr) ; 541 (void) *(volatile uint32_t *)dev_priv->last_pause_ptr;
558 542
559 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); 543 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
560 VIA_WRITE(VIA_REG_TRANSPACE, command); 544 VIA_WRITE(VIA_REG_TRANSPACE, command);
@@ -566,6 +550,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
566 DRM_WRITEMEMORYBARRIER(); 550 DRM_WRITEMEMORYBARRIER();
567 VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); 551 VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
568 VIA_READ(VIA_REG_TRANSPACE); 552 VIA_READ(VIA_REG_TRANSPACE);
553
554 dev_priv->dma_diff = 0;
555
556 count = 10000000;
557 while (!(VIA_READ(0x41c) & 0x80000000) && count--);
558
559 reader = *(dev_priv->hw_addr_ptr);
560 ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
561 dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
562
563 /*
564 * This is the difference between where we tell the
565 * command reader to pause and where it actually pauses.
566 * This differs between hw implementation so we need to
567 * detect it.
568 */
569
570 dev_priv->dma_diff = ptr - reader;
569} 571}
570 572
571static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) 573static void via_pad_cache(drm_via_private_t * dev_priv, int qwords)
@@ -592,7 +594,6 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
592 uint32_t pause_addr_lo, pause_addr_hi; 594 uint32_t pause_addr_lo, pause_addr_hi;
593 uint32_t jump_addr_lo, jump_addr_hi; 595 uint32_t jump_addr_lo, jump_addr_hi;
594 volatile uint32_t *last_pause_ptr; 596 volatile uint32_t *last_pause_ptr;
595 uint32_t dma_low_save1, dma_low_save2;
596 597
597 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 598 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
598 via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, 599 via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
@@ -619,31 +620,11 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
619 &pause_addr_lo, 0); 620 &pause_addr_lo, 0);
620 621
621 *last_pause_ptr = pause_addr_lo; 622 *last_pause_ptr = pause_addr_lo;
622 dma_low_save1 = dev_priv->dma_low;
623
624 /*
625 * Now, set a trap that will pause the regulator if it tries to rerun the old
626 * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
627 * and reissues the jump command over PCI, while the regulator has already taken the jump
628 * and actually paused at the current buffer end).
629 * There appears to be no other way to detect this condition, since the hw_addr_pointer
630 * does not seem to get updated immediately when a jump occurs.
631 */
632 623
633 last_pause_ptr = 624 via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
634 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
635 &pause_addr_lo, 0) - 1;
636 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
637 &pause_addr_lo, 0);
638 *last_pause_ptr = pause_addr_lo;
639
640 dma_low_save2 = dev_priv->dma_low;
641 dev_priv->dma_low = dma_low_save1;
642 via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
643 dev_priv->dma_low = dma_low_save2;
644 via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
645} 625}
646 626
627
647static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) 628static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
648{ 629{
649 via_cmdbuf_jump(dev_priv); 630 via_cmdbuf_jump(dev_priv);
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index 8b8778d4a423..b46ca8e6306d 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -29,11 +29,11 @@
29 29
30#define DRIVER_NAME "via" 30#define DRIVER_NAME "via"
31#define DRIVER_DESC "VIA Unichrome / Pro" 31#define DRIVER_DESC "VIA Unichrome / Pro"
32#define DRIVER_DATE "20061227" 32#define DRIVER_DATE "20070202"
33 33
34#define DRIVER_MAJOR 2 34#define DRIVER_MAJOR 2
35#define DRIVER_MINOR 11 35#define DRIVER_MINOR 11
36#define DRIVER_PATCHLEVEL 0 36#define DRIVER_PATCHLEVEL 1
37 37
38#include "via_verifier.h" 38#include "via_verifier.h"
39 39
@@ -93,6 +93,7 @@ typedef struct drm_via_private {
93 unsigned long vram_offset; 93 unsigned long vram_offset;
94 unsigned long agp_offset; 94 unsigned long agp_offset;
95 drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; 95 drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
96 uint32_t dma_diff;
96} drm_via_private_t; 97} drm_via_private_t;
97 98
98enum via_family { 99enum via_family {