OSDN Git Service

nouveau: enable/disable engine-specific interrupts in _init()/_takedown()
[android-x86/external-libdrm.git] / shared-core / nv50_fifo.c
1 /*
2  * Copyright (C) 2007 Ben Skeggs.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  */
26
27 #include "drmP.h"
28 #include "drm.h"
29 #include "nouveau_drv.h"
30
31 typedef struct {
32         struct nouveau_gpuobj_ref *thingo;
33         struct nouveau_gpuobj_ref *dummyctx;
34 } nv50_fifo_priv;
35
36 #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
37
38 static void
39 nv50_fifo_init_thingo(struct drm_device *dev)
40 {
41         struct drm_nouveau_private *dev_priv = dev->dev_private;
42         nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
43         struct nouveau_gpuobj_ref *thingo = priv->thingo;
44         int i, fi=2;
45
46         DRM_DEBUG("\n");
47
48         INSTANCE_WR(thingo->gpuobj, 0, 0x7e);
49         INSTANCE_WR(thingo->gpuobj, 1, 0x7e);
50         for (i = 0; i <NV_MAX_FIFO_NUMBER; i++, fi) {
51                 if (dev_priv->fifos[i]) {
52                         INSTANCE_WR(thingo->gpuobj, fi, i);
53                         fi++;
54                 }
55         }
56
57         NV_WRITE(0x32f4, thingo->instance >> 12);
58         NV_WRITE(0x32ec, fi);
59         NV_WRITE(0x2500, 0x101);
60 }
61
62 static int
63 nv50_fifo_channel_enable(struct drm_device *dev, int channel)
64 {
65         struct drm_nouveau_private *dev_priv = dev->dev_private;
66         struct nouveau_channel *chan = dev_priv->fifos[channel];
67
68         DRM_DEBUG("ch%d\n", channel);
69
70         if (IS_G80) {
71                 if (!chan->ramin)
72                         return -EINVAL;
73
74                 NV_WRITE(NV50_PFIFO_CTX_TABLE(channel),
75                          (chan->ramin->instance >> 12) |
76                          NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED);
77         } else {
78                 if (!chan->ramfc)
79                         return -EINVAL;
80
81                 NV_WRITE(NV50_PFIFO_CTX_TABLE(channel),
82                          (chan->ramfc->instance >> 8) |
83                          NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED);
84         }
85
86         nv50_fifo_init_thingo(dev);
87         return 0;
88 }
89
90 static void
91 nv50_fifo_channel_disable(struct drm_device *dev, int channel, int nt)
92 {
93         struct drm_nouveau_private *dev_priv = dev->dev_private;
94
95         DRM_DEBUG("ch%d, nt=%d\n", channel, nt);
96
97         if (IS_G80) {
98                 NV_WRITE(NV50_PFIFO_CTX_TABLE(channel),
99                          NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80);
100         } else {
101                 NV_WRITE(NV50_PFIFO_CTX_TABLE(channel),
102                          NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84);
103         }
104
105         if (!nt) nv50_fifo_init_thingo(dev);
106 }
107
108 static void
109 nv50_fifo_init_reset(struct drm_device *dev)
110 {
111         struct drm_nouveau_private *dev_priv = dev->dev_private;
112         uint32_t pmc_e;
113
114         DRM_DEBUG("\n");
115
116         pmc_e = NV_READ(NV03_PMC_ENABLE);
117         NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PFIFO);
118         pmc_e = NV_READ(NV03_PMC_ENABLE);
119         NV_WRITE(NV03_PMC_ENABLE, pmc_e |  NV_PMC_ENABLE_PFIFO);
120 }
121
122 static void
123 nv50_fifo_init_intr(struct drm_device *dev)
124 {
125         struct drm_nouveau_private *dev_priv = dev->dev_private;
126
127         DRM_DEBUG("\n");
128
129         NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
130         NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
131 }
132
133 static void
134 nv50_fifo_init_context_table(struct drm_device *dev)
135 {
136         int i;
137
138         DRM_DEBUG("\n");
139
140         for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++)
141                 nv50_fifo_channel_disable(dev, i, 1);
142         nv50_fifo_init_thingo(dev);
143 }
144
145 static void
146 nv50_fifo_init_regs__nv(struct drm_device *dev)
147 {
148         struct drm_nouveau_private *dev_priv = dev->dev_private;
149
150         DRM_DEBUG("\n");
151
152         NV_WRITE(0x250c, 0x6f3cfc34);
153 }
154
155 static int
156 nv50_fifo_init_regs(struct drm_device *dev)
157 {
158         struct drm_nouveau_private *dev_priv = dev->dev_private;
159         nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
160         int ret;
161
162         DRM_DEBUG("\n");
163
164         if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 0x1000,
165                                           0x1000,
166                                           NVOBJ_FLAG_ZERO_ALLOC |
167                                           NVOBJ_FLAG_ZERO_FREE,
168                                           &priv->dummyctx)))
169                 return ret;
170
171         NV_WRITE(0x2500, 0);
172         NV_WRITE(0x3250, 0);
173         NV_WRITE(0x3220, 0);
174         NV_WRITE(0x3204, 0);
175         NV_WRITE(0x3210, 0);
176         NV_WRITE(0x3270, 0);
177
178         if (IS_G80) {
179                 NV_WRITE(0x2600, (priv->dummyctx->instance>>8) | (1<<31));
180                 NV_WRITE(0x27fc, (priv->dummyctx->instance>>8) | (1<<31));
181         } else {
182                 NV_WRITE(0x2600, (priv->dummyctx->instance>>12) | (1<<31));
183                 NV_WRITE(0x27fc, (priv->dummyctx->instance>>12) | (1<<31));
184         }
185
186         return 0;
187 }
188
189 int
190 nv50_fifo_init(struct drm_device *dev)
191 {
192         struct drm_nouveau_private *dev_priv = dev->dev_private;
193         nv50_fifo_priv *priv;
194         int ret;
195
196         DRM_DEBUG("\n");
197
198         priv = drm_calloc(1, sizeof(*priv), DRM_MEM_DRIVER);
199         if (!priv)
200                 return -ENOMEM;
201         dev_priv->Engine.fifo.priv = priv;
202
203         nv50_fifo_init_reset(dev);
204         nv50_fifo_init_intr(dev);
205
206         if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, (128+2)*4, 0x1000,
207                                    NVOBJ_FLAG_ZERO_ALLOC,
208                                    &priv->thingo))) {
209                 DRM_ERROR("error creating thingo: %d\n", ret);
210                 return ret;
211         }
212         nv50_fifo_init_context_table(dev);
213
214         nv50_fifo_init_regs__nv(dev);
215         if ((ret = nv50_fifo_init_regs(dev)))
216                 return ret;
217
218         return 0;
219 }
220
221 void
222 nv50_fifo_takedown(struct drm_device *dev)
223 {
224         struct drm_nouveau_private *dev_priv = dev->dev_private;
225         nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
226
227         DRM_DEBUG("\n");
228
229         if (!priv)
230                 return;
231
232         nouveau_gpuobj_ref_del(dev, &priv->thingo);
233         nouveau_gpuobj_ref_del(dev, &priv->dummyctx);
234
235         dev_priv->Engine.fifo.priv = NULL;
236         drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER);
237 }
238
239 int
240 nv50_fifo_create_context(struct nouveau_channel *chan)
241 {
242         struct drm_device *dev = chan->dev;
243         struct drm_nouveau_private *dev_priv = dev->dev_private;
244         struct nouveau_gpuobj *ramfc = NULL;
245         int ret;
246
247         DRM_DEBUG("ch%d\n", chan->id);
248
249         if (IS_G80) {
250                 uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start;
251                 if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, 0x100,
252                                                    NVOBJ_FLAG_ZERO_ALLOC |
253                                                    NVOBJ_FLAG_ZERO_FREE,
254                                                    &ramfc, &chan->ramfc)))
255                                 return ret;
256         } else {
257                 if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100,
258                                                   256,
259                                                   NVOBJ_FLAG_ZERO_ALLOC |
260                                                   NVOBJ_FLAG_ZERO_FREE,
261                                                   &chan->ramfc)))
262                         return ret;
263                 ramfc = chan->ramfc->gpuobj;
264         }
265
266         INSTANCE_WR(ramfc, 0x48/4, chan->pushbuf->instance >> 4);
267         INSTANCE_WR(ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4));
268         INSTANCE_WR(ramfc, 0x3c/4, 0x000f0078); /* fetch? */
269         INSTANCE_WR(ramfc, 0x44/4, 0x2101ffff);
270         INSTANCE_WR(ramfc, 0x60/4, 0x7fffffff);
271         INSTANCE_WR(ramfc, 0x10/4, 0x00000000);
272         INSTANCE_WR(ramfc, 0x08/4, 0x00000000);
273         INSTANCE_WR(ramfc, 0x40/4, 0x00000000);
274         INSTANCE_WR(ramfc, 0x50/4, 0x2039b2e0);
275         INSTANCE_WR(ramfc, 0x54/4, 0x000f0000);
276         INSTANCE_WR(ramfc, 0x7c/4, 0x30000001);
277         INSTANCE_WR(ramfc, 0x78/4, 0x00000000);
278         INSTANCE_WR(ramfc, 0x4c/4, chan->pushbuf_mem->size - 1);
279
280         if (!IS_G80) {
281                 INSTANCE_WR(chan->ramin->gpuobj, 0, chan->id);
282                 INSTANCE_WR(chan->ramin->gpuobj, 1, chan->ramfc->instance);
283
284                 INSTANCE_WR(ramfc, 0x88/4, 0x3d520); /* some vram addy >> 10 */
285                 INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12);
286         }
287
288         if ((ret = nv50_fifo_channel_enable(dev, chan->id))) {
289                 DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret);
290                 nouveau_gpuobj_ref_del(dev, &chan->ramfc);
291                 return ret;
292         }
293
294         return 0;
295 }
296
297 void
298 nv50_fifo_destroy_context(struct nouveau_channel *chan)
299 {
300         struct drm_device *dev = chan->dev;
301
302         DRM_DEBUG("ch%d\n", chan->id);
303
304         nv50_fifo_channel_disable(dev, chan->id, 0);
305         nouveau_gpuobj_ref_del(dev, &chan->ramfc);
306 }
307
308 int
309 nv50_fifo_load_context(struct nouveau_channel *chan)
310 {
311         struct drm_device *dev = chan->dev;
312         struct drm_nouveau_private *dev_priv = dev->dev_private;
313         struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj;
314
315         DRM_DEBUG("ch%d\n", chan->id);
316
317         /*XXX: incomplete, only touches the regs that NV does */
318
319         NV_WRITE(0x3244, 0);
320         NV_WRITE(0x3240, 0);
321
322         NV_WRITE(0x3224, INSTANCE_RD(ramfc, 0x3c/4));
323         NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, INSTANCE_RD(ramfc, 0x48/4));
324         NV_WRITE(0x3234, INSTANCE_RD(ramfc, 0x4c/4));
325         NV_WRITE(0x3254, 1);
326         NV_WRITE(NV03_PFIFO_RAMHT, INSTANCE_RD(ramfc, 0x80/4));
327
328         if (!IS_G80) {
329                 NV_WRITE(0x340c, INSTANCE_RD(ramfc, 0x88/4));
330                 NV_WRITE(0x3410, INSTANCE_RD(ramfc, 0x98/4));
331         }
332
333         NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16));
334         return 0;
335 }
336
337 int
338 nv50_fifo_save_context(struct nouveau_channel *chan)
339 {
340         DRM_DEBUG("ch%d\n", chan->id);
341         DRM_ERROR("stub!\n");
342         return 0;
343 }
344