nv10_fb.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include "drmP.h"
  2. #include "drm.h"
  3. #include "nouveau_drv.h"
  4. #include "nouveau_drm.h"
  5. static struct drm_mm_node *
  6. nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size)
  7. {
  8. struct drm_nouveau_private *dev_priv = dev->dev_private;
  9. struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
  10. struct drm_mm_node *mem;
  11. int ret;
  12. ret = drm_mm_pre_get(&pfb->tag_heap);
  13. if (ret)
  14. return NULL;
  15. spin_lock(&dev_priv->tile.lock);
  16. mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0);
  17. if (mem)
  18. mem = drm_mm_get_block_atomic(mem, size, 0);
  19. spin_unlock(&dev_priv->tile.lock);
  20. return mem;
  21. }
  22. static void
  23. nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem)
  24. {
  25. struct drm_nouveau_private *dev_priv = dev->dev_private;
  26. spin_lock(&dev_priv->tile.lock);
  27. drm_mm_put_block(mem);
  28. spin_unlock(&dev_priv->tile.lock);
  29. }
  30. void
  31. nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
  32. uint32_t size, uint32_t pitch, uint32_t flags)
  33. {
  34. struct drm_nouveau_private *dev_priv = dev->dev_private;
  35. struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
  36. int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16);
  37. tile->addr = addr;
  38. tile->limit = max(1u, addr + size) - 1;
  39. tile->pitch = pitch;
  40. if (dev_priv->card_type == NV_20) {
  41. if (flags & NOUVEAU_GEM_TILE_ZETA) {
  42. /*
  43. * Allocate some of the on-die tag memory,
  44. * used to store Z compression meta-data (most
  45. * likely just a bitmap determining if a given
  46. * tile is compressed or not).
  47. */
  48. tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256);
  49. if (tile->tag_mem) {
  50. /* Enable Z compression */
  51. if (dev_priv->chipset >= 0x25)
  52. tile->zcomp = tile->tag_mem->start |
  53. (bpp == 16 ?
  54. NV25_PFB_ZCOMP_MODE_16 :
  55. NV25_PFB_ZCOMP_MODE_32);
  56. else
  57. tile->zcomp = tile->tag_mem->start |
  58. NV20_PFB_ZCOMP_EN |
  59. (bpp == 16 ? 0 :
  60. NV20_PFB_ZCOMP_MODE_32);
  61. }
  62. tile->addr |= 3;
  63. } else {
  64. tile->addr |= 1;
  65. }
  66. } else {
  67. tile->addr |= 1 << 31;
  68. }
  69. }
  70. void
  71. nv10_fb_free_tile_region(struct drm_device *dev, int i)
  72. {
  73. struct drm_nouveau_private *dev_priv = dev->dev_private;
  74. struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
  75. if (tile->tag_mem) {
  76. nv20_fb_free_tag(dev, tile->tag_mem);
  77. tile->tag_mem = NULL;
  78. }
  79. tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
  80. }
  81. void
  82. nv10_fb_set_tile_region(struct drm_device *dev, int i)
  83. {
  84. struct drm_nouveau_private *dev_priv = dev->dev_private;
  85. struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
  86. nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
  87. nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
  88. nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
  89. if (dev_priv->card_type == NV_20)
  90. nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp);
  91. }
  92. int
  93. nv10_fb_init(struct drm_device *dev)
  94. {
  95. struct drm_nouveau_private *dev_priv = dev->dev_private;
  96. struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
  97. int i;
  98. pfb->num_tiles = NV10_PFB_TILE__SIZE;
  99. if (dev_priv->card_type == NV_20)
  100. drm_mm_init(&pfb->tag_heap, 0,
  101. (dev_priv->chipset >= 0x25 ?
  102. 64 * 1024 : 32 * 1024));
  103. /* Turn all the tiling regions off. */
  104. for (i = 0; i < pfb->num_tiles; i++)
  105. pfb->set_tile_region(dev, i);
  106. return 0;
  107. }
  108. void
  109. nv10_fb_takedown(struct drm_device *dev)
  110. {
  111. struct drm_nouveau_private *dev_priv = dev->dev_private;
  112. struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
  113. int i;
  114. for (i = 0; i < pfb->num_tiles; i++)
  115. pfb->free_tile_region(dev, i);
  116. if (dev_priv->card_type == NV_20)
  117. drm_mm_takedown(&pfb->tag_heap);
  118. }