Add GART in FB support for ati pcigart, and PCIE support for r300
authorDave Airlie <airlied@linux.ie>
Sun, 11 Sep 2005 08:51:23 +0000 (08:51 +0000)
committerDave Airlie <airlied@linux.ie>
Sun, 11 Sep 2005 08:51:23 +0000 (08:51 +0000)
linux-core/ati_pcigart.c
linux-core/drmP.h
shared-core/r128_cce.c
shared-core/r128_drv.h
shared-core/radeon_cp.c
shared-core/radeon_drm.h
shared-core/radeon_drv.h
shared-core/radeon_state.c

index c9ace51..1dde5ab 100644 (file)
@@ -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 (!dev->pdev) {
-               DRM_ERROR("PCI device unknown!\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;
+               }
        }
-
-       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;
index 8b1728b..81c542d 100644 (file)
@@ -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);
index 3355367..cb84fa8 100644 (file)
@@ -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),
index c6bdf56..34724fd 100644 (file)
@@ -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 {
index 09a473d..b7e0ec0 100644 (file)
@@ -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));
index 64b9693..6065674 100644 (file)
@@ -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
  */
index 58e4c17..265697c 100644 (file)
@@ -38,7 +38,7 @@
 
 #define DRIVER_NAME            "radeon"
 #define DRIVER_DESC            "ATI Radeon"
-#define DRIVER_DATE            "20050905"
+#define DRIVER_DATE            "20050911"
 
 /* Interface history:
  *
  * 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) )
index 8b3317b..91fc9f2 100644 (file)
@@ -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);