Commit 5335a40b authored by Linus Torvalds's avatar Linus Torvalds

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
parents 393bfca1 ef68d295
...@@ -33,59 +33,44 @@ ...@@ -33,59 +33,44 @@
#include "drmP.h" #include "drmP.h"
#if PAGE_SIZE == 65536
# define ATI_PCIGART_TABLE_ORDER 0
# define ATI_PCIGART_TABLE_PAGES (1 << 0)
#elif PAGE_SIZE == 16384
# define ATI_PCIGART_TABLE_ORDER 1
# define ATI_PCIGART_TABLE_PAGES (1 << 1)
#elif PAGE_SIZE == 8192
# define ATI_PCIGART_TABLE_ORDER 2
# define ATI_PCIGART_TABLE_PAGES (1 << 2)
#elif PAGE_SIZE == 4096
# define ATI_PCIGART_TABLE_ORDER 3
# define ATI_PCIGART_TABLE_PAGES (1 << 3)
#else
# error - PAGE_SIZE not 64K, 16K, 8K or 4K
#endif
# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
static void *drm_ati_alloc_pcigart_table(void) static void *drm_ati_alloc_pcigart_table(int order)
{ {
unsigned long address; unsigned long address;
struct page *page; struct page *page;
int i; int i;
DRM_DEBUG("%s\n", __FUNCTION__);
DRM_DEBUG("%s: alloc %d order\n", __FUNCTION__, order);
address = __get_free_pages(GFP_KERNEL | __GFP_COMP, address = __get_free_pages(GFP_KERNEL | __GFP_COMP,
ATI_PCIGART_TABLE_ORDER); order);
if (address == 0UL) { if (address == 0UL) {
return NULL; return NULL;
} }
page = virt_to_page(address); page = virt_to_page(address);
for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) for (i = 0; i < order; i++, page++)
SetPageReserved(page); SetPageReserved(page);
DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
return (void *)address; return (void *)address;
} }
static void drm_ati_free_pcigart_table(void *address) static void drm_ati_free_pcigart_table(void *address, int order)
{ {
struct page *page; struct page *page;
int i; int i;
int num_pages = 1 << order;
DRM_DEBUG("%s\n", __FUNCTION__); DRM_DEBUG("%s\n", __FUNCTION__);
page = virt_to_page((unsigned long)address); page = virt_to_page((unsigned long)address);
for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) for (i = 0; i < num_pages; i++, page++)
ClearPageReserved(page); ClearPageReserved(page);
free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER); free_pages((unsigned long)address, order);
} }
int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) 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,6 +78,8 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
drm_sg_mem_t *entry = dev->sg; drm_sg_mem_t *entry = dev->sg;
unsigned long pages; unsigned long pages;
int i; int i;
int order;
int num_pages, max_pages;
/* we need to support large memory configurations */ /* we need to support large memory configurations */
if (!entry) { if (!entry) {
...@@ -100,15 +87,19 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) ...@@ -100,15 +87,19 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
return 0; return 0;
} }
order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE);
num_pages = 1 << order;
if (gart_info->bus_addr) { if (gart_info->bus_addr) {
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
pci_unmap_single(dev->pdev, gart_info->bus_addr, pci_unmap_single(dev->pdev, gart_info->bus_addr,
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, num_pages * PAGE_SIZE,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
} }
pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) max_pages = (gart_info->table_size / sizeof(u32));
? entry->pages : ATI_MAX_PCIGART_PAGES; pages = (entry->pages <= max_pages)
? entry->pages : max_pages;
for (i = 0; i < pages; i++) { for (i = 0; i < pages; i++) {
if (!entry->busaddr[i]) if (!entry->busaddr[i])
...@@ -123,13 +114,12 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) ...@@ -123,13 +114,12 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN if (gart_info->gart_table_location == DRM_ATI_GART_MAIN
&& gart_info->addr) { && gart_info->addr) {
drm_ati_free_pcigart_table(gart_info->addr); drm_ati_free_pcigart_table(gart_info->addr, order);
gart_info->addr = NULL; gart_info->addr = NULL;
} }
return 1; return 1;
} }
EXPORT_SYMBOL(drm_ati_pcigart_cleanup); EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) 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,6 +129,9 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
unsigned long pages; unsigned long pages;
u32 *pci_gart, page_base, bus_address = 0; u32 *pci_gart, page_base, bus_address = 0;
int i, j, ret = 0; int i, j, ret = 0;
int order;
int max_pages;
int num_pages;
if (!entry) { if (!entry) {
DRM_ERROR("no scatter/gather memory!\n"); 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,7 +141,10 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
address = drm_ati_alloc_pcigart_table(); order = drm_order((gart_info->table_size +
(PAGE_SIZE-1)) / PAGE_SIZE);
num_pages = 1 << order;
address = drm_ati_alloc_pcigart_table(order);
if (!address) { if (!address) {
DRM_ERROR("cannot allocate PCI GART page!\n"); DRM_ERROR("cannot allocate PCI GART page!\n");
goto done; goto done;
...@@ -160,11 +156,13 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) ...@@ -160,11 +156,13 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
} }
bus_address = pci_map_single(dev->pdev, address, bus_address = pci_map_single(dev->pdev, address,
ATI_PCIGART_TABLE_PAGES * num_pages * PAGE_SIZE,
PAGE_SIZE, PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
if (bus_address == 0) { if (bus_address == 0) {
DRM_ERROR("unable to map PCIGART pages!\n"); DRM_ERROR("unable to map PCIGART pages!\n");
drm_ati_free_pcigart_table(address); order = drm_order((gart_info->table_size +
(PAGE_SIZE-1)) / PAGE_SIZE);
drm_ati_free_pcigart_table(address, order);
address = NULL; address = NULL;
goto done; goto done;
} }
...@@ -177,10 +175,11 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) ...@@ -177,10 +175,11 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
pci_gart = (u32 *) address; pci_gart = (u32 *) address;
pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) max_pages = (gart_info->table_size / sizeof(u32));
? entry->pages : ATI_MAX_PCIGART_PAGES; pages = (entry->pages <= max_pages)
? entry->pages : max_pages;
memset(pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32)); memset(pci_gart, 0, max_pages * sizeof(u32));
for (i = 0; i < pages; i++) { for (i = 0; i < pages; i++) {
/* we need to support large memory configurations */ /* 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,10 +197,18 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
page_base = (u32) entry->busaddr[i]; page_base = (u32) entry->busaddr[i];
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
if (gart_info->is_pcie) switch(gart_info->gart_reg_if) {
case DRM_ATI_GART_IGP:
*pci_gart = cpu_to_le32((page_base) | 0xc);
break;
case DRM_ATI_GART_PCIE:
*pci_gart = cpu_to_le32((page_base >> 8) | 0xc); *pci_gart = cpu_to_le32((page_base >> 8) | 0xc);
else break;
default:
case DRM_ATI_GART_PCI:
*pci_gart = cpu_to_le32(page_base); *pci_gart = cpu_to_le32(page_base);
break;
}
pci_gart++; pci_gart++;
page_base += ATI_PCIGART_PAGE_SIZE; page_base += ATI_PCIGART_PAGE_SIZE;
} }
...@@ -220,5 +227,4 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) ...@@ -220,5 +227,4 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
gart_info->bus_addr = bus_address; gart_info->bus_addr = bus_address;
return ret; return ret;
} }
EXPORT_SYMBOL(drm_ati_pcigart_init); EXPORT_SYMBOL(drm_ati_pcigart_init);
...@@ -519,12 +519,17 @@ typedef struct drm_vbl_sig { ...@@ -519,12 +519,17 @@ typedef struct drm_vbl_sig {
#define DRM_ATI_GART_MAIN 1 #define DRM_ATI_GART_MAIN 1
#define DRM_ATI_GART_FB 2 #define DRM_ATI_GART_FB 2
#define DRM_ATI_GART_PCI 1
#define DRM_ATI_GART_PCIE 2
#define DRM_ATI_GART_IGP 3
typedef struct ati_pcigart_info { typedef struct ati_pcigart_info {
int gart_table_location; int gart_table_location;
int is_pcie; int gart_reg_if;
void *addr; void *addr;
dma_addr_t bus_addr; dma_addr_t bus_addr;
drm_local_map_t mapping; drm_local_map_t mapping;
int table_size;
} drm_ati_pcigart_info; } drm_ati_pcigart_info;
/* /*
......
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
* #define DRIVER_DESC "Matrox G200/G400" * #define DRIVER_DESC "Matrox G200/G400"
* #define DRIVER_DATE "20001127" * #define DRIVER_DATE "20001127"
* *
* #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
*
* #define drm_x mga_##x * #define drm_x mga_##x
* \endcode * \endcode
*/ */
...@@ -120,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = { ...@@ -120,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
}; };
#define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
/** /**
* Take down the DRM device. * Take down the DRM device.
...@@ -496,11 +494,11 @@ int drm_ioctl(struct inode *inode, struct file *filp, ...@@ -496,11 +494,11 @@ int drm_ioctl(struct inode *inode, struct file *filp,
(long)old_encode_dev(priv->head->device), (long)old_encode_dev(priv->head->device),
priv->authenticated); priv->authenticated);
if ((nr >= DRIVER_IOCTL_COUNT) && if ((nr >= DRM_CORE_IOCTL_COUNT) &&
((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
goto err_i1; goto err_i1;
if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
&& (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE))
ioctl = &drm_ioctls[nr]; ioctl = &drm_ioctls[nr];
......
...@@ -70,9 +70,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size) ...@@ -70,9 +70,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
#endif #endif
/** Task queue handler arguments */
#define DRM_TASKQUEUE_ARGS void *arg
/** For data going into the kernel through the ioctl argument */ /** For data going into the kernel through the ioctl argument */
#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \ #define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
if ( copy_from_user(&arg1, arg2, arg3) ) \ if ( copy_from_user(&arg1, arg2, arg3) ) \
......
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
{0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \ {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
{0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
{0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
{0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
......
...@@ -560,9 +560,10 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init) ...@@ -560,9 +560,10 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
if (dev_priv->is_pci) { if (dev_priv->is_pci) {
#endif #endif
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
dev_priv->gart_info.addr = NULL; dev_priv->gart_info.addr = NULL;
dev_priv->gart_info.bus_addr = 0; dev_priv->gart_info.bus_addr = 0;
dev_priv->gart_info.is_pcie = 0; dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
DRM_ERROR("failed to init PCI GART!\n"); DRM_ERROR("failed to init PCI GART!\n");
dev->dev_private = (void *)dev_priv; dev->dev_private = (void *)dev_priv;
......
...@@ -383,6 +383,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, ...@@ -383,6 +383,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
#define R128_PERFORMANCE_BOXES 0 #define R128_PERFORMANCE_BOXES 0
#define R128_PCIGART_TABLE_SIZE 32768
#define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) #define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
#define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) #define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
#define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) #define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
......
...@@ -830,6 +830,15 @@ static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) ...@@ -830,6 +830,15 @@ static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
return RADEON_READ(RADEON_PCIE_DATA); return RADEON_READ(RADEON_PCIE_DATA);
} }
static u32 RADEON_READ_IGPGART(drm_radeon_private_t *dev_priv, int addr)
{
u32 ret;
RADEON_WRITE(RADEON_IGPGART_INDEX, addr & 0x7f);
ret = RADEON_READ(RADEON_IGPGART_DATA);
RADEON_WRITE(RADEON_IGPGART_INDEX, 0x7f);
return ret;
}
#if RADEON_FIFO_DEBUG #if RADEON_FIFO_DEBUG
static void radeon_status(drm_radeon_private_t * dev_priv) static void radeon_status(drm_radeon_private_t * dev_priv)
{ {
...@@ -1267,7 +1276,44 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv) ...@@ -1267,7 +1276,44 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
} }
} }
/* Enable or disable PCI-E GART on the chip */ /* Enable or disable IGP GART on the chip */
static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
{
u32 temp, tmp;
tmp = RADEON_READ(RADEON_AIC_CNTL);
if (on) {
DRM_DEBUG("programming igpgart %08X %08lX %08X\n",
dev_priv->gart_vm_start,
(long)dev_priv->gart_info.bus_addr,
dev_priv->gart_size);
RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_18, 0x1000);
RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, 0x1);
RADEON_WRITE_IGPGART(RADEON_IGPGART_CTRL, 0x42040800);
RADEON_WRITE_IGPGART(RADEON_IGPGART_BASE_ADDR,
dev_priv->gart_info.bus_addr);
temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_UNK_39);
RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_39, temp);
RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev_priv->gart_vm_start);
dev_priv->gart_size = 32*1024*1024;
RADEON_WRITE(RADEON_MC_AGP_LOCATION,
(((dev_priv->gart_vm_start - 1 +
dev_priv->gart_size) & 0xffff0000) |
(dev_priv->gart_vm_start >> 16)));
temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_ENABLE);
RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, temp);
RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x1);
RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x0);
}
}
static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
{ {
u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); 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,6 +1348,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
{ {
u32 tmp; u32 tmp;
if (dev_priv->flags & RADEON_IS_IGPGART) {
radeon_set_igpgart(dev_priv, on);
return;
}
if (dev_priv->flags & RADEON_IS_PCIE) { if (dev_priv->flags & RADEON_IS_PCIE) {
radeon_set_pciegart(dev_priv, on); radeon_set_pciegart(dev_priv, on);
return; return;
...@@ -1620,20 +1671,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1620,20 +1671,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
#endif #endif
{ {
/* if we have an offset set from userspace */ /* if we have an offset set from userspace */
if (dev_priv->pcigart_offset) { if (dev_priv->pcigart_offset_set) {
dev_priv->gart_info.bus_addr = dev_priv->gart_info.bus_addr =
dev_priv->pcigart_offset + dev_priv->fb_location; dev_priv->pcigart_offset + dev_priv->fb_location;
dev_priv->gart_info.mapping.offset = dev_priv->gart_info.mapping.offset =
dev_priv->gart_info.bus_addr; dev_priv->gart_info.bus_addr;
dev_priv->gart_info.mapping.size = dev_priv->gart_info.mapping.size =
RADEON_PCIGART_TABLE_SIZE; dev_priv->gart_info.table_size;
drm_core_ioremap(&dev_priv->gart_info.mapping, dev); drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
dev_priv->gart_info.addr = dev_priv->gart_info.addr =
dev_priv->gart_info.mapping.handle; dev_priv->gart_info.mapping.handle;
dev_priv->gart_info.is_pcie = if (dev_priv->flags & RADEON_IS_PCIE)
!!(dev_priv->flags & RADEON_IS_PCIE); dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
else
dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
dev_priv->gart_info.gart_table_location = dev_priv->gart_info.gart_table_location =
DRM_ATI_GART_FB; DRM_ATI_GART_FB;
...@@ -1641,6 +1694,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1641,6 +1694,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->gart_info.addr, dev_priv->gart_info.addr,
dev_priv->pcigart_offset); dev_priv->pcigart_offset);
} else { } else {
if (dev_priv->flags & RADEON_IS_IGPGART)
dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
else
dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
dev_priv->gart_info.gart_table_location = dev_priv->gart_info.gart_table_location =
DRM_ATI_GART_MAIN; DRM_ATI_GART_MAIN;
dev_priv->gart_info.addr = NULL; dev_priv->gart_info.addr = NULL;
...@@ -1714,7 +1771,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) ...@@ -1714,7 +1771,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
{ {
drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
dev_priv->gart_info.addr = NULL; dev_priv->gart_info.addr = 0;
} }
} }
/* only clear to the start of flags */ /* only clear to the start of flags */
...@@ -2222,6 +2279,8 @@ int radeon_driver_firstopen(struct drm_device *dev) ...@@ -2222,6 +2279,8 @@ int radeon_driver_firstopen(struct drm_device *dev)
drm_local_map_t *map; drm_local_map_t *map;
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
ret = drm_addmap(dev, drm_get_resource_start(dev, 2), ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
drm_get_resource_len(dev, 2), _DRM_REGISTERS, drm_get_resource_len(dev, 2), _DRM_REGISTERS,
_DRM_READ_ONLY, &dev_priv->mmio); _DRM_READ_ONLY, &dev_priv->mmio);
......
...@@ -707,6 +707,7 @@ typedef struct drm_radeon_setparam { ...@@ -707,6 +707,7 @@ typedef struct drm_radeon_setparam {
#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */
/* 1.14: Clients can allocate/free a surface /* 1.14: Clients can allocate/free a surface
*/ */
......
...@@ -95,9 +95,11 @@ ...@@ -95,9 +95,11 @@
* 1.24- Add general-purpose packet for manipulating scratch registers (r300) * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
* 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
* new packet type) * new packet type)
* 1.26- Add support for variable size PCI(E) gart aperture
* 1.27- Add support for IGP GART
*/ */
#define DRIVER_MAJOR 1 #define DRIVER_MAJOR 1
#define DRIVER_MINOR 25 #define DRIVER_MINOR 27
#define DRIVER_PATCHLEVEL 0 #define DRIVER_PATCHLEVEL 0
/* /*
...@@ -143,6 +145,7 @@ enum radeon_chip_flags { ...@@ -143,6 +145,7 @@ enum radeon_chip_flags {
RADEON_IS_PCIE = 0x00200000UL, RADEON_IS_PCIE = 0x00200000UL,
RADEON_NEW_MEMMAP = 0x00400000UL, RADEON_NEW_MEMMAP = 0x00400000UL,
RADEON_IS_PCI = 0x00800000UL, RADEON_IS_PCI = 0x00800000UL,
RADEON_IS_IGPGART = 0x01000000UL,
}; };
#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \
...@@ -240,7 +243,6 @@ typedef struct drm_radeon_private { ...@@ -240,7 +243,6 @@ typedef struct drm_radeon_private {
int do_boxes; int do_boxes;
int page_flipping; int page_flipping;
int current_page;
u32 color_fmt; u32 color_fmt;
unsigned int front_offset; unsigned int front_offset;
...@@ -280,6 +282,7 @@ typedef struct drm_radeon_private { ...@@ -280,6 +282,7 @@ typedef struct drm_radeon_private {
struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES]; struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
unsigned long pcigart_offset; unsigned long pcigart_offset;
unsigned int pcigart_offset_set;
drm_ati_pcigart_info gart_info; drm_ati_pcigart_info gart_info;
u32 scratch_ages[5]; u32 scratch_ages[5];
...@@ -432,6 +435,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, ...@@ -432,6 +435,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
#define RADEON_PCIE_TX_GART_END_LO 0x16 #define RADEON_PCIE_TX_GART_END_LO 0x16
#define RADEON_PCIE_TX_GART_END_HI 0x17 #define RADEON_PCIE_TX_GART_END_HI 0x17
#define RADEON_IGPGART_INDEX 0x168
#define RADEON_IGPGART_DATA 0x16c
#define RADEON_IGPGART_UNK_18 0x18
#define RADEON_IGPGART_CTRL 0x2b
#define RADEON_IGPGART_BASE_ADDR 0x2c
#define RADEON_IGPGART_FLUSH 0x2e
#define RADEON_IGPGART_ENABLE 0x38
#define RADEON_IGPGART_UNK_39 0x39
#define RADEON_MPP_TB_CONFIG 0x01c0 #define RADEON_MPP_TB_CONFIG 0x01c0
#define RADEON_MEM_CNTL 0x0140 #define RADEON_MEM_CNTL 0x0140
#define RADEON_MEM_SDRAM_MODE_REG 0x0158 #define RADEON_MEM_SDRAM_MODE_REG 0x0158
...@@ -964,6 +976,14 @@ do { \ ...@@ -964,6 +976,14 @@ do { \
RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \ RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
} while (0) } while (0)
#define RADEON_WRITE_IGPGART( addr, val ) \
do { \
RADEON_WRITE( RADEON_IGPGART_INDEX, \
((addr) & 0x7f) | (1 << 8)); \
RADEON_WRITE( RADEON_IGPGART_DATA, (val) ); \
RADEON_WRITE( RADEON_IGPGART_INDEX, 0x7f ); \
} while (0)
#define RADEON_WRITE_PCIE( addr, val ) \ #define RADEON_WRITE_PCIE( addr, val ) \
do { \ do { \
RADEON_WRITE8( RADEON_PCIE_INDEX, \ RADEON_WRITE8( RADEON_PCIE_INDEX, \
......
...@@ -773,7 +773,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv, ...@@ -773,7 +773,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,
RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_GMC_SRC_DATATYPE_COLOR |
RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
if (dev_priv->page_flipping && dev_priv->current_page == 1) { if (dev_priv->sarea_priv->pfCurrentPage == 1) {
OUT_RING(dev_priv->front_pitch_offset); OUT_RING(dev_priv->front_pitch_offset);
} else { } else {
OUT_RING(dev_priv->back_pitch_offset); OUT_RING(dev_priv->back_pitch_offset);
...@@ -861,7 +861,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, ...@@ -861,7 +861,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
dev_priv->stats.clears++; dev_priv->stats.clears++;
if (dev_priv->page_flipping && dev_priv->current_page == 1) { if (dev_priv->sarea_priv->pfCurrentPage == 1) {
unsigned int tmp = flags; unsigned int tmp = flags;
flags &= ~(RADEON_FRONT | RADEON_BACK); flags &= ~(RADEON_FRONT | RADEON_BACK);
...@@ -1382,7 +1382,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) ...@@ -1382,7 +1382,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
/* Make this work even if front & back are flipped: /* Make this work even if front & back are flipped:
*/ */
OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
if (dev_priv->current_page == 0) { if (dev_priv->sarea_priv->pfCurrentPage == 0) {
OUT_RING(dev_priv->back_pitch_offset); OUT_RING(dev_priv->back_pitch_offset);
OUT_RING(dev_priv->front_pitch_offset); OUT_RING(dev_priv->front_pitch_offset);
} else { } else {
...@@ -1416,12 +1416,12 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev) ...@@ -1416,12 +1416,12 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle; drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
int offset = (dev_priv->current_page == 1) int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
? dev_priv->front_offset : dev_priv->back_offset; ? dev_priv->front_offset : dev_priv->back_offset;
RING_LOCALS; RING_LOCALS;
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", DRM_DEBUG("%s: pfCurrentPage=%d\n",
__FUNCTION__, __FUNCTION__,
dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); dev_priv->sarea_priv->pfCurrentPage);
/* Do some trivial performance monitoring... /* Do some trivial performance monitoring...
*/ */
...@@ -1449,8 +1449,8 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev) ...@@ -1449,8 +1449,8 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
* performing the swapbuffer ioctl. * performing the swapbuffer ioctl.
*/ */
dev_priv->sarea_priv->last_frame++; dev_priv->sarea_priv->last_frame++;
dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = dev_priv->sarea_priv->pfCurrentPage =
1 - dev_priv->current_page; 1 - dev_priv->sarea_priv->pfCurrentPage;
BEGIN_RING(2); BEGIN_RING(2);
...@@ -2152,24 +2152,10 @@ static int radeon_do_init_pageflip(drm_device_t * dev) ...@@ -2152,24 +2152,10 @@ static int radeon_do_init_pageflip(drm_device_t * dev)
ADVANCE_RING(); ADVANCE_RING();
dev_priv->page_flipping = 1; dev_priv->page_flipping = 1;
dev_priv->current_page = 0;
dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
return 0; if (dev_priv->sarea_priv->pfCurrentPage != 1)
} dev_priv->sarea_priv->pfCurrentPage = 0;
/* Called whenever a client dies, from drm_release.
* NOTE: Lock isn't necessarily held when this is called!
*/
static int radeon_do_cleanup_pageflip(drm_device_t * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("\n");
if (dev_priv->current_page != 0)
radeon_cp_dispatch_flip(dev);
dev_priv->page_flipping = 0;
return 0; return 0;
} }
...@@ -3145,10 +3131,16 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) ...@@ -3145,10 +3131,16 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
break; break;
case RADEON_SETPARAM_PCIGART_LOCATION: case RADEON_SETPARAM_PCIGART_LOCATION:
dev_priv->pcigart_offset = sp.value; dev_priv->pcigart_offset = sp.value;
dev_priv->pcigart_offset_set = 1;
break; break;
case RADEON_SETPARAM_NEW_MEMMAP: case RADEON_SETPARAM_NEW_MEMMAP:
dev_priv->new_memmap = sp.value; dev_priv->new_memmap = sp.value;
break; break;
case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
dev_priv->gart_info.table_size = sp.value;
if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
break;
default: default:
DRM_DEBUG("Invalid parameter %d\n", sp.param); DRM_DEBUG("Invalid parameter %d\n", sp.param);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
...@@ -3168,9 +3160,7 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp) ...@@ -3168,9 +3160,7 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
{ {
if (dev->dev_private) { if (dev->dev_private) {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
if (dev_priv->page_flipping) { dev_priv->page_flipping = 0;
radeon_do_cleanup_pageflip(dev);
}
radeon_mem_release(filp, dev_priv->gart_heap); radeon_mem_release(filp, dev_priv->gart_heap);
radeon_mem_release(filp, dev_priv->fb_heap); radeon_mem_release(filp, dev_priv->fb_heap);
radeon_surfaces_release(filp, dev_priv); radeon_surfaces_release(filp, dev_priv);
...@@ -3179,6 +3169,14 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp) ...@@ -3179,6 +3169,14 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
void radeon_driver_lastclose(drm_device_t * dev) void radeon_driver_lastclose(drm_device_t * dev)
{ {
if (dev->dev_private) {
drm_radeon_private_t *dev_priv = dev->dev_private;
if (dev_priv->sarea_priv &&
dev_priv->sarea_priv->pfCurrentPage != 0)
radeon_cp_dispatch_flip(dev);
}
radeon_do_release(dev); radeon_do_release(dev);
} }
......
...@@ -252,7 +252,7 @@ static int via_dma_init(DRM_IOCTL_ARGS) ...@@ -252,7 +252,7 @@ static int via_dma_init(DRM_IOCTL_ARGS)
break; break;
case VIA_DMA_INITIALIZED: case VIA_DMA_INITIALIZED:
retcode = (dev_priv->ring.virtual_start != NULL) ? retcode = (dev_priv->ring.virtual_start != NULL) ?
0 : DRM_ERR(EFAULT); 0 : DRM_ERR(EFAULT);
break; break;
default: default:
retcode = DRM_ERR(EINVAL); retcode = DRM_ERR(EINVAL);
...@@ -432,56 +432,34 @@ static int via_hook_segment(drm_via_private_t * dev_priv, ...@@ -432,56 +432,34 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
{ {
int paused, count; int paused, count;
volatile uint32_t *paused_at = dev_priv->last_pause_ptr; volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
uint32_t reader,ptr;
paused = 0;
via_flush_write_combine(); via_flush_write_combine();
while (!*(via_get_dma(dev_priv) - 1)) ; (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1);
*dev_priv->last_pause_ptr = pause_addr_lo; *paused_at = pause_addr_lo;
via_flush_write_combine(); via_flush_write_combine();
(void) *paused_at;
/* reader = *(dev_priv->hw_addr_ptr);
* The below statement is inserted to really force the flush. ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
* Not sure it is needed. dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
*/
while (!*dev_priv->last_pause_ptr) ;
dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
while (!*dev_priv->last_pause_ptr) ;
paused = 0; if ((ptr - reader) <= dev_priv->dma_diff ) {
count = 20; count = 10000000;
while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--) ;
if ((count <= 8) && (count >= 0)) {
uint32_t rgtr, ptr;
rgtr = *(dev_priv->hw_addr_ptr);
ptr = ((volatile char *)dev_priv->last_pause_ptr -
dev_priv->dma_ptr) + dev_priv->dma_offset +
(uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE;
if (rgtr <= ptr) {
DRM_ERROR
("Command regulator\npaused at count %d, address %x, "
"while current pause address is %x.\n"
"Please mail this message to "
"<unichrome-devel@lists.sourceforge.net>\n", count,
rgtr, ptr);
}
} }
if (paused && !no_pci_fire) { if (paused && !no_pci_fire) {
uint32_t rgtr, ptr; reader = *(dev_priv->hw_addr_ptr);
uint32_t ptr_low; if ((ptr - reader) == dev_priv->dma_diff) {
count = 1000000; /*
while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) * There is a concern that these writes may stall the PCI bus
&& count--) ; * if the GPU is not idle. However, idling the GPU first
* doesn't make a difference.
*/
rgtr = *(dev_priv->hw_addr_ptr);
ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ?
ptr - 3 * CMDBUF_ALIGNMENT_SIZE : 0;
if (rgtr <= ptr && rgtr >= ptr_low) {
VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
...@@ -494,6 +472,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv, ...@@ -494,6 +472,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
static int via_wait_idle(drm_via_private_t * dev_priv) static int via_wait_idle(drm_via_private_t * dev_priv)
{ {
int count = 10000000; int count = 10000000;
while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
while (count-- && (VIA_READ(VIA_REG_STATUS) & while (count-- && (VIA_READ(VIA_REG_STATUS) &
(VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
VIA_3D_ENG_BUSY))) ; VIA_3D_ENG_BUSY))) ;
...@@ -537,6 +518,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) ...@@ -537,6 +518,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
uint32_t end_addr, end_addr_lo; uint32_t end_addr, end_addr_lo;
uint32_t command; uint32_t command;
uint32_t agp_base; uint32_t agp_base;
uint32_t ptr;
uint32_t reader;
int count;
dev_priv->dma_low = 0; dev_priv->dma_low = 0;
...@@ -554,7 +538,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) ...@@ -554,7 +538,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
&pause_addr_hi, &pause_addr_lo, 1) - 1; &pause_addr_hi, &pause_addr_lo, 1) - 1;
via_flush_write_combine(); via_flush_write_combine();
while (!*dev_priv->last_pause_ptr) ; (void) *(volatile uint32_t *)dev_priv->last_pause_ptr;
VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
VIA_WRITE(VIA_REG_TRANSPACE, command); VIA_WRITE(VIA_REG_TRANSPACE, command);
...@@ -566,6 +550,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) ...@@ -566,6 +550,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
DRM_WRITEMEMORYBARRIER(); DRM_WRITEMEMORYBARRIER();
VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
VIA_READ(VIA_REG_TRANSPACE); VIA_READ(VIA_REG_TRANSPACE);
dev_priv->dma_diff = 0;
count = 10000000;
while (!(VIA_READ(0x41c) & 0x80000000) && count--);
reader = *(dev_priv->hw_addr_ptr);
ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
/*
* This is the difference between where we tell the
* command reader to pause and where it actually pauses.
* This differs between hw implementation so we need to
* detect it.
*/
dev_priv->dma_diff = ptr - reader;
} }
static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) static 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,7 +594,6 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
uint32_t pause_addr_lo, pause_addr_hi; uint32_t pause_addr_lo, pause_addr_hi;
uint32_t jump_addr_lo, jump_addr_hi; uint32_t jump_addr_lo, jump_addr_hi;
volatile uint32_t *last_pause_ptr; volatile uint32_t *last_pause_ptr;
uint32_t dma_low_save1, dma_low_save2;
agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, 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,31 +620,11 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
&pause_addr_lo, 0); &pause_addr_lo, 0);
*last_pause_ptr = pause_addr_lo; *last_pause_ptr = pause_addr_lo;
dma_low_save1 = dev_priv->dma_low;
/*
* Now, set a trap that will pause the regulator if it tries to rerun the old
* command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
* and reissues the jump command over PCI, while the regulator has already taken the jump
* and actually paused at the current buffer end).
* There appears to be no other way to detect this condition, since the hw_addr_pointer
* does not seem to get updated immediately when a jump occurs.
*/
last_pause_ptr = via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
&pause_addr_lo, 0) - 1;
via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
&pause_addr_lo, 0);
*last_pause_ptr = pause_addr_lo;
dma_low_save2 = dev_priv->dma_low;
dev_priv->dma_low = dma_low_save1;
via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
dev_priv->dma_low = dma_low_save2;
via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
} }
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
{ {
via_cmdbuf_jump(dev_priv); via_cmdbuf_jump(dev_priv);
......
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
#define DRIVER_NAME "via" #define DRIVER_NAME "via"
#define DRIVER_DESC "VIA Unichrome / Pro" #define DRIVER_DESC "VIA Unichrome / Pro"
#define DRIVER_DATE "20061227" #define DRIVER_DATE "20070202"
#define DRIVER_MAJOR 2 #define DRIVER_MAJOR 2
#define DRIVER_MINOR 11 #define DRIVER_MINOR 11
#define DRIVER_PATCHLEVEL 0 #define DRIVER_PATCHLEVEL 1
#include "via_verifier.h" #include "via_verifier.h"
...@@ -93,6 +93,7 @@ typedef struct drm_via_private { ...@@ -93,6 +93,7 @@ typedef struct drm_via_private {
unsigned long vram_offset; unsigned long vram_offset;
unsigned long agp_offset; unsigned long agp_offset;
drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
uint32_t dma_diff;
} drm_via_private_t; } drm_via_private_t;
enum via_family { enum via_family {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment