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