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