- Update to 2.6.25-rc3.
[linux-flexiantxendom0-3.2.10.git] / drivers / char / drm / radeon_cp.c
index 24fca8e..833abc7 100644 (file)
@@ -816,6 +816,58 @@ static const u32 R300_cp_microcode[][2] = {
        {0000000000, 0000000000},
 };
 
+static u32 RADEON_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+       u32 ret;
+       RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff));
+       ret = RADEON_READ(R520_MC_IND_DATA);
+       RADEON_WRITE(R520_MC_IND_INDEX, 0);
+       return ret;
+}
+
+static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+       RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK));
+       return RADEON_READ(RS690_MC_DATA);
+}
+
+u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
+{
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
+               return RADEON_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
+               return RADEON_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
+       else
+               return RADEON_READ(RADEON_MC_FB_LOCATION);
+}
+
+static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
+{
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
+               RADEON_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
+               RADEON_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
+       else
+               RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc);
+}
+
+static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc)
+{
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
+               RADEON_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
+               RADEON_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
+       else
+               RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc);
+}
+
 static int RADEON_READ_PLL(struct drm_device * dev, int addr)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -824,7 +876,7 @@ static int RADEON_READ_PLL(struct drm_device * dev, int addr)
        return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
 }
 
-static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
+static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
 {
        RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
        return RADEON_READ(RADEON_PCIE_DATA);
@@ -1074,41 +1126,43 @@ static int radeon_do_engine_reset(struct drm_device * dev)
 
        radeon_do_pixcache_flush(dev_priv);
 
-       clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
-       mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
-
-       RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
-                                           RADEON_FORCEON_MCLKA |
-                                           RADEON_FORCEON_MCLKB |
-                                           RADEON_FORCEON_YCLKA |
-                                           RADEON_FORCEON_YCLKB |
-                                           RADEON_FORCEON_MC |
-                                           RADEON_FORCEON_AIC));
-
-       rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
-
-       RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
-                                             RADEON_SOFT_RESET_CP |
-                                             RADEON_SOFT_RESET_HI |
-                                             RADEON_SOFT_RESET_SE |
-                                             RADEON_SOFT_RESET_RE |
-                                             RADEON_SOFT_RESET_PP |
-                                             RADEON_SOFT_RESET_E2 |
-                                             RADEON_SOFT_RESET_RB));
-       RADEON_READ(RADEON_RBBM_SOFT_RESET);
-       RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
-                                             ~(RADEON_SOFT_RESET_CP |
-                                               RADEON_SOFT_RESET_HI |
-                                               RADEON_SOFT_RESET_SE |
-                                               RADEON_SOFT_RESET_RE |
-                                               RADEON_SOFT_RESET_PP |
-                                               RADEON_SOFT_RESET_E2 |
-                                               RADEON_SOFT_RESET_RB)));
-       RADEON_READ(RADEON_RBBM_SOFT_RESET);
-
-       RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
-       RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
-       RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
+               clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
+               mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
+
+               RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
+                                                   RADEON_FORCEON_MCLKA |
+                                                   RADEON_FORCEON_MCLKB |
+                                                   RADEON_FORCEON_YCLKA |
+                                                   RADEON_FORCEON_YCLKB |
+                                                   RADEON_FORCEON_MC |
+                                                   RADEON_FORCEON_AIC));
+
+               rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+               RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
+                                                     RADEON_SOFT_RESET_CP |
+                                                     RADEON_SOFT_RESET_HI |
+                                                     RADEON_SOFT_RESET_SE |
+                                                     RADEON_SOFT_RESET_RE |
+                                                     RADEON_SOFT_RESET_PP |
+                                                     RADEON_SOFT_RESET_E2 |
+                                                     RADEON_SOFT_RESET_RB));
+               RADEON_READ(RADEON_RBBM_SOFT_RESET);
+               RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
+                                                     ~(RADEON_SOFT_RESET_CP |
+                                                       RADEON_SOFT_RESET_HI |
+                                                       RADEON_SOFT_RESET_SE |
+                                                       RADEON_SOFT_RESET_RE |
+                                                       RADEON_SOFT_RESET_PP |
+                                                       RADEON_SOFT_RESET_E2 |
+                                                       RADEON_SOFT_RESET_RB)));
+               RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+               RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
+               RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
+               RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
+       }
 
        /* Reset the CP ring */
        radeon_do_cp_reset(dev_priv);
