mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2025-12-24 05:30:13 +01:00
Add GART in FB support for ati pcigart, and PCIE support for r300
This commit is contained in:
parent
29326c1a89
commit
5565a00916
8 changed files with 117 additions and 65 deletions
|
|
@ -91,9 +91,7 @@ static void drm_ati_free_pcigart_table(unsigned long address)
|
|||
free_pages(address, ATI_PCIGART_TABLE_ORDER);
|
||||
}
|
||||
|
||||
int drm_ati_pcigart_init(drm_device_t * dev,
|
||||
unsigned long *addr, dma_addr_t * bus_addr,
|
||||
int is_pcie)
|
||||
int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info *gart_info)
|
||||
{
|
||||
drm_sg_mem_t *entry = dev->sg;
|
||||
unsigned long address = 0;
|
||||
|
|
@ -106,25 +104,36 @@ int drm_ati_pcigart_init(drm_device_t * dev,
|
|||
goto done;
|
||||
}
|
||||
|
||||
address = drm_ati_alloc_pcigart_table();
|
||||
if (!address) {
|
||||
DRM_ERROR("cannot allocate PCI GART page!\n");
|
||||
goto done;
|
||||
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();
|
||||
if (!address) {
|
||||
DRM_ERROR("cannot allocate PCI GART page!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!dev->pdev) {
|
||||
DRM_ERROR("PCI device unknown!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
bus_address = pci_map_single(dev->pdev, (void *)address,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (bus_address == 0) {
|
||||
DRM_ERROR("unable to map PCIGART pages!\n");
|
||||
drm_ati_free_pcigart_table(address);
|
||||
address = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev->pdev) {
|
||||
DRM_ERROR("PCI device unknown!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
bus_address = pci_map_single(dev->pdev, (void *)address,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (bus_address == 0) {
|
||||
DRM_ERROR("unable to map PCIGART pages!\n");
|
||||
drm_ati_free_pcigart_table(address);
|
||||
address = 0;
|
||||
goto done;
|
||||
else
|
||||
{
|
||||
address = gart_info->addr;
|
||||
bus_address = gart_info->bus_addr;
|
||||
DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n", bus_address, address);
|
||||
}
|
||||
|
||||
pci_gart = (u32 *) address;
|
||||
|
|
@ -142,7 +151,7 @@ int drm_ati_pcigart_init(drm_device_t * dev,
|
|||
PAGE_SIZE, PCI_DMA_TODEVICE);
|
||||
if (entry->busaddr[i] == 0) {
|
||||
DRM_ERROR("unable to map PCIGART pages!\n");
|
||||
drm_ati_pcigart_cleanup(dev, address, bus_address);
|
||||
drm_ati_pcigart_cleanup(dev, gart_info);
|
||||
address = 0;
|
||||
bus_address = 0;
|
||||
goto done;
|
||||
|
|
@ -150,11 +159,8 @@ int drm_ati_pcigart_init(drm_device_t * dev,
|
|||
page_base = (u32) entry->busaddr[i];
|
||||
|
||||
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
|
||||
if (is_pcie)
|
||||
{
|
||||
if (gart_info->is_pcie)
|
||||
*pci_gart = (cpu_to_le32(page_base)>>8) | 0xc;
|
||||
// DRM_DEBUG("PCIE: %d %08X %08X to %p\n", i, page_base, (cpu_to_le32(page_base)>>8)|0xc, pci_gart);
|
||||
}
|
||||
else
|
||||
*pci_gart = cpu_to_le32(page_base);
|
||||
pci_gart++;
|
||||
|
|
@ -171,14 +177,13 @@ int drm_ati_pcigart_init(drm_device_t * dev,
|
|||
#endif
|
||||
|
||||
done:
|
||||
*addr = address;
|
||||
*bus_addr = bus_address;
|
||||
gart_info->addr = address;
|
||||
gart_info->bus_addr = bus_address;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ati_pcigart_init);
|
||||
|
||||
int drm_ati_pcigart_cleanup(drm_device_t * dev,
|
||||
unsigned long addr, dma_addr_t bus_addr)
|
||||
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;
|
||||
|
|
@ -190,10 +195,12 @@ int drm_ati_pcigart_cleanup(drm_device_t * dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (bus_addr) {
|
||||
pci_unmap_single(dev->pdev, bus_addr,
|
||||
ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
|
||||
PCI_DMA_TODEVICE);
|
||||
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,
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
pages = (entry->pages <= ATI_MAX_PCIGART_PAGES)
|
||||
? entry->pages : ATI_MAX_PCIGART_PAGES;
|
||||
|
|
@ -204,10 +211,15 @@ int drm_ati_pcigart_cleanup(drm_device_t * dev,
|
|||
pci_unmap_single(dev->pdev, entry->busaddr[i],
|
||||
PAGE_SIZE, PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
if (gart_info->gart_table_location==DRM_ATI_GART_MAIN)
|
||||
gart_info->bus_addr=0;
|
||||
}
|
||||
|
||||
if (addr) {
|
||||
drm_ati_free_pcigart_table(addr);
|
||||
|
||||
if (gart_info->gart_table_location==DRM_ATI_GART_MAIN && gart_info->addr) {
|
||||
drm_ati_free_pcigart_table(gart_info->addr);
|
||||
gart_info->addr=0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -523,6 +523,17 @@ typedef struct drm_vbl_sig {
|
|||
struct task_struct *task;
|
||||
} drm_vbl_sig_t;
|
||||
|
||||
/* location of GART table */
|
||||
#define DRM_ATI_GART_MAIN 1
|
||||
#define DRM_ATI_GART_FB 2
|
||||
|
||||
typedef struct ati_pcigart_info {
|
||||
int gart_table_location;
|
||||
int is_pcie;
|
||||
unsigned long addr;
|
||||
dma_addr_t bus_addr;
|
||||
} drm_ati_pcigart_info;
|
||||
|
||||
/**
|
||||
* DRM driver structure. This structure represent the common code for
|
||||
* a family of cards. There will one drm_device for each card present
|
||||
|
|
@ -978,10 +989,8 @@ extern int drm_sg_free(struct inode *inode, struct file *filp,
|
|||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
/* ATI PCIGART support (ati_pcigart.h) */
|
||||
extern int drm_ati_pcigart_init(drm_device_t * dev,
|
||||
unsigned long *addr, dma_addr_t * bus_addr, int is_pcie);
|
||||
extern int drm_ati_pcigart_cleanup(drm_device_t * dev,
|
||||
unsigned long addr, dma_addr_t bus_addr);
|
||||
extern int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info *gart_info);
|
||||
extern int drm_ati_pcigart_cleanup(drm_device_t * dev, drm_ati_pcigart_info *gart_info);
|
||||
|
||||
extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size,
|
||||
size_t align, dma_addr_t maxaddr);
|
||||
|
|
|
|||
|
|
@ -558,14 +558,16 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
|
|||
#if __OS_HAS_AGP
|
||||
if (dev_priv->is_pci) {
|
||||
#endif
|
||||
if (!drm_ati_pcigart_init(dev, &dev_priv->phys_pci_gart,
|
||||
&dev_priv->bus_pci_gart, 0)) {
|
||||
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
|
||||
dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr = 0;
|
||||
dev_priv->gart_info.is_pcie = 0;
|
||||
if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
|
||||
DRM_ERROR("failed to init PCI GART!\n");
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
r128_do_cleanup_cce(dev);
|
||||
return DRM_ERR(ENOMEM);
|
||||
}
|
||||
R128_WRITE(R128_PCI_GART_PAGE, dev_priv->bus_pci_gart);
|
||||
R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
|
||||
#if __OS_HAS_AGP
|
||||
}
|
||||
#endif
|
||||
|
|
@ -606,10 +608,9 @@ int r128_do_cleanup_cce(drm_device_t * dev)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
if (!drm_ati_pcigart_cleanup(dev,
|
||||
dev_priv->phys_pci_gart,
|
||||
dev_priv->bus_pci_gart))
|
||||
DRM_ERROR("failed to cleanup PCI GART!\n");
|
||||
if (dev_priv->gart_info.bus_addr)
|
||||
if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
|
||||
DRM_ERROR("failed to cleanup PCI GART!\n");
|
||||
}
|
||||
|
||||
drm_free(dev->dev_private, sizeof(drm_r128_private_t),
|
||||
|
|
|
|||
|
|
@ -87,8 +87,6 @@ typedef struct drm_r128_private {
|
|||
|
||||
int usec_timeout;
|
||||
int is_pci;
|
||||
unsigned long phys_pci_gart;
|
||||
dma_addr_t bus_pci_gart;
|
||||
unsigned long cce_buffers_offset;
|
||||
|
||||
atomic_t idle_count;
|
||||
|
|
@ -119,6 +117,7 @@ typedef struct drm_r128_private {
|
|||
drm_local_map_t *cce_ring;
|
||||
drm_local_map_t *ring_rptr;
|
||||
drm_local_map_t *agp_textures;
|
||||
drm_ati_pcigart_info gart_info;
|
||||
} drm_r128_private_t;
|
||||
|
||||
typedef struct drm_r128_buf_priv {
|
||||
|
|
|
|||
|
|
@ -1246,17 +1246,17 @@ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
|
|||
if (on) {
|
||||
|
||||
DRM_DEBUG("programming pcie %08X %08lX %08X\n",
|
||||
dev_priv->gart_vm_start, (long)dev_priv->bus_pci_gart,
|
||||
dev_priv->gart_vm_start, (long)dev_priv->gart_info.bus_addr,
|
||||
dev_priv->gart_size);
|
||||
RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, dev_priv->gart_vm_start);
|
||||
RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, dev_priv->bus_pci_gart);
|
||||
RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, dev_priv->gart_info.bus_addr);
|
||||
RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO, dev_priv->gart_vm_start);
|
||||
RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO, dev_priv->gart_vm_start
|
||||
+ dev_priv->gart_size - 1);
|
||||
|
||||
RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0); /* ?? */
|
||||
|
||||
RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, RADEON_PCIE_TX_GART_EN | RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD | RADEON_PCIE_TX_GART_CHK_RW_VALID_EN);
|
||||
RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, RADEON_PCIE_TX_GART_EN);
|
||||
} else {
|
||||
RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
|
||||
}
|
||||
|
|
@ -1279,7 +1279,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
|
|||
|
||||
/* set PCI GART page-table base address
|
||||
*/
|
||||
RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart);
|
||||
RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
|
||||
|
||||
/* set address range for PCI address translate
|
||||
*/
|
||||
|
|
@ -1526,8 +1526,28 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
if (!drm_ati_pcigart_init(dev, &dev_priv->phys_pci_gart,
|
||||
&dev_priv->bus_pci_gart, (dev_priv->flags & CHIP_IS_PCIE))) {
|
||||
/* if we have an offset set from userspace */
|
||||
if (dev_priv->pcigart_offset) {
|
||||
dev_priv->gart_info.bus_addr = dev_priv->pcigart_offset + dev_priv->fb_location;
|
||||
dev_priv->gart_info.addr = (unsigned long)drm_ioremap(dev_priv->gart_info.bus_addr, RADEON_PCIGART_TABLE_SIZE, dev);
|
||||
|
||||
dev_priv->gart_info.is_pcie = !!(dev_priv->flags & CHIP_IS_PCIE);
|
||||
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB;
|
||||
|
||||
DRM_DEBUG("Setting phys_pci_gart to %08lX %08lX\n", dev_priv->gart_info.addr, dev_priv->pcigart_offset);
|
||||
}
|
||||
else {
|
||||
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
|
||||
dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr= 0;
|
||||
if (dev_priv->flags & CHIP_IS_PCIE)
|
||||
{
|
||||
DRM_ERROR("Cannot use PCI Express without GART in FB memory\n");
|
||||
radeon_do_cleanup_cp(dev);
|
||||
return DRM_ERR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
|
||||
DRM_ERROR("failed to init PCI GART!\n");
|
||||
radeon_do_cleanup_cp(dev);
|
||||
return DRM_ERR(ENOMEM);
|
||||
|
|
@ -1576,10 +1596,15 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
if (!drm_ati_pcigart_cleanup(dev,
|
||||
dev_priv->phys_pci_gart,
|
||||
dev_priv->bus_pci_gart))
|
||||
DRM_ERROR("failed to cleanup PCI GART!\n");
|
||||
if (dev_priv->gart_info.bus_addr)
|
||||
if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
|
||||
DRM_ERROR("failed to cleanup PCI GART!\n");
|
||||
|
||||
if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
|
||||
{
|
||||
drm_ioremapfree((void *)dev_priv->gart_info.addr, RADEON_PCIGART_TABLE_SIZE, dev);
|
||||
dev_priv->gart_info.addr = 0;
|
||||
}
|
||||
}
|
||||
/* only clear to the start of flags */
|
||||
memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
|
||||
|
|
|
|||
|
|
@ -690,6 +690,7 @@ typedef struct drm_radeon_setparam {
|
|||
|
||||
#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
|
||||
#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
|
||||
#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
|
||||
|
||||
/* 1.14: Clients can allocate/free a surface
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#define DRIVER_NAME "radeon"
|
||||
#define DRIVER_DESC "ATI Radeon"
|
||||
#define DRIVER_DATE "20050905"
|
||||
#define DRIVER_DATE "20050911"
|
||||
|
||||
/* Interface history:
|
||||
*
|
||||
|
|
@ -86,10 +86,11 @@
|
|||
* 1.18- Add support for GL_ATI_fragment_shader, new packets R200_EMIT_PP_AFS_0/1,
|
||||
R200_EMIT_PP_TXCTLALL_0-5 (replaces R200_EMIT_PP_TXFILTER_0-5, 2 more regs)
|
||||
and R200_EMIT_ATF_TFACTOR (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6)
|
||||
* 1.19- Add support for gart table in FB memory and PCIE r300
|
||||
*/
|
||||
|
||||
#define DRIVER_MAJOR 1
|
||||
#define DRIVER_MINOR 18
|
||||
#define DRIVER_MINOR 19
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
|
||||
enum radeon_family {
|
||||
|
|
@ -211,9 +212,6 @@ typedef struct drm_radeon_private {
|
|||
|
||||
int microcode_version;
|
||||
|
||||
unsigned long phys_pci_gart;
|
||||
dma_addr_t bus_pci_gart;
|
||||
|
||||
struct {
|
||||
u32 boxes;
|
||||
int freelist_timeouts;
|
||||
|
|
@ -265,7 +263,9 @@ typedef struct drm_radeon_private {
|
|||
|
||||
struct radeon_surface surfaces[RADEON_MAX_SURFACES];
|
||||
struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES];
|
||||
|
||||
|
||||
unsigned long pcigart_offset;
|
||||
drm_ati_pcigart_info gart_info;
|
||||
/* starting from here on, data is preserved accross an open */
|
||||
uint32_t flags; /* see radeon_chip_flags */
|
||||
|
||||
|
|
@ -920,6 +920,8 @@ extern int r300_do_cp_cmdbuf( drm_device_t* dev,
|
|||
|
||||
#define RADEON_RING_HIGH_MARK 128
|
||||
|
||||
#define RADEON_PCIGART_TABLE_SIZE (32*1024)
|
||||
|
||||
#define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
|
||||
#define RADEON_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
|
||||
#define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
|
||||
|
|
|
|||
|
|
@ -3007,6 +3007,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
|
|||
dev_priv->sarea_priv->tiling_enabled = 1;
|
||||
}
|
||||
break;
|
||||
case RADEON_SETPARAM_PCIGART_LOCATION:
|
||||
dev_priv->pcigart_offset = sp.value;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Invalid parameter %d\n", sp.param);
|
||||
return DRM_ERR(EINVAL);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue