aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-02-13 18:57:35 -0500
committerBen Skeggs <bskeggs@redhat.com>2011-02-24 15:46:07 -0500
commit8f7286f8e4e80f7b868ba3d117ae900f0d207cbe (patch)
tree018804469b7bce4033b4156442c904512282fab2
parent26c0c9e33a2eb44b345d22d5928d5c8b7b261226 (diff)
drm/nv50: support for compression
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.h7
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fb.c51
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vm.c8
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vram.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_vm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_vram.c2
-rw-r--r--include/drm/nouveau_drm.h1
10 files changed, 79 insertions, 27 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 4bdc726a072b..00aff226397d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -72,6 +72,7 @@ struct nouveau_mem {
72 struct nouveau_vma tmp_vma; 72 struct nouveau_vma tmp_vma;
73 u8 page_shift; 73 u8 page_shift;
74 74
75 struct drm_mm_node *tag;
75 struct list_head regions; 76 struct list_head regions;
76 dma_addr_t *pages; 77 dma_addr_t *pages;
77 u32 memtype; 78 u32 memtype;
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 73f37bd0adfa..63b9040b5f30 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -740,7 +740,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
740 740
741 ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, 741 ret = vram->get(dev, mem->num_pages << PAGE_SHIFT,
742 mem->page_alignment << PAGE_SHIFT, size_nc, 742 mem->page_alignment << PAGE_SHIFT, size_nc,
743 (nvbo->tile_flags >> 8) & 0xff, &node); 743 (nvbo->tile_flags >> 8) & 0x3ff, &node);
744 if (ret) 744 if (ret)
745 return ret; 745 return ret;
746 746
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c
index 3d9c1595eaa8..62824c80bcb8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.c
@@ -40,6 +40,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
40 u32 max = 1 << (vm->pgt_bits - bits); 40 u32 max = 1 << (vm->pgt_bits - bits);
41 u32 end, len; 41 u32 end, len;
42 42
43 delta = 0;
43 list_for_each_entry(r, &node->regions, rl_entry) { 44 list_for_each_entry(r, &node->regions, rl_entry) {
44 u64 phys = (u64)r->offset << 12; 45 u64 phys = (u64)r->offset << 12;
45 u32 num = r->length >> bits; 46 u32 num = r->length >> bits;
@@ -52,7 +53,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
52 end = max; 53 end = max;
53 len = end - pte; 54 len = end - pte;
54 55
55 vm->map(vma, pgt, node, pte, len, phys); 56 vm->map(vma, pgt, node, pte, len, phys, delta);
56 57
57 num -= len; 58 num -= len;
58 pte += len; 59 pte += len;
@@ -60,6 +61,8 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
60 pde++; 61 pde++;
61 pte = 0; 62 pte = 0;
62 } 63 }
64
65 delta += (u64)len << vma->node->type;
63 } 66 }
64 } 67 }
65 68
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
index 0e00264b8f49..2e06b55cfdc1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -67,7 +67,8 @@ struct nouveau_vm {
67 void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, 67 void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde,
68 struct nouveau_gpuobj *pgt[2]); 68 struct nouveau_gpuobj *pgt[2]);
69 void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, 69 void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *,
70 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys); 70 struct nouveau_mem *, u32 pte, u32 cnt,
71 u64 phys, u64 delta);
71 void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, 72 void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *,
72 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); 73 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
73 void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); 74 void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt);
@@ -93,7 +94,7 @@ void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
93void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, 94void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
94 struct nouveau_gpuobj *pgt[2]); 95 struct nouveau_gpuobj *pgt[2]);
95void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, 96void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
96 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys); 97 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta);
97void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, 98void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
98 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); 99 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
99void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); 100void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
@@ -104,7 +105,7 @@ void nv50_vm_flush_engine(struct drm_device *, int engine);
104void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, 105void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
105 struct nouveau_gpuobj *pgt[2]); 106 struct nouveau_gpuobj *pgt[2]);
106void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, 107void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
107 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys); 108 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta);
108void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, 109void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
109 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); 110 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
110void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); 111void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c
index 50290dea0ac4..ed411d88451d 100644
--- a/drivers/gpu/drm/nouveau/nv50_fb.c
+++ b/drivers/gpu/drm/nouveau/nv50_fb.c
@@ -8,31 +8,61 @@ struct nv50_fb_priv {
8 dma_addr_t r100c08; 8 dma_addr_t r100c08;
9}; 9};
10 10
11static void
12nv50_fb_destroy(struct drm_device *dev)
13{
14 struct drm_nouveau_private *dev_priv = dev->dev_private;
15 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
16 struct nv50_fb_priv *priv = pfb->priv;
17
18 if (drm_mm_initialized(&pfb->tag_heap))
19 drm_mm_takedown(&pfb->tag_heap);
20
21 if (priv->r100c08_page) {
22 pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
23 PCI_DMA_BIDIRECTIONAL);
24 __free_page(priv->r100c08_page);
25 }
26
27 kfree(priv);
28 pfb->priv = NULL;
29}
30
11static int 31static int
12nv50_fb_create(struct drm_device *dev) 32nv50_fb_create(struct drm_device *dev)
13{ 33{
14 struct drm_nouveau_private *dev_priv = dev->dev_private; 34 struct drm_nouveau_private *dev_priv = dev->dev_private;
35 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
15 struct nv50_fb_priv *priv; 36 struct nv50_fb_priv *priv;
37 u32 tagmem;
38 int ret;
16 39
17 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 40 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
18 if (!priv) 41 if (!priv)
19 return -ENOMEM; 42 return -ENOMEM;
43 pfb->priv = priv;
20 44
21 priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); 45 priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
22 if (!priv->r100c08_page) { 46 if (!priv->r100c08_page) {
23 kfree(priv); 47 nv50_fb_destroy(dev);
24 return -ENOMEM; 48 return -ENOMEM;
25 } 49 }
26 50
27 priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, 51 priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0,
28 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 52 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
29 if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { 53 if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) {
30 __free_page(priv->r100c08_page); 54 nv50_fb_destroy(dev);
31 kfree(priv);
32 return -EFAULT; 55 return -EFAULT;
33 } 56 }
34 57
35 dev_priv->engine.fb.priv = priv; 58 tagmem = nv_rd32(dev, 0x100320);
59 NV_DEBUG(dev, "%d tags available\n", tagmem);
60 ret = drm_mm_init(&pfb->tag_heap, 0, tagmem);
61 if (ret) {
62 nv50_fb_destroy(dev);
63 return ret;
64 }
65
36 return 0; 66 return 0;
37} 67}
38 68
@@ -81,18 +111,7 @@ nv50_fb_init(struct drm_device *dev)
81void 111void
82nv50_fb_takedown(struct drm_device *dev) 112nv50_fb_takedown(struct drm_device *dev)
83{ 113{
84 struct drm_nouveau_private *dev_priv = dev->dev_private; 114 nv50_fb_destroy(dev);
85 struct nv50_fb_priv *priv;
86
87 priv = dev_priv->engine.fb.priv;
88 if (!priv)
89 return;
90 dev_priv->engine.fb.priv = NULL;
91
92 pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
93 PCI_DMA_BIDIRECTIONAL);
94 __free_page(priv->r100c08_page);
95 kfree(priv);
96} 115}
97 116
98void 117void
diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c
index 37f941bf4a0b..b23794c8859b 100644
--- a/drivers/gpu/drm/nouveau/nv50_vm.c
+++ b/drivers/gpu/drm/nouveau/nv50_vm.c
@@ -83,8 +83,9 @@ nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target)
83 83
84void 84void
85nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, 85nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
86 struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys) 86 struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
87{ 87{
88 u32 comp = (mem->memtype & 0x180) >> 7;
88 u32 block; 89 u32 block;
89 int i; 90 int i;
90 91
@@ -105,6 +106,11 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
105 106
106 phys += block << (vma->node->type - 3); 107 phys += block << (vma->node->type - 3);
107 cnt -= block; 108 cnt -= block;
109 if (comp) {
110 u32 tag = mem->tag->start + ((delta >> 16) * comp);
111 offset_h |= (tag << 17);
112 delta += block << (vma->node->type - 3);
113 }
108 114
109 while (block) { 115 while (block) {
110 nv_wo32(pgt, pte + 0, offset_l); 116 nv_wo32(pgt, pte + 0, offset_l);
diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c
index ff6cbae40e58..ffbc3d8cf5be 100644
--- a/drivers/gpu/drm/nouveau/nv50_vram.c
+++ b/drivers/gpu/drm/nouveau/nv50_vram.c
@@ -69,6 +69,11 @@ nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
69 list_del(&this->rl_entry); 69 list_del(&this->rl_entry);
70 nouveau_mm_put(mm, this); 70 nouveau_mm_put(mm, this);
71 } 71 }
72
73 if (mem->tag) {
74 drm_mm_put_block(mem->tag);
75 mem->tag = NULL;
76 }
72 mutex_unlock(&mm->mutex); 77 mutex_unlock(&mm->mutex);
73 78
74 kfree(mem); 79 kfree(mem);
@@ -76,7 +81,7 @@ nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
76 81
77int 82int
78nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, 83nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
79 u32 type, struct nouveau_mem **pmem) 84 u32 memtype, struct nouveau_mem **pmem)
80{ 85{
81 struct drm_nouveau_private *dev_priv = dev->dev_private; 86 struct drm_nouveau_private *dev_priv = dev->dev_private;
82 struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; 87 struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
@@ -84,6 +89,8 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
84 struct nouveau_mm *mm = man->priv; 89 struct nouveau_mm *mm = man->priv;
85 struct nouveau_mm_node *r; 90 struct nouveau_mm_node *r;
86 struct nouveau_mem *mem; 91 struct nouveau_mem *mem;
92 int comp = (memtype & 0x300) >> 8;
93 int type = (memtype & 0x07f);
87 int ret; 94 int ret;
88 95
89 if (!types[type]) 96 if (!types[type])
@@ -96,12 +103,26 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
96 if (!mem) 103 if (!mem)
97 return -ENOMEM; 104 return -ENOMEM;
98 105
106 mutex_lock(&mm->mutex);
107 if (comp) {
108 if (align == 16) {
109 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
110 int n = (size >> 4) * comp;
111
112 mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0);
113 if (mem->tag)
114 mem->tag = drm_mm_get_block(mem->tag, n, 0);
115 }
116
117 if (unlikely(!mem->tag))
118 comp = 0;
119 }
120
99 INIT_LIST_HEAD(&mem->regions); 121 INIT_LIST_HEAD(&mem->regions);
100 mem->dev = dev_priv->dev; 122 mem->dev = dev_priv->dev;
101 mem->memtype = type; 123 mem->memtype = (comp << 7) | type;
102 mem->size = size; 124 mem->size = size;
103 125
104 mutex_lock(&mm->mutex);
105 do { 126 do {
106 ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); 127 ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r);
107 if (ret) { 128 if (ret) {
diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c
index 2b984b25f27e..69af0ba7edd3 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vm.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vm.c
@@ -59,7 +59,7 @@ nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target)
59 59
60void 60void
61nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, 61nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
62 struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys) 62 struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
63{ 63{
64 u32 next = 1 << (vma->node->type - 8); 64 u32 next = 1 << (vma->node->type - 8);
65 65
diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c
index 6d777a2a04dd..67c6ec6f34ea 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vram.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c
@@ -78,7 +78,7 @@ nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
78 78
79 INIT_LIST_HEAD(&mem->regions); 79 INIT_LIST_HEAD(&mem->regions);
80 mem->dev = dev_priv->dev; 80 mem->dev = dev_priv->dev;
81 mem->memtype = type; 81 mem->memtype = (type & 0xff);
82 mem->size = size; 82 mem->size = size;
83 83
84 mutex_lock(&mm->mutex); 84 mutex_lock(&mm->mutex);
diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h
index e2cfe80f6fca..5edd3a76fffa 100644
--- a/include/drm/nouveau_drm.h
+++ b/include/drm/nouveau_drm.h
@@ -94,6 +94,7 @@ struct drm_nouveau_setparam {
94#define NOUVEAU_GEM_DOMAIN_GART (1 << 2) 94#define NOUVEAU_GEM_DOMAIN_GART (1 << 2)
95#define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3) 95#define NOUVEAU_GEM_DOMAIN_MAPPABLE (1 << 3)
96 96
97#define NOUVEAU_GEM_TILE_COMP 0x00030000 /* nv50-only */
97#define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00 98#define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00
98#define NOUVEAU_GEM_TILE_16BPP 0x00000001 99#define NOUVEAU_GEM_TILE_16BPP 0x00000001
99#define NOUVEAU_GEM_TILE_32BPP 0x00000002 100#define NOUVEAU_GEM_TILE_32BPP 0x00000002