mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-30 16:07:39 +00:00
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
This commit is contained in:
commit
5335a40be6
13 changed files with 224 additions and 154 deletions
|
@ -33,59 +33,44 @@
|
|||
|
||||
#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 */
|
||||
|
||||
static void *drm_ati_alloc_pcigart_table(void)
|
||||
static void *drm_ati_alloc_pcigart_table(int order)
|
||||
{
|
||||
unsigned long address;
|
||||
struct page *page;
|
||||
int i;
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
DRM_DEBUG("%s: alloc %d order\n", __FUNCTION__, order);
|
||||
|
||||
address = __get_free_pages(GFP_KERNEL | __GFP_COMP,
|
||||
ATI_PCIGART_TABLE_ORDER);
|
||||
order);
|
||||
if (address == 0UL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
page = virt_to_page(address);
|
||||
|
||||
for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++)
|
||||
for (i = 0; i < order; i++, page++)
|
||||
SetPageReserved(page);
|
||||
|
||||
DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, 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;
|
||||
int i;
|
||||
int num_pages = 1 << order;
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
|
@ -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;
|
||||
unsigned long pages;
|
||||
int i;
|
||||
int order;
|
||||
int num_pages, max_pages;
|
||||
|
||||
/* we need to support large memory configurations */
|
||||
if (!entry) {
|
||||
|
@ -100,15 +87,19 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
|
|||
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->gart_table_location == DRM_ATI_GART_MAIN) {
|
||||
pci_unmap_single(dev->pdev, gart_info->bus_addr,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
num_pages * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
max_pages = (gart_info->table_size / sizeof(u32));
|
||||
pages = (entry->pages <= max_pages)
|
||||
? entry->pages : max_pages;
|
||||
|
||||
for (i = 0; i < pages; i++) {
|
||||
if (!entry->busaddr[i])
|
||||
|
@ -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
|
||||
&& gart_info->addr) {
|
||||
drm_ati_free_pcigart_table(gart_info->addr);
|
||||
drm_ati_free_pcigart_table(gart_info->addr, order);
|
||||
gart_info->addr = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
|
||||
|
||||
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;
|
||||
u32 *pci_gart, page_base, bus_address = 0;
|
||||
int i, j, ret = 0;
|
||||
int order;
|
||||
int max_pages;
|
||||
int num_pages;
|
||||
|
||||
if (!entry) {
|
||||
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)
|
|||
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
|
||||
DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
|
||||
|
||||
address = drm_ati_alloc_pcigart_table();
|
||||
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) {
|
||||
DRM_ERROR("cannot allocate PCI GART page!\n");
|
||||
goto done;
|
||||
|
@ -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,
|
||||
ATI_PCIGART_TABLE_PAGES *
|
||||
PAGE_SIZE, PCI_DMA_TODEVICE);
|
||||
num_pages * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (bus_address == 0) {
|
||||
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;
|
||||
goto done;
|
||||
}
|
||||
|
@ -177,10 +175,11 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
|
|||
|
||||
pci_gart = (u32 *) address;
|
||||
|
||||
pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
max_pages = (gart_info->table_size / sizeof(u32));
|
||||
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++) {
|
||||
/* 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)
|
|||
page_base = (u32) entry->busaddr[i];
|
||||
|
||||
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);
|
||||
else
|
||||
break;
|
||||
default:
|
||||
case DRM_ATI_GART_PCI:
|
||||
*pci_gart = cpu_to_le32(page_base);
|
||||
break;
|
||||
}
|
||||
pci_gart++;
|
||||
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)
|
|||
gart_info->bus_addr = bus_address;
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_ati_pcigart_init);
|
||||
|
|
|
@ -519,12 +519,17 @@ typedef struct drm_vbl_sig {
|
|||
#define DRM_ATI_GART_MAIN 1
|
||||
#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 {
|
||||
int gart_table_location;
|
||||
int is_pcie;
|
||||
int gart_reg_if;
|
||||
void *addr;
|
||||
dma_addr_t bus_addr;
|
||||
drm_local_map_t mapping;
|
||||
int table_size;
|
||||
} drm_ati_pcigart_info;
|
||||
|
||||
/*
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
* #define DRIVER_DESC "Matrox G200/G400"
|
||||
* #define DRIVER_DATE "20001127"
|
||||
*
|
||||
* #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
|
||||
*
|
||||
* #define drm_x mga_##x
|
||||
* \endcode
|
||||
*/
|
||||
|
@ -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},
|
||||
};
|
||||
|
||||
#define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
|
||||
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
|
||||
|
||||
/**
|
||||
* Take down the DRM device.
|
||||
|
@ -496,11 +494,11 @@ int drm_ioctl(struct inode *inode, struct file *filp,
|
|||
(long)old_encode_dev(priv->head->device),
|
||||
priv->authenticated);
|
||||
|
||||
if ((nr >= DRIVER_IOCTL_COUNT) &&
|
||||
if ((nr >= DRM_CORE_IOCTL_COUNT) &&
|
||||
((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
|
||||
goto err_i1;
|
||||
if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
|
||||
&& (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
|
||||
if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
|
||||
(nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
|
||||
ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
|
||||
else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE))
|
||||
ioctl = &drm_ioctls[nr];
|
||||
|
|
|
@ -70,9 +70,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
|
|||
|
||||
#endif
|
||||
|
||||
/** Task queue handler arguments */
|
||||
#define DRM_TASKQUEUE_ARGS void *arg
|
||||
|
||||
/** For data going into the kernel through the ioctl argument */
|
||||
#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
|
||||
if ( copy_from_user(&arg1, arg2, arg3) ) \
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
{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, 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, 0x5961, 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)
|
|||
if (dev_priv->is_pci) {
|
||||
#endif
|
||||
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.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)) {
|
||||
DRM_ERROR("failed to init PCI GART!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
|
|
|
@ -383,6 +383,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
|
|||
|
||||
#define R128_PERFORMANCE_BOXES 0
|
||||
|
||||
#define R128_PCIGART_TABLE_SIZE 32768
|
||||
|
||||
#define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
|
||||
#define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
|
||||
#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)
|
|||
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
|
||||
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)
|
|||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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)
|
|||
{
|
||||
u32 tmp;
|
||||
|
||||
if (dev_priv->flags & RADEON_IS_IGPGART) {
|
||||
radeon_set_igpgart(dev_priv, on);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev_priv->flags & RADEON_IS_PCIE) {
|
||||
radeon_set_pciegart(dev_priv, on);
|
||||
return;
|
||||
|
@ -1620,20 +1671,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
|
|||
#endif
|
||||
{
|
||||
/* 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->pcigart_offset + dev_priv->fb_location;
|
||||
dev_priv->gart_info.mapping.offset =
|
||||
dev_priv->gart_info.bus_addr;
|
||||
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);
|
||||
dev_priv->gart_info.addr =
|
||||
dev_priv->gart_info.mapping.handle;
|
||||
|
||||
dev_priv->gart_info.is_pcie =
|
||||
!!(dev_priv->flags & RADEON_IS_PCIE);
|
||||
if (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 =
|
||||
DRM_ATI_GART_FB;
|
||||
|
||||
|
@ -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->pcigart_offset);
|
||||
} 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 =
|
||||
DRM_ATI_GART_MAIN;
|
||||
dev_priv->gart_info.addr = NULL;
|
||||
|
@ -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)
|
||||
{
|
||||
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 */
|
||||
|
@ -2222,6 +2279,8 @@ int radeon_driver_firstopen(struct drm_device *dev)
|
|||
drm_local_map_t *map;
|
||||
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),
|
||||
drm_get_resource_len(dev, 2), _DRM_REGISTERS,
|
||||
_DRM_READ_ONLY, &dev_priv->mmio);
|
||||
|
|
|
@ -707,6 +707,7 @@ typedef struct drm_radeon_setparam {
|
|||
#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
|
||||
#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
|
||||
#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
|
||||
*/
|
||||
|
|
|
@ -95,9 +95,11 @@
|
|||
* 1.24- Add general-purpose packet for manipulating scratch registers (r300)
|
||||
* 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
|
||||
* 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_MINOR 25
|
||||
#define DRIVER_MINOR 27
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
/*
|
||||
|
@ -143,6 +145,7 @@ enum radeon_chip_flags {
|
|||
RADEON_IS_PCIE = 0x00200000UL,
|
||||
RADEON_NEW_MEMMAP = 0x00400000UL,
|
||||
RADEON_IS_PCI = 0x00800000UL,
|
||||
RADEON_IS_IGPGART = 0x01000000UL,
|
||||
};
|
||||
|
||||
#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \
|
||||
|
@ -240,7 +243,6 @@ typedef struct drm_radeon_private {
|
|||
|
||||
int do_boxes;
|
||||
int page_flipping;
|
||||
int current_page;
|
||||
|
||||
u32 color_fmt;
|
||||
unsigned int front_offset;
|
||||
|
@ -280,6 +282,7 @@ typedef struct drm_radeon_private {
|
|||
struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
|
||||
|
||||
unsigned long pcigart_offset;
|
||||
unsigned int pcigart_offset_set;
|
||||
drm_ati_pcigart_info gart_info;
|
||||
|
||||
u32 scratch_ages[5];
|
||||
|
@ -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_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_MEM_CNTL 0x0140
|
||||
#define RADEON_MEM_SDRAM_MODE_REG 0x0158
|
||||
|
@ -964,6 +976,14 @@ do { \
|
|||
RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
|
||||
} 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 ) \
|
||||
do { \
|
||||
RADEON_WRITE8( RADEON_PCIE_INDEX, \
|
||||
|
|
|
@ -773,7 +773,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,
|
|||
RADEON_GMC_SRC_DATATYPE_COLOR |
|
||||
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);
|
||||
} else {
|
||||
OUT_RING(dev_priv->back_pitch_offset);
|
||||
|
@ -861,7 +861,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
|
|||
|
||||
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;
|
||||
|
||||
flags &= ~(RADEON_FRONT | RADEON_BACK);
|
||||
|
@ -1382,7 +1382,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
|
|||
/* Make this work even if front & back are flipped:
|
||||
*/
|
||||
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->front_pitch_offset);
|
||||
} else {
|
||||
|
@ -1416,12 +1416,12 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
|
|||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
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;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
|
||||
DRM_DEBUG("%s: pfCurrentPage=%d\n",
|
||||
__FUNCTION__,
|
||||
dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
|
||||
dev_priv->sarea_priv->pfCurrentPage);
|
||||
|
||||
/* Do some trivial performance monitoring...
|
||||
*/
|
||||
|
@ -1449,8 +1449,8 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev)
|
|||
* performing the swapbuffer ioctl.
|
||||
*/
|
||||
dev_priv->sarea_priv->last_frame++;
|
||||
dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
|
||||
1 - dev_priv->current_page;
|
||||
dev_priv->sarea_priv->pfCurrentPage =
|
||||
1 - dev_priv->sarea_priv->pfCurrentPage;
|
||||
|
||||
BEGIN_RING(2);
|
||||
|
||||
|
@ -2152,24 +2152,10 @@ static int radeon_do_init_pageflip(drm_device_t * dev)
|
|||
ADVANCE_RING();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -3145,10 +3131,16 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
|
|||
break;
|
||||
case RADEON_SETPARAM_PCIGART_LOCATION:
|
||||
dev_priv->pcigart_offset = sp.value;
|
||||
dev_priv->pcigart_offset_set = 1;
|
||||
break;
|
||||
case RADEON_SETPARAM_NEW_MEMMAP:
|
||||
dev_priv->new_memmap = sp.value;
|
||||
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:
|
||||
DRM_DEBUG("Invalid parameter %d\n", sp.param);
|
||||
return DRM_ERR(EINVAL);
|
||||
|
@ -3168,9 +3160,7 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
|
|||
{
|
||||
if (dev->dev_private) {
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
if (dev_priv->page_flipping) {
|
||||
radeon_do_cleanup_pageflip(dev);
|
||||
}
|
||||
dev_priv->page_flipping = 0;
|
||||
radeon_mem_release(filp, dev_priv->gart_heap);
|
||||
radeon_mem_release(filp, dev_priv->fb_heap);
|
||||
radeon_surfaces_release(filp, dev_priv);
|
||||
|
@ -3179,6 +3169,14 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -432,56 +432,34 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
|
|||
{
|
||||
int paused, count;
|
||||
volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
|
||||
|
||||
via_flush_write_combine();
|
||||
while (!*(via_get_dma(dev_priv) - 1)) ;
|
||||
*dev_priv->last_pause_ptr = pause_addr_lo;
|
||||
via_flush_write_combine();
|
||||
|
||||
/*
|
||||
* The below statement is inserted to really force the flush.
|
||||
* Not sure it is needed.
|
||||
*/
|
||||
|
||||
while (!*dev_priv->last_pause_ptr) ;
|
||||
dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
|
||||
while (!*dev_priv->last_pause_ptr) ;
|
||||
uint32_t reader,ptr;
|
||||
|
||||
paused = 0;
|
||||
count = 20;
|
||||
via_flush_write_combine();
|
||||
(void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1);
|
||||
*paused_at = pause_addr_lo;
|
||||
via_flush_write_combine();
|
||||
(void) *paused_at;
|
||||
reader = *(dev_priv->hw_addr_ptr);
|
||||
ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
|
||||
dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
|
||||
dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
|
||||
|
||||
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 ((ptr - reader) <= dev_priv->dma_diff ) {
|
||||
count = 10000000;
|
||||
while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
|
||||
}
|
||||
|
||||
if (paused && !no_pci_fire) {
|
||||
uint32_t rgtr, ptr;
|
||||
uint32_t ptr_low;
|
||||
reader = *(dev_priv->hw_addr_ptr);
|
||||
if ((ptr - reader) == dev_priv->dma_diff) {
|
||||
|
||||
count = 1000000;
|
||||
while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY)
|
||||
&& count--) ;
|
||||
/*
|
||||
* There is a concern that these writes may stall the PCI bus
|
||||
* 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_TRANSPACE, pause_addr_hi);
|
||||
VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
|
||||
|
@ -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)
|
||||
{
|
||||
int count = 10000000;
|
||||
|
||||
while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
|
||||
|
||||
while (count-- && (VIA_READ(VIA_REG_STATUS) &
|
||||
(VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
|
||||
VIA_3D_ENG_BUSY))) ;
|
||||
|
@ -537,6 +518,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
|
|||
uint32_t end_addr, end_addr_lo;
|
||||
uint32_t command;
|
||||
uint32_t agp_base;
|
||||
uint32_t ptr;
|
||||
uint32_t reader;
|
||||
int count;
|
||||
|
||||
dev_priv->dma_low = 0;
|
||||
|
||||
|
@ -554,7 +538,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
|
|||
&pause_addr_hi, &pause_addr_lo, 1) - 1;
|
||||
|
||||
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_TRANSPACE, command);
|
||||
|
@ -566,6 +550,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
|
|||
DRM_WRITEMEMORYBARRIER();
|
||||
VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
|
||||
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)
|
||||
|
@ -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 jump_addr_lo, jump_addr_hi;
|
||||
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;
|
||||
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)
|
|||
&pause_addr_lo, 0);
|
||||
|
||||
*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_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);
|
||||
via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
|
||||
}
|
||||
|
||||
|
||||
static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
|
||||
{
|
||||
via_cmdbuf_jump(dev_priv);
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
|
||||
#define DRIVER_NAME "via"
|
||||
#define DRIVER_DESC "VIA Unichrome / Pro"
|
||||
#define DRIVER_DATE "20061227"
|
||||
#define DRIVER_DATE "20070202"
|
||||
|
||||
#define DRIVER_MAJOR 2
|
||||
#define DRIVER_MINOR 11
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
#define DRIVER_PATCHLEVEL 1
|
||||
|
||||
#include "via_verifier.h"
|
||||
|
||||
|
@ -93,6 +93,7 @@ typedef struct drm_via_private {
|
|||
unsigned long vram_offset;
|
||||
unsigned long agp_offset;
|
||||
drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
|
||||
uint32_t dma_diff;
|
||||
} drm_via_private_t;
|
||||
|
||||
enum via_family {
|
||||
|
|
Loading…
Reference in a new issue