@@ -1127,21 +1181,21 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
 {
        u32 ring_start, cur_read_ptr;
        u32 tmp;
-       
+
        /* Initialize the memory controller. With new memory map, the fb location
         * is not changed, it should have been properly initialized already. Part
         * of the problem is that the code below is bogus, assuming the GART is
         * always appended to the fb which is not necessarily the case
         */
        if (!dev_priv->new_memmap)
-               RADEON_WRITE(RADEON_MC_FB_LOCATION,
+               radeon_write_fb_location(dev_priv,
                             ((dev_priv->gart_vm_start - 1) & 0xffff0000)
                             | (dev_priv->fb_location >> 16));
 
 #if __OS_HAS_AGP
        if (dev_priv->flags & RADEON_IS_AGP) {
                RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
-               RADEON_WRITE(RADEON_MC_AGP_LOCATION,
+               radeon_write_agp_location(dev_priv,
                             (((dev_priv->gart_vm_start - 1 +
                                dev_priv->gart_size) & 0xffff0000) |
                              (dev_priv->gart_vm_start >> 16)));
@@ -1190,9 +1244,15 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
        /* Set ring buffer size */
 #ifdef __BIG_ENDIAN
        RADEON_WRITE(RADEON_CP_RB_CNTL,
-                    dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
+                    RADEON_BUF_SWAP_32BIT |
+                    (dev_priv->ring.fetch_size_l2ow << 18) |
+                    (dev_priv->ring.rptr_update_l2qw << 8) |
+                    dev_priv->ring.size_l2qw);
 #else
-       RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
+       RADEON_WRITE(RADEON_CP_RB_CNTL,
+                    (dev_priv->ring.fetch_size_l2ow << 18) |
+                    (dev_priv->ring.rptr_update_l2qw << 8) |
+                    dev_priv->ring.size_l2qw);
 #endif
 
        /* Start with assuming that writeback doesn't work */
@@ -1299,7 +1359,7 @@ static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
 
                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,
+               radeon_write_agp_location(dev_priv,
                             (((dev_priv->gart_vm_start - 1 +
                               dev_priv->gart_size) & 0xffff0000) |
                             (dev_priv->gart_vm_start >> 16)));
@@ -1314,6 +1374,70 @@ static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
        }
 }
 
+/* Enable or disable RS690 GART on the chip */
+static void radeon_set_rs690gart(drm_radeon_private_t *dev_priv, int on)
+{
+       u32 temp;
+
+       if (on) {
+               DRM_DEBUG("programming rs690 gart %08X %08lX %08X\n",
+                         dev_priv->gart_vm_start,
+                         (long)dev_priv->gart_info.bus_addr,
+                         dev_priv->gart_size);
+
+               temp = RS690_READ_MCIND(dev_priv, RS690_MC_MISC_CNTL);
+               RS690_WRITE_MCIND(RS690_MC_MISC_CNTL, 0x5000);
+
+               RS690_WRITE_MCIND(RS690_MC_AGP_SIZE,
+                                 RS690_MC_GART_EN | RS690_MC_AGP_SIZE_32MB);
+
+               temp = RS690_READ_MCIND(dev_priv, RS690_MC_GART_FEATURE_ID);
+               RS690_WRITE_MCIND(RS690_MC_GART_FEATURE_ID, 0x42040800);
+
+               RS690_WRITE_MCIND(RS690_MC_GART_BASE,
+                                 dev_priv->gart_info.bus_addr);
+
+               temp = RS690_READ_MCIND(dev_priv, RS690_MC_AGP_MODE_CONTROL);
+               RS690_WRITE_MCIND(RS690_MC_AGP_MODE_CONTROL, 0x01400000);
+
+               RS690_WRITE_MCIND(RS690_MC_AGP_BASE,
+                                 (unsigned int)dev_priv->gart_vm_start);
+
+               dev_priv->gart_size = 32*1024*1024;
+               temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) &
+                        0xffff0000) | (dev_priv->gart_vm_start >> 16));
+
+               RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, temp);
+
+               temp = RS690_READ_MCIND(dev_priv, RS690_MC_AGP_SIZE);
+               RS690_WRITE_MCIND(RS690_MC_AGP_SIZE,
+                                 RS690_MC_GART_EN | RS690_MC_AGP_SIZE_32MB);
+
+               do {
+                       temp = RS690_READ_MCIND(dev_priv, RS690_MC_GART_CACHE_CNTL);
+                       if ((temp & RS690_MC_GART_CLEAR_STATUS) ==
+                           RS690_MC_GART_CLEAR_DONE)
+                               break;
+                       DRM_UDELAY(1);
+               } while (1);
+
+               RS690_WRITE_MCIND(RS690_MC_GART_CACHE_CNTL,
+                                 RS690_MC_GART_CC_CLEAR);
+               do {
+                       temp = RS690_READ_MCIND(dev_priv, RS690_MC_GART_CACHE_CNTL);
+                       if ((temp & RS690_MC_GART_CLEAR_STATUS) ==
+                                  RS690_MC_GART_CLEAR_DONE)
+                               break;
+                       DRM_UDELAY(1);
+               } while (1);
+
+               RS690_WRITE_MCIND(RS690_MC_GART_CACHE_CNTL,
+                                 RS690_MC_GART_CC_NO_CHANGE);
+       } else {
+               RS690_WRITE_MCIND(RS690_MC_AGP_SIZE, RS690_MC_GART_DIS);
+       }
+}
+
 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);
