blob: 5f671a21b8bbd9ac242f2ab8cf261784c8ad3dfd [file] [log] [blame]
Ben Skeggsab394542012-03-13 13:05:13 +10001/*
2 * Copyright 2010 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <linux/firmware.h>
26#include <linux/module.h>
27
28#include "drmP.h"
29
30#include "nouveau_drv.h"
Ben Skeggs02a841d2012-07-04 23:44:54 +100031#include <core/mm.h>
32#include <engine/fifo.h>
Ben Skeggsab394542012-03-13 13:05:13 +100033
Ben Skeggs02a841d2012-07-04 23:44:54 +100034#include "nve0.h"
Ben Skeggsab394542012-03-13 13:05:13 +100035
36static void
37nve0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base)
38{
39 NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base,
40 nv_rd32(dev, base + 0x400));
41 NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
42 nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804),
43 nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c));
44 NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
45 nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814),
46 nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c));
47}
48
49static void
50nve0_graph_ctxctl_debug(struct drm_device *dev)
51{
52 u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff;
53 u32 gpc;
54
55 nve0_graph_ctxctl_debug_unit(dev, 0x409000);
56 for (gpc = 0; gpc < gpcnr; gpc++)
57 nve0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000));
58}
59
60static int
61nve0_graph_load_context(struct nouveau_channel *chan)
62{
63 struct drm_device *dev = chan->dev;
64
65 nv_wr32(dev, 0x409840, 0x00000030);
66 nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
67 nv_wr32(dev, 0x409504, 0x00000003);
68 if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010))
69 NV_ERROR(dev, "PGRAPH: load_ctx timeout\n");
70
71 return 0;
72}
73
74static int
75nve0_graph_unload_context_to(struct drm_device *dev, u64 chan)
76{
77 nv_wr32(dev, 0x409840, 0x00000003);
78 nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12);
79 nv_wr32(dev, 0x409504, 0x00000009);
80 if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) {
81 NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n");
82 return -EBUSY;
83 }
84
85 return 0;
86}
87
88static int
89nve0_graph_construct_context(struct nouveau_channel *chan)
90{
91 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
92 struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
93 struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
94 struct drm_device *dev = chan->dev;
95 int ret, i;
96 u32 *ctx;
97
98 ctx = kmalloc(priv->grctx_size, GFP_KERNEL);
99 if (!ctx)
100 return -ENOMEM;
101
102 nve0_graph_load_context(chan);
103
104 nv_wo32(grch->grctx, 0x1c, 1);
105 nv_wo32(grch->grctx, 0x20, 0);
106 nv_wo32(grch->grctx, 0x28, 0);
107 nv_wo32(grch->grctx, 0x2c, 0);
108 dev_priv->engine.instmem.flush(dev);
109
110 ret = nve0_grctx_generate(chan);
111 if (ret)
112 goto err;
113
114 ret = nve0_graph_unload_context_to(dev, chan->ramin->vinst);
115 if (ret)
116 goto err;
117
118 for (i = 0; i < priv->grctx_size; i += 4)
119 ctx[i / 4] = nv_ro32(grch->grctx, i);
120
121 priv->grctx_vals = ctx;
122 return 0;
123
124err:
125 kfree(ctx);
126 return ret;
127}
128
129static int
130nve0_graph_create_context_mmio_list(struct nouveau_channel *chan)
131{
132 struct nve0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
133 struct nve0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
134 struct drm_device *dev = chan->dev;
135 u32 magic[GPC_MAX][2];
136 u16 offset = 0x0000;
137 int gpc;
138 int ret;
139
Ben Skeggs73a60c02012-07-13 17:21:22 +1000140 ret = nouveau_gpuobj_new(dev, NULL, 0x3000, 256, 0, &grch->unk408004);
Ben Skeggsab394542012-03-13 13:05:13 +1000141 if (ret)
142 return ret;
143
Ben Skeggs73a60c02012-07-13 17:21:22 +1000144 ret = nouveau_gpuobj_map_vm(grch->unk408004, NV_MEM_ACCESS_RW |
145 NV_MEM_ACCESS_SYS, chan->vm,
146 &grch->unk408004_vma);
Ben Skeggsab394542012-03-13 13:05:13 +1000147 if (ret)
148 return ret;
149
Ben Skeggs73a60c02012-07-13 17:21:22 +1000150 ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, 0, &grch->unk40800c);
151 if (ret)
152 return ret;
153
154 ret = nouveau_gpuobj_map_vm(grch->unk40800c, NV_MEM_ACCESS_RW |
155 NV_MEM_ACCESS_SYS, chan->vm,
156 &grch->unk40800c_vma);
157 if (ret)
158 return ret;
159
160 ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, 0,
Ben Skeggsab394542012-03-13 13:05:13 +1000161 &grch->unk418810);
162 if (ret)
163 return ret;
164
Ben Skeggs73a60c02012-07-13 17:21:22 +1000165 ret = nouveau_gpuobj_map_vm(grch->unk418810, NV_MEM_ACCESS_RW,
166 chan->vm, &grch->unk418810_vma);
167 if (ret)
168 return ret;
169
170 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, 0, &grch->mmio);
171 if (ret)
172 return ret;
173
174 ret = nouveau_gpuobj_map_vm(grch->mmio, NV_MEM_ACCESS_RW |
175 NV_MEM_ACCESS_SYS, chan->vm,
176 &grch->mmio_vma);
Ben Skeggsab394542012-03-13 13:05:13 +1000177 if (ret)
178 return ret;
179
180#define mmio(r,v) do { \
181 nv_wo32(grch->mmio, (grch->mmio_nr * 8) + 0, (r)); \
182 nv_wo32(grch->mmio, (grch->mmio_nr * 8) + 4, (v)); \
183 grch->mmio_nr++; \
184} while (0)
Ben Skeggs73a60c02012-07-13 17:21:22 +1000185 mmio(0x40800c, grch->unk40800c_vma.offset >> 8);
Ben Skeggsab394542012-03-13 13:05:13 +1000186 mmio(0x408010, 0x80000000);
Ben Skeggs73a60c02012-07-13 17:21:22 +1000187 mmio(0x419004, grch->unk40800c_vma.offset >> 8);
Ben Skeggsab394542012-03-13 13:05:13 +1000188 mmio(0x419008, 0x00000000);
189 mmio(0x4064cc, 0x80000000);
Ben Skeggs73a60c02012-07-13 17:21:22 +1000190 mmio(0x408004, grch->unk408004_vma.offset >> 8);
Ben Skeggsab394542012-03-13 13:05:13 +1000191 mmio(0x408008, 0x80000030);
Ben Skeggs73a60c02012-07-13 17:21:22 +1000192 mmio(0x418808, grch->unk408004_vma.offset >> 8);
Ben Skeggsab394542012-03-13 13:05:13 +1000193 mmio(0x41880c, 0x80000030);
194 mmio(0x4064c8, 0x01800600);
Ben Skeggs73a60c02012-07-13 17:21:22 +1000195 mmio(0x418810, 0x80000000 | grch->unk418810_vma.offset >> 12);
196 mmio(0x419848, 0x10000000 | grch->unk418810_vma.offset >> 12);
Ben Skeggsab394542012-03-13 13:05:13 +1000197 mmio(0x405830, 0x02180648);
198 mmio(0x4064c4, 0x0192ffff);
199
200 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
201 u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
202 u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
203 magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset;
204 magic[gpc][1] = 0x00000000 | (magic1 << 16);
205 offset += 0x0324 * priv->tpc_nr[gpc];
206 }
207
208 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
209 mmio(GPC_UNIT(gpc, 0x30c0), magic[gpc][0]);
210 mmio(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset);
211 offset += 0x07ff * priv->tpc_nr[gpc];
212 }
213
214 mmio(0x17e91c, 0x06060609);
215 mmio(0x17e920, 0x00090a05);
216#undef mmio
217 return 0;
218}
219
220static int
221nve0_graph_context_new(struct nouveau_channel *chan, int engine)
222{
223 struct drm_device *dev = chan->dev;
224 struct drm_nouveau_private *dev_priv = dev->dev_private;
225 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
226 struct nve0_graph_priv *priv = nv_engine(dev, engine);
227 struct nve0_graph_chan *grch;
228 struct nouveau_gpuobj *grctx;
229 int ret, i;
230
231 grch = kzalloc(sizeof(*grch), GFP_KERNEL);
232 if (!grch)
233 return -ENOMEM;
234 chan->engctx[NVOBJ_ENGINE_GR] = grch;
235
Ben Skeggs73a60c02012-07-13 17:21:22 +1000236 ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, 0,
Ben Skeggsab394542012-03-13 13:05:13 +1000237 &grch->grctx);
238 if (ret)
239 goto error;
Ben Skeggs73a60c02012-07-13 17:21:22 +1000240
241 ret = nouveau_gpuobj_map_vm(grch->grctx, NV_MEM_ACCESS_RW |
242 NV_MEM_ACCESS_SYS, chan->vm,
243 &grch->grctx_vma);
244 if (ret)
245 return ret;
246
Ben Skeggsab394542012-03-13 13:05:13 +1000247 grctx = grch->grctx;
248
249 ret = nve0_graph_create_context_mmio_list(chan);
250 if (ret)
251 goto error;
252
Ben Skeggs73a60c02012-07-13 17:21:22 +1000253 nv_wo32(chan->ramin, 0x0210, lower_32_bits(grch->grctx_vma.offset) | 4);
254 nv_wo32(chan->ramin, 0x0214, upper_32_bits(grch->grctx_vma.offset));
Ben Skeggsab394542012-03-13 13:05:13 +1000255 pinstmem->flush(dev);
256
257 if (!priv->grctx_vals) {
258 ret = nve0_graph_construct_context(chan);
259 if (ret)
260 goto error;
261 }
262
263 for (i = 0; i < priv->grctx_size; i += 4)
264 nv_wo32(grctx, i, priv->grctx_vals[i / 4]);
265 nv_wo32(grctx, 0xf4, 0);
266 nv_wo32(grctx, 0xf8, 0);
267 nv_wo32(grctx, 0x10, grch->mmio_nr);
Ben Skeggs73a60c02012-07-13 17:21:22 +1000268 nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio_vma.offset));
269 nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio_vma.offset));
Ben Skeggsab394542012-03-13 13:05:13 +1000270 nv_wo32(grctx, 0x1c, 1);
271 nv_wo32(grctx, 0x20, 0);
272 nv_wo32(grctx, 0x28, 0);
273 nv_wo32(grctx, 0x2c, 0);
274
275 pinstmem->flush(dev);
276 return 0;
277
278error:
279 priv->base.context_del(chan, engine);
280 return ret;
281}
282
283static void
284nve0_graph_context_del(struct nouveau_channel *chan, int engine)
285{
286 struct nve0_graph_chan *grch = chan->engctx[engine];
287
Ben Skeggs73a60c02012-07-13 17:21:22 +1000288 nouveau_gpuobj_unmap(&grch->mmio_vma);
289 nouveau_gpuobj_unmap(&grch->unk418810_vma);
290 nouveau_gpuobj_unmap(&grch->unk40800c_vma);
291 nouveau_gpuobj_unmap(&grch->unk408004_vma);
292 nouveau_gpuobj_unmap(&grch->grctx_vma);
Ben Skeggsab394542012-03-13 13:05:13 +1000293 nouveau_gpuobj_ref(NULL, &grch->mmio);
294 nouveau_gpuobj_ref(NULL, &grch->unk418810);
295 nouveau_gpuobj_ref(NULL, &grch->unk40800c);
296 nouveau_gpuobj_ref(NULL, &grch->unk408004);
297 nouveau_gpuobj_ref(NULL, &grch->grctx);
298 chan->engctx[engine] = NULL;
299}
300
301static int
302nve0_graph_object_new(struct nouveau_channel *chan, int engine,
303 u32 handle, u16 class)
304{
305 return 0;
306}
307
308static int
309nve0_graph_fini(struct drm_device *dev, int engine, bool suspend)
310{
311 return 0;
312}
313
314static void
315nve0_graph_init_obj418880(struct drm_device *dev)
316{
317 struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
318 int i;
319
320 nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000);
321 nv_wr32(dev, GPC_BCAST(0x08a4), 0x00000000);
322 for (i = 0; i < 4; i++)
323 nv_wr32(dev, GPC_BCAST(0x0888) + (i * 4), 0x00000000);
324 nv_wr32(dev, GPC_BCAST(0x08b4), priv->unk4188b4->vinst >> 8);
325 nv_wr32(dev, GPC_BCAST(0x08b8), priv->unk4188b8->vinst >> 8);
326}
327
328static void
329nve0_graph_init_regs(struct drm_device *dev)
330{
331 nv_wr32(dev, 0x400080, 0x003083c2);
332 nv_wr32(dev, 0x400088, 0x0001ffe7);
333 nv_wr32(dev, 0x40008c, 0x00000000);
334 nv_wr32(dev, 0x400090, 0x00000030);
335 nv_wr32(dev, 0x40013c, 0x003901f7);
336 nv_wr32(dev, 0x400140, 0x00000100);
337 nv_wr32(dev, 0x400144, 0x00000000);
338 nv_wr32(dev, 0x400148, 0x00000110);
339 nv_wr32(dev, 0x400138, 0x00000000);
340 nv_wr32(dev, 0x400130, 0x00000000);
341 nv_wr32(dev, 0x400134, 0x00000000);
342 nv_wr32(dev, 0x400124, 0x00000002);
343}
344
345static void
346nve0_graph_init_units(struct drm_device *dev)
347{
348 nv_wr32(dev, 0x409ffc, 0x00000000);
349 nv_wr32(dev, 0x409c14, 0x00003e3e);
350 nv_wr32(dev, 0x409c24, 0x000f0000);
351
352 nv_wr32(dev, 0x404000, 0xc0000000);
353 nv_wr32(dev, 0x404600, 0xc0000000);
354 nv_wr32(dev, 0x408030, 0xc0000000);
355 nv_wr32(dev, 0x404490, 0xc0000000);
356 nv_wr32(dev, 0x406018, 0xc0000000);
357 nv_wr32(dev, 0x407020, 0xc0000000);
358 nv_wr32(dev, 0x405840, 0xc0000000);
359 nv_wr32(dev, 0x405844, 0x00ffffff);
360
361 nv_mask(dev, 0x419cc0, 0x00000008, 0x00000008);
362 nv_mask(dev, 0x419eb4, 0x00001000, 0x00001000);
363
364}
365
366static void
367nve0_graph_init_gpc_0(struct drm_device *dev)
368{
369 struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
370 const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
371 u32 data[TPC_MAX / 8];
372 u8 tpcnr[GPC_MAX];
373 int i, gpc, tpc;
374
375 nv_wr32(dev, GPC_UNIT(0, 0x3018), 0x00000001);
376
377 memset(data, 0x00, sizeof(data));
378 memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
379 for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
380 do {
381 gpc = (gpc + 1) % priv->gpc_nr;
382 } while (!tpcnr[gpc]);
383 tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
384
385 data[i / 8] |= tpc << ((i % 8) * 4);
386 }
387
388 nv_wr32(dev, GPC_BCAST(0x0980), data[0]);
389 nv_wr32(dev, GPC_BCAST(0x0984), data[1]);
390 nv_wr32(dev, GPC_BCAST(0x0988), data[2]);
391 nv_wr32(dev, GPC_BCAST(0x098c), data[3]);
392
393 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
394 nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
395 priv->tpc_nr[gpc]);
396 nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total);
397 nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918);
398 }
399
400 nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918);
401 nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800));
402}
403
404static void
405nve0_graph_init_gpc_1(struct drm_device *dev)
406{
407 struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
408 int gpc, tpc;
409
410 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
411 nv_wr32(dev, GPC_UNIT(gpc, 0x3038), 0xc0000000);
412 nv_wr32(dev, GPC_UNIT(gpc, 0x0420), 0xc0000000);
413 nv_wr32(dev, GPC_UNIT(gpc, 0x0900), 0xc0000000);
414 nv_wr32(dev, GPC_UNIT(gpc, 0x1028), 0xc0000000);
415 nv_wr32(dev, GPC_UNIT(gpc, 0x0824), 0xc0000000);
416 for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
417 nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
418 nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
419 nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
420 nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
421 nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
422 nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe);
423 nv_wr32(dev, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f);
424 }
425 nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
426 nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
427 }
428}
429
430static void
431nve0_graph_init_rop(struct drm_device *dev)
432{
433 struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
434 int rop;
435
436 for (rop = 0; rop < priv->rop_nr; rop++) {
437 nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000);
438 nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000);
439 nv_wr32(dev, ROP_UNIT(rop, 0x204), 0xffffffff);
440 nv_wr32(dev, ROP_UNIT(rop, 0x208), 0xffffffff);
441 }
442}
443
444static void
445nve0_graph_init_fuc(struct drm_device *dev, u32 fuc_base,
446 struct nve0_graph_fuc *code, struct nve0_graph_fuc *data)
447{
448 int i;
449
450 nv_wr32(dev, fuc_base + 0x01c0, 0x01000000);
451 for (i = 0; i < data->size / 4; i++)
452 nv_wr32(dev, fuc_base + 0x01c4, data->data[i]);
453
454 nv_wr32(dev, fuc_base + 0x0180, 0x01000000);
455 for (i = 0; i < code->size / 4; i++) {
456 if ((i & 0x3f) == 0)
457 nv_wr32(dev, fuc_base + 0x0188, i >> 6);
458 nv_wr32(dev, fuc_base + 0x0184, code->data[i]);
459 }
460}
461
462static int
463nve0_graph_init_ctxctl(struct drm_device *dev)
464{
465 struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
466 u32 r000260;
467
468 /* load fuc microcode */
469 r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
470 nve0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, &priv->fuc409d);
471 nve0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, &priv->fuc41ad);
472 nv_wr32(dev, 0x000260, r000260);
473
474 /* start both of them running */
475 nv_wr32(dev, 0x409840, 0xffffffff);
476 nv_wr32(dev, 0x41a10c, 0x00000000);
477 nv_wr32(dev, 0x40910c, 0x00000000);
478 nv_wr32(dev, 0x41a100, 0x00000002);
479 nv_wr32(dev, 0x409100, 0x00000002);
480 if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001))
481 NV_INFO(dev, "0x409800 wait failed\n");
482
483 nv_wr32(dev, 0x409840, 0xffffffff);
484 nv_wr32(dev, 0x409500, 0x7fffffff);
485 nv_wr32(dev, 0x409504, 0x00000021);
486
487 nv_wr32(dev, 0x409840, 0xffffffff);
488 nv_wr32(dev, 0x409500, 0x00000000);
489 nv_wr32(dev, 0x409504, 0x00000010);
490 if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
491 NV_ERROR(dev, "fuc09 req 0x10 timeout\n");
492 return -EBUSY;
493 }
494 priv->grctx_size = nv_rd32(dev, 0x409800);
495
496 nv_wr32(dev, 0x409840, 0xffffffff);
497 nv_wr32(dev, 0x409500, 0x00000000);
498 nv_wr32(dev, 0x409504, 0x00000016);
499 if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
500 NV_ERROR(dev, "fuc09 req 0x16 timeout\n");
501 return -EBUSY;
502 }
503
504 nv_wr32(dev, 0x409840, 0xffffffff);
505 nv_wr32(dev, 0x409500, 0x00000000);
506 nv_wr32(dev, 0x409504, 0x00000025);
507 if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
508 NV_ERROR(dev, "fuc09 req 0x25 timeout\n");
509 return -EBUSY;
510 }
511
512 nv_wr32(dev, 0x409800, 0x00000000);
513 nv_wr32(dev, 0x409500, 0x00000001);
514 nv_wr32(dev, 0x409504, 0x00000030);
515 if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
516 NV_ERROR(dev, "fuc09 req 0x30 timeout\n");
517 return -EBUSY;
518 }
519
520 nv_wr32(dev, 0x409810, 0xb00095c8);
521 nv_wr32(dev, 0x409800, 0x00000000);
522 nv_wr32(dev, 0x409500, 0x00000001);
523 nv_wr32(dev, 0x409504, 0x00000031);
524 if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
525 NV_ERROR(dev, "fuc09 req 0x31 timeout\n");
526 return -EBUSY;
527 }
528
529 nv_wr32(dev, 0x409810, 0x00080420);
530 nv_wr32(dev, 0x409800, 0x00000000);
531 nv_wr32(dev, 0x409500, 0x00000001);
532 nv_wr32(dev, 0x409504, 0x00000032);
533 if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) {
534 NV_ERROR(dev, "fuc09 req 0x32 timeout\n");
535 return -EBUSY;
536 }
537
538 nv_wr32(dev, 0x409614, 0x00000070);
539 nv_wr32(dev, 0x409614, 0x00000770);
540 nv_wr32(dev, 0x40802c, 0x00000001);
541 return 0;
542}
543
544static int
545nve0_graph_init(struct drm_device *dev, int engine)
546{
547 int ret;
548
549 nv_mask(dev, 0x000200, 0x18001000, 0x00000000);
550 nv_mask(dev, 0x000200, 0x18001000, 0x18001000);
551
552 nve0_graph_init_obj418880(dev);
553 nve0_graph_init_regs(dev);
554 nve0_graph_init_gpc_0(dev);
555
556 nv_wr32(dev, 0x400500, 0x00010001);
557 nv_wr32(dev, 0x400100, 0xffffffff);
558 nv_wr32(dev, 0x40013c, 0xffffffff);
559
560 nve0_graph_init_units(dev);
561 nve0_graph_init_gpc_1(dev);
562 nve0_graph_init_rop(dev);
563
564 nv_wr32(dev, 0x400108, 0xffffffff);
565 nv_wr32(dev, 0x400138, 0xffffffff);
566 nv_wr32(dev, 0x400118, 0xffffffff);
567 nv_wr32(dev, 0x400130, 0xffffffff);
568 nv_wr32(dev, 0x40011c, 0xffffffff);
569 nv_wr32(dev, 0x400134, 0xffffffff);
570 nv_wr32(dev, 0x400054, 0x34ce3464);
571
572 ret = nve0_graph_init_ctxctl(dev);
573 if (ret)
574 return ret;
575
576 return 0;
577}
578
579int
580nve0_graph_isr_chid(struct drm_device *dev, u64 inst)
581{
Ben Skeggsc420b2d2012-05-01 20:48:08 +1000582 struct nouveau_fifo_priv *pfifo = nv_engine(dev, NVOBJ_ENGINE_FIFO);
Ben Skeggsab394542012-03-13 13:05:13 +1000583 struct drm_nouveau_private *dev_priv = dev->dev_private;
584 struct nouveau_channel *chan;
585 unsigned long flags;
586 int i;
587
588 spin_lock_irqsave(&dev_priv->channels.lock, flags);
Ben Skeggsc420b2d2012-05-01 20:48:08 +1000589 for (i = 0; i < pfifo->channels; i++) {
Ben Skeggsab394542012-03-13 13:05:13 +1000590 chan = dev_priv->channels.ptr[i];
591 if (!chan || !chan->ramin)
592 continue;
593
594 if (inst == chan->ramin->vinst)
595 break;
596 }
597 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
598 return i;
599}
600
601static void
602nve0_graph_ctxctl_isr(struct drm_device *dev)
603{
604 u32 ustat = nv_rd32(dev, 0x409c18);
605
606 if (ustat & 0x00000001)
607 NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n");
608 if (ustat & 0x00080000)
609 NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n");
610 if (ustat & ~0x00080001)
611 NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat);
612
613 nve0_graph_ctxctl_debug(dev);
614 nv_wr32(dev, 0x409c20, ustat);
615}
616
617static void
618nve0_graph_trap_isr(struct drm_device *dev, int chid)
619{
620 struct nve0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
621 u32 trap = nv_rd32(dev, 0x400108);
622 int rop;
623
624 if (trap & 0x00000001) {
625 u32 stat = nv_rd32(dev, 0x404000);
626 NV_INFO(dev, "PGRAPH: DISPATCH ch %d 0x%08x\n", chid, stat);
627 nv_wr32(dev, 0x404000, 0xc0000000);
628 nv_wr32(dev, 0x400108, 0x00000001);
629 trap &= ~0x00000001;
630 }
631
632 if (trap & 0x00000010) {
633 u32 stat = nv_rd32(dev, 0x405840);
634 NV_INFO(dev, "PGRAPH: SHADER ch %d 0x%08x\n", chid, stat);
635 nv_wr32(dev, 0x405840, 0xc0000000);
636 nv_wr32(dev, 0x400108, 0x00000010);
637 trap &= ~0x00000010;
638 }
639
640 if (trap & 0x02000000) {
641 for (rop = 0; rop < priv->rop_nr; rop++) {
642 u32 statz = nv_rd32(dev, ROP_UNIT(rop, 0x070));
643 u32 statc = nv_rd32(dev, ROP_UNIT(rop, 0x144));
644 NV_INFO(dev, "PGRAPH: ROP%d ch %d 0x%08x 0x%08x\n",
645 rop, chid, statz, statc);
646 nv_wr32(dev, ROP_UNIT(rop, 0x070), 0xc0000000);
647 nv_wr32(dev, ROP_UNIT(rop, 0x144), 0xc0000000);
648 }
649 nv_wr32(dev, 0x400108, 0x02000000);
650 trap &= ~0x02000000;
651 }
652
653 if (trap) {
654 NV_INFO(dev, "PGRAPH: TRAP ch %d 0x%08x\n", chid, trap);
655 nv_wr32(dev, 0x400108, trap);
656 }
657}
658
659static void
660nve0_graph_isr(struct drm_device *dev)
661{
662 u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12;
663 u32 chid = nve0_graph_isr_chid(dev, inst);
664 u32 stat = nv_rd32(dev, 0x400100);
665 u32 addr = nv_rd32(dev, 0x400704);
666 u32 mthd = (addr & 0x00003ffc);
667 u32 subc = (addr & 0x00070000) >> 16;
668 u32 data = nv_rd32(dev, 0x400708);
669 u32 code = nv_rd32(dev, 0x400110);
670 u32 class = nv_rd32(dev, 0x404200 + (subc * 4));
671
672 if (stat & 0x00000010) {
673 if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) {
674 NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] "
675 "subc %d class 0x%04x mthd 0x%04x "
676 "data 0x%08x\n",
677 chid, inst, subc, class, mthd, data);
678 }
679 nv_wr32(dev, 0x400100, 0x00000010);
680 stat &= ~0x00000010;
681 }
682
683 if (stat & 0x00000020) {
684 NV_INFO(dev, "PGRAPH: ILLEGAL_CLASS ch %d [0x%010llx] subc %d "
685 "class 0x%04x mthd 0x%04x data 0x%08x\n",
686 chid, inst, subc, class, mthd, data);
687 nv_wr32(dev, 0x400100, 0x00000020);
688 stat &= ~0x00000020;
689 }
690
691 if (stat & 0x00100000) {
692 NV_INFO(dev, "PGRAPH: DATA_ERROR [");
693 nouveau_enum_print(nv50_data_error_names, code);
694 printk("] ch %d [0x%010llx] subc %d class 0x%04x "
695 "mthd 0x%04x data 0x%08x\n",
696 chid, inst, subc, class, mthd, data);
697 nv_wr32(dev, 0x400100, 0x00100000);
698 stat &= ~0x00100000;
699 }
700
701 if (stat & 0x00200000) {
702 nve0_graph_trap_isr(dev, chid);
703 nv_wr32(dev, 0x400100, 0x00200000);
704 stat &= ~0x00200000;
705 }
706
707 if (stat & 0x00080000) {
708 nve0_graph_ctxctl_isr(dev);
709 nv_wr32(dev, 0x400100, 0x00080000);
710 stat &= ~0x00080000;
711 }
712
713 if (stat) {
714 NV_INFO(dev, "PGRAPH: unknown stat 0x%08x\n", stat);
715 nv_wr32(dev, 0x400100, stat);
716 }
717
718 nv_wr32(dev, 0x400500, 0x00010001);
719}
720
721static int
722nve0_graph_create_fw(struct drm_device *dev, const char *fwname,
723 struct nve0_graph_fuc *fuc)
724{
725 struct drm_nouveau_private *dev_priv = dev->dev_private;
726 const struct firmware *fw;
727 char f[32];
728 int ret;
729
730 snprintf(f, sizeof(f), "nouveau/nv%02x_%s", dev_priv->chipset, fwname);
731 ret = request_firmware(&fw, f, &dev->pdev->dev);
732 if (ret)
733 return ret;
734
735 fuc->size = fw->size;
736 fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
737 release_firmware(fw);
738 return (fuc->data != NULL) ? 0 : -ENOMEM;
739}
740
741static void
742nve0_graph_destroy_fw(struct nve0_graph_fuc *fuc)
743{
744 if (fuc->data) {
745 kfree(fuc->data);
746 fuc->data = NULL;
747 }
748}
749
750static void
751nve0_graph_destroy(struct drm_device *dev, int engine)
752{
753 struct nve0_graph_priv *priv = nv_engine(dev, engine);
754
755 nve0_graph_destroy_fw(&priv->fuc409c);
756 nve0_graph_destroy_fw(&priv->fuc409d);
757 nve0_graph_destroy_fw(&priv->fuc41ac);
758 nve0_graph_destroy_fw(&priv->fuc41ad);
759
760 nouveau_irq_unregister(dev, 12);
761
762 nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
763 nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
764
765 if (priv->grctx_vals)
766 kfree(priv->grctx_vals);
767
768 NVOBJ_ENGINE_DEL(dev, GR);
769 kfree(priv);
770}
771
772int
773nve0_graph_create(struct drm_device *dev)
774{
775 struct drm_nouveau_private *dev_priv = dev->dev_private;
776 struct nve0_graph_priv *priv;
777 int ret, gpc, i;
778 u32 kepler;
779
780 kepler = nve0_graph_class(dev);
781 if (!kepler) {
782 NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n");
783 return 0;
784 }
785
786 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
787 if (!priv)
788 return -ENOMEM;
789
790 priv->base.destroy = nve0_graph_destroy;
791 priv->base.init = nve0_graph_init;
792 priv->base.fini = nve0_graph_fini;
793 priv->base.context_new = nve0_graph_context_new;
794 priv->base.context_del = nve0_graph_context_del;
795 priv->base.object_new = nve0_graph_object_new;
796
797 NVOBJ_ENGINE_ADD(dev, GR, &priv->base);
798 nouveau_irq_register(dev, 12, nve0_graph_isr);
799
800 NV_INFO(dev, "PGRAPH: using external firmware\n");
801 if (nve0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) ||
802 nve0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) ||
803 nve0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) ||
804 nve0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) {
805 ret = 0;
806 goto error;
807 }
808
809 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4);
810 if (ret)
811 goto error;
812
813 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8);
814 if (ret)
815 goto error;
816
817 for (i = 0; i < 0x1000; i += 4) {
818 nv_wo32(priv->unk4188b4, i, 0x00000010);
819 nv_wo32(priv->unk4188b8, i, 0x00000010);
820 }
821
822 priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f;
823 priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16;
824 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
825 priv->tpc_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608));
826 priv->tpc_total += priv->tpc_nr[gpc];
827 }
828
829 switch (dev_priv->chipset) {
830 case 0xe4:
831 if (priv->tpc_total == 8)
832 priv->magic_not_rop_nr = 3;
833 else
834 if (priv->tpc_total == 7)
835 priv->magic_not_rop_nr = 1;
836 break;
837 case 0xe7:
838 priv->magic_not_rop_nr = 1;
839 break;
840 default:
841 break;
842 }
843
844 if (!priv->magic_not_rop_nr) {
845 NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n",
846 priv->tpc_nr[0], priv->tpc_nr[1], priv->tpc_nr[2],
847 priv->tpc_nr[3], priv->rop_nr);
848 priv->magic_not_rop_nr = 0x00;
849 }
850
851 NVOBJ_CLASS(dev, 0xa097, GR); /* subc 0: 3D */
852 NVOBJ_CLASS(dev, 0xa0c0, GR); /* subc 1: COMPUTE */
853 NVOBJ_CLASS(dev, 0xa040, GR); /* subc 2: P2MF */
854 NVOBJ_CLASS(dev, 0x902d, GR); /* subc 3: 2D */
Ben Skeggsd1b167e2012-05-04 14:01:52 +1000855 NVOBJ_CLASS(dev, 0xa0b5, GR); /* subc 4: COPY */
Ben Skeggsab394542012-03-13 13:05:13 +1000856 return 0;
857
858error:
859 nve0_graph_destroy(dev, NVOBJ_ENGINE_GR);
860 return ret;
861}