8dafd410656833cd2a9b78e94e4500bbc9b9b872
[cascardo/linux.git] / drivers / gpu / drm / nouveau / core / engine / disp / nv50.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 <core/object.h>
26 #include <core/client.h>
27 #include <core/parent.h>
28 #include <core/handle.h>
29 #include <core/enum.h>
30 #include <nvif/unpack.h>
31 #include <nvif/class.h>
32
33 #include <subdev/bios.h>
34 #include <subdev/bios/dcb.h>
35 #include <subdev/bios/disp.h>
36 #include <subdev/bios/init.h>
37 #include <subdev/bios/pll.h>
38 #include <subdev/devinit.h>
39 #include <subdev/timer.h>
40 #include <subdev/fb.h>
41
42 #include "nv50.h"
43
44 /*******************************************************************************
45  * EVO channel base class
46  ******************************************************************************/
47
48 static int
49 nv50_disp_chan_create_(struct nouveau_object *parent,
50                        struct nouveau_object *engine,
51                        struct nouveau_oclass *oclass, int head,
52                        int length, void **pobject)
53 {
54         const struct nv50_disp_chan_impl *impl = (void *)oclass->ofuncs;
55         struct nv50_disp_base *base = (void *)parent;
56         struct nv50_disp_chan *chan;
57         int chid = impl->chid + head;
58         int ret;
59
60         if (base->chan & (1 << chid))
61                 return -EBUSY;
62         base->chan |= (1 << chid);
63
64         ret = nouveau_namedb_create_(parent, engine, oclass, 0, NULL,
65                                      (1ULL << NVDEV_ENGINE_DMAOBJ),
66                                      length, pobject);
67         chan = *pobject;
68         if (ret)
69                 return ret;
70         chan->chid = chid;
71
72         nv_parent(chan)->object_attach = impl->attach;
73         nv_parent(chan)->object_detach = impl->detach;
74         return 0;
75 }
76
77 static void
78 nv50_disp_chan_destroy(struct nv50_disp_chan *chan)
79 {
80         struct nv50_disp_base *base = (void *)nv_object(chan)->parent;
81         base->chan &= ~(1 << chan->chid);
82         nouveau_namedb_destroy(&chan->base);
83 }
84
85 u32
86 nv50_disp_chan_rd32(struct nouveau_object *object, u64 addr)
87 {
88         struct nv50_disp_priv *priv = (void *)object->engine;
89         struct nv50_disp_chan *chan = (void *)object;
90         return nv_rd32(priv, 0x640000 + (chan->chid * 0x1000) + addr);
91 }
92
93 void
94 nv50_disp_chan_wr32(struct nouveau_object *object, u64 addr, u32 data)
95 {
96         struct nv50_disp_priv *priv = (void *)object->engine;
97         struct nv50_disp_chan *chan = (void *)object;
98         nv_wr32(priv, 0x640000 + (chan->chid * 0x1000) + addr, data);
99 }
100
101 /*******************************************************************************
102  * EVO DMA channel base class
103  ******************************************************************************/
104
105 static int
106 nv50_disp_dmac_object_attach(struct nouveau_object *parent,
107                              struct nouveau_object *object, u32 name)
108 {
109         struct nv50_disp_base *base = (void *)parent->parent;
110         struct nv50_disp_chan *chan = (void *)parent;
111         u32 addr = nv_gpuobj(object)->node->offset;
112         u32 chid = chan->chid;
113         u32 data = (chid << 28) | (addr << 10) | chid;
114         return nouveau_ramht_insert(base->ramht, chid, name, data);
115 }
116
117 static void
118 nv50_disp_dmac_object_detach(struct nouveau_object *parent, int cookie)
119 {
120         struct nv50_disp_base *base = (void *)parent->parent;
121         nouveau_ramht_remove(base->ramht, cookie);
122 }
123
124 static int
125 nv50_disp_dmac_create_(struct nouveau_object *parent,
126                        struct nouveau_object *engine,
127                        struct nouveau_oclass *oclass, u32 pushbuf, int head,
128                        int length, void **pobject)
129 {
130         struct nv50_disp_dmac *dmac;
131         int ret;
132
133         ret = nv50_disp_chan_create_(parent, engine, oclass, head,
134                                      length, pobject);
135         dmac = *pobject;
136         if (ret)
137                 return ret;
138
139         dmac->pushdma = (void *)nouveau_handle_ref(parent, pushbuf);
140         if (!dmac->pushdma)
141                 return -ENOENT;
142
143         switch (nv_mclass(dmac->pushdma)) {
144         case 0x0002:
145         case 0x003d:
146                 if (dmac->pushdma->limit - dmac->pushdma->start != 0xfff)
147                         return -EINVAL;
148
149                 switch (dmac->pushdma->target) {
150                 case NV_MEM_TARGET_VRAM:
151                         dmac->push = 0x00000000 | dmac->pushdma->start >> 8;
152                         break;
153                 case NV_MEM_TARGET_PCI_NOSNOOP:
154                         dmac->push = 0x00000003 | dmac->pushdma->start >> 8;
155                         break;
156                 default:
157                         return -EINVAL;
158                 }
159                 break;
160         default:
161                 return -EINVAL;
162         }
163
164         return 0;
165 }
166
167 void
168 nv50_disp_dmac_dtor(struct nouveau_object *object)
169 {
170         struct nv50_disp_dmac *dmac = (void *)object;
171         nouveau_object_ref(NULL, (struct nouveau_object **)&dmac->pushdma);
172         nv50_disp_chan_destroy(&dmac->base);
173 }
174
175 static int
176 nv50_disp_dmac_init(struct nouveau_object *object)
177 {
178         struct nv50_disp_priv *priv = (void *)object->engine;
179         struct nv50_disp_dmac *dmac = (void *)object;
180         int chid = dmac->base.chid;
181         int ret;
182
183         ret = nv50_disp_chan_init(&dmac->base);
184         if (ret)
185                 return ret;
186
187         /* enable error reporting */
188         nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00010001 << chid);
189
190         /* initialise channel for dma command submission */
191         nv_wr32(priv, 0x610204 + (chid * 0x0010), dmac->push);
192         nv_wr32(priv, 0x610208 + (chid * 0x0010), 0x00010000);
193         nv_wr32(priv, 0x61020c + (chid * 0x0010), chid);
194         nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010);
195         nv_wr32(priv, 0x640000 + (chid * 0x1000), 0x00000000);
196         nv_wr32(priv, 0x610200 + (chid * 0x0010), 0x00000013);
197
198         /* wait for it to go inactive */
199         if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x80000000, 0x00000000)) {
200                 nv_error(dmac, "init timeout, 0x%08x\n",
201                          nv_rd32(priv, 0x610200 + (chid * 0x10)));
202                 return -EBUSY;
203         }
204
205         return 0;
206 }
207
208 static int
209 nv50_disp_dmac_fini(struct nouveau_object *object, bool suspend)
210 {
211         struct nv50_disp_priv *priv = (void *)object->engine;
212         struct nv50_disp_dmac *dmac = (void *)object;
213         int chid = dmac->base.chid;
214
215         /* deactivate channel */
216         nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00001010, 0x00001000);
217         nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00000003, 0x00000000);
218         if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x001e0000, 0x00000000)) {
219                 nv_error(dmac, "fini timeout, 0x%08x\n",
220                          nv_rd32(priv, 0x610200 + (chid * 0x10)));
221                 if (suspend)
222                         return -EBUSY;
223         }
224
225         /* disable error reporting */
226         nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00000000 << chid);
227
228         return nv50_disp_chan_fini(&dmac->base, suspend);
229 }
230
231 /*******************************************************************************
232  * EVO master channel object
233  ******************************************************************************/
234
235 static void
236 nv50_disp_mthd_list(struct nv50_disp_priv *priv, int debug, u32 base, int c,
237                     const struct nv50_disp_mthd_list *list, int inst)
238 {
239         struct nouveau_object *disp = nv_object(priv);
240         int i;
241
242         for (i = 0; list->data[i].mthd; i++) {
243                 if (list->data[i].addr) {
244                         u32 next = nv_rd32(priv, list->data[i].addr + base + 0);
245                         u32 prev = nv_rd32(priv, list->data[i].addr + base + c);
246                         u32 mthd = list->data[i].mthd + (list->mthd * inst);
247                         const char *name = list->data[i].name;
248                         char mods[16];
249
250                         if (prev != next)
251                                 snprintf(mods, sizeof(mods), "-> 0x%08x", next);
252                         else
253                                 snprintf(mods, sizeof(mods), "%13c", ' ');
254
255                         nv_printk_(disp, debug, "\t0x%04x: 0x%08x %s%s%s\n",
256                                    mthd, prev, mods, name ? " // " : "",
257                                    name ? name : "");
258                 }
259         }
260 }
261
262 void
263 nv50_disp_mthd_chan(struct nv50_disp_priv *priv, int debug, int head,
264                     const struct nv50_disp_mthd_chan *chan)
265 {
266         struct nouveau_object *disp = nv_object(priv);
267         const struct nv50_disp_impl *impl = (void *)disp->oclass;
268         const struct nv50_disp_mthd_list *list;
269         int i, j;
270
271         if (debug > nv_subdev(priv)->debug)
272                 return;
273
274         for (i = 0; (list = chan->data[i].mthd) != NULL; i++) {
275                 u32 base = head * chan->addr;
276                 for (j = 0; j < chan->data[i].nr; j++, base += list->addr) {
277                         const char *cname = chan->name;
278                         const char *sname = "";
279                         char cname_[16], sname_[16];
280
281                         if (chan->addr) {
282                                 snprintf(cname_, sizeof(cname_), "%s %d",
283                                          chan->name, head);
284                                 cname = cname_;
285                         }
286
287                         if (chan->data[i].nr > 1) {
288                                 snprintf(sname_, sizeof(sname_), " - %s %d",
289                                          chan->data[i].name, j);
290                                 sname = sname_;
291                         }
292
293                         nv_printk_(disp, debug, "%s%s:\n", cname, sname);
294                         nv50_disp_mthd_list(priv, debug, base, impl->mthd.prev,
295                                             list, j);
296                 }
297         }
298 }
299
300 const struct nv50_disp_mthd_list
301 nv50_disp_mast_mthd_base = {
302         .mthd = 0x0000,
303         .addr = 0x000000,
304         .data = {
305                 { 0x0080, 0x000000 },
306                 { 0x0084, 0x610bb8 },
307                 { 0x0088, 0x610b9c },
308                 { 0x008c, 0x000000 },
309                 {}
310         }
311 };
312
313 static const struct nv50_disp_mthd_list
314 nv50_disp_mast_mthd_dac = {
315         .mthd = 0x0080,
316         .addr = 0x000008,
317         .data = {
318                 { 0x0400, 0x610b58 },
319                 { 0x0404, 0x610bdc },
320                 { 0x0420, 0x610828 },
321                 {}
322         }
323 };
324
325 const struct nv50_disp_mthd_list
326 nv50_disp_mast_mthd_sor = {
327         .mthd = 0x0040,
328         .addr = 0x000008,
329         .data = {
330                 { 0x0600, 0x610b70 },
331                 {}
332         }
333 };
334
335 const struct nv50_disp_mthd_list
336 nv50_disp_mast_mthd_pior = {
337         .mthd = 0x0040,
338         .addr = 0x000008,
339         .data = {
340                 { 0x0700, 0x610b80 },
341                 {}
342         }
343 };
344
345 static const struct nv50_disp_mthd_list
346 nv50_disp_mast_mthd_head = {
347         .mthd = 0x0400,
348         .addr = 0x000540,
349         .data = {
350                 { 0x0800, 0x610ad8 },
351                 { 0x0804, 0x610ad0 },
352                 { 0x0808, 0x610a48 },
353                 { 0x080c, 0x610a78 },
354                 { 0x0810, 0x610ac0 },
355                 { 0x0814, 0x610af8 },
356                 { 0x0818, 0x610b00 },
357                 { 0x081c, 0x610ae8 },
358                 { 0x0820, 0x610af0 },
359                 { 0x0824, 0x610b08 },
360                 { 0x0828, 0x610b10 },
361                 { 0x082c, 0x610a68 },
362                 { 0x0830, 0x610a60 },
363                 { 0x0834, 0x000000 },
364                 { 0x0838, 0x610a40 },
365                 { 0x0840, 0x610a24 },
366                 { 0x0844, 0x610a2c },
367                 { 0x0848, 0x610aa8 },
368                 { 0x084c, 0x610ab0 },
369                 { 0x0860, 0x610a84 },
370                 { 0x0864, 0x610a90 },
371                 { 0x0868, 0x610b18 },
372                 { 0x086c, 0x610b20 },
373                 { 0x0870, 0x610ac8 },
374                 { 0x0874, 0x610a38 },
375                 { 0x0880, 0x610a58 },
376                 { 0x0884, 0x610a9c },
377                 { 0x08a0, 0x610a70 },
378                 { 0x08a4, 0x610a50 },
379                 { 0x08a8, 0x610ae0 },
380                 { 0x08c0, 0x610b28 },
381                 { 0x08c4, 0x610b30 },
382                 { 0x08c8, 0x610b40 },
383                 { 0x08d4, 0x610b38 },
384                 { 0x08d8, 0x610b48 },
385                 { 0x08dc, 0x610b50 },
386                 { 0x0900, 0x610a18 },
387                 { 0x0904, 0x610ab8 },
388                 {}
389         }
390 };
391
392 static const struct nv50_disp_mthd_chan
393 nv50_disp_mast_mthd_chan = {
394         .name = "Core",
395         .addr = 0x000000,
396         .data = {
397                 { "Global", 1, &nv50_disp_mast_mthd_base },
398                 {    "DAC", 3, &nv50_disp_mast_mthd_dac  },
399                 {    "SOR", 2, &nv50_disp_mast_mthd_sor  },
400                 {   "PIOR", 3, &nv50_disp_mast_mthd_pior },
401                 {   "HEAD", 2, &nv50_disp_mast_mthd_head },
402                 {}
403         }
404 };
405
406 int
407 nv50_disp_mast_ctor(struct nouveau_object *parent,
408                     struct nouveau_object *engine,
409                     struct nouveau_oclass *oclass, void *data, u32 size,
410                     struct nouveau_object **pobject)
411 {
412         union {
413                 struct nv50_disp_core_channel_dma_v0 v0;
414         } *args = data;
415         struct nv50_disp_dmac *mast;
416         int ret;
417
418         nv_ioctl(parent, "create disp core channel dma size %d\n", size);
419         if (nvif_unpack(args->v0, 0, 0, false)) {
420                 nv_ioctl(parent, "create disp core channel dma vers %d "
421                                  "pushbuf %08x\n",
422                          args->v0.version, args->v0.pushbuf);
423         } else
424                 return ret;
425
426         ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
427                                      0, sizeof(*mast), (void **)&mast);
428         *pobject = nv_object(mast);
429         if (ret)
430                 return ret;
431
432         return 0;
433 }
434
435 static int
436 nv50_disp_mast_init(struct nouveau_object *object)
437 {
438         struct nv50_disp_priv *priv = (void *)object->engine;
439         struct nv50_disp_dmac *mast = (void *)object;
440         int ret;
441
442         ret = nv50_disp_chan_init(&mast->base);
443         if (ret)
444                 return ret;
445
446         /* enable error reporting */
447         nv_mask(priv, 0x610028, 0x00010001, 0x00010001);
448
449         /* attempt to unstick channel from some unknown state */
450         if ((nv_rd32(priv, 0x610200) & 0x009f0000) == 0x00020000)
451                 nv_mask(priv, 0x610200, 0x00800000, 0x00800000);
452         if ((nv_rd32(priv, 0x610200) & 0x003f0000) == 0x00030000)
453                 nv_mask(priv, 0x610200, 0x00600000, 0x00600000);
454
455         /* initialise channel for dma command submission */
456         nv_wr32(priv, 0x610204, mast->push);
457         nv_wr32(priv, 0x610208, 0x00010000);
458         nv_wr32(priv, 0x61020c, 0x00000000);
459         nv_mask(priv, 0x610200, 0x00000010, 0x00000010);
460         nv_wr32(priv, 0x640000, 0x00000000);
461         nv_wr32(priv, 0x610200, 0x01000013);
462
463         /* wait for it to go inactive */
464         if (!nv_wait(priv, 0x610200, 0x80000000, 0x00000000)) {
465                 nv_error(mast, "init: 0x%08x\n", nv_rd32(priv, 0x610200));
466                 return -EBUSY;
467         }
468
469         return 0;
470 }
471
472 static int
473 nv50_disp_mast_fini(struct nouveau_object *object, bool suspend)
474 {
475         struct nv50_disp_priv *priv = (void *)object->engine;
476         struct nv50_disp_dmac *mast = (void *)object;
477
478         /* deactivate channel */
479         nv_mask(priv, 0x610200, 0x00000010, 0x00000000);
480         nv_mask(priv, 0x610200, 0x00000003, 0x00000000);
481         if (!nv_wait(priv, 0x610200, 0x001e0000, 0x00000000)) {
482                 nv_error(mast, "fini: 0x%08x\n", nv_rd32(priv, 0x610200));
483                 if (suspend)
484                         return -EBUSY;
485         }
486
487         /* disable error reporting */
488         nv_mask(priv, 0x610028, 0x00010001, 0x00000000);
489
490         return nv50_disp_chan_fini(&mast->base, suspend);
491 }
492
493 struct nv50_disp_chan_impl
494 nv50_disp_mast_ofuncs = {
495         .base.ctor = nv50_disp_mast_ctor,
496         .base.dtor = nv50_disp_dmac_dtor,
497         .base.init = nv50_disp_mast_init,
498         .base.fini = nv50_disp_mast_fini,
499         .base.rd32 = nv50_disp_chan_rd32,
500         .base.wr32 = nv50_disp_chan_wr32,
501         .chid = 0,
502         .attach = nv50_disp_dmac_object_attach,
503         .detach = nv50_disp_dmac_object_detach,
504 };
505
506 /*******************************************************************************
507  * EVO sync channel objects
508  ******************************************************************************/
509
510 static const struct nv50_disp_mthd_list
511 nv50_disp_sync_mthd_base = {
512         .mthd = 0x0000,
513         .addr = 0x000000,
514         .data = {
515                 { 0x0080, 0x000000 },
516                 { 0x0084, 0x0008c4 },
517                 { 0x0088, 0x0008d0 },
518                 { 0x008c, 0x0008dc },
519                 { 0x0090, 0x0008e4 },
520                 { 0x0094, 0x610884 },
521                 { 0x00a0, 0x6108a0 },
522                 { 0x00a4, 0x610878 },
523                 { 0x00c0, 0x61086c },
524                 { 0x00e0, 0x610858 },
525                 { 0x00e4, 0x610860 },
526                 { 0x00e8, 0x6108ac },
527                 { 0x00ec, 0x6108b4 },
528                 { 0x0100, 0x610894 },
529                 { 0x0110, 0x6108bc },
530                 { 0x0114, 0x61088c },
531                 {}
532         }
533 };
534
535 const struct nv50_disp_mthd_list
536 nv50_disp_sync_mthd_image = {
537         .mthd = 0x0400,
538         .addr = 0x000000,
539         .data = {
540                 { 0x0800, 0x6108f0 },
541                 { 0x0804, 0x6108fc },
542                 { 0x0808, 0x61090c },
543                 { 0x080c, 0x610914 },
544                 { 0x0810, 0x610904 },
545                 {}
546         }
547 };
548
549 static const struct nv50_disp_mthd_chan
550 nv50_disp_sync_mthd_chan = {
551         .name = "Base",
552         .addr = 0x000540,
553         .data = {
554                 { "Global", 1, &nv50_disp_sync_mthd_base },
555                 {  "Image", 2, &nv50_disp_sync_mthd_image },
556                 {}
557         }
558 };
559
560 int
561 nv50_disp_sync_ctor(struct nouveau_object *parent,
562                     struct nouveau_object *engine,
563                     struct nouveau_oclass *oclass, void *data, u32 size,
564                     struct nouveau_object **pobject)
565 {
566         union {
567                 struct nv50_disp_base_channel_dma_v0 v0;
568         } *args = data;
569         struct nv50_disp_priv *priv = (void *)engine;
570         struct nv50_disp_dmac *dmac;
571         int ret;
572
573         nv_ioctl(parent, "create disp base channel dma size %d\n", size);
574         if (nvif_unpack(args->v0, 0, 0, false)) {
575                 nv_ioctl(parent, "create disp base channel dma vers %d "
576                                  "pushbuf %08x head %d\n",
577                          args->v0.version, args->v0.pushbuf, args->v0.head);
578                 if (args->v0.head > priv->head.nr)
579                         return -EINVAL;
580         } else
581                 return ret;
582
583         ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
584                                      args->v0.head, sizeof(*dmac),
585                                      (void **)&dmac);
586         *pobject = nv_object(dmac);
587         if (ret)
588                 return ret;
589
590         return 0;
591 }
592
593 struct nv50_disp_chan_impl
594 nv50_disp_sync_ofuncs = {
595         .base.ctor = nv50_disp_sync_ctor,
596         .base.dtor = nv50_disp_dmac_dtor,
597         .base.init = nv50_disp_dmac_init,
598         .base.fini = nv50_disp_dmac_fini,
599         .base.rd32 = nv50_disp_chan_rd32,
600         .base.wr32 = nv50_disp_chan_wr32,
601         .chid = 1,
602         .attach = nv50_disp_dmac_object_attach,
603         .detach = nv50_disp_dmac_object_detach,
604 };
605
606 /*******************************************************************************
607  * EVO overlay channel objects
608  ******************************************************************************/
609
610 const struct nv50_disp_mthd_list
611 nv50_disp_ovly_mthd_base = {
612         .mthd = 0x0000,
613         .addr = 0x000000,
614         .data = {
615                 { 0x0080, 0x000000 },
616                 { 0x0084, 0x0009a0 },
617                 { 0x0088, 0x0009c0 },
618                 { 0x008c, 0x0009c8 },
619                 { 0x0090, 0x6109b4 },
620                 { 0x0094, 0x610970 },
621                 { 0x00a0, 0x610998 },
622                 { 0x00a4, 0x610964 },
623                 { 0x00c0, 0x610958 },
624                 { 0x00e0, 0x6109a8 },
625                 { 0x00e4, 0x6109d0 },
626                 { 0x00e8, 0x6109d8 },
627                 { 0x0100, 0x61094c },
628                 { 0x0104, 0x610984 },
629                 { 0x0108, 0x61098c },
630                 { 0x0800, 0x6109f8 },
631                 { 0x0808, 0x610a08 },
632                 { 0x080c, 0x610a10 },
633                 { 0x0810, 0x610a00 },
634                 {}
635         }
636 };
637
638 static const struct nv50_disp_mthd_chan
639 nv50_disp_ovly_mthd_chan = {
640         .name = "Overlay",
641         .addr = 0x000540,
642         .data = {
643                 { "Global", 1, &nv50_disp_ovly_mthd_base },
644                 {}
645         }
646 };
647
648 int
649 nv50_disp_ovly_ctor(struct nouveau_object *parent,
650                     struct nouveau_object *engine,
651                     struct nouveau_oclass *oclass, void *data, u32 size,
652                     struct nouveau_object **pobject)
653 {
654         union {
655                 struct nv50_disp_overlay_channel_dma_v0 v0;
656         } *args = data;
657         struct nv50_disp_priv *priv = (void *)engine;
658         struct nv50_disp_dmac *dmac;
659         int ret;
660
661         nv_ioctl(parent, "create disp overlay channel dma size %d\n", size);
662         if (nvif_unpack(args->v0, 0, 0, false)) {
663                 nv_ioctl(parent, "create disp overlay channel dma vers %d "
664                                  "pushbuf %08x head %d\n",
665                          args->v0.version, args->v0.pushbuf, args->v0.head);
666                 if (args->v0.head > priv->head.nr)
667                         return -EINVAL;
668         } else
669                 return ret;
670
671         ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
672                                      args->v0.head, sizeof(*dmac),
673                                      (void **)&dmac);
674         *pobject = nv_object(dmac);
675         if (ret)
676                 return ret;
677
678         return 0;
679 }
680
681 struct nv50_disp_chan_impl
682 nv50_disp_ovly_ofuncs = {
683         .base.ctor = nv50_disp_ovly_ctor,
684         .base.dtor = nv50_disp_dmac_dtor,
685         .base.init = nv50_disp_dmac_init,
686         .base.fini = nv50_disp_dmac_fini,
687         .base.rd32 = nv50_disp_chan_rd32,
688         .base.wr32 = nv50_disp_chan_wr32,
689         .chid = 3,
690         .attach = nv50_disp_dmac_object_attach,
691         .detach = nv50_disp_dmac_object_detach,
692 };
693
694 /*******************************************************************************
695  * EVO PIO channel base class
696  ******************************************************************************/
697
698 static int
699 nv50_disp_pioc_create_(struct nouveau_object *parent,
700                        struct nouveau_object *engine,
701                        struct nouveau_oclass *oclass, int head,
702                        int length, void **pobject)
703 {
704         return nv50_disp_chan_create_(parent, engine, oclass, head,
705                                       length, pobject);
706 }
707
708 void
709 nv50_disp_pioc_dtor(struct nouveau_object *object)
710 {
711         struct nv50_disp_pioc *pioc = (void *)object;
712         nv50_disp_chan_destroy(&pioc->base);
713 }
714
715 static int
716 nv50_disp_pioc_init(struct nouveau_object *object)
717 {
718         struct nv50_disp_priv *priv = (void *)object->engine;
719         struct nv50_disp_pioc *pioc = (void *)object;
720         int chid = pioc->base.chid;
721         int ret;
722
723         ret = nv50_disp_chan_init(&pioc->base);
724         if (ret)
725                 return ret;
726
727         nv_wr32(priv, 0x610200 + (chid * 0x10), 0x00002000);
728         if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00000000, 0x00000000)) {
729                 nv_error(pioc, "timeout0: 0x%08x\n",
730                          nv_rd32(priv, 0x610200 + (chid * 0x10)));
731                 return -EBUSY;
732         }
733
734         nv_wr32(priv, 0x610200 + (chid * 0x10), 0x00000001);
735         if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00030000, 0x00010000)) {
736                 nv_error(pioc, "timeout1: 0x%08x\n",
737                          nv_rd32(priv, 0x610200 + (chid * 0x10)));
738                 return -EBUSY;
739         }
740
741         return 0;
742 }
743
744 static int
745 nv50_disp_pioc_fini(struct nouveau_object *object, bool suspend)
746 {
747         struct nv50_disp_priv *priv = (void *)object->engine;
748         struct nv50_disp_pioc *pioc = (void *)object;
749         int chid = pioc->base.chid;
750
751         nv_mask(priv, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000);
752         if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00030000, 0x00000000)) {
753                 nv_error(pioc, "timeout: 0x%08x\n",
754                          nv_rd32(priv, 0x610200 + (chid * 0x10)));
755                 if (suspend)
756                         return -EBUSY;
757         }
758
759         return nv50_disp_chan_fini(&pioc->base, suspend);
760 }
761
762 /*******************************************************************************
763  * EVO immediate overlay channel objects
764  ******************************************************************************/
765
766 int
767 nv50_disp_oimm_ctor(struct nouveau_object *parent,
768                     struct nouveau_object *engine,
769                     struct nouveau_oclass *oclass, void *data, u32 size,
770                     struct nouveau_object **pobject)
771 {
772         union {
773                 struct nv50_disp_overlay_v0 v0;
774         } *args = data;
775         struct nv50_disp_priv *priv = (void *)engine;
776         struct nv50_disp_pioc *pioc;
777         int ret;
778
779         nv_ioctl(parent, "create disp overlay size %d\n", size);
780         if (nvif_unpack(args->v0, 0, 0, false)) {
781                 nv_ioctl(parent, "create disp overlay vers %d head %d\n",
782                          args->v0.version, args->v0.head);
783                 if (args->v0.head > priv->head.nr)
784                         return -EINVAL;
785         } else
786                 return ret;
787
788         ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
789                                      sizeof(*pioc), (void **)&pioc);
790         *pobject = nv_object(pioc);
791         if (ret)
792                 return ret;
793
794         return 0;
795 }
796
797 struct nv50_disp_chan_impl
798 nv50_disp_oimm_ofuncs = {
799         .base.ctor = nv50_disp_oimm_ctor,
800         .base.dtor = nv50_disp_pioc_dtor,
801         .base.init = nv50_disp_pioc_init,
802         .base.fini = nv50_disp_pioc_fini,
803         .base.rd32 = nv50_disp_chan_rd32,
804         .base.wr32 = nv50_disp_chan_wr32,
805         .chid = 5,
806 };
807
808 /*******************************************************************************
809  * EVO cursor channel objects
810  ******************************************************************************/
811
812 int
813 nv50_disp_curs_ctor(struct nouveau_object *parent,
814                     struct nouveau_object *engine,
815                     struct nouveau_oclass *oclass, void *data, u32 size,
816                     struct nouveau_object **pobject)
817 {
818         union {
819                 struct nv50_disp_cursor_v0 v0;
820         } *args = data;
821         struct nv50_disp_priv *priv = (void *)engine;
822         struct nv50_disp_pioc *pioc;
823         int ret;
824
825         nv_ioctl(parent, "create disp cursor size %d\n", size);
826         if (nvif_unpack(args->v0, 0, 0, false)) {
827                 nv_ioctl(parent, "create disp cursor vers %d head %d\n",
828                          args->v0.version, args->v0.head);
829                 if (args->v0.head > priv->head.nr)
830                         return -EINVAL;
831         } else
832                 return ret;
833
834         ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
835                                      sizeof(*pioc), (void **)&pioc);
836         *pobject = nv_object(pioc);
837         if (ret)
838                 return ret;
839
840         return 0;
841 }
842
843 struct nv50_disp_chan_impl
844 nv50_disp_curs_ofuncs = {
845         .base.ctor = nv50_disp_curs_ctor,
846         .base.dtor = nv50_disp_pioc_dtor,
847         .base.init = nv50_disp_pioc_init,
848         .base.fini = nv50_disp_pioc_fini,
849         .base.rd32 = nv50_disp_chan_rd32,
850         .base.wr32 = nv50_disp_chan_wr32,
851         .chid = 7,
852 };
853
854 /*******************************************************************************
855  * Base display object
856  ******************************************************************************/
857
858 int
859 nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
860 {
861         const u32 blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
862         const u32 blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
863         const u32 total  = nv_rd32(priv, 0x610afc + (head * 0x540));
864         union {
865                 struct nv04_disp_scanoutpos_v0 v0;
866         } *args = data;
867         int ret;
868
869         nv_ioctl(object, "disp scanoutpos size %d\n", size);
870         if (nvif_unpack(args->v0, 0, 0, false)) {
871                 nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
872                 args->v0.vblanke = (blanke & 0xffff0000) >> 16;
873                 args->v0.hblanke = (blanke & 0x0000ffff);
874                 args->v0.vblanks = (blanks & 0xffff0000) >> 16;
875                 args->v0.hblanks = (blanks & 0x0000ffff);
876                 args->v0.vtotal  = ( total & 0xffff0000) >> 16;
877                 args->v0.htotal  = ( total & 0x0000ffff);
878                 args->v0.time[0] = ktime_to_ns(ktime_get());
879                 args->v0.vline = /* vline read locks hline */
880                         nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
881                 args->v0.time[1] = ktime_to_ns(ktime_get());
882                 args->v0.hline =
883                         nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
884         } else
885                 return ret;
886
887         return 0;
888 }
889
890 int
891 nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
892                     void *data, u32 size)
893 {
894         const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
895         union {
896                 struct nv50_disp_mthd_v0 v0;
897                 struct nv50_disp_mthd_v1 v1;
898         } *args = data;
899         struct nv50_disp_priv *priv = (void *)object->engine;
900         struct nvkm_output *outp = NULL;
901         struct nvkm_output *temp;
902         u16 type, mask = 0;
903         int head, ret;
904
905         if (mthd != NV50_DISP_MTHD)
906                 return -EINVAL;
907
908         nv_ioctl(object, "disp mthd size %d\n", size);
909         if (nvif_unpack(args->v0, 0, 0, true)) {
910                 nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
911                          args->v0.version, args->v0.method, args->v0.head);
912                 mthd = args->v0.method;
913                 head = args->v0.head;
914         } else
915         if (nvif_unpack(args->v1, 1, 1, true)) {
916                 nv_ioctl(object, "disp mthd vers %d mthd %02x "
917                                  "type %04x mask %04x\n",
918                          args->v1.version, args->v1.method,
919                          args->v1.hasht, args->v1.hashm);
920                 mthd = args->v1.method;
921                 type = args->v1.hasht;
922                 mask = args->v1.hashm;
923                 head = ffs((mask >> 8) & 0x0f) - 1;
924         } else
925                 return ret;
926
927         if (head < 0 || head >= priv->head.nr)
928                 return -ENXIO;
929
930         if (mask) {
931                 list_for_each_entry(temp, &priv->base.outp, head) {
932                         if ((temp->info.hasht         == type) &&
933                             (temp->info.hashm & mask) == mask) {
934                                 outp = temp;
935                                 break;
936                         }
937                 }
938                 if (outp == NULL)
939                         return -ENXIO;
940         }
941
942         switch (mthd) {
943         case NV50_DISP_SCANOUTPOS:
944                 return impl->head.scanoutpos(object, priv, data, size, head);
945         default:
946                 break;
947         }
948
949         switch (mthd * !!outp) {
950         case NV50_DISP_MTHD_V1_DAC_PWR:
951                 return priv->dac.power(object, priv, data, size, head, outp);
952         case NV50_DISP_MTHD_V1_DAC_LOAD:
953                 return priv->dac.sense(object, priv, data, size, head, outp);
954         case NV50_DISP_MTHD_V1_SOR_PWR:
955                 return priv->sor.power(object, priv, data, size, head, outp);
956         case NV50_DISP_MTHD_V1_SOR_HDA_ELD:
957                 if (!priv->sor.hda_eld)
958                         return -ENODEV;
959                 return priv->sor.hda_eld(object, priv, data, size, head, outp);
960         case NV50_DISP_MTHD_V1_SOR_HDMI_PWR:
961                 if (!priv->sor.hdmi)
962                         return -ENODEV;
963                 return priv->sor.hdmi(object, priv, data, size, head, outp);
964         case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: {
965                 union {
966                         struct nv50_disp_sor_lvds_script_v0 v0;
967                 } *args = data;
968                 nv_ioctl(object, "disp sor lvds script size %d\n", size);
969                 if (nvif_unpack(args->v0, 0, 0, false)) {
970                         nv_ioctl(object, "disp sor lvds script "
971                                          "vers %d name %04x\n",
972                                  args->v0.version, args->v0.script);
973                         priv->sor.lvdsconf = args->v0.script;
974                         return 0;
975                 } else
976                         return ret;
977         }
978                 break;
979         case NV50_DISP_MTHD_V1_SOR_DP_PWR: {
980                 struct nvkm_output_dp *outpdp = (void *)outp;
981                 union {
982                         struct nv50_disp_sor_dp_pwr_v0 v0;
983                 } *args = data;
984                 nv_ioctl(object, "disp sor dp pwr size %d\n", size);
985                 if (nvif_unpack(args->v0, 0, 0, false)) {
986                         nv_ioctl(object, "disp sor dp pwr vers %d state %d\n",
987                                  args->v0.version, args->v0.state);
988                         if (args->v0.state == 0) {
989                                 nvkm_notify_put(&outpdp->irq);
990                                 ((struct nvkm_output_dp_impl *)nv_oclass(outp))
991                                         ->lnk_pwr(outpdp, 0);
992                                 atomic_set(&outpdp->lt.done, 0);
993                                 return 0;
994                         } else
995                         if (args->v0.state != 0) {
996                                 nvkm_output_dp_train(&outpdp->base, 0, true);
997                                 return 0;
998                         }
999                 } else
1000                         return ret;
1001         }
1002                 break;
1003         case NV50_DISP_MTHD_V1_PIOR_PWR:
1004                 if (!priv->pior.power)
1005                         return -ENODEV;
1006                 return priv->pior.power(object, priv, data, size, head, outp);
1007         default:
1008                 break;
1009         }
1010
1011         return -EINVAL;
1012 }
1013
1014 int
1015 nv50_disp_base_ctor(struct nouveau_object *parent,
1016                     struct nouveau_object *engine,
1017                     struct nouveau_oclass *oclass, void *data, u32 size,
1018                     struct nouveau_object **pobject)
1019 {
1020         struct nv50_disp_priv *priv = (void *)engine;
1021         struct nv50_disp_base *base;
1022         int ret;
1023
1024         ret = nouveau_parent_create(parent, engine, oclass, 0,
1025                                     priv->sclass, 0, &base);
1026         *pobject = nv_object(base);
1027         if (ret)
1028                 return ret;
1029
1030         return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
1031                                 &base->ramht);
1032 }
1033
1034 void
1035 nv50_disp_base_dtor(struct nouveau_object *object)
1036 {
1037         struct nv50_disp_base *base = (void *)object;
1038         nouveau_ramht_ref(NULL, &base->ramht);
1039         nouveau_parent_destroy(&base->base);
1040 }
1041
1042 static int
1043 nv50_disp_base_init(struct nouveau_object *object)
1044 {
1045         struct nv50_disp_priv *priv = (void *)object->engine;
1046         struct nv50_disp_base *base = (void *)object;
1047         int ret, i;
1048         u32 tmp;
1049
1050         ret = nouveau_parent_init(&base->base);
1051         if (ret)
1052                 return ret;
1053
1054         /* The below segments of code copying values from one register to
1055          * another appear to inform EVO of the display capabilities or
1056          * something similar.  NFI what the 0x614004 caps are for..
1057          */
1058         tmp = nv_rd32(priv, 0x614004);
1059         nv_wr32(priv, 0x610184, tmp);
1060
1061         /* ... CRTC caps */
1062         for (i = 0; i < priv->head.nr; i++) {
1063                 tmp = nv_rd32(priv, 0x616100 + (i * 0x800));
1064                 nv_wr32(priv, 0x610190 + (i * 0x10), tmp);
1065                 tmp = nv_rd32(priv, 0x616104 + (i * 0x800));
1066                 nv_wr32(priv, 0x610194 + (i * 0x10), tmp);
1067                 tmp = nv_rd32(priv, 0x616108 + (i * 0x800));
1068                 nv_wr32(priv, 0x610198 + (i * 0x10), tmp);
1069                 tmp = nv_rd32(priv, 0x61610c + (i * 0x800));
1070                 nv_wr32(priv, 0x61019c + (i * 0x10), tmp);
1071         }
1072
1073         /* ... DAC caps */
1074         for (i = 0; i < priv->dac.nr; i++) {
1075                 tmp = nv_rd32(priv, 0x61a000 + (i * 0x800));
1076                 nv_wr32(priv, 0x6101d0 + (i * 0x04), tmp);
1077         }
1078
1079         /* ... SOR caps */
1080         for (i = 0; i < priv->sor.nr; i++) {
1081                 tmp = nv_rd32(priv, 0x61c000 + (i * 0x800));
1082                 nv_wr32(priv, 0x6101e0 + (i * 0x04), tmp);
1083         }
1084
1085         /* ... PIOR caps */
1086         for (i = 0; i < priv->pior.nr; i++) {
1087                 tmp = nv_rd32(priv, 0x61e000 + (i * 0x800));
1088                 nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp);
1089         }
1090
1091         /* steal display away from vbios, or something like that */
1092         if (nv_rd32(priv, 0x610024) & 0x00000100) {
1093                 nv_wr32(priv, 0x610024, 0x00000100);
1094                 nv_mask(priv, 0x6194e8, 0x00000001, 0x00000000);
1095                 if (!nv_wait(priv, 0x6194e8, 0x00000002, 0x00000000)) {
1096                         nv_error(priv, "timeout acquiring display\n");
1097                         return -EBUSY;
1098                 }
1099         }
1100
1101         /* point at display engine memory area (hash table, objects) */
1102         nv_wr32(priv, 0x610010, (nv_gpuobj(base->ramht)->addr >> 8) | 9);
1103
1104         /* enable supervisor interrupts, disable everything else */
1105         nv_wr32(priv, 0x61002c, 0x00000370);
1106         nv_wr32(priv, 0x610028, 0x00000000);
1107         return 0;
1108 }
1109
1110 static int
1111 nv50_disp_base_fini(struct nouveau_object *object, bool suspend)
1112 {
1113         struct nv50_disp_priv *priv = (void *)object->engine;
1114         struct nv50_disp_base *base = (void *)object;
1115
1116         /* disable all interrupts */
1117         nv_wr32(priv, 0x610024, 0x00000000);
1118         nv_wr32(priv, 0x610020, 0x00000000);
1119
1120         return nouveau_parent_fini(&base->base, suspend);
1121 }
1122
1123 struct nouveau_ofuncs
1124 nv50_disp_base_ofuncs = {
1125         .ctor = nv50_disp_base_ctor,
1126         .dtor = nv50_disp_base_dtor,
1127         .init = nv50_disp_base_init,
1128         .fini = nv50_disp_base_fini,
1129         .mthd = nv50_disp_base_mthd,
1130 };
1131
1132 static struct nouveau_oclass
1133 nv50_disp_base_oclass[] = {
1134         { NV50_DISP, &nv50_disp_base_ofuncs },
1135         {}
1136 };
1137
1138 static struct nouveau_oclass
1139 nv50_disp_sclass[] = {
1140         { NV50_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
1141         { NV50_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
1142         { NV50_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
1143         { NV50_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
1144         { NV50_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
1145         {}
1146 };
1147
1148 /*******************************************************************************
1149  * Display context, tracks instmem allocation and prevents more than one
1150  * client using the display hardware at any time.
1151  ******************************************************************************/
1152
1153 static int
1154 nv50_disp_data_ctor(struct nouveau_object *parent,
1155                     struct nouveau_object *engine,
1156                     struct nouveau_oclass *oclass, void *data, u32 size,
1157                     struct nouveau_object **pobject)
1158 {
1159         struct nv50_disp_priv *priv = (void *)engine;
1160         struct nouveau_engctx *ectx;
1161         int ret = -EBUSY;
1162
1163         /* no context needed for channel objects... */
1164         if (nv_mclass(parent) != NV_DEVICE) {
1165                 atomic_inc(&parent->refcount);
1166                 *pobject = parent;
1167                 return 1;
1168         }
1169
1170         /* allocate display hardware to client */
1171         mutex_lock(&nv_subdev(priv)->mutex);
1172         if (list_empty(&nv_engine(priv)->contexts)) {
1173                 ret = nouveau_engctx_create(parent, engine, oclass, NULL,
1174                                             0x10000, 0x10000,
1175                                             NVOBJ_FLAG_HEAP, &ectx);
1176                 *pobject = nv_object(ectx);
1177         }
1178         mutex_unlock(&nv_subdev(priv)->mutex);
1179         return ret;
1180 }
1181
1182 struct nouveau_oclass
1183 nv50_disp_cclass = {
1184         .handle = NV_ENGCTX(DISP, 0x50),
1185         .ofuncs = &(struct nouveau_ofuncs) {
1186                 .ctor = nv50_disp_data_ctor,
1187                 .dtor = _nouveau_engctx_dtor,
1188                 .init = _nouveau_engctx_init,
1189                 .fini = _nouveau_engctx_fini,
1190                 .rd32 = _nouveau_engctx_rd32,
1191                 .wr32 = _nouveau_engctx_wr32,
1192         },
1193 };
1194
1195 /*******************************************************************************
1196  * Display engine implementation
1197  ******************************************************************************/
1198
1199 static void
1200 nv50_disp_vblank_fini(struct nvkm_event *event, int type, int head)
1201 {
1202         struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
1203         nv_mask(disp, 0x61002c, (4 << head), 0);
1204 }
1205
1206 static void
1207 nv50_disp_vblank_init(struct nvkm_event *event, int type, int head)
1208 {
1209         struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
1210         nv_mask(disp, 0x61002c, (4 << head), (4 << head));
1211 }
1212
1213 const struct nvkm_event_func
1214 nv50_disp_vblank_func = {
1215         .ctor = nouveau_disp_vblank_ctor,
1216         .init = nv50_disp_vblank_init,
1217         .fini = nv50_disp_vblank_fini,
1218 };
1219
1220 static const struct nouveau_enum
1221 nv50_disp_intr_error_type[] = {
1222         { 3, "ILLEGAL_MTHD" },
1223         { 4, "INVALID_VALUE" },
1224         { 5, "INVALID_STATE" },
1225         { 7, "INVALID_HANDLE" },
1226         {}
1227 };
1228
1229 static const struct nouveau_enum
1230 nv50_disp_intr_error_code[] = {
1231         { 0x00, "" },
1232         {}
1233 };
1234
1235 static void
1236 nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid)
1237 {
1238         struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
1239         u32 data = nv_rd32(priv, 0x610084 + (chid * 0x08));
1240         u32 addr = nv_rd32(priv, 0x610080 + (chid * 0x08));
1241         u32 code = (addr & 0x00ff0000) >> 16;
1242         u32 type = (addr & 0x00007000) >> 12;
1243         u32 mthd = (addr & 0x00000ffc);
1244         const struct nouveau_enum *ec, *et;
1245         char ecunk[6], etunk[6];
1246
1247         et = nouveau_enum_find(nv50_disp_intr_error_type, type);
1248         if (!et)
1249                 snprintf(etunk, sizeof(etunk), "UNK%02X", type);
1250
1251         ec = nouveau_enum_find(nv50_disp_intr_error_code, code);
1252         if (!ec)
1253                 snprintf(ecunk, sizeof(ecunk), "UNK%02X", code);
1254
1255         nv_error(priv, "%s [%s] chid %d mthd 0x%04x data 0x%08x\n",
1256                  et ? et->name : etunk, ec ? ec->name : ecunk,
1257                  chid, mthd, data);
1258
1259         if (chid == 0) {
1260                 switch (mthd) {
1261                 case 0x0080:
1262                         nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
1263                                             impl->mthd.core);
1264                         break;
1265                 default:
1266                         break;
1267                 }
1268         } else
1269         if (chid <= 2) {
1270                 switch (mthd) {
1271                 case 0x0080:
1272                         nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
1273                                             impl->mthd.base);
1274                         break;
1275                 default:
1276                         break;
1277                 }
1278         } else
1279         if (chid <= 4) {
1280                 switch (mthd) {
1281                 case 0x0080:
1282                         nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 3,
1283                                             impl->mthd.ovly);
1284                         break;
1285                 default:
1286                         break;
1287                 }
1288         }
1289
1290         nv_wr32(priv, 0x610020, 0x00010000 << chid);
1291         nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);
1292 }
1293
1294 static struct nvkm_output *
1295 exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
1296             u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
1297             struct nvbios_outp *info)
1298 {
1299         struct nouveau_bios *bios = nouveau_bios(priv);
1300         struct nvkm_output *outp;
1301         u16 mask, type;
1302
1303         if (or < 4) {
1304                 type = DCB_OUTPUT_ANALOG;
1305                 mask = 0;
1306         } else
1307         if (or < 8) {
1308                 switch (ctrl & 0x00000f00) {
1309                 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
1310                 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
1311                 case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break;
1312                 case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break;
1313                 case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break;
1314                 case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
1315                 default:
1316                         nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
1317                         return NULL;
1318                 }
1319                 or  -= 4;
1320         } else {
1321                 or   = or - 8;
1322                 type = 0x0010;
1323                 mask = 0;
1324                 switch (ctrl & 0x00000f00) {
1325                 case 0x00000000: type |= priv->pior.type[or]; break;
1326                 default:
1327                         nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl);
1328                         return NULL;
1329                 }
1330         }
1331
1332         mask  = 0x00c0 & (mask << 6);
1333         mask |= 0x0001 << or;
1334         mask |= 0x0100 << head;
1335
1336         list_for_each_entry(outp, &priv->base.outp, head) {
1337                 if ((outp->info.hasht & 0xff) == type &&
1338                     (outp->info.hashm & mask) == mask) {
1339                         *data = nvbios_outp_match(bios, outp->info.hasht,
1340                                                         outp->info.hashm,
1341                                                   ver, hdr, cnt, len, info);
1342                         if (!*data)
1343                                 return NULL;
1344                         return outp;
1345                 }
1346         }
1347
1348         return NULL;
1349 }
1350
1351 static struct nvkm_output *
1352 exec_script(struct nv50_disp_priv *priv, int head, int id)
1353 {
1354         struct nouveau_bios *bios = nouveau_bios(priv);
1355         struct nvkm_output *outp;
1356         struct nvbios_outp info;
1357         u8  ver, hdr, cnt, len;
1358         u32 data, ctrl = 0;
1359         u32 reg;
1360         int i;
1361
1362         /* DAC */
1363         for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++)
1364                 ctrl = nv_rd32(priv, 0x610b5c + (i * 8));
1365
1366         /* SOR */
1367         if (!(ctrl & (1 << head))) {
1368                 if (nv_device(priv)->chipset  < 0x90 ||
1369                     nv_device(priv)->chipset == 0x92 ||
1370                     nv_device(priv)->chipset == 0xa0) {
1371                         reg = 0x610b74;
1372                 } else {
1373                         reg = 0x610798;
1374                 }
1375                 for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++)
1376                         ctrl = nv_rd32(priv, reg + (i * 8));
1377                 i += 4;
1378         }
1379
1380         /* PIOR */
1381         if (!(ctrl & (1 << head))) {
1382                 for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++)
1383                         ctrl = nv_rd32(priv, 0x610b84 + (i * 8));
1384                 i += 8;
1385         }
1386
1387         if (!(ctrl & (1 << head)))
1388                 return NULL;
1389         i--;
1390
1391         outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
1392         if (outp) {
1393                 struct nvbios_init init = {
1394                         .subdev = nv_subdev(priv),
1395                         .bios = bios,
1396                         .offset = info.script[id],
1397                         .outp = &outp->info,
1398                         .crtc = head,
1399                         .execute = 1,
1400                 };
1401
1402                 nvbios_exec(&init);
1403         }
1404
1405         return outp;
1406 }
1407
1408 static struct nvkm_output *
1409 exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf)
1410 {
1411         struct nouveau_bios *bios = nouveau_bios(priv);
1412         struct nvkm_output *outp;
1413         struct nvbios_outp info1;
1414         struct nvbios_ocfg info2;
1415         u8  ver, hdr, cnt, len;
1416         u32 data, ctrl = 0;
1417         u32 reg;
1418         int i;
1419
1420         /* DAC */
1421         for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++)
1422                 ctrl = nv_rd32(priv, 0x610b58 + (i * 8));
1423
1424         /* SOR */
1425         if (!(ctrl & (1 << head))) {
1426                 if (nv_device(priv)->chipset  < 0x90 ||
1427                     nv_device(priv)->chipset == 0x92 ||
1428                     nv_device(priv)->chipset == 0xa0) {
1429                         reg = 0x610b70;
1430                 } else {
1431                         reg = 0x610794;
1432                 }
1433                 for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++)
1434                         ctrl = nv_rd32(priv, reg + (i * 8));
1435                 i += 4;
1436         }
1437
1438         /* PIOR */
1439         if (!(ctrl & (1 << head))) {
1440                 for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++)
1441                         ctrl = nv_rd32(priv, 0x610b80 + (i * 8));
1442                 i += 8;
1443         }
1444
1445         if (!(ctrl & (1 << head)))
1446                 return NULL;
1447         i--;
1448
1449         outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
1450         if (!outp)
1451                 return NULL;
1452
1453         if (outp->info.location == 0) {
1454                 switch (outp->info.type) {
1455                 case DCB_OUTPUT_TMDS:
1456                         *conf = (ctrl & 0x00000f00) >> 8;
1457                         if (pclk >= 165000)
1458                                 *conf |= 0x0100;
1459                         break;
1460                 case DCB_OUTPUT_LVDS:
1461                         *conf = priv->sor.lvdsconf;
1462                         break;
1463                 case DCB_OUTPUT_DP:
1464                         *conf = (ctrl & 0x00000f00) >> 8;
1465                         break;
1466                 case DCB_OUTPUT_ANALOG:
1467                 default:
1468                         *conf = 0x00ff;
1469                         break;
1470                 }
1471         } else {
1472                 *conf = (ctrl & 0x00000f00) >> 8;
1473                 pclk = pclk / 2;
1474         }
1475
1476         data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
1477         if (data && id < 0xff) {
1478                 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
1479                 if (data) {
1480                         struct nvbios_init init = {
1481                                 .subdev = nv_subdev(priv),
1482                                 .bios = bios,
1483                                 .offset = data,
1484                                 .outp = &outp->info,
1485                                 .crtc = head,
1486                                 .execute = 1,
1487                         };
1488
1489                         nvbios_exec(&init);
1490                 }
1491         }
1492
1493         return outp;
1494 }
1495
1496 static void
1497 nv50_disp_intr_unk10_0(struct nv50_disp_priv *priv, int head)
1498 {
1499         exec_script(priv, head, 1);
1500 }
1501
1502 static void
1503 nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head)
1504 {
1505         struct nvkm_output *outp = exec_script(priv, head, 2);
1506
1507         /* the binary driver does this outside of the supervisor handling
1508          * (after the third supervisor from a detach).  we (currently?)
1509          * allow both detach/attach to happen in the same set of
1510          * supervisor interrupts, so it would make sense to execute this
1511          * (full power down?) script after all the detach phases of the
1512          * supervisor handling.  like with training if needed from the
1513          * second supervisor, nvidia doesn't do this, so who knows if it's
1514          * entirely safe, but it does appear to work..
1515          *
1516          * without this script being run, on some configurations i've
1517          * seen, switching from DP to TMDS on a DP connector may result
1518          * in a blank screen (SOR_PWR off/on can restore it)
1519          */
1520         if (outp && outp->info.type == DCB_OUTPUT_DP) {
1521                 struct nvkm_output_dp *outpdp = (void *)outp;
1522                 struct nvbios_init init = {
1523                         .subdev = nv_subdev(priv),
1524                         .bios = nouveau_bios(priv),
1525                         .outp = &outp->info,
1526                         .crtc = head,
1527                         .offset = outpdp->info.script[4],
1528                         .execute = 1,
1529                 };
1530
1531                 nvbios_exec(&init);
1532                 atomic_set(&outpdp->lt.done, 0);
1533         }
1534 }
1535
1536 static void
1537 nv50_disp_intr_unk20_1(struct nv50_disp_priv *priv, int head)
1538 {
1539         struct nouveau_devinit *devinit = nouveau_devinit(priv);
1540         u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
1541         if (pclk)
1542                 devinit->pll_set(devinit, PLL_VPLL0 + head, pclk);
1543 }
1544
1545 static void
1546 nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv,
1547                           struct dcb_output *outp, u32 pclk)
1548 {
1549         const int link = !(outp->sorconf.link & 1);
1550         const int   or = ffs(outp->or) - 1;
1551         const u32 soff = (  or * 0x800);
1552         const u32 loff = (link * 0x080) + soff;
1553         const u32 ctrl = nv_rd32(priv, 0x610794 + (or * 8));
1554         const u32 symbol = 100000;
1555         u32 dpctrl = nv_rd32(priv, 0x61c10c + loff) & 0x0000f0000;
1556         u32 clksor = nv_rd32(priv, 0x614300 + soff);
1557         int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0;
1558         int TU, VTUi, VTUf, VTUa;
1559         u64 link_data_rate, link_ratio, unk;
1560         u32 best_diff = 64 * symbol;
1561         u32 link_nr, link_bw, bits, r;
1562
1563         /* calculate packed data rate for each lane */
1564         if      (dpctrl > 0x00030000) link_nr = 4;
1565         else if (dpctrl > 0x00010000) link_nr = 2;
1566         else                          link_nr = 1;
1567
1568         if (clksor & 0x000c0000)
1569                 link_bw = 270000;
1570         else
1571                 link_bw = 162000;
1572
1573         if      ((ctrl & 0xf0000) == 0x60000) bits = 30;
1574         else if ((ctrl & 0xf0000) == 0x50000) bits = 24;
1575         else                                  bits = 18;
1576
1577         link_data_rate = (pclk * bits / 8) / link_nr;
1578
1579         /* calculate ratio of packed data rate to link symbol rate */
1580         link_ratio = link_data_rate * symbol;
1581         r = do_div(link_ratio, link_bw);
1582
1583         for (TU = 64; TU >= 32; TU--) {
1584                 /* calculate average number of valid symbols in each TU */
1585                 u32 tu_valid = link_ratio * TU;
1586                 u32 calc, diff;
1587
1588                 /* find a hw representation for the fraction.. */
1589                 VTUi = tu_valid / symbol;
1590                 calc = VTUi * symbol;
1591                 diff = tu_valid - calc;
1592                 if (diff) {
1593                         if (diff >= (symbol / 2)) {
1594                                 VTUf = symbol / (symbol - diff);
1595                                 if (symbol - (VTUf * diff))
1596                                         VTUf++;
1597
1598                                 if (VTUf <= 15) {
1599                                         VTUa  = 1;
1600                                         calc += symbol - (symbol / VTUf);
1601                                 } else {
1602                                         VTUa  = 0;
1603                                         VTUf  = 1;
1604                                         calc += symbol;
1605                                 }
1606                         } else {
1607                                 VTUa  = 0;
1608                                 VTUf  = min((int)(symbol / diff), 15);
1609                                 calc += symbol / VTUf;
1610                         }
1611
1612                         diff = calc - tu_valid;
1613                 } else {
1614                         /* no remainder, but the hw doesn't like the fractional
1615                          * part to be zero.  decrement the integer part and
1616                          * have the fraction add a whole symbol back
1617                          */
1618                         VTUa = 0;
1619                         VTUf = 1;
1620                         VTUi--;
1621                 }
1622
1623                 if (diff < best_diff) {
1624                         best_diff = diff;
1625                         bestTU = TU;
1626                         bestVTUa = VTUa;
1627                         bestVTUf = VTUf;
1628                         bestVTUi = VTUi;
1629                         if (diff == 0)
1630                                 break;
1631                 }
1632         }
1633
1634         if (!bestTU) {
1635                 nv_error(priv, "unable to find suitable dp config\n");
1636                 return;
1637         }
1638
1639         /* XXX close to vbios numbers, but not right */
1640         unk  = (symbol - link_ratio) * bestTU;
1641         unk *= link_ratio;
1642         r = do_div(unk, symbol);
1643         r = do_div(unk, symbol);
1644         unk += 6;
1645
1646         nv_mask(priv, 0x61c10c + loff, 0x000001fc, bestTU << 2);
1647         nv_mask(priv, 0x61c128 + loff, 0x010f7f3f, bestVTUa << 24 |
1648                                                    bestVTUf << 16 |
1649                                                    bestVTUi << 8 | unk);
1650 }
1651
1652 static void
1653 nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
1654 {
1655         struct nvkm_output *outp;
1656         u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
1657         u32 hval, hreg = 0x614200 + (head * 0x800);
1658         u32 oval, oreg;
1659         u32 mask, conf;
1660
1661         outp = exec_clkcmp(priv, head, 0xff, pclk, &conf);
1662         if (!outp)
1663                 return;
1664
1665         /* we allow both encoder attach and detach operations to occur
1666          * within a single supervisor (ie. modeset) sequence.  the
1667          * encoder detach scripts quite often switch off power to the
1668          * lanes, which requires the link to be re-trained.
1669          *
1670          * this is not generally an issue as the sink "must" (heh)
1671          * signal an irq when it's lost sync so the driver can
1672          * re-train.
1673          *
1674          * however, on some boards, if one does not configure at least
1675          * the gpu side of the link *before* attaching, then various
1676          * things can go horribly wrong (PDISP disappearing from mmio,
1677          * third supervisor never happens, etc).
1678          *
1679          * the solution is simply to retrain here, if necessary.  last
1680          * i checked, the binary driver userspace does not appear to
1681          * trigger this situation (it forces an UPDATE between steps).
1682          */
1683         if (outp->info.type == DCB_OUTPUT_DP) {
1684                 u32 soff = (ffs(outp->info.or) - 1) * 0x08;
1685                 u32 ctrl, datarate;
1686
1687                 if (outp->info.location == 0) {
1688                         ctrl = nv_rd32(priv, 0x610794 + soff);
1689                         soff = 1;
1690                 } else {
1691                         ctrl = nv_rd32(priv, 0x610b80 + soff);
1692                         soff = 2;
1693                 }
1694
1695                 switch ((ctrl & 0x000f0000) >> 16) {
1696                 case 6: datarate = pclk * 30; break;
1697                 case 5: datarate = pclk * 24; break;
1698                 case 2:
1699                 default:
1700                         datarate = pclk * 18;
1701                         break;
1702                 }
1703
1704                 if (nvkm_output_dp_train(outp, datarate / soff, true))
1705                         ERR("link not trained before attach\n");
1706         }
1707
1708         exec_clkcmp(priv, head, 0, pclk, &conf);
1709
1710         if (!outp->info.location && outp->info.type == DCB_OUTPUT_ANALOG) {
1711                 oreg = 0x614280 + (ffs(outp->info.or) - 1) * 0x800;
1712                 oval = 0x00000000;
1713                 hval = 0x00000000;
1714                 mask = 0xffffffff;
1715         } else
1716         if (!outp->info.location) {
1717                 if (outp->info.type == DCB_OUTPUT_DP)
1718                         nv50_disp_intr_unk20_2_dp(priv, &outp->info, pclk);
1719                 oreg = 0x614300 + (ffs(outp->info.or) - 1) * 0x800;
1720                 oval = (conf & 0x0100) ? 0x00000101 : 0x00000000;
1721                 hval = 0x00000000;
1722                 mask = 0x00000707;
1723         } else {
1724                 oreg = 0x614380 + (ffs(outp->info.or) - 1) * 0x800;
1725                 oval = 0x00000001;
1726                 hval = 0x00000001;
1727                 mask = 0x00000707;
1728         }
1729
1730         nv_mask(priv, hreg, 0x0000000f, hval);
1731         nv_mask(priv, oreg, mask, oval);
1732 }
1733
1734 /* If programming a TMDS output on a SOR that can also be configured for
1735  * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off.
1736  *
1737  * It looks like the VBIOS TMDS scripts make an attempt at this, however,
1738  * the VBIOS scripts on at least one board I have only switch it off on
1739  * link 0, causing a blank display if the output has previously been
1740  * programmed for DisplayPort.
1741  */
1742 static void
1743 nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp)
1744 {
1745         struct nouveau_bios *bios = nouveau_bios(priv);
1746         const int link = !(outp->sorconf.link & 1);
1747         const int   or = ffs(outp->or) - 1;
1748         const u32 loff = (or * 0x800) + (link * 0x80);
1749         const u16 mask = (outp->sorconf.link << 6) | outp->or;
1750         u8  ver, hdr;
1751
1752         if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, outp))
1753                 nv_mask(priv, 0x61c10c + loff, 0x00000001, 0x00000000);
1754 }
1755
1756 static void
1757 nv50_disp_intr_unk40_0(struct nv50_disp_priv *priv, int head)
1758 {
1759         struct nvkm_output *outp;
1760         u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
1761         u32 conf;
1762
1763         outp = exec_clkcmp(priv, head, 1, pclk, &conf);
1764         if (!outp)
1765                 return;
1766
1767         if (outp->info.location == 0 && outp->info.type == DCB_OUTPUT_TMDS)
1768                 nv50_disp_intr_unk40_0_tmds(priv, &outp->info);
1769 }
1770
1771 void
1772 nv50_disp_intr_supervisor(struct work_struct *work)
1773 {
1774         struct nv50_disp_priv *priv =
1775                 container_of(work, struct nv50_disp_priv, supervisor);
1776         struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
1777         u32 super = nv_rd32(priv, 0x610030);
1778         int head;
1779
1780         nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super);
1781
1782         if (priv->super & 0x00000010) {
1783                 nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);
1784                 for (head = 0; head < priv->head.nr; head++) {
1785                         if (!(super & (0x00000020 << head)))
1786                                 continue;
1787                         if (!(super & (0x00000080 << head)))
1788                                 continue;
1789                         nv50_disp_intr_unk10_0(priv, head);
1790                 }
1791         } else
1792         if (priv->super & 0x00000020) {
1793                 for (head = 0; head < priv->head.nr; head++) {
1794                         if (!(super & (0x00000080 << head)))
1795                                 continue;
1796                         nv50_disp_intr_unk20_0(priv, head);
1797                 }
1798                 for (head = 0; head < priv->head.nr; head++) {
1799                         if (!(super & (0x00000200 << head)))
1800                                 continue;
1801                         nv50_disp_intr_unk20_1(priv, head);
1802                 }
1803                 for (head = 0; head < priv->head.nr; head++) {
1804                         if (!(super & (0x00000080 << head)))
1805                                 continue;
1806                         nv50_disp_intr_unk20_2(priv, head);
1807                 }
1808         } else
1809         if (priv->super & 0x00000040) {
1810                 for (head = 0; head < priv->head.nr; head++) {
1811                         if (!(super & (0x00000080 << head)))
1812                                 continue;
1813                         nv50_disp_intr_unk40_0(priv, head);
1814                 }
1815         }
1816
1817         nv_wr32(priv, 0x610030, 0x80000000);
1818 }
1819
1820 void
1821 nv50_disp_intr(struct nouveau_subdev *subdev)
1822 {
1823         struct nv50_disp_priv *priv = (void *)subdev;
1824         u32 intr0 = nv_rd32(priv, 0x610020);
1825         u32 intr1 = nv_rd32(priv, 0x610024);
1826
1827         while (intr0 & 0x001f0000) {
1828                 u32 chid = __ffs(intr0 & 0x001f0000) - 16;
1829                 nv50_disp_intr_error(priv, chid);
1830                 intr0 &= ~(0x00010000 << chid);
1831         }
1832
1833         if (intr1 & 0x00000004) {
1834                 nouveau_disp_vblank(&priv->base, 0);
1835                 nv_wr32(priv, 0x610024, 0x00000004);
1836                 intr1 &= ~0x00000004;
1837         }
1838
1839         if (intr1 & 0x00000008) {
1840                 nouveau_disp_vblank(&priv->base, 1);
1841                 nv_wr32(priv, 0x610024, 0x00000008);
1842                 intr1 &= ~0x00000008;
1843         }
1844
1845         if (intr1 & 0x00000070) {
1846                 priv->super = (intr1 & 0x00000070);
1847                 schedule_work(&priv->supervisor);
1848                 nv_wr32(priv, 0x610024, priv->super);
1849                 intr1 &= ~0x00000070;
1850         }
1851 }
1852
1853 static int
1854 nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1855                struct nouveau_oclass *oclass, void *data, u32 size,
1856                struct nouveau_object **pobject)
1857 {
1858         struct nv50_disp_priv *priv;
1859         int ret;
1860
1861         ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
1862                                   "display", &priv);
1863         *pobject = nv_object(priv);
1864         if (ret)
1865                 return ret;
1866
1867         nv_engine(priv)->sclass = nv50_disp_base_oclass;
1868         nv_engine(priv)->cclass = &nv50_disp_cclass;
1869         nv_subdev(priv)->intr = nv50_disp_intr;
1870         INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
1871         priv->sclass = nv50_disp_sclass;
1872         priv->head.nr = 2;
1873         priv->dac.nr = 3;
1874         priv->sor.nr = 2;
1875         priv->pior.nr = 3;
1876         priv->dac.power = nv50_dac_power;
1877         priv->dac.sense = nv50_dac_sense;
1878         priv->sor.power = nv50_sor_power;
1879         priv->pior.power = nv50_pior_power;
1880         return 0;
1881 }
1882
1883 struct nouveau_oclass *
1884 nv50_disp_outp_sclass[] = {
1885         &nv50_pior_dp_impl.base.base,
1886         NULL
1887 };
1888
1889 struct nouveau_oclass *
1890 nv50_disp_oclass = &(struct nv50_disp_impl) {
1891         .base.base.handle = NV_ENGINE(DISP, 0x50),
1892         .base.base.ofuncs = &(struct nouveau_ofuncs) {
1893                 .ctor = nv50_disp_ctor,
1894                 .dtor = _nouveau_disp_dtor,
1895                 .init = _nouveau_disp_init,
1896                 .fini = _nouveau_disp_fini,
1897         },
1898         .base.vblank = &nv50_disp_vblank_func,
1899         .base.outp =  nv50_disp_outp_sclass,
1900         .mthd.core = &nv50_disp_mast_mthd_chan,
1901         .mthd.base = &nv50_disp_sync_mthd_chan,
1902         .mthd.ovly = &nv50_disp_ovly_mthd_chan,
1903         .mthd.prev = 0x000004,
1904         .head.scanoutpos = nv50_disp_base_scanoutpos,
1905 }.base.base;