@@ -1333,7 +1457,7 @@ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
                                  dev_priv->gart_vm_start +
                                  dev_priv->gart_size - 1);
 
-               RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);       /* ?? */
+               radeon_write_agp_location(dev_priv, 0xffffffc0); /* ?? */
 
                RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
                                  RADEON_PCIE_TX_GART_EN);
@@ -1348,6 +1472,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
 {
        u32 tmp;
 
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
+               radeon_set_rs690gart(dev_priv, on);
+               return;
+       }
+
        if (dev_priv->flags & RADEON_IS_IGPGART) {
                radeon_set_igpgart(dev_priv, on);
                return;
@@ -1358,7 +1487,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
                return;
        }
 
-       tmp = RADEON_READ(RADEON_AIC_CNTL);
+       tmp = RADEON_READ(RADEON_AIC_CNTL);
 
        if (on) {
                RADEON_WRITE(RADEON_AIC_CNTL,
@@ -1376,7 +1505,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
 
                /* Turn off AGP aperture -- is this required for PCI GART?
                 */
-               RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);       /* ?? */
+               radeon_write_agp_location(dev_priv, 0xffffffc0);
                RADEON_WRITE(RADEON_AGP_COMMAND, 0);    /* clear AGP_COMMAND */
        } else {
                RADEON_WRITE(RADEON_AIC_CNTL,
@@ -1581,10 +1710,9 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
                          dev->agp_buffer_map->handle);
        }
 
-       dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION)
-                                & 0xffff) << 16;
-       dev_priv->fb_size = 
-               ((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000)
+       dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16;
+       dev_priv->fb_size =
+               ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000)
                - dev_priv->fb_location;
 
        dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
@@ -1630,7 +1758,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
                            ((base + dev_priv->gart_size) & 0xfffffffful) < base)
                                base = dev_priv->fb_location
                                        - dev_priv->gart_size;
-               }               
+               }
                dev_priv->gart_vm_start = base & 0xffc00000u;
                if (dev_priv->gart_vm_start != base)
                        DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
@@ -1663,6 +1791,11 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
        dev_priv->ring.size = init->ring_size;
        dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
 
+       dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
+       dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8);
+
+       dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
+       dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16);
        dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
 
        dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
@@ -1830,7 +1963,7 @@ int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_pri
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (init->func == RADEON_INIT_R300_CP)
-               r300_init_reg_flags();
+               r300_init_reg_flags(dev);
 
        switch (init->func) {
        case RADEON_INIT_CP:
@@ -1852,12 +1985,12 @@ int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_pr
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (dev_priv->cp_running) {
-               DRM_DEBUG("%s while CP running\n", __FUNCTION__);
+               DRM_DEBUG("while CP running\n");
                return 0;
        }
        if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
-               DRM_DEBUG("%s called with bogus CP mode (%d)\n",
-                         __FUNCTION__, dev_priv->cp_mode);
+               DRM_DEBUG("called with bogus CP mode (%d)\n",
+                         dev_priv->cp_mode);
                return 0;
        }
 
@@ -1962,7 +2095,7 @@ int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_pr
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
-               DRM_DEBUG("%s called before init done\n", __FUNCTION__);
+               DRM_DEBUG("called before init done\n");
                return -EINVAL;
        }
 
@@ -2239,6 +2372,10 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
        case CHIP_R350:
        case CHIP_R420:
        case CHIP_RV410:
+       case CHIP_RV515:
+       case CHIP_R520:
+       case CHIP_RV570:
+       case CHIP_R580:
                dev_priv->flags |= RADEON_HAS_HIERZ;
                break;
        default: