/drivers/gpu/drm/nouveau/nv10_fb.c
C | 144 lines | 110 code | 26 blank | 8 comment | 20 complexity | eb136a2b4bc02ce49706cbeba8391b9c MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1#include "drmP.h" 2#include "drm.h" 3#include "nouveau_drv.h" 4#include "nouveau_drm.h" 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 37void 38nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, 39 uint32_t size, uint32_t pitch, uint32_t flags) 40{ 41 struct drm_nouveau_private *dev_priv = dev->dev_private; 42 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; 43 int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16); 44 45 tile->addr = addr; 46 tile->limit = max(1u, addr + size) - 1; 47 tile->pitch = pitch; 48 49 if (dev_priv->card_type == NV_20) { 50 if (flags & NOUVEAU_GEM_TILE_ZETA) { 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 { 79 tile->addr |= 1 << 31; 80 } 81} 82 83void 84nv10_fb_free_tile_region(struct drm_device *dev, int i) 85{ 86 struct drm_nouveau_private *dev_priv = dev->dev_private; 87 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; 88 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; 95} 96 97void 98nv10_fb_set_tile_region(struct drm_device *dev, int i) 99{ 100 struct drm_nouveau_private *dev_priv = dev->dev_private; 101 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; 102 103 nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); 104 nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); 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); 109} 110 111int 112nv10_fb_init(struct drm_device *dev) 113{ 114 struct drm_nouveau_private *dev_priv = dev->dev_private; 115 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; 116 int i; 117 118 pfb->num_tiles = NV10_PFB_TILE__SIZE; 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 125 /* Turn all the tiling regions off. */ 126 for (i = 0; i < pfb->num_tiles; i++) 127 pfb->set_tile_region(dev, i); 128 129 return 0; 130} 131 132void 133nv10_fb_takedown(struct drm_device *dev) 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); 144}