Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
[pandora-kernel.git] / drivers / gpu / drm / radeon / r100.c
index 7fcdbbb..ad158ea 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/module.h>
 
 #include "r100_reg_safe.h"
 #include "rn50_reg_safe.h"
@@ -68,6 +69,108 @@ MODULE_FIRMWARE(FIRMWARE_R520);
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
  */
 
+int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
+                           struct radeon_cs_packet *pkt,
+                           unsigned idx,
+                           unsigned reg)
+{
+       int r;
+       u32 tile_flags = 0;
+       u32 tmp;
+       struct radeon_cs_reloc *reloc;
+       u32 value;
+
+       r = r100_cs_packet_next_reloc(p, &reloc);
+       if (r) {
+               DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                         idx, reg);
+               r100_cs_dump_packet(p, pkt);
+               return r;
+       }
+       value = radeon_get_ib_value(p, idx);
+       tmp = value & 0x003fffff;
+       tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
+
+       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+               tile_flags |= RADEON_DST_TILE_MACRO;
+       if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+               if (reg == RADEON_SRC_PITCH_OFFSET) {
+                       DRM_ERROR("Cannot src blit from microtiled surface\n");
+                       r100_cs_dump_packet(p, pkt);
+                       return -EINVAL;
+               }
+               tile_flags |= RADEON_DST_TILE_MICRO;
+       }
+
+       tmp |= tile_flags;
+       p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
+       return 0;
+}
+
+int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
+                            struct radeon_cs_packet *pkt,
+                            int idx)
+{
+       unsigned c, i;
+       struct radeon_cs_reloc *reloc;
+       struct r100_cs_track *track;
+       int r = 0;
+       volatile uint32_t *ib;
+       u32 idx_value;
+
+       ib = p->ib->ptr;
+       track = (struct r100_cs_track *)p->track;
+       c = radeon_get_ib_value(p, idx++) & 0x1F;
+       if (c > 16) {
+           DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
+                     pkt->opcode);
+           r100_cs_dump_packet(p, pkt);
+           return -EINVAL;
+       }
+       track->num_arrays = c;
+       for (i = 0; i < (c - 1); i+=2, idx+=3) {
+               r = r100_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("No reloc for packet3 %d\n",
+                                 pkt->opcode);
+                       r100_cs_dump_packet(p, pkt);
+                       return r;
+               }
+               idx_value = radeon_get_ib_value(p, idx);
+               ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+
+               track->arrays[i + 0].esize = idx_value >> 8;
+               track->arrays[i + 0].robj = reloc->robj;
+               track->arrays[i + 0].esize &= 0x7F;
+               r = r100_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("No reloc for packet3 %d\n",
+                                 pkt->opcode);
+                       r100_cs_dump_packet(p, pkt);
+                       return r;
+               }
+               ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
+               track->arrays[i + 1].robj = reloc->robj;
+               track->arrays[i + 1].esize = idx_value >> 24;
+               track->arrays[i + 1].esize &= 0x7F;
+       }
+       if (c & 1) {
+               r = r100_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("No reloc for packet3 %d\n",
+                                         pkt->opcode);
+                       r100_cs_dump_packet(p, pkt);
+                       return r;
+               }
+               idx_value = radeon_get_ib_value(p, idx);
+               ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+               track->arrays[i + 0].robj = reloc->robj;
+               track->arrays[i + 0].esize = idx_value >> 8;
+               track->arrays[i + 0].esize &= 0x7F;
+       }
+       return r;
+}
+
 void r100_pre_page_flip(struct radeon_device *rdev, int crtc)
 {
        /* enable the pflip int */
@@ -434,6 +537,7 @@ void r100_hpd_init(struct radeon_device *rdev)
                default:
                        break;
                }
+               radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
        }
        if (rdev->irq.installed)
                r100_irq_set(rdev);
@@ -474,7 +578,7 @@ int r100_pci_gart_init(struct radeon_device *rdev)
 {
        int r;
 
-       if (rdev->gart.table.ram.ptr) {
+       if (rdev->gart.ptr) {
                WARN(1, "R100 PCI GART already initialized\n");
                return 0;
        }
@@ -513,6 +617,9 @@ int r100_pci_gart_enable(struct radeon_device *rdev)
        tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
        WREG32(RADEON_AIC_CNTL, tmp);
        r100_pci_gart_tlb_flush(rdev);
+       DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+                (unsigned)(rdev->mc.gtt_size >> 20),
+                (unsigned long long)rdev->gart.table_addr);
        rdev->gart.ready = true;
        return 0;
 }
@@ -530,10 +637,12 @@ void r100_pci_gart_disable(struct radeon_device *rdev)
 
 int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
+       u32 *gtt = rdev->gart.ptr;
+
        if (i < 0 || i > rdev->gart.num_gpu_pages) {
                return -EINVAL;
        }
-       rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr));
+       gtt[i] = cpu_to_le32(lower_32_bits(addr));
        return 0;
 }
 
@@ -588,7 +697,7 @@ void r100_irq_disable(struct radeon_device *rdev)
        WREG32(R_000044_GEN_INT_STATUS, tmp);
 }
 
-static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
+static uint32_t r100_irq_ack(struct radeon_device *rdev)
 {
        uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
        uint32_t irq_mask = RADEON_SW_INT_TEST |
@@ -3147,7 +3256,7 @@ void r100_bandwidth_update(struct radeon_device *rdev)
        }
 }
 
-static inline void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
+static void r100_cs_track_texture_print(struct r100_cs_track_texture *t)
 {
        DRM_ERROR("pitch                      %d\n", t->pitch);
        DRM_ERROR("use_pitch                  %d\n", t->use_pitch);
@@ -3965,3 +4074,43 @@ int r100_init(struct radeon_device *rdev)
        }
        return 0;
 }
+
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+       if (reg < rdev->rmmio_size)
+               return readl(((void __iomem *)rdev->rmmio) + reg);
+       else {
+               writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+               return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+       }
+}
+
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+       if (reg < rdev->rmmio_size)
+               writel(v, ((void __iomem *)rdev->rmmio) + reg);
+       else {
+               writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+               writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+       }
+}
+
+u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
+{
+       if (reg < rdev->rio_mem_size)
+               return ioread32(rdev->rio_mem + reg);
+       else {
+               iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+               return ioread32(rdev->rio_mem + RADEON_MM_DATA);
+       }
+}
+
+void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
+{
+       if (reg < rdev->rio_mem_size)
+               iowrite32(v, rdev->rio_mem + reg);
+       else {
+               iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+               iowrite32(v, rdev->rio_mem + RADEON_MM_DATA);
+       }
+}