aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-10-24 10:36:12 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-12-03 00:11:21 -0500
commit87a326a38589e1c919af5f86a59cd571ff0aa831 (patch)
treec8e829f79f4f20bc876d73ba7c3d545b15d12ee0
parenta5cf68b04b2b8ea716cf6fd8499c1c54d05fdf5e (diff)
drm/nv20: Add Z compression support.
Signed-off-by: Francisco Jerez <currojerez@riseup.net> Tested-by: Xavier Chantry <chantry.xavier@gmail.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_reg.h6
-rw-r--r--drivers/gpu/drm/nouveau/nv10_fb.c90
-rw-r--r--drivers/gpu/drm/nouveau/nv20_graph.c21
4 files changed, 106 insertions, 14 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 8b524d894f18..a94430b94a20 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -70,6 +70,8 @@ struct nouveau_tile_reg {
70 uint32_t addr; 70 uint32_t addr;
71 uint32_t limit; 71 uint32_t limit;
72 uint32_t pitch; 72 uint32_t pitch;
73 uint32_t zcomp;
74 struct drm_mm_node *tag_mem;
73 struct nouveau_fence *fence; 75 struct nouveau_fence *fence;
74}; 76};
75 77
@@ -306,6 +308,7 @@ struct nouveau_timer_engine {
306 308
307struct nouveau_fb_engine { 309struct nouveau_fb_engine {
308 int num_tiles; 310 int num_tiles;
311 struct drm_mm tag_heap;
309 312
310 int (*init)(struct drm_device *dev); 313 int (*init)(struct drm_device *dev);
311 void (*takedown)(struct drm_device *dev); 314 void (*takedown)(struct drm_device *dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h
index b6384d36d5d0..df3a87e792f2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_reg.h
+++ b/drivers/gpu/drm/nouveau/nouveau_reg.h
@@ -45,6 +45,11 @@
45# define NV04_PFB_REF_CMD_REFRESH (1 << 0) 45# define NV04_PFB_REF_CMD_REFRESH (1 << 0)
46#define NV04_PFB_PRE 0x001002d4 46#define NV04_PFB_PRE 0x001002d4
47# define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0) 47# define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0)
48#define NV20_PFB_ZCOMP(i) (0x00100300 + 4*(i))
49# define NV20_PFB_ZCOMP_MODE_32 (4 << 24)
50# define NV20_PFB_ZCOMP_EN (1 << 31)
51# define NV25_PFB_ZCOMP_MODE_16 (1 << 20)
52# define NV25_PFB_ZCOMP_MODE_32 (2 << 20)
48#define NV10_PFB_CLOSE_PAGE2 0x0010033c 53#define NV10_PFB_CLOSE_PAGE2 0x0010033c
49#define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) 54#define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i))
50#define NV40_PFB_TILE(i) (0x00100600 + (i*16)) 55#define NV40_PFB_TILE(i) (0x00100600 + (i*16))
@@ -379,6 +384,7 @@
379#define NV20_PGRAPH_TLIMIT(i) (0x00400904 + (i*16)) 384#define NV20_PGRAPH_TLIMIT(i) (0x00400904 + (i*16))
380#define NV20_PGRAPH_TSIZE(i) (0x00400908 + (i*16)) 385#define NV20_PGRAPH_TSIZE(i) (0x00400908 + (i*16))
381#define NV20_PGRAPH_TSTATUS(i) (0x0040090C + (i*16)) 386#define NV20_PGRAPH_TSTATUS(i) (0x0040090C + (i*16))
387#define NV20_PGRAPH_ZCOMP(i) (0x00400980 + 4*(i))
382#define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) 388#define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16))
383#define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) 389#define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16))
384#define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) 390#define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16))
diff --git a/drivers/gpu/drm/nouveau/nv10_fb.c b/drivers/gpu/drm/nouveau/nv10_fb.c
index d50acc6a90d1..f78181a59b4a 100644
--- a/drivers/gpu/drm/nouveau/nv10_fb.c
+++ b/drivers/gpu/drm/nouveau/nv10_fb.c
@@ -3,21 +3,81 @@
3#include "nouveau_drv.h" 3#include "nouveau_drv.h"
4#include "nouveau_drm.h" 4#include "nouveau_drm.h"
5 5
6static struct drm_mm_node *
7nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size)
8{
9 struct drm_nouveau_private *dev_priv = dev->dev_private;
10 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
11 struct drm_mm_node *mem;
12 int ret;
13
14 ret = drm_mm_pre_get(&pfb->tag_heap);
15 if (ret)
16 return NULL;
17
18 spin_lock(&dev_priv->tile.lock);
19 mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0);
20 if (mem)
21 mem = drm_mm_get_block_atomic(mem, size, 0);
22 spin_unlock(&dev_priv->tile.lock);
23
24 return mem;
25}
26
27static void
28nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem)
29{
30 struct drm_nouveau_private *dev_priv = dev->dev_private;
31
32 spin_lock(&dev_priv->tile.lock);
33 drm_mm_put_block(mem);
34 spin_unlock(&dev_priv->tile.lock);
35}
36
6void 37void
7nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, 38nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
8 uint32_t size, uint32_t pitch, uint32_t flags) 39 uint32_t size, uint32_t pitch, uint32_t flags)
9{ 40{
10 struct drm_nouveau_private *dev_priv = dev->dev_private; 41 struct drm_nouveau_private *dev_priv = dev->dev_private;
11 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; 42 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
43 int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16);
12 44
13 tile->addr = addr; 45 tile->addr = addr;
14 tile->limit = max(1u, addr + size) - 1; 46 tile->limit = max(1u, addr + size) - 1;
15 tile->pitch = pitch; 47 tile->pitch = pitch;
16 48
17 if (dev_priv->card_type == NV_20) 49 if (dev_priv->card_type == NV_20) {
18 tile->addr |= 1; 50 if (flags & NOUVEAU_GEM_TILE_ZETA) {
19 else 51 /*
52 * Allocate some of the on-die tag memory,
53 * used to store Z compression meta-data (most
54 * likely just a bitmap determining if a given
55 * tile is compressed or not).
56 */
57 tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256);
58
59 if (tile->tag_mem) {
60 /* Enable Z compression */
61 if (dev_priv->chipset >= 0x25)
62 tile->zcomp = tile->tag_mem->start |
63 (bpp == 16 ?
64 NV25_PFB_ZCOMP_MODE_16 :
65 NV25_PFB_ZCOMP_MODE_32);
66 else
67 tile->zcomp = tile->tag_mem->start |
68 NV20_PFB_ZCOMP_EN |
69 (bpp == 16 ? 0 :
70 NV20_PFB_ZCOMP_MODE_32);
71 }
72
73 tile->addr |= 3;
74 } else {
75 tile->addr |= 1;
76 }
77
78 } else {
20 tile->addr |= 1 << 31; 79 tile->addr |= 1 << 31;
80 }
21} 81}
22 82
23void 83void
@@ -26,7 +86,12 @@ nv10_fb_free_tile_region(struct drm_device *dev, int i)
26 struct drm_nouveau_private *dev_priv = dev->dev_private; 86 struct drm_nouveau_private *dev_priv = dev->dev_private;
27 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; 87 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
28 88
29 tile->addr = tile->limit = tile->pitch = 0; 89 if (tile->tag_mem) {
90 nv20_fb_free_tag(dev, tile->tag_mem);
91 tile->tag_mem = NULL;
92 }
93
94 tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
30} 95}
31 96
32void 97void
@@ -38,6 +103,9 @@ nv10_fb_set_tile_region(struct drm_device *dev, int i)
38 nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); 103 nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
39 nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); 104 nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
40 nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); 105 nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
106
107 if (dev_priv->card_type == NV_20)
108 nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp);
41} 109}
42 110
43int 111int
@@ -49,6 +117,11 @@ nv10_fb_init(struct drm_device *dev)
49 117
50 pfb->num_tiles = NV10_PFB_TILE__SIZE; 118 pfb->num_tiles = NV10_PFB_TILE__SIZE;
51 119
120 if (dev_priv->card_type == NV_20)
121 drm_mm_init(&pfb->tag_heap, 0,
122 (dev_priv->chipset >= 0x25 ?
123 64 * 1024 : 32 * 1024));
124
52 /* Turn all the tiling regions off. */ 125 /* Turn all the tiling regions off. */
53 for (i = 0; i < pfb->num_tiles; i++) 126 for (i = 0; i < pfb->num_tiles; i++)
54 pfb->set_tile_region(dev, i); 127 pfb->set_tile_region(dev, i);
@@ -59,4 +132,13 @@ nv10_fb_init(struct drm_device *dev)
59void 132void
60nv10_fb_takedown(struct drm_device *dev) 133nv10_fb_takedown(struct drm_device *dev)
61{ 134{
135 struct drm_nouveau_private *dev_priv = dev->dev_private;
136 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
137 int i;
138
139 for (i = 0; i < pfb->num_tiles; i++)
140 pfb->free_tile_region(dev, i);
141
142 if (dev_priv->card_type == NV_20)
143 drm_mm_takedown(&pfb->tag_heap);
62} 144}
diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c
index a71871b91c69..bd065c2fcba4 100644
--- a/drivers/gpu/drm/nouveau/nv20_graph.c
+++ b/drivers/gpu/drm/nouveau/nv20_graph.c
@@ -526,6 +526,12 @@ nv20_graph_set_tile_region(struct drm_device *dev, int i)
526 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->pitch); 526 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->pitch);
527 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); 527 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i);
528 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->addr); 528 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->addr);
529
530 if (dev_priv->card_type == NV_20) {
531 nv_wr32(dev, NV20_PGRAPH_ZCOMP(i), tile->zcomp);
532 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i);
533 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->zcomp);
534 }
529} 535}
530 536
531int 537int
@@ -589,16 +595,17 @@ nv20_graph_init(struct drm_device *dev)
589 nv_wr32(dev, 0x40009C , 0x00000040); 595 nv_wr32(dev, 0x40009C , 0x00000040);
590 596
591 if (dev_priv->chipset >= 0x25) { 597 if (dev_priv->chipset >= 0x25) {
592 nv_wr32(dev, 0x400890, 0x00080000); 598 nv_wr32(dev, 0x400890, 0x00a8cfff);
593 nv_wr32(dev, 0x400610, 0x304B1FB6); 599 nv_wr32(dev, 0x400610, 0x304B1FB6);
594 nv_wr32(dev, 0x400B80, 0x18B82880); 600 nv_wr32(dev, 0x400B80, 0x1cbd3883);
595 nv_wr32(dev, 0x400B84, 0x44000000); 601 nv_wr32(dev, 0x400B84, 0x44000000);
596 nv_wr32(dev, 0x400098, 0x40000080); 602 nv_wr32(dev, 0x400098, 0x40000080);
597 nv_wr32(dev, 0x400B88, 0x000000ff); 603 nv_wr32(dev, 0x400B88, 0x000000ff);
604
598 } else { 605 } else {
599 nv_wr32(dev, 0x400880, 0x00080000); /* 0x0008c7df */ 606 nv_wr32(dev, 0x400880, 0x0008c7df);
600 nv_wr32(dev, 0x400094, 0x00000005); 607 nv_wr32(dev, 0x400094, 0x00000005);
601 nv_wr32(dev, 0x400B80, 0x45CAA208); /* 0x45eae20e */ 608 nv_wr32(dev, 0x400B80, 0x45eae20e);
602 nv_wr32(dev, 0x400B84, 0x24000000); 609 nv_wr32(dev, 0x400B84, 0x24000000);
603 nv_wr32(dev, 0x400098, 0x00000040); 610 nv_wr32(dev, 0x400098, 0x00000040);
604 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038); 611 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038);
@@ -611,12 +618,6 @@ nv20_graph_init(struct drm_device *dev)
611 for (i = 0; i < NV10_PFB_TILE__SIZE; i++) 618 for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
612 nv20_graph_set_tile_region(dev, i); 619 nv20_graph_set_tile_region(dev, i);
613 620
614 for (i = 0; i < 8; i++) {
615 nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4));
616 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4);
617 nv_wr32(dev, NV10_PGRAPH_RDI_DATA,
618 nv_rd32(dev, 0x100300 + i * 4));
619 }
620 nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324)); 621 nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324));
621 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); 622 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C);
622 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324)); 623 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324));