Merge master.kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-drm-fsl-dcu.git] / drivers / char / drm / radeon_cp.c
index 5ad43ba7b5aa16fa526a8428d507a212073688ae..68338389d836b244258e9db82406f8cb4dc5936b 100644 (file)
@@ -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)
 {
@@ -864,13 +873,13 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
 
        dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
-       tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT);
-       tmp |= RADEON_RB2D_DC_FLUSH_ALL;
-       RADEON_WRITE(RADEON_RB2D_DSTCACHE_CTLSTAT, tmp);
+       tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
+       tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+       RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
 
        for (i = 0; i < dev_priv->usec_timeout; i++) {
-               if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT)
-                     & RADEON_RB2D_DC_BUSY)) {
+               if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
+                     & RADEON_RB3D_DC_BUSY)) {
                        return 0;
                }
                DRM_UDELAY(1);
@@ -1130,7 +1139,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
                             | (dev_priv->fb_location >> 16));
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
                RADEON_WRITE(RADEON_MC_AGP_LOCATION,
                             (((dev_priv->gart_vm_start - 1 +
@@ -1158,7 +1167,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
        dev_priv->ring.tail = cur_read_ptr;
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
                             dev_priv->ring_rptr->offset
                             - dev->agp->base + dev_priv->gart_vm_start);
@@ -1258,9 +1267,53 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
                dev_priv->writeback_works = 0;
                DRM_INFO("writeback forced off\n");
        }
+
+       if (!dev_priv->writeback_works) {
+               /* Disable writeback to avoid unnecessary bus master transfer */
+               RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) |
+                            RADEON_RB_NO_UPDATE);
+               RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
+       }
+}
+
+/* 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);
+       }
 }
 
-/* Enable or disable PCI-E GART on the chip */
 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);
@@ -1295,7 +1348,12 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
 {
        u32 tmp;
 
-       if (dev_priv->flags & CHIP_IS_PCIE) {
+       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;
        }
@@ -1333,20 +1391,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        DRM_DEBUG("\n");
 
        /* if we require new memory map but we don't have it fail */
-       if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap)
-       {
-               DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n");
+       if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
+               DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
                radeon_do_cleanup_cp(dev);
                return DRM_ERR(EINVAL);
        }
 
-       if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP))
-       {
+       if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
                DRM_DEBUG("Forcing AGP card to PCI mode\n");
-               dev_priv->flags &= ~CHIP_IS_AGP;
+               dev_priv->flags &= ~RADEON_IS_AGP;
+       } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
+                  && !init->is_pci) {
+               DRM_DEBUG("Restoring AGP flag\n");
+               dev_priv->flags |= RADEON_IS_AGP;
        }
 
-       if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) {
+       if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
                DRM_ERROR("PCI GART memory not allocated!\n");
                radeon_do_cleanup_cp(dev);
                return DRM_ERR(EINVAL);
@@ -1489,7 +1549,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                                    init->sarea_priv_offset);
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                drm_core_ioremap(dev_priv->cp_ring, dev);
                drm_core_ioremap(dev_priv->ring_rptr, dev);
                drm_core_ioremap(dev->agp_buffer_map, dev);
@@ -1548,11 +1608,11 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                 * align it down.
                 */
 #if __OS_HAS_AGP
-               if (dev_priv->flags & CHIP_IS_AGP) {
+               if (dev_priv->flags & RADEON_IS_AGP) {
                        base = dev->agp->base;
                        /* Check if valid */
-                       if ((base + dev_priv->gart_size) > dev_priv->fb_location &&
-                           base < (dev_priv->fb_location + dev_priv->fb_size)) {
+                       if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
+                           base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
                                DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
                                         dev->agp->base);
                                base = 0;
@@ -1562,8 +1622,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                /* If not or if AGP is at 0 (Macs), try to put it elsewhere */
                if (base == 0) {
                        base = dev_priv->fb_location + dev_priv->fb_size;
-                       if (((base + dev_priv->gart_size) & 0xfffffffful)
-                           < base)
+                       if (base < dev_priv->fb_location ||
+                           ((base + dev_priv->gart_size) & 0xfffffffful) < base)
                                base = dev_priv->fb_location
                                        - dev_priv->gart_size;
                }               
@@ -1578,7 +1638,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        }
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP)
+       if (dev_priv->flags & RADEON_IS_AGP)
                dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
                                                 - dev->agp->base
                                                 + dev_priv->gart_vm_start);
@@ -1604,27 +1664,29 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                /* Turn off PCI GART */
                radeon_set_pcigart(dev_priv, 0);
        } else
 #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 & CHIP_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;
 
@@ -1632,11 +1694,15 @@ 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;
                        dev_priv->gart_info.bus_addr = 0;
-                       if (dev_priv->flags & CHIP_IS_PCIE) {
+                       if (dev_priv->flags & RADEON_IS_PCIE) {
                                DRM_ERROR
                                    ("Cannot use PCI Express without GART in FB memory\n");
                                radeon_do_cleanup_cp(dev);
@@ -1678,7 +1744,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
                drm_irq_uninstall(dev);
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                if (dev_priv->cp_ring != NULL) {
                        drm_core_ioremapfree(dev_priv->cp_ring, dev);
                        dev_priv->cp_ring = NULL;
@@ -1705,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 */
@@ -1733,7 +1799,7 @@ static int radeon_do_resume_cp(drm_device_t * dev)
        DRM_DEBUG("Starting radeon_do_resume_cp()\n");
 
 #if __OS_HAS_AGP
-       if (dev_priv->flags & CHIP_IS_AGP) {
+       if (dev_priv->flags & RADEON_IS_AGP) {
                /* Turn off PCI GART */
                radeon_set_pcigart(dev_priv, 0);
        } else
@@ -2177,13 +2243,15 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
        dev->dev_private = (void *)dev_priv;
        dev_priv->flags = flags;
 
-       switch (flags & CHIP_FAMILY_MASK) {
+       switch (flags & RADEON_FAMILY_MASK) {
        case CHIP_R100:
        case CHIP_RV200:
        case CHIP_R200:
        case CHIP_R300:
+       case CHIP_R350:
        case CHIP_R420:
-               dev_priv->flags |= CHIP_HAS_HIERZ;
+       case CHIP_RV410:
+               dev_priv->flags |= RADEON_HAS_HIERZ;
                break;
        default:
                /* all other chips have no hierarchical z buffer */
@@ -2191,13 +2259,14 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
        }
 
        if (drm_device_is_agp(dev))
-               dev_priv->flags |= CHIP_IS_AGP;
-
-       if (drm_device_is_pcie(dev))
-               dev_priv->flags |= CHIP_IS_PCIE;
+               dev_priv->flags |= RADEON_IS_AGP;
+       else if (drm_device_is_pcie(dev))
+               dev_priv->flags |= RADEON_IS_PCIE;
+       else
+               dev_priv->flags |= RADEON_IS_PCI;
 
        DRM_DEBUG("%s card detected\n",
-                 ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI"))));
+                 ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
        return ret;
 }
 
@@ -2210,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);