drm/nouveau: move vram detection funcs to chipset-specific fb code
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / gpu / drm / nouveau / nv10_fb.c
CommitLineData
6ee73861
BS
1#include "drmP.h"
2#include "drm.h"
3#include "nouveau_drv.h"
4#include "nouveau_drm.h"
5
7ad2d31c
BS
6int
7nv1a_fb_vram_init(struct drm_device *dev)
8{
9 struct drm_nouveau_private *dev_priv = dev->dev_private;
10 struct pci_dev *bridge;
11 uint32_t mem, mib;
12
13 bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
14 if (!bridge) {
15 NV_ERROR(dev, "no bridge device\n");
16 return 0;
17 }
18
19 if (dev_priv->chipset == 0x1a) {
20 pci_read_config_dword(bridge, 0x7c, &mem);
21 mib = ((mem >> 6) & 31) + 1;
22 } else {
23 pci_read_config_dword(bridge, 0x84, &mem);
24 mib = ((mem >> 4) & 127) + 1;
25 }
26
27 dev_priv->vram_size = mib * 1024 * 1024;
28 return 0;
29}
30
31int
32nv10_fb_vram_init(struct drm_device *dev)
33{
34 struct drm_nouveau_private *dev_priv = dev->dev_private;
35 u32 fifo_data = nv_rd32(dev, NV04_PFB_FIFO_DATA);
36
37 dev_priv->vram_size = fifo_data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
38 return 0;
39}
40
87a326a3
FJ
41static struct drm_mm_node *
42nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size)
43{
44 struct drm_nouveau_private *dev_priv = dev->dev_private;
45 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
46 struct drm_mm_node *mem;
47 int ret;
48
49 ret = drm_mm_pre_get(&pfb->tag_heap);
50 if (ret)
51 return NULL;
52
53 spin_lock(&dev_priv->tile.lock);
54 mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0);
55 if (mem)
56 mem = drm_mm_get_block_atomic(mem, size, 0);
57 spin_unlock(&dev_priv->tile.lock);
58
59 return mem;
60}
61
62static void
63nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem)
64{
65 struct drm_nouveau_private *dev_priv = dev->dev_private;
66
67 spin_lock(&dev_priv->tile.lock);
68 drm_mm_put_block(mem);
69 spin_unlock(&dev_priv->tile.lock);
70}
71
0d87c100 72void
a5cf68b0
FJ
73nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
74 uint32_t size, uint32_t pitch, uint32_t flags)
0d87c100
FJ
75{
76 struct drm_nouveau_private *dev_priv = dev->dev_private;
a5cf68b0 77 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
87a326a3 78 int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16);
a5cf68b0
FJ
79
80 tile->addr = addr;
81 tile->limit = max(1u, addr + size) - 1;
82 tile->pitch = pitch;
83
87a326a3
FJ
84 if (dev_priv->card_type == NV_20) {
85 if (flags & NOUVEAU_GEM_TILE_ZETA) {
86 /*
87 * Allocate some of the on-die tag memory,
88 * used to store Z compression meta-data (most
89 * likely just a bitmap determining if a given
90 * tile is compressed or not).
91 */
92 tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256);
93
94 if (tile->tag_mem) {
95 /* Enable Z compression */
96 if (dev_priv->chipset >= 0x25)
97 tile->zcomp = tile->tag_mem->start |
98 (bpp == 16 ?
99 NV25_PFB_ZCOMP_MODE_16 :
100 NV25_PFB_ZCOMP_MODE_32);
101 else
102 tile->zcomp = tile->tag_mem->start |
103 NV20_PFB_ZCOMP_EN |
104 (bpp == 16 ? 0 :
105 NV20_PFB_ZCOMP_MODE_32);
106 }
107
108 tile->addr |= 3;
109 } else {
110 tile->addr |= 1;
111 }
112
113 } else {
a5cf68b0 114 tile->addr |= 1 << 31;
87a326a3 115 }
a5cf68b0
FJ
116}
117
118void
119nv10_fb_free_tile_region(struct drm_device *dev, int i)
120{
121 struct drm_nouveau_private *dev_priv = dev->dev_private;
122 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
123
87a326a3
FJ
124 if (tile->tag_mem) {
125 nv20_fb_free_tag(dev, tile->tag_mem);
126 tile->tag_mem = NULL;
127 }
128
129 tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
a5cf68b0
FJ
130}
131
132void
133nv10_fb_set_tile_region(struct drm_device *dev, int i)
134{
135 struct drm_nouveau_private *dev_priv = dev->dev_private;
136 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
137
138 nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
139 nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
140 nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
87a326a3
FJ
141
142 if (dev_priv->card_type == NV_20)
143 nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp);
0d87c100
FJ
144}
145
6ee73861
BS
146int
147nv10_fb_init(struct drm_device *dev)
148{
0d87c100
FJ
149 struct drm_nouveau_private *dev_priv = dev->dev_private;
150 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
6ee73861
BS
151 int i;
152
0d87c100
FJ
153 pfb->num_tiles = NV10_PFB_TILE__SIZE;
154
87a326a3
FJ
155 if (dev_priv->card_type == NV_20)
156 drm_mm_init(&pfb->tag_heap, 0,
157 (dev_priv->chipset >= 0x25 ?
158 64 * 1024 : 32 * 1024));
159
0d87c100
FJ
160 /* Turn all the tiling regions off. */
161 for (i = 0; i < pfb->num_tiles; i++)
a5cf68b0 162 pfb->set_tile_region(dev, i);
6ee73861
BS
163
164 return 0;
165}
166
167void
168nv10_fb_takedown(struct drm_device *dev)
169{
87a326a3
FJ
170 struct drm_nouveau_private *dev_priv = dev->dev_private;
171 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
172 int i;
173
174 for (i = 0; i < pfb->num_tiles; i++)
175 pfb->free_tile_region(dev, i);
176
177 if (dev_priv->card_type == NV_20)
178 drm_mm_takedown(&pfb->tag_heap);
6ee73861 179}