nv20_fb.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 **pmem)
  24. {
  25. struct drm_nouveau_private *dev_priv = dev->dev_private;
  26. struct drm_mm_node *mem = *pmem;
  27. if (mem) {
  28. spin_lock(&dev_priv->tile.lock);
  29. drm_mm_put_block(mem);
  30. spin_unlock(&dev_priv->tile.lock);
  31. *pmem = NULL;
  32. }
  33. }
  34. void
  35. nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
  36. uint32_t size, uint32_t pitch, uint32_t flags)
  37. {
  38. struct drm_nouveau_private *dev_priv = dev->dev_private;
  39. struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
  40. int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16);
  41. tile->addr = 0x00000001 | addr;
  42. tile->limit = max(1u, addr + size) - 1;
  43. tile->pitch = pitch;
  44. /* Allocate some of the on-die tag memory, used to store Z
  45. * compression meta-data (most likely just a bitmap determining
  46. * if a given tile is compressed or not).
  47. */
  48. if (flags & NOUVEAU_GEM_TILE_ZETA) {
  49. tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256);
  50. if (tile->tag_mem) {
  51. /* Enable Z compression */
  52. tile->zcomp = tile->tag_mem->start;
  53. if (dev_priv->chipset >= 0x25) {
  54. if (bpp == 16)
  55. tile->zcomp |= NV25_PFB_ZCOMP_MODE_16;
  56. else
  57. tile->zcomp |= NV25_PFB_ZCOMP_MODE_32;
  58. } else {
  59. tile->zcomp |= NV20_PFB_ZCOMP_EN;
  60. if (bpp != 16)
  61. tile->zcomp |= NV20_PFB_ZCOMP_MODE_32;
  62. }
  63. }
  64. tile->addr |= 2;
  65. }
  66. }
  67. void
  68. nv20_fb_free_tile_region(struct drm_device *dev, int i)
  69. {
  70. struct drm_nouveau_private *dev_priv = dev->dev_private;
  71. struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
  72. tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
  73. nv20_fb_free_tag(dev, &tile->tag_mem);
  74. }
  75. void
  76. nv20_fb_set_tile_region(struct drm_device *dev, int i)
  77. {
  78. struct drm_nouveau_private *dev_priv = dev->dev_private;
  79. struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
  80. nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
  81. nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
  82. nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
  83. nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp);
  84. }
  85. int
  86. nv20_fb_vram_init(struct drm_device *dev)
  87. {
  88. struct drm_nouveau_private *dev_priv = dev->dev_private;
  89. u32 mem_size = nv_rd32(dev, 0x10020c);
  90. u32 pbus1218 = nv_rd32(dev, 0x001218);
  91. dev_priv->vram_size = mem_size & 0xff000000;
  92. switch (pbus1218 & 0x00000300) {
  93. case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break;
  94. case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
  95. case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
  96. case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_GDDR2; break;
  97. }
  98. return 0;
  99. }
  100. int
  101. nv20_fb_init(struct drm_device *dev)
  102. {
  103. struct drm_nouveau_private *dev_priv = dev->dev_private;
  104. struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
  105. int i;
  106. if (dev_priv->chipset >= 0x25)
  107. drm_mm_init(&pfb->tag_heap, 0, 64 * 1024);
  108. else
  109. drm_mm_init(&pfb->tag_heap, 0, 32 * 1024);
  110. /* Turn all the tiling regions off. */
  111. pfb->num_tiles = NV10_PFB_TILE__SIZE;
  112. for (i = 0; i < pfb->num_tiles; i++)
  113. pfb->set_tile_region(dev, i);
  114. return 0;
  115. }
  116. void
  117. nv20_fb_takedown(struct drm_device *dev)
  118. {
  119. struct drm_nouveau_private *dev_priv = dev->dev_private;
  120. struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
  121. int i;
  122. for (i = 0; i < pfb->num_tiles; i++)
  123. pfb->free_tile_region(dev, i);
  124. drm_mm_takedown(&pfb->tag_heap);
  125. }