diff options
| author | Francisco Jerez <currojerez@riseup.net> | 2010-10-24 10:36:12 -0400 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2010-12-03 00:11:21 -0500 |
| commit | 87a326a38589e1c919af5f86a59cd571ff0aa831 (patch) | |
| tree | c8e829f79f4f20bc876d73ba7c3d545b15d12ee0 | |
| parent | a5cf68b04b2b8ea716cf6fd8499c1c54d05fdf5e (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.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_reg.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv10_fb.c | 90 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv20_graph.c | 21 |
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 | ||
| 307 | struct nouveau_fb_engine { | 309 | struct 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 | ||
| 6 | static struct drm_mm_node * | ||
| 7 | nv20_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 | |||
| 27 | static void | ||
| 28 | nv20_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 | |||
| 6 | void | 37 | void |
| 7 | nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, | 38 | nv10_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 | ||
| 23 | void | 83 | void |
| @@ -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 | ||
| 32 | void | 97 | void |
| @@ -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 | ||
| 43 | int | 111 | int |
| @@ -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) | |||
| 59 | void | 132 | void |
| 60 | nv10_fb_takedown(struct drm_device *dev) | 133 | nv10_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 | ||
| 531 | int | 537 | int |
| @@ -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)); |
