2ba125bb5f378388df331afefd1b43fa7f9adf56
[pandora-kernel.git] / drivers / gpu / drm / nouveau / core / engine / graph / nve0.c
1 /*
2  * Copyright 2012 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 "nvc0.h"
26
27 /*******************************************************************************
28  * Graphics object classes
29  ******************************************************************************/
30
31 static struct nouveau_oclass
32 nve0_graph_sclass[] = {
33         { 0x902d, &nouveau_object_ofuncs },
34         { 0xa040, &nouveau_object_ofuncs },
35         { 0xa097, &nouveau_object_ofuncs },
36         { 0xa0c0, &nouveau_object_ofuncs },
37         { 0xa0b5, &nouveau_object_ofuncs },
38         {}
39 };
40
41 /*******************************************************************************
42  * PGRAPH context
43  ******************************************************************************/
44
45 static struct nouveau_oclass
46 nve0_graph_cclass = {
47         .handle = NV_ENGCTX(GR, 0xe0),
48         .ofuncs = &(struct nouveau_ofuncs) {
49                 .ctor = nvc0_graph_context_ctor,
50                 .dtor = nvc0_graph_context_dtor,
51                 .init = _nouveau_graph_context_init,
52                 .fini = _nouveau_graph_context_fini,
53                 .rd32 = _nouveau_graph_context_rd32,
54                 .wr32 = _nouveau_graph_context_wr32,
55         },
56 };
57
58 /*******************************************************************************
59  * PGRAPH engine/subdev functions
60  ******************************************************************************/
61
62 static void
63 nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv)
64 {
65         u32 ustat = nv_rd32(priv, 0x409c18);
66
67         if (ustat & 0x00000001)
68                 nv_error(priv, "CTXCTRL ucode error\n");
69         if (ustat & 0x00080000)
70                 nv_error(priv, "CTXCTRL watchdog timeout\n");
71         if (ustat & ~0x00080001)
72                 nv_error(priv, "CTXCTRL 0x%08x\n", ustat);
73
74         nvc0_graph_ctxctl_debug(priv);
75         nv_wr32(priv, 0x409c20, ustat);
76 }
77
78 static void
79 nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst)
80 {
81         u32 trap = nv_rd32(priv, 0x400108);
82         int rop;
83
84         if (trap & 0x00000001) {
85                 u32 stat = nv_rd32(priv, 0x404000);
86                 nv_error(priv, "DISPATCH ch %d [0x%010llx] 0x%08x\n",
87                          chid, inst, stat);
88                 nv_wr32(priv, 0x404000, 0xc0000000);
89                 nv_wr32(priv, 0x400108, 0x00000001);
90                 trap &= ~0x00000001;
91         }
92
93         if (trap & 0x00000010) {
94                 u32 stat = nv_rd32(priv, 0x405840);
95                 nv_error(priv, "SHADER ch %d [0x%010llx] 0x%08x\n",
96                          chid, inst, stat);
97                 nv_wr32(priv, 0x405840, 0xc0000000);
98                 nv_wr32(priv, 0x400108, 0x00000010);
99                 trap &= ~0x00000010;
100         }
101
102         if (trap & 0x02000000) {
103                 for (rop = 0; rop < priv->rop_nr; rop++) {
104                         u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070));
105                         u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144));
106                         nv_error(priv, "ROP%d ch %d [0x%010llx] 0x%08x 0x%08x\n",
107                                  rop, chid, inst, statz, statc);
108                         nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
109                         nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
110                 }
111                 nv_wr32(priv, 0x400108, 0x02000000);
112                 trap &= ~0x02000000;
113         }
114
115         if (trap) {
116                 nv_error(priv, "TRAP ch %d [0x%010llx] 0x%08x\n",
117                          chid, inst, trap);
118                 nv_wr32(priv, 0x400108, trap);
119         }
120 }
121
122 static void
123 nve0_graph_intr(struct nouveau_subdev *subdev)
124 {
125         struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
126         struct nouveau_engine *engine = nv_engine(subdev);
127         struct nouveau_object *engctx;
128         struct nouveau_handle *handle;
129         struct nvc0_graph_priv *priv = (void *)subdev;
130         u64 inst = nv_rd32(priv, 0x409b00) & 0x0fffffff;
131         u32 stat = nv_rd32(priv, 0x400100);
132         u32 addr = nv_rd32(priv, 0x400704);
133         u32 mthd = (addr & 0x00003ffc);
134         u32 subc = (addr & 0x00070000) >> 16;
135         u32 data = nv_rd32(priv, 0x400708);
136         u32 code = nv_rd32(priv, 0x400110);
137         u32 class = nv_rd32(priv, 0x404200 + (subc * 4));
138         int chid;
139
140         engctx = nouveau_engctx_get(engine, inst);
141         chid   = pfifo->chid(pfifo, engctx);
142
143         if (stat & 0x00000010) {
144                 handle = nouveau_handle_get_class(engctx, class);
145                 if (!handle || nv_call(handle->object, mthd, data)) {
146                         nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] "
147                                      "subc %d class 0x%04x mthd 0x%04x "
148                                      "data 0x%08x\n",
149                                  chid, inst, subc, class, mthd, data);
150                 }
151                 nouveau_handle_put(handle);
152                 nv_wr32(priv, 0x400100, 0x00000010);
153                 stat &= ~0x00000010;
154         }
155
156         if (stat & 0x00000020) {
157                 nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d "
158                              "class 0x%04x mthd 0x%04x data 0x%08x\n",
159                          chid, inst, subc, class, mthd, data);
160                 nv_wr32(priv, 0x400100, 0x00000020);
161                 stat &= ~0x00000020;
162         }
163
164         if (stat & 0x00100000) {
165                 nv_error(priv, "DATA_ERROR [");
166                 nouveau_enum_print(nv50_data_error_names, code);
167                 printk("] ch %d [0x%010llx] subc %d class 0x%04x "
168                        "mthd 0x%04x data 0x%08x\n",
169                        chid, inst, subc, class, mthd, data);
170                 nv_wr32(priv, 0x400100, 0x00100000);
171                 stat &= ~0x00100000;
172         }
173
174         if (stat & 0x00200000) {
175                 nve0_graph_trap_isr(priv, chid, inst);
176                 nv_wr32(priv, 0x400100, 0x00200000);
177                 stat &= ~0x00200000;
178         }
179
180         if (stat & 0x00080000) {
181                 nve0_graph_ctxctl_isr(priv);
182                 nv_wr32(priv, 0x400100, 0x00080000);
183                 stat &= ~0x00080000;
184         }
185
186         if (stat) {
187                 nv_error(priv, "unknown stat 0x%08x\n", stat);
188                 nv_wr32(priv, 0x400100, stat);
189         }
190
191         nv_wr32(priv, 0x400500, 0x00010001);
192         nouveau_engctx_put(engctx);
193 }
194
195 static int
196 nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
197                struct nouveau_oclass *oclass, void *data, u32 size,
198                struct nouveau_object **pobject)
199 {
200         struct nvc0_graph_priv *priv;
201         int ret, i;
202
203         ret = nouveau_graph_create(parent, engine, oclass, false, &priv);
204         *pobject = nv_object(priv);
205         if (ret)
206                 return ret;
207
208         nv_subdev(priv)->unit = 0x18001000;
209         nv_subdev(priv)->intr = nve0_graph_intr;
210         nv_engine(priv)->cclass = &nve0_graph_cclass;
211         nv_engine(priv)->sclass = nve0_graph_sclass;
212
213         nv_info(priv, "using external firmware\n");
214         if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) ||
215             nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) ||
216             nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) ||
217             nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad))
218                 return -EINVAL;
219         priv->firmware = true;
220
221         ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4);
222         if (ret)
223                 return ret;
224
225         ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8);
226         if (ret)
227                 return ret;
228
229         for (i = 0; i < 0x1000; i += 4) {
230                 nv_wo32(priv->unk4188b4, i, 0x00000010);
231                 nv_wo32(priv->unk4188b8, i, 0x00000010);
232         }
233
234         priv->gpc_nr =  nv_rd32(priv, 0x409604) & 0x0000001f;
235         priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16;
236         for (i = 0; i < priv->gpc_nr; i++) {
237                 priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608));
238                 priv->tpc_total += priv->tpc_nr[i];
239         }
240
241         switch (nv_device(priv)->chipset) {
242         case 0xe4:
243                 if (priv->tpc_total == 8)
244                         priv->magic_not_rop_nr = 3;
245                 else
246                 if (priv->tpc_total == 7)
247                         priv->magic_not_rop_nr = 1;
248                 break;
249         case 0xe7:
250                 priv->magic_not_rop_nr = 1;
251                 break;
252         default:
253                 break;
254         }
255
256         return 0;
257 }
258
259 static void
260 nve0_graph_init_obj418880(struct nvc0_graph_priv *priv)
261 {
262         int i;
263
264         nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000);
265         nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000);
266         for (i = 0; i < 4; i++)
267                 nv_wr32(priv, GPC_BCAST(0x0888) + (i * 4), 0x00000000);
268         nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
269         nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
270 }
271
272 static void
273 nve0_graph_init_regs(struct nvc0_graph_priv *priv)
274 {
275         nv_wr32(priv, 0x400080, 0x003083c2);
276         nv_wr32(priv, 0x400088, 0x0001ffe7);
277         nv_wr32(priv, 0x40008c, 0x00000000);
278         nv_wr32(priv, 0x400090, 0x00000030);
279         nv_wr32(priv, 0x40013c, 0x003901f7);
280         nv_wr32(priv, 0x400140, 0x00000100);
281         nv_wr32(priv, 0x400144, 0x00000000);
282         nv_wr32(priv, 0x400148, 0x00000110);
283         nv_wr32(priv, 0x400138, 0x00000000);
284         nv_wr32(priv, 0x400130, 0x00000000);
285         nv_wr32(priv, 0x400134, 0x00000000);
286         nv_wr32(priv, 0x400124, 0x00000002);
287 }
288
289 static void
290 nve0_graph_init_units(struct nvc0_graph_priv *priv)
291 {
292         nv_wr32(priv, 0x409ffc, 0x00000000);
293         nv_wr32(priv, 0x409c14, 0x00003e3e);
294         nv_wr32(priv, 0x409c24, 0x000f0000);
295
296         nv_wr32(priv, 0x404000, 0xc0000000);
297         nv_wr32(priv, 0x404600, 0xc0000000);
298         nv_wr32(priv, 0x408030, 0xc0000000);
299         nv_wr32(priv, 0x404490, 0xc0000000);
300         nv_wr32(priv, 0x406018, 0xc0000000);
301         nv_wr32(priv, 0x407020, 0xc0000000);
302         nv_wr32(priv, 0x405840, 0xc0000000);
303         nv_wr32(priv, 0x405844, 0x00ffffff);
304
305         nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008);
306         nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000);
307
308 }
309
310 static void
311 nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv)
312 {
313         const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
314         u32 data[TPC_MAX / 8];
315         u8  tpcnr[GPC_MAX];
316         int i, gpc, tpc;
317
318         nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001);
319
320         memset(data, 0x00, sizeof(data));
321         memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
322         for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
323                 do {
324                         gpc = (gpc + 1) % priv->gpc_nr;
325                 } while (!tpcnr[gpc]);
326                 tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
327
328                 data[i / 8] |= tpc << ((i % 8) * 4);
329         }
330
331         nv_wr32(priv, GPC_BCAST(0x0980), data[0]);
332         nv_wr32(priv, GPC_BCAST(0x0984), data[1]);
333         nv_wr32(priv, GPC_BCAST(0x0988), data[2]);
334         nv_wr32(priv, GPC_BCAST(0x098c), data[3]);
335
336         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
337                 nv_wr32(priv, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
338                                                   priv->tpc_nr[gpc]);
339                 nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tpc_total);
340                 nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
341         }
342
343         nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918);
344         nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
345 }
346
347 static void
348 nve0_graph_init_gpc_1(struct nvc0_graph_priv *priv)
349 {
350         int gpc, tpc;
351
352         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
353                 nv_wr32(priv, GPC_UNIT(gpc, 0x3038), 0xc0000000);
354                 nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
355                 nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
356                 nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
357                 nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
358                 for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
359                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
360                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
361                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
362                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
363                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
364                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe);
365                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f);
366                 }
367                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
368                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
369         }
370 }
371
372 static void
373 nve0_graph_init_rop(struct nvc0_graph_priv *priv)
374 {
375         int rop;
376
377         for (rop = 0; rop < priv->rop_nr; rop++) {
378                 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
379                 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
380                 nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff);
381                 nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff);
382         }
383 }
384
385 static int
386 nve0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
387 {
388         u32 r000260;
389
390         /* load fuc microcode */
391         r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
392         nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c, &priv->fuc409d);
393         nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac, &priv->fuc41ad);
394         nv_wr32(priv, 0x000260, r000260);
395
396         /* start both of them running */
397         nv_wr32(priv, 0x409840, 0xffffffff);
398         nv_wr32(priv, 0x41a10c, 0x00000000);
399         nv_wr32(priv, 0x40910c, 0x00000000);
400         nv_wr32(priv, 0x41a100, 0x00000002);
401         nv_wr32(priv, 0x409100, 0x00000002);
402         if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001))
403                 nv_error(priv, "0x409800 wait failed\n");
404
405         nv_wr32(priv, 0x409840, 0xffffffff);
406         nv_wr32(priv, 0x409500, 0x7fffffff);
407         nv_wr32(priv, 0x409504, 0x00000021);
408
409         nv_wr32(priv, 0x409840, 0xffffffff);
410         nv_wr32(priv, 0x409500, 0x00000000);
411         nv_wr32(priv, 0x409504, 0x00000010);
412         if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
413                 nv_error(priv, "fuc09 req 0x10 timeout\n");
414                 return -EBUSY;
415         }
416         priv->size = nv_rd32(priv, 0x409800);
417
418         nv_wr32(priv, 0x409840, 0xffffffff);
419         nv_wr32(priv, 0x409500, 0x00000000);
420         nv_wr32(priv, 0x409504, 0x00000016);
421         if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
422                 nv_error(priv, "fuc09 req 0x16 timeout\n");
423                 return -EBUSY;
424         }
425
426         nv_wr32(priv, 0x409840, 0xffffffff);
427         nv_wr32(priv, 0x409500, 0x00000000);
428         nv_wr32(priv, 0x409504, 0x00000025);
429         if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
430                 nv_error(priv, "fuc09 req 0x25 timeout\n");
431                 return -EBUSY;
432         }
433
434         nv_wr32(priv, 0x409800, 0x00000000);
435         nv_wr32(priv, 0x409500, 0x00000001);
436         nv_wr32(priv, 0x409504, 0x00000030);
437         if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
438                 nv_error(priv, "fuc09 req 0x30 timeout\n");
439                 return -EBUSY;
440         }
441
442         nv_wr32(priv, 0x409810, 0xb00095c8);
443         nv_wr32(priv, 0x409800, 0x00000000);
444         nv_wr32(priv, 0x409500, 0x00000001);
445         nv_wr32(priv, 0x409504, 0x00000031);
446         if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
447                 nv_error(priv, "fuc09 req 0x31 timeout\n");
448                 return -EBUSY;
449         }
450
451         nv_wr32(priv, 0x409810, 0x00080420);
452         nv_wr32(priv, 0x409800, 0x00000000);
453         nv_wr32(priv, 0x409500, 0x00000001);
454         nv_wr32(priv, 0x409504, 0x00000032);
455         if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
456                 nv_error(priv, "fuc09 req 0x32 timeout\n");
457                 return -EBUSY;
458         }
459
460         nv_wr32(priv, 0x409614, 0x00000070);
461         nv_wr32(priv, 0x409614, 0x00000770);
462         nv_wr32(priv, 0x40802c, 0x00000001);
463
464         if (priv->data == NULL) {
465                 int ret = nve0_grctx_generate(priv);
466                 if (ret) {
467                         nv_error(priv, "failed to construct context\n");
468                         return ret;
469                 }
470         }
471
472         return 0;
473 }
474
475 static int
476 nve0_graph_init(struct nouveau_object *object)
477 {
478         struct nvc0_graph_priv *priv = (void *)object;
479         int ret;
480
481         ret = nouveau_graph_init(&priv->base);
482         if (ret)
483                 return ret;
484
485         nve0_graph_init_obj418880(priv);
486         nve0_graph_init_regs(priv);
487         nve0_graph_init_gpc_0(priv);
488
489         nv_wr32(priv, 0x400500, 0x00010001);
490         nv_wr32(priv, 0x400100, 0xffffffff);
491         nv_wr32(priv, 0x40013c, 0xffffffff);
492
493         nve0_graph_init_units(priv);
494         nve0_graph_init_gpc_1(priv);
495         nve0_graph_init_rop(priv);
496
497         nv_wr32(priv, 0x400108, 0xffffffff);
498         nv_wr32(priv, 0x400138, 0xffffffff);
499         nv_wr32(priv, 0x400118, 0xffffffff);
500         nv_wr32(priv, 0x400130, 0xffffffff);
501         nv_wr32(priv, 0x40011c, 0xffffffff);
502         nv_wr32(priv, 0x400134, 0xffffffff);
503         nv_wr32(priv, 0x400054, 0x34ce3464);
504
505         ret = nve0_graph_init_ctxctl(priv);
506         if (ret)
507                 return ret;
508
509         return 0;
510 }
511
512 struct nouveau_oclass
513 nve0_graph_oclass = {
514         .handle = NV_ENGINE(GR, 0xe0),
515         .ofuncs = &(struct nouveau_ofuncs) {
516                 .ctor = nve0_graph_ctor,
517                 .dtor = nvc0_graph_dtor,
518                 .init = nve0_graph_init,
519                 .fini = _nouveau_graph_fini,
520         },
521 };