OSDN Git Service

nv50: when destroying a channel make sure it's not still current on PFIFO
[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 struct nv50_fifo_priv {
32         struct nouveau_gpuobj_ref *thingo[2];
33         int cur_thingo;
34 };
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         struct nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
43         struct nouveau_gpuobj_ref *cur;
44         int i, nr;
45
46         DRM_DEBUG("\n");
47
48         cur = priv->thingo[priv->cur_thingo];
49         priv->cur_thingo = !priv->cur_thingo;
50
51         /* We never schedule channel 0 or 127 */
52         for (i = 1, nr = 0; i < 127; i++) {
53                 if (dev_priv->fifos[i]) {
54                         INSTANCE_WR(cur->gpuobj, nr++, i);
55                 }
56         }
57         NV_WRITE(0x32f4, cur->instance >> 12);
58         NV_WRITE(0x32ec, nr);
59         NV_WRITE(0x2500, 0x101);
60 }
61
62 static int
63 nv50_fifo_channel_enable(struct drm_device *dev, int channel, int nt)
64 {
65         struct drm_nouveau_private *dev_priv = dev->dev_private;
66         struct nouveau_channel *chan = dev_priv->fifos[channel];
67         uint32_t inst;
68
69         DRM_DEBUG("ch%d\n", channel);
70
71         if (!chan->ramfc)
72                 return -EINVAL;
73
74         if (IS_G80) inst = chan->ramfc->instance >> 12;
75         else        inst = chan->ramfc->instance >> 8;
76         NV_WRITE(NV50_PFIFO_CTX_TABLE(channel),
77                  inst | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED);
78
79         if (!nt) nv50_fifo_init_thingo(dev);
80         return 0;
81 }
82
83 static void
84 nv50_fifo_channel_disable(struct drm_device *dev, int channel, int nt)
85 {
86         struct drm_nouveau_private *dev_priv = dev->dev_private;
87         uint32_t inst;
88
89         DRM_DEBUG("ch%d, nt=%d\n", channel, nt);
90
91         if (IS_G80) inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80;
92         else        inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84;
93         NV_WRITE(NV50_PFIFO_CTX_TABLE(channel), inst);
94
95         if (!nt) nv50_fifo_init_thingo(dev);
96 }
97
98 static void
99 nv50_fifo_init_reset(struct drm_device *dev)
100 {
101         struct drm_nouveau_private *dev_priv = dev->dev_private;
102         uint32_t pmc_e = NV_PMC_ENABLE_PFIFO;
103
104         DRM_DEBUG("\n");
105
106         NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) & ~pmc_e);
107         NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |  pmc_e);
108 }
109
110 static void
111 nv50_fifo_init_intr(struct drm_device *dev)
112 {
113         struct drm_nouveau_private *dev_priv = dev->dev_private;
114
115         DRM_DEBUG("\n");
116
117         NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
118         NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
119 }
120
121 static void
122 nv50_fifo_init_context_table(struct drm_device *dev)
123 {
124         int i;
125
126         DRM_DEBUG("\n");
127
128         for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++)
129                 nv50_fifo_channel_disable(dev, i, 1);
130         nv50_fifo_init_thingo(dev);
131 }
132
133 static void
134 nv50_fifo_init_regs__nv(struct drm_device *dev)
135 {
136         struct drm_nouveau_private *dev_priv = dev->dev_private;
137
138         DRM_DEBUG("\n");
139
140         NV_WRITE(0x250c, 0x6f3cfc34);
141 }
142
143 static void
144 nv50_fifo_init_regs(struct drm_device *dev)
145 {
146         struct drm_nouveau_private *dev_priv = dev->dev_private;
147
148         DRM_DEBUG("\n");
149
150         NV_WRITE(0x2500, 0);
151         NV_WRITE(0x3250, 0);
152         NV_WRITE(0x3220, 0);
153         NV_WRITE(0x3204, 0);
154         NV_WRITE(0x3210, 0);
155         NV_WRITE(0x3270, 0);
156
157         /* Enable dummy channels setup by nv50_instmem.c */
158         nv50_fifo_channel_enable(dev, 0, 1);
159         nv50_fifo_channel_enable(dev, 127, 1);
160 }
161
162 int
163 nv50_fifo_init(struct drm_device *dev)
164 {
165         struct drm_nouveau_private *dev_priv = dev->dev_private;
166         struct nv50_fifo_priv *priv;
167         int ret;
168
169         DRM_DEBUG("\n");
170
171         priv = drm_calloc(1, sizeof(*priv), DRM_MEM_DRIVER);
172         if (!priv)
173                 return -ENOMEM;
174         dev_priv->Engine.fifo.priv = priv;
175
176         nv50_fifo_init_reset(dev);
177         nv50_fifo_init_intr(dev);
178
179         ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000,
180                                      NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[0]);
181         if (ret) {
182                 DRM_ERROR("error creating thingo0: %d\n", ret);
183                 return ret;
184         }
185
186         ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000,
187                                      NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[1]);
188         if (ret) {
189                 DRM_ERROR("error creating thingo1: %d\n", ret);
190                 return ret;
191         }
192
193         nv50_fifo_init_context_table(dev);
194         nv50_fifo_init_regs__nv(dev);
195         nv50_fifo_init_regs(dev);
196
197         return 0;
198 }
199
200 void
201 nv50_fifo_takedown(struct drm_device *dev)
202 {
203         struct drm_nouveau_private *dev_priv = dev->dev_private;
204         struct nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
205
206         DRM_DEBUG("\n");
207
208         if (!priv)
209                 return;
210
211         nouveau_gpuobj_ref_del(dev, &priv->thingo[0]);
212         nouveau_gpuobj_ref_del(dev, &priv->thingo[1]);
213
214         dev_priv->Engine.fifo.priv = NULL;
215         drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER);
216 }
217
218 int
219 nv50_fifo_channel_id(struct drm_device *dev)
220 {
221         struct drm_nouveau_private *dev_priv = dev->dev_private;
222
223         return (NV_READ(NV03_PFIFO_CACHE1_PUSH1) &
224                         NV50_PFIFO_CACHE1_PUSH1_CHID_MASK);
225 }
226
227 int
228 nv50_fifo_create_context(struct nouveau_channel *chan)
229 {
230         struct drm_device *dev = chan->dev;
231         struct drm_nouveau_private *dev_priv = dev->dev_private;
232         struct nouveau_gpuobj *ramfc = NULL;
233         int ret;
234
235         DRM_DEBUG("ch%d\n", chan->id);
236
237         if (IS_G80) {
238                 uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start;
239                 uint32_t vram_offset = chan->ramin->gpuobj->im_backing->start;
240                 ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, vram_offset,
241                                               0x100, NVOBJ_FLAG_ZERO_ALLOC |
242                                               NVOBJ_FLAG_ZERO_FREE, &ramfc,
243                                               &chan->ramfc);
244                 if (ret)
245                         return ret;
246         } else {
247                 ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, 256,
248                                              NVOBJ_FLAG_ZERO_ALLOC |
249                                              NVOBJ_FLAG_ZERO_FREE,
250                                              &chan->ramfc);
251                 if (ret)
252                         return ret;
253                 ramfc = chan->ramfc->gpuobj;
254         }
255
256         INSTANCE_WR(ramfc, 0x48/4, chan->pushbuf->instance >> 4);
257         INSTANCE_WR(ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4));
258         INSTANCE_WR(ramfc, 0x3c/4, 0x000f0078); /* fetch? */
259         INSTANCE_WR(ramfc, 0x44/4, 0x2101ffff);
260         INSTANCE_WR(ramfc, 0x60/4, 0x7fffffff);
261         INSTANCE_WR(ramfc, 0x10/4, 0x00000000);
262         INSTANCE_WR(ramfc, 0x08/4, 0x00000000);
263         INSTANCE_WR(ramfc, 0x40/4, 0x00000000);
264         INSTANCE_WR(ramfc, 0x50/4, 0x2039b2e0);
265         INSTANCE_WR(ramfc, 0x54/4, 0x000f0000);
266         INSTANCE_WR(ramfc, 0x7c/4, 0x30000001);
267         INSTANCE_WR(ramfc, 0x78/4, 0x00000000);
268         INSTANCE_WR(ramfc, 0x4c/4, chan->pushbuf_mem->size - 1);
269
270         if (!IS_G80) {
271                 INSTANCE_WR(chan->ramin->gpuobj, 0, chan->id);
272                 INSTANCE_WR(chan->ramin->gpuobj, 1, chan->ramfc->instance);
273
274                 INSTANCE_WR(ramfc, 0x88/4, 0x3d520); /* some vram addy >> 10 */
275                 INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12);
276         }
277
278         ret = nv50_fifo_channel_enable(dev, chan->id, 0);
279         if (ret) {
280                 DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret);
281                 nouveau_gpuobj_ref_del(dev, &chan->ramfc);
282                 return ret;
283         }
284
285         return 0;
286 }
287
288 void
289 nv50_fifo_destroy_context(struct nouveau_channel *chan)
290 {
291         struct drm_device *dev = chan->dev;
292         struct drm_nouveau_private *dev_priv = dev->dev_private;
293
294         DRM_DEBUG("ch%d\n", chan->id);
295
296         nv50_fifo_channel_disable(dev, chan->id, 0);
297
298         /* Dummy channel, also used on ch 127 */
299         if (chan->id == 0)
300                 nv50_fifo_channel_disable(dev, 127, 0);
301
302         if ((NV_READ(NV03_PFIFO_CACHE1_PUSH1) & 0xffff) == chan->id)
303                 NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 127);
304
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 }