Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / r100.c
index 2b534c5..11c9a3f 100644 (file)
@@ -131,7 +131,8 @@ void r100_hpd_init(struct radeon_device *rdev)
                        break;
                }
        }
-       r100_irq_set(rdev);
+       if (rdev->irq.installed)
+               r100_irq_set(rdev);
 }
 
 void r100_hpd_fini(struct radeon_device *rdev)
@@ -243,6 +244,11 @@ int r100_irq_set(struct radeon_device *rdev)
 {
        uint32_t tmp = 0;
 
+       if (!rdev->irq.installed) {
+               WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n");
+               WREG32(R_000040_GEN_INT_CNTL, 0);
+               return -EINVAL;
+       }
        if (rdev->irq.sw_int) {
                tmp |= RADEON_SW_INT_ENABLE;
        }
@@ -289,6 +295,7 @@ static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
 int r100_irq_process(struct radeon_device *rdev)
 {
        uint32_t status, msi_rearm;
+       bool queue_hotplug = false;
 
        status = r100_irq_ack(rdev);
        if (!status) {
@@ -310,13 +317,17 @@ int r100_irq_process(struct radeon_device *rdev)
                        drm_handle_vblank(rdev->ddev, 1);
                }
                if (status & RADEON_FP_DETECT_STAT) {
-                       DRM_INFO("HPD1\n");
+                       queue_hotplug = true;
+                       DRM_DEBUG("HPD1\n");
                }
                if (status & RADEON_FP2_DETECT_STAT) {
-                       DRM_INFO("HPD2\n");
+                       queue_hotplug = true;
+                       DRM_DEBUG("HPD2\n");
                }
                status = r100_irq_ack(rdev);
        }
+       if (queue_hotplug)
+               queue_work(rdev->wq, &rdev->hotplug_work);
        if (rdev->msi_enabled) {
                switch (rdev->family) {
                case CHIP_RS400:
@@ -351,6 +362,11 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
        /* Wait until IDLE & CLEAN */
        radeon_ring_write(rdev, PACKET0(0x1720, 0));
        radeon_ring_write(rdev, (1 << 16) | (1 << 17));
+       radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+       radeon_ring_write(rdev, rdev->config.r100.hdp_cntl |
+                               RADEON_HDP_READ_BUFFER_INVALIDATE);
+       radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+       radeon_ring_write(rdev, rdev->config.r100.hdp_cntl);
        /* Emit fence sequence & fire IRQ */
        radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0));
        radeon_ring_write(rdev, fence->seq);
@@ -1369,7 +1385,6 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                case RADEON_TXFORMAT_ARGB4444:
                case RADEON_TXFORMAT_VYUY422:
                case RADEON_TXFORMAT_YVYU422:
-               case RADEON_TXFORMAT_DXT1:
                case RADEON_TXFORMAT_SHADOW16:
                case RADEON_TXFORMAT_LDUDV655:
                case RADEON_TXFORMAT_DUDV88:
@@ -1377,12 +1392,19 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                        break;
                case RADEON_TXFORMAT_ARGB8888:
                case RADEON_TXFORMAT_RGBA8888:
-               case RADEON_TXFORMAT_DXT23:
-               case RADEON_TXFORMAT_DXT45:
                case RADEON_TXFORMAT_SHADOW32:
                case RADEON_TXFORMAT_LDUDUV8888:
                        track->textures[i].cpp = 4;
                        break;
+               case RADEON_TXFORMAT_DXT1:
+                       track->textures[i].cpp = 1;
+                       track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
+                       break;
+               case RADEON_TXFORMAT_DXT23:
+               case RADEON_TXFORMAT_DXT45:
+                       track->textures[i].cpp = 1;
+                       track->textures[i].compress_format = R100_TRACK_COMP_DXT35;
+                       break;
                }
                track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
                track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
@@ -1482,6 +1504,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
                        DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
                        return -EINVAL;
                }
+               track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 0));
                track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
                track->immd_dwords = pkt->count - 1;
                r = r100_cs_track_check(p->rdev, track);
@@ -1702,14 +1725,6 @@ void r100_gpu_init(struct radeon_device *rdev)
        r100_hdp_reset(rdev);
 }
 
-void r100_hdp_flush(struct radeon_device *rdev)
-{
-       u32 tmp;
-       tmp = RREG32(RADEON_HOST_PATH_CNTL);
-       tmp |= RADEON_HDP_READ_BUFFER_INVALIDATE;
-       WREG32(RADEON_HOST_PATH_CNTL, tmp);
-}
-
 void r100_hdp_reset(struct radeon_device *rdev)
 {
        uint32_t tmp;
@@ -2726,6 +2741,7 @@ static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
        DRM_ERROR("coordinate type            %d\n", t->tex_coord_type);
        DRM_ERROR("width round to power of 2  %d\n", t->roundup_w);
        DRM_ERROR("height round to power of 2 %d\n", t->roundup_h);
+       DRM_ERROR("compress format            %d\n", t->compress_format);
 }
 
 static int r100_cs_track_cube(struct radeon_device *rdev,
@@ -2755,6 +2771,36 @@ static int r100_cs_track_cube(struct radeon_device *rdev,
        return 0;
 }
 
+static int r100_track_compress_size(int compress_format, int w, int h)
+{
+       int block_width, block_height, block_bytes;
+       int wblocks, hblocks;
+       int min_wblocks;
+       int sz;
+
+       block_width = 4;
+       block_height = 4;
+
+       switch (compress_format) {
+       case R100_TRACK_COMP_DXT1:
+               block_bytes = 8;
+               min_wblocks = 4;
+               break;
+       default:
+       case R100_TRACK_COMP_DXT35:
+               block_bytes = 16;
+               min_wblocks = 2;
+               break;
+       }
+
+       hblocks = (h + block_height - 1) / block_height;
+       wblocks = (w + block_width - 1) / block_width;
+       if (wblocks < min_wblocks)
+               wblocks = min_wblocks;
+       sz = wblocks * hblocks * block_bytes;
+       return sz;
+}
+
 static int r100_cs_track_texture_check(struct radeon_device *rdev,
                                       struct r100_cs_track *track)
 {
@@ -2792,9 +2838,15 @@ static int r100_cs_track_texture_check(struct radeon_device *rdev,
                        h = h / (1 << i);
                        if (track->textures[u].roundup_h)
                                h = roundup_pow_of_two(h);
-                       size += w * h;
+                       if (track->textures[u].compress_format) {
+
+                               size += r100_track_compress_size(track->textures[u].compress_format, w, h);
+                               /* compressed textures are block based */
+                       } else
+                               size += w * h;
                }
                size *= track->textures[u].cpp;
+
                switch (track->textures[u].tex_coord_type) {
                case 0:
                        break;
@@ -2833,6 +2885,10 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track)
 
        for (i = 0; i < track->num_cb; i++) {
                if (track->cb[i].robj == NULL) {
+                       if (!(track->fastfill || track->color_channel_mask ||
+                             track->blend_read_enable)) {
+                               continue;
+                       }
                        DRM_ERROR("[drm] No buffer for color buffer %d !\n", i);
                        return -EINVAL;
                }
@@ -2962,6 +3018,7 @@ void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track
                track->arrays[i].esize = 0x7F;
        }
        for (i = 0; i < track->num_texture; i++) {
+               track->textures[i].compress_format = R100_TRACK_COMP_NONE;
                track->textures[i].pitch = 16536;
                track->textures[i].width = 16536;
                track->textures[i].height = 16536;
@@ -3260,6 +3317,7 @@ static int r100_startup(struct radeon_device *rdev)
        }
        /* Enable IRQ */
        r100_irq_set(rdev);
+       rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
        /* 1M ring buffer */
        r = r100_cp_init(rdev, 1024 * 1024);
        if (r) {
@@ -3294,6 +3352,8 @@ int r100_resume(struct radeon_device *rdev)
        radeon_combios_asic_init(rdev->ddev);
        /* Resume clock after posting */
        r100_clock_startup(rdev);
+       /* Initialize surface registers */
+       radeon_surface_init(rdev);
        return r100_startup(rdev);
 }
 
@@ -3316,6 +3376,7 @@ void r100_fini(struct radeon_device *rdev)
        radeon_gem_fini(rdev);
        if (rdev->flags & RADEON_IS_PCI)
                r100_pci_gart_fini(rdev);
+       radeon_agp_fini(rdev);
        radeon_irq_kms_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_bo_fini(rdev);
@@ -3339,9 +3400,7 @@ int r100_mc_init(struct radeon_device *rdev)
        if (rdev->flags & RADEON_IS_AGP) {
                r = radeon_agp_init(rdev);
                if (r) {
-                       printk(KERN_WARNING "[drm] Disabling AGP\n");
-                       rdev->flags &= ~RADEON_IS_AGP;
-                       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+                       radeon_agp_disable(rdev);
                } else {
                        rdev->mc.gtt_location = rdev->mc.agp_base;
                }
@@ -3392,6 +3451,8 @@ int r100_init(struct radeon_device *rdev)
        r100_errata(rdev);
        /* Initialize clocks */
        radeon_get_clock_info(rdev->ddev);
+       /* Initialize power management */
+       radeon_pm_init(rdev);
        /* Get vram informations */
        r100_vram_info(rdev);
        /* Initialize memory controller (also test AGP) */