diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_instmem.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_instmem.c | 140 |
1 files changed, 39 insertions, 101 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c index 4408232d33f..0b5ae297abd 100644 --- a/drivers/gpu/drm/nouveau/nv04_instmem.c +++ b/drivers/gpu/drm/nouveau/nv04_instmem.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include "drmP.h" | 1 | #include "drmP.h" |
2 | #include "drm.h" | 2 | #include "drm.h" |
3 | #include "nouveau_drv.h" | 3 | #include "nouveau_drv.h" |
4 | #include "nouveau_ramht.h" | ||
4 | 5 | ||
5 | /* returns the size of fifo context */ | 6 | /* returns the size of fifo context */ |
6 | static int | 7 | static int |
@@ -17,102 +18,51 @@ nouveau_fifo_ctx_size(struct drm_device *dev) | |||
17 | return 32; | 18 | return 32; |
18 | } | 19 | } |
19 | 20 | ||
20 | static void | 21 | int nv04_instmem_init(struct drm_device *dev) |
21 | nv04_instmem_determine_amount(struct drm_device *dev) | ||
22 | { | 22 | { |
23 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 23 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
24 | int i; | 24 | struct nouveau_gpuobj *ramht = NULL; |
25 | u32 offset, length; | ||
26 | int ret; | ||
25 | 27 | ||
26 | /* Figure out how much instance memory we need */ | 28 | /* RAMIN always available */ |
27 | if (dev_priv->card_type >= NV_40) { | 29 | dev_priv->ramin_available = true; |
28 | /* We'll want more instance memory than this on some NV4x cards. | ||
29 | * There's a 16MB aperture to play with that maps onto the end | ||
30 | * of vram. For now, only reserve a small piece until we know | ||
31 | * more about what each chipset requires. | ||
32 | */ | ||
33 | switch (dev_priv->chipset) { | ||
34 | case 0x40: | ||
35 | case 0x47: | ||
36 | case 0x49: | ||
37 | case 0x4b: | ||
38 | dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024); | ||
39 | break; | ||
40 | default: | ||
41 | dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024); | ||
42 | break; | ||
43 | } | ||
44 | } else { | ||
45 | /*XXX: what *are* the limits on <NV40 cards? | ||
46 | */ | ||
47 | dev_priv->ramin_rsvd_vram = (512 * 1024); | ||
48 | } | ||
49 | NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10); | ||
50 | 30 | ||
51 | /* Clear all of it, except the BIOS image that's in the first 64KiB */ | 31 | /* Setup shared RAMHT */ |
52 | for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4) | 32 | ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, |
53 | nv_wi32(dev, i, 0x00000000); | 33 | NVOBJ_FLAG_ZERO_ALLOC, &ramht); |
54 | } | 34 | if (ret) |
35 | return ret; | ||
55 | 36 | ||
56 | static void | 37 | ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht); |
57 | nv04_instmem_configure_fixed_tables(struct drm_device *dev) | 38 | nouveau_gpuobj_ref(NULL, &ramht); |
58 | { | 39 | if (ret) |
59 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 40 | return ret; |
60 | struct nouveau_engine *engine = &dev_priv->engine; | ||
61 | 41 | ||
62 | /* FIFO hash table (RAMHT) | 42 | /* And RAMRO */ |
63 | * use 4k hash table at RAMIN+0x10000 | 43 | ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512, |
64 | * TODO: extend the hash table | 44 | NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro); |
65 | */ | 45 | if (ret) |
66 | dev_priv->ramht_offset = 0x10000; | 46 | return ret; |
67 | dev_priv->ramht_bits = 9; | 47 | |
68 | dev_priv->ramht_size = (1 << dev_priv->ramht_bits); /* nr entries */ | 48 | /* And RAMFC */ |
69 | dev_priv->ramht_size *= 8; /* 2 32-bit values per entry in RAMHT */ | 49 | length = dev_priv->engine.fifo.channels * nouveau_fifo_ctx_size(dev); |
70 | NV_DEBUG(dev, "RAMHT offset=0x%x, size=%d\n", dev_priv->ramht_offset, | ||
71 | dev_priv->ramht_size); | ||
72 | |||
73 | /* FIFO runout table (RAMRO) - 512k at 0x11200 */ | ||
74 | dev_priv->ramro_offset = 0x11200; | ||
75 | dev_priv->ramro_size = 512; | ||
76 | NV_DEBUG(dev, "RAMRO offset=0x%x, size=%d\n", dev_priv->ramro_offset, | ||
77 | dev_priv->ramro_size); | ||
78 | |||
79 | /* FIFO context table (RAMFC) | ||
80 | * NV40 : Not sure exactly how to position RAMFC on some cards, | ||
81 | * 0x30002 seems to position it at RAMIN+0x20000 on these | ||
82 | * cards. RAMFC is 4kb (32 fifos, 128byte entries). | ||
83 | * Others: Position RAMFC at RAMIN+0x11400 | ||
84 | */ | ||
85 | dev_priv->ramfc_size = engine->fifo.channels * | ||
86 | nouveau_fifo_ctx_size(dev); | ||
87 | switch (dev_priv->card_type) { | 50 | switch (dev_priv->card_type) { |
88 | case NV_40: | 51 | case NV_40: |
89 | dev_priv->ramfc_offset = 0x20000; | 52 | offset = 0x20000; |
90 | break; | 53 | break; |
91 | case NV_30: | ||
92 | case NV_20: | ||
93 | case NV_10: | ||
94 | case NV_04: | ||
95 | default: | 54 | default: |
96 | dev_priv->ramfc_offset = 0x11400; | 55 | offset = 0x11400; |
97 | break; | 56 | break; |
98 | } | 57 | } |
99 | NV_DEBUG(dev, "RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset, | ||
100 | dev_priv->ramfc_size); | ||
101 | } | ||
102 | 58 | ||
103 | int nv04_instmem_init(struct drm_device *dev) | 59 | ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length, |
104 | { | 60 | NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc); |
105 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 61 | if (ret) |
106 | uint32_t offset; | 62 | return ret; |
107 | int ret; | ||
108 | |||
109 | nv04_instmem_determine_amount(dev); | ||
110 | nv04_instmem_configure_fixed_tables(dev); | ||
111 | 63 | ||
112 | /* Create a heap to manage RAMIN allocations, we don't allocate | 64 | /* Only allow space after RAMFC to be used for object allocation */ |
113 | * the space that was reserved for RAMHT/FC/RO. | 65 | offset += length; |
114 | */ | ||
115 | offset = dev_priv->ramfc_offset + dev_priv->ramfc_size; | ||
116 | 66 | ||
117 | /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 | 67 | /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 |
118 | * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 | 68 | * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 |
@@ -140,46 +90,34 @@ int nv04_instmem_init(struct drm_device *dev) | |||
140 | void | 90 | void |
141 | nv04_instmem_takedown(struct drm_device *dev) | 91 | nv04_instmem_takedown(struct drm_device *dev) |
142 | { | 92 | { |
93 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
94 | |||
95 | nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); | ||
96 | nouveau_gpuobj_ref(NULL, &dev_priv->ramro); | ||
97 | nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); | ||
143 | } | 98 | } |
144 | 99 | ||
145 | int | 100 | int |
146 | nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz) | 101 | nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, |
102 | uint32_t *sz) | ||
147 | { | 103 | { |
148 | if (gpuobj->im_backing) | ||
149 | return -EINVAL; | ||
150 | |||
151 | return 0; | 104 | return 0; |
152 | } | 105 | } |
153 | 106 | ||
154 | void | 107 | void |
155 | nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | 108 | nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) |
156 | { | 109 | { |
157 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
158 | |||
159 | if (gpuobj && gpuobj->im_backing) { | ||
160 | if (gpuobj->im_bound) | ||
161 | dev_priv->engine.instmem.unbind(dev, gpuobj); | ||
162 | gpuobj->im_backing = NULL; | ||
163 | } | ||
164 | } | 110 | } |
165 | 111 | ||
166 | int | 112 | int |
167 | nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | 113 | nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) |
168 | { | 114 | { |
169 | if (!gpuobj->im_pramin || gpuobj->im_bound) | ||
170 | return -EINVAL; | ||
171 | |||
172 | gpuobj->im_bound = 1; | ||
173 | return 0; | 115 | return 0; |
174 | } | 116 | } |
175 | 117 | ||
176 | int | 118 | int |
177 | nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | 119 | nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) |
178 | { | 120 | { |
179 | if (gpuobj->im_bound == 0) | ||
180 | return -EINVAL; | ||
181 | |||
182 | gpuobj->im_bound = 0; | ||
183 | return 0; | 121 | return 0; |
184 | } | 122 | } |
185 | 123 | ||