drm/radeon: upgrade to 1.27 - make PCI GART more flexible
radeon: make PCI GART aperture size variable, but making table size variable This is precursor to getting a TTM backend for this stuff, and also allows the PCI table to be allocated at fb 0 radeon: add support for reverse engineered xpress200m The IGPGART setup code was traced using mmio-trace on fglrx by myself and Phillip Ezolt <phillipezolt@gmail.com> on dri-devel. This code doesn't let the 3D driver work properly as the card has no vertex shader support. Thanks to Matthew Garrett + Ubuntu for providing me some hardware to do this work on. Signed-off-by: Dave Airlie <airlied@linux.ie>
This commit is contained in:
parent
5b94f675f5
commit
f2b04cd219
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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 {
|
||||||
#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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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)
|
||||||
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,
|
||||||
|
|
||||||
#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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
#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)
|
||||||
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)
|
||||||
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)
|
||||||
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 {
|
||||||
#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 @@
|
||||||
* 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 {
|
||||||
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 ? \
|
||||||
|
@ -280,6 +283,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 +436,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 +977,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, \
|
||||||
|
|
|
@ -3145,10 +3145,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);
|
||||||
|
|
Loading…
Reference in New Issue