evergreen_irq_set(rdev);
 
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            R600_CP_RB_RPTR, R600_CP_RB_WPTR);
+                            R600_CP_RB_RPTR, R600_CP_RB_WPTR,
+                            0, 0xfffff, RADEON_CP_PACKET2);
        if (r)
                return r;
        r = evergreen_cp_load_microcode(rdev);
 
        evergreen_irq_set(rdev);
 
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            CP_RB0_RPTR, CP_RB0_WPTR);
+                            CP_RB0_RPTR, CP_RB0_WPTR,
+                            0, 0xfffff, RADEON_CP_PACKET2);
        if (r)
                return r;
        r = cayman_cp_load_microcode(rdev);
 
        ring_size = (1 << (rb_bufsz + 1)) * 4;
        r100_cp_load_microcode(rdev);
        r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR);
+                            RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR,
+                            0, 0x7fffff, RADEON_CP_PACKET2);
        if (r) {
                return r;
        }
 
        r600_irq_set(rdev);
 
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            R600_CP_RB_RPTR, R600_CP_RB_WPTR);
+                            R600_CP_RB_RPTR, R600_CP_RB_WPTR,
+                            0, 0xfffff, RADEON_CP_PACKET2);
 
        if (r)
                return r;
 
        uint32_t                ptr_mask;
        struct mutex            mutex;
        bool                    ready;
+       u32                     ptr_reg_shift;
+       u32                     ptr_reg_mask;
+       u32                     nop;
 };
 
 /*
 void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp);
 int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
 int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size,
-                    unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg);
+                    unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg,
+                    u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop);
 void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *cp);
 
 
 
 
 void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring)
 {
+       u32 rptr;
+
        if (rdev->wb.enabled)
-               ring->rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
+               rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
        else
-               ring->rptr = RREG32(ring->rptr_reg);
+               rptr = RREG32(ring->rptr_reg);
+       ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift;
        /* This works because ring_size is a power of 2 */
        ring->ring_free_dw = (ring->rptr + (ring->ring_size / 4));
        ring->ring_free_dw -= ring->wptr;
        count_dw_pad = (ring->align_mask + 1) -
                       (ring->wptr & ring->align_mask);
        for (i = 0; i < count_dw_pad; i++) {
-               radeon_ring_write(ring, 2 << 30);
+               radeon_ring_write(ring, ring->nop);
        }
        DRM_MEMORYBARRIER();
-       WREG32(ring->wptr_reg, ring->wptr);
+       WREG32(ring->wptr_reg, (ring->wptr << ring->ptr_reg_shift) & ring->ptr_reg_mask);
        (void)RREG32(ring->wptr_reg);
 }
 
 }
 
 int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size,
-                    unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg)
+                    unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg,
+                    u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop)
 {
        int r;
 
        ring->rptr_offs = rptr_offs;
        ring->rptr_reg = rptr_reg;
        ring->wptr_reg = wptr_reg;
+       ring->ptr_reg_shift = ptr_reg_shift;
+       ring->ptr_reg_mask = ptr_reg_mask;
+       ring->nop = nop;
        /* Allocate ring buffer */
        if (ring->ring_obj == NULL) {
                r = radeon_bo_create(rdev, ring->ring_size, PAGE_SIZE, true,
 
        r600_irq_set(rdev);
 
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            R600_CP_RB_RPTR, R600_CP_RB_WPTR);
+                            R600_CP_RB_RPTR, R600_CP_RB_WPTR,
+                            0, 0xfffff, RADEON_CP_PACKET2);
        if (r)
                return r;
        r = rv770_cp_load_microcode(rdev);