ARM: pmu: add support for interrupt-affinity property
[linux/fpc-iii.git] / drivers / gpu / drm / nouveau / nvkm / engine / disp / nv50.c
blob84ade810e27c331e057a49da0a28fe42f10062b7
1 /*
2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
22 * Authors: Ben Skeggs
24 #include "nv50.h"
25 #include "outp.h"
26 #include "outpdp.h"
28 #include <core/client.h>
29 #include <core/device.h>
30 #include <core/engctx.h>
31 #include <core/enum.h>
32 #include <core/handle.h>
33 #include <core/ramht.h>
34 #include <engine/dmaobj.h>
35 #include <subdev/bios.h>
36 #include <subdev/bios/dcb.h>
37 #include <subdev/bios/disp.h>
38 #include <subdev/bios/init.h>
39 #include <subdev/bios/pll.h>
40 #include <subdev/devinit.h>
41 #include <subdev/fb.h>
42 #include <subdev/timer.h>
44 #include <nvif/class.h>
45 #include <nvif/event.h>
46 #include <nvif/unpack.h>
48 /*******************************************************************************
49 * EVO channel base class
50 ******************************************************************************/
52 static int
53 nv50_disp_chan_create_(struct nvkm_object *parent,
54 struct nvkm_object *engine,
55 struct nvkm_oclass *oclass, int head,
56 int length, void **pobject)
58 const struct nv50_disp_chan_impl *impl = (void *)oclass->ofuncs;
59 struct nv50_disp_base *base = (void *)parent;
60 struct nv50_disp_chan *chan;
61 int chid = impl->chid + head;
62 int ret;
64 if (base->chan & (1 << chid))
65 return -EBUSY;
66 base->chan |= (1 << chid);
68 ret = nvkm_namedb_create_(parent, engine, oclass, 0, NULL,
69 (1ULL << NVDEV_ENGINE_DMAOBJ),
70 length, pobject);
71 chan = *pobject;
72 if (ret)
73 return ret;
74 chan->chid = chid;
76 nv_parent(chan)->object_attach = impl->attach;
77 nv_parent(chan)->object_detach = impl->detach;
78 return 0;
81 static void
82 nv50_disp_chan_destroy(struct nv50_disp_chan *chan)
84 struct nv50_disp_base *base = (void *)nv_object(chan)->parent;
85 base->chan &= ~(1 << chan->chid);
86 nvkm_namedb_destroy(&chan->base);
89 static void
90 nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index)
92 struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent);
93 nv_mask(priv, 0x610028, 0x00000001 << index, 0x00000000 << index);
94 nv_wr32(priv, 0x610020, 0x00000001 << index);
97 static void
98 nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index)
100 struct nv50_disp_priv *priv = container_of(event, typeof(*priv), uevent);
101 nv_wr32(priv, 0x610020, 0x00000001 << index);
102 nv_mask(priv, 0x610028, 0x00000001 << index, 0x00000001 << index);
105 void
106 nv50_disp_chan_uevent_send(struct nv50_disp_priv *priv, int chid)
108 struct nvif_notify_uevent_rep {
109 } rep;
111 nvkm_event_send(&priv->uevent, 1, chid, &rep, sizeof(rep));
115 nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size,
116 struct nvkm_notify *notify)
118 struct nv50_disp_dmac *dmac = (void *)object;
119 union {
120 struct nvif_notify_uevent_req none;
121 } *args = data;
122 int ret;
124 if (nvif_unvers(args->none)) {
125 notify->size = sizeof(struct nvif_notify_uevent_rep);
126 notify->types = 1;
127 notify->index = dmac->base.chid;
128 return 0;
131 return ret;
134 const struct nvkm_event_func
135 nv50_disp_chan_uevent = {
136 .ctor = nv50_disp_chan_uevent_ctor,
137 .init = nv50_disp_chan_uevent_init,
138 .fini = nv50_disp_chan_uevent_fini,
142 nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type,
143 struct nvkm_event **pevent)
145 struct nv50_disp_priv *priv = (void *)object->engine;
146 switch (type) {
147 case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT:
148 *pevent = &priv->uevent;
149 return 0;
150 default:
151 break;
153 return -EINVAL;
157 nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size)
159 struct nv50_disp_chan *chan = (void *)object;
160 *addr = nv_device_resource_start(nv_device(object), 0) +
161 0x640000 + (chan->chid * 0x1000);
162 *size = 0x001000;
163 return 0;
167 nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr)
169 struct nv50_disp_priv *priv = (void *)object->engine;
170 struct nv50_disp_chan *chan = (void *)object;
171 return nv_rd32(priv, 0x640000 + (chan->chid * 0x1000) + addr);
174 void
175 nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data)
177 struct nv50_disp_priv *priv = (void *)object->engine;
178 struct nv50_disp_chan *chan = (void *)object;
179 nv_wr32(priv, 0x640000 + (chan->chid * 0x1000) + addr, data);
182 /*******************************************************************************
183 * EVO DMA channel base class
184 ******************************************************************************/
186 static int
187 nv50_disp_dmac_object_attach(struct nvkm_object *parent,
188 struct nvkm_object *object, u32 name)
190 struct nv50_disp_base *base = (void *)parent->parent;
191 struct nv50_disp_chan *chan = (void *)parent;
192 u32 addr = nv_gpuobj(object)->node->offset;
193 u32 chid = chan->chid;
194 u32 data = (chid << 28) | (addr << 10) | chid;
195 return nvkm_ramht_insert(base->ramht, chid, name, data);
198 static void
199 nv50_disp_dmac_object_detach(struct nvkm_object *parent, int cookie)
201 struct nv50_disp_base *base = (void *)parent->parent;
202 nvkm_ramht_remove(base->ramht, cookie);
205 static int
206 nv50_disp_dmac_create_(struct nvkm_object *parent,
207 struct nvkm_object *engine,
208 struct nvkm_oclass *oclass, u32 pushbuf, int head,
209 int length, void **pobject)
211 struct nv50_disp_dmac *dmac;
212 int ret;
214 ret = nv50_disp_chan_create_(parent, engine, oclass, head,
215 length, pobject);
216 dmac = *pobject;
217 if (ret)
218 return ret;
220 dmac->pushdma = (void *)nvkm_handle_ref(parent, pushbuf);
221 if (!dmac->pushdma)
222 return -ENOENT;
224 switch (nv_mclass(dmac->pushdma)) {
225 case 0x0002:
226 case 0x003d:
227 if (dmac->pushdma->limit - dmac->pushdma->start != 0xfff)
228 return -EINVAL;
230 switch (dmac->pushdma->target) {
231 case NV_MEM_TARGET_VRAM:
232 dmac->push = 0x00000000 | dmac->pushdma->start >> 8;
233 break;
234 case NV_MEM_TARGET_PCI_NOSNOOP:
235 dmac->push = 0x00000003 | dmac->pushdma->start >> 8;
236 break;
237 default:
238 return -EINVAL;
240 break;
241 default:
242 return -EINVAL;
245 return 0;
248 void
249 nv50_disp_dmac_dtor(struct nvkm_object *object)
251 struct nv50_disp_dmac *dmac = (void *)object;
252 nvkm_object_ref(NULL, (struct nvkm_object **)&dmac->pushdma);
253 nv50_disp_chan_destroy(&dmac->base);
256 static int
257 nv50_disp_dmac_init(struct nvkm_object *object)
259 struct nv50_disp_priv *priv = (void *)object->engine;
260 struct nv50_disp_dmac *dmac = (void *)object;
261 int chid = dmac->base.chid;
262 int ret;
264 ret = nv50_disp_chan_init(&dmac->base);
265 if (ret)
266 return ret;
268 /* enable error reporting */
269 nv_mask(priv, 0x610028, 0x00010000 << chid, 0x00010000 << chid);
271 /* initialise channel for dma command submission */
272 nv_wr32(priv, 0x610204 + (chid * 0x0010), dmac->push);
273 nv_wr32(priv, 0x610208 + (chid * 0x0010), 0x00010000);
274 nv_wr32(priv, 0x61020c + (chid * 0x0010), chid);
275 nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010);
276 nv_wr32(priv, 0x640000 + (chid * 0x1000), 0x00000000);
277 nv_wr32(priv, 0x610200 + (chid * 0x0010), 0x00000013);
279 /* wait for it to go inactive */
280 if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x80000000, 0x00000000)) {
281 nv_error(dmac, "init timeout, 0x%08x\n",
282 nv_rd32(priv, 0x610200 + (chid * 0x10)));
283 return -EBUSY;
286 return 0;
289 static int
290 nv50_disp_dmac_fini(struct nvkm_object *object, bool suspend)
292 struct nv50_disp_priv *priv = (void *)object->engine;
293 struct nv50_disp_dmac *dmac = (void *)object;
294 int chid = dmac->base.chid;
296 /* deactivate channel */
297 nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00001010, 0x00001000);
298 nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00000003, 0x00000000);
299 if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x001e0000, 0x00000000)) {
300 nv_error(dmac, "fini timeout, 0x%08x\n",
301 nv_rd32(priv, 0x610200 + (chid * 0x10)));
302 if (suspend)
303 return -EBUSY;
306 /* disable error reporting and completion notifications */
307 nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00000000 << chid);
309 return nv50_disp_chan_fini(&dmac->base, suspend);
312 /*******************************************************************************
313 * EVO master channel object
314 ******************************************************************************/
316 static void
317 nv50_disp_mthd_list(struct nv50_disp_priv *priv, int debug, u32 base, int c,
318 const struct nv50_disp_mthd_list *list, int inst)
320 struct nvkm_object *disp = nv_object(priv);
321 int i;
323 for (i = 0; list->data[i].mthd; i++) {
324 if (list->data[i].addr) {
325 u32 next = nv_rd32(priv, list->data[i].addr + base + 0);
326 u32 prev = nv_rd32(priv, list->data[i].addr + base + c);
327 u32 mthd = list->data[i].mthd + (list->mthd * inst);
328 const char *name = list->data[i].name;
329 char mods[16];
331 if (prev != next)
332 snprintf(mods, sizeof(mods), "-> 0x%08x", next);
333 else
334 snprintf(mods, sizeof(mods), "%13c", ' ');
336 nv_printk_(disp, debug, "\t0x%04x: 0x%08x %s%s%s\n",
337 mthd, prev, mods, name ? " // " : "",
338 name ? name : "");
343 void
344 nv50_disp_mthd_chan(struct nv50_disp_priv *priv, int debug, int head,
345 const struct nv50_disp_mthd_chan *chan)
347 struct nvkm_object *disp = nv_object(priv);
348 const struct nv50_disp_impl *impl = (void *)disp->oclass;
349 const struct nv50_disp_mthd_list *list;
350 int i, j;
352 if (debug > nv_subdev(priv)->debug)
353 return;
355 for (i = 0; (list = chan->data[i].mthd) != NULL; i++) {
356 u32 base = head * chan->addr;
357 for (j = 0; j < chan->data[i].nr; j++, base += list->addr) {
358 const char *cname = chan->name;
359 const char *sname = "";
360 char cname_[16], sname_[16];
362 if (chan->addr) {
363 snprintf(cname_, sizeof(cname_), "%s %d",
364 chan->name, head);
365 cname = cname_;
368 if (chan->data[i].nr > 1) {
369 snprintf(sname_, sizeof(sname_), " - %s %d",
370 chan->data[i].name, j);
371 sname = sname_;
374 nv_printk_(disp, debug, "%s%s:\n", cname, sname);
375 nv50_disp_mthd_list(priv, debug, base, impl->mthd.prev,
376 list, j);
381 const struct nv50_disp_mthd_list
382 nv50_disp_core_mthd_base = {
383 .mthd = 0x0000,
384 .addr = 0x000000,
385 .data = {
386 { 0x0080, 0x000000 },
387 { 0x0084, 0x610bb8 },
388 { 0x0088, 0x610b9c },
389 { 0x008c, 0x000000 },
394 static const struct nv50_disp_mthd_list
395 nv50_disp_core_mthd_dac = {
396 .mthd = 0x0080,
397 .addr = 0x000008,
398 .data = {
399 { 0x0400, 0x610b58 },
400 { 0x0404, 0x610bdc },
401 { 0x0420, 0x610828 },
406 const struct nv50_disp_mthd_list
407 nv50_disp_core_mthd_sor = {
408 .mthd = 0x0040,
409 .addr = 0x000008,
410 .data = {
411 { 0x0600, 0x610b70 },
416 const struct nv50_disp_mthd_list
417 nv50_disp_core_mthd_pior = {
418 .mthd = 0x0040,
419 .addr = 0x000008,
420 .data = {
421 { 0x0700, 0x610b80 },
426 static const struct nv50_disp_mthd_list
427 nv50_disp_core_mthd_head = {
428 .mthd = 0x0400,
429 .addr = 0x000540,
430 .data = {
431 { 0x0800, 0x610ad8 },
432 { 0x0804, 0x610ad0 },
433 { 0x0808, 0x610a48 },
434 { 0x080c, 0x610a78 },
435 { 0x0810, 0x610ac0 },
436 { 0x0814, 0x610af8 },
437 { 0x0818, 0x610b00 },
438 { 0x081c, 0x610ae8 },
439 { 0x0820, 0x610af0 },
440 { 0x0824, 0x610b08 },
441 { 0x0828, 0x610b10 },
442 { 0x082c, 0x610a68 },
443 { 0x0830, 0x610a60 },
444 { 0x0834, 0x000000 },
445 { 0x0838, 0x610a40 },
446 { 0x0840, 0x610a24 },
447 { 0x0844, 0x610a2c },
448 { 0x0848, 0x610aa8 },
449 { 0x084c, 0x610ab0 },
450 { 0x0860, 0x610a84 },
451 { 0x0864, 0x610a90 },
452 { 0x0868, 0x610b18 },
453 { 0x086c, 0x610b20 },
454 { 0x0870, 0x610ac8 },
455 { 0x0874, 0x610a38 },
456 { 0x0880, 0x610a58 },
457 { 0x0884, 0x610a9c },
458 { 0x08a0, 0x610a70 },
459 { 0x08a4, 0x610a50 },
460 { 0x08a8, 0x610ae0 },
461 { 0x08c0, 0x610b28 },
462 { 0x08c4, 0x610b30 },
463 { 0x08c8, 0x610b40 },
464 { 0x08d4, 0x610b38 },
465 { 0x08d8, 0x610b48 },
466 { 0x08dc, 0x610b50 },
467 { 0x0900, 0x610a18 },
468 { 0x0904, 0x610ab8 },
473 static const struct nv50_disp_mthd_chan
474 nv50_disp_core_mthd_chan = {
475 .name = "Core",
476 .addr = 0x000000,
477 .data = {
478 { "Global", 1, &nv50_disp_core_mthd_base },
479 { "DAC", 3, &nv50_disp_core_mthd_dac },
480 { "SOR", 2, &nv50_disp_core_mthd_sor },
481 { "PIOR", 3, &nv50_disp_core_mthd_pior },
482 { "HEAD", 2, &nv50_disp_core_mthd_head },
488 nv50_disp_core_ctor(struct nvkm_object *parent,
489 struct nvkm_object *engine,
490 struct nvkm_oclass *oclass, void *data, u32 size,
491 struct nvkm_object **pobject)
493 union {
494 struct nv50_disp_core_channel_dma_v0 v0;
495 } *args = data;
496 struct nv50_disp_dmac *mast;
497 int ret;
499 nv_ioctl(parent, "create disp core channel dma size %d\n", size);
500 if (nvif_unpack(args->v0, 0, 0, false)) {
501 nv_ioctl(parent, "create disp core channel dma vers %d "
502 "pushbuf %08x\n",
503 args->v0.version, args->v0.pushbuf);
504 } else
505 return ret;
507 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
508 0, sizeof(*mast), (void **)&mast);
509 *pobject = nv_object(mast);
510 if (ret)
511 return ret;
513 return 0;
516 static int
517 nv50_disp_core_init(struct nvkm_object *object)
519 struct nv50_disp_priv *priv = (void *)object->engine;
520 struct nv50_disp_dmac *mast = (void *)object;
521 int ret;
523 ret = nv50_disp_chan_init(&mast->base);
524 if (ret)
525 return ret;
527 /* enable error reporting */
528 nv_mask(priv, 0x610028, 0x00010000, 0x00010000);
530 /* attempt to unstick channel from some unknown state */
531 if ((nv_rd32(priv, 0x610200) & 0x009f0000) == 0x00020000)
532 nv_mask(priv, 0x610200, 0x00800000, 0x00800000);
533 if ((nv_rd32(priv, 0x610200) & 0x003f0000) == 0x00030000)
534 nv_mask(priv, 0x610200, 0x00600000, 0x00600000);
536 /* initialise channel for dma command submission */
537 nv_wr32(priv, 0x610204, mast->push);
538 nv_wr32(priv, 0x610208, 0x00010000);
539 nv_wr32(priv, 0x61020c, 0x00000000);
540 nv_mask(priv, 0x610200, 0x00000010, 0x00000010);
541 nv_wr32(priv, 0x640000, 0x00000000);
542 nv_wr32(priv, 0x610200, 0x01000013);
544 /* wait for it to go inactive */
545 if (!nv_wait(priv, 0x610200, 0x80000000, 0x00000000)) {
546 nv_error(mast, "init: 0x%08x\n", nv_rd32(priv, 0x610200));
547 return -EBUSY;
550 return 0;
553 static int
554 nv50_disp_core_fini(struct nvkm_object *object, bool suspend)
556 struct nv50_disp_priv *priv = (void *)object->engine;
557 struct nv50_disp_dmac *mast = (void *)object;
559 /* deactivate channel */
560 nv_mask(priv, 0x610200, 0x00000010, 0x00000000);
561 nv_mask(priv, 0x610200, 0x00000003, 0x00000000);
562 if (!nv_wait(priv, 0x610200, 0x001e0000, 0x00000000)) {
563 nv_error(mast, "fini: 0x%08x\n", nv_rd32(priv, 0x610200));
564 if (suspend)
565 return -EBUSY;
568 /* disable error reporting and completion notifications */
569 nv_mask(priv, 0x610028, 0x00010001, 0x00000000);
571 return nv50_disp_chan_fini(&mast->base, suspend);
574 struct nv50_disp_chan_impl
575 nv50_disp_core_ofuncs = {
576 .base.ctor = nv50_disp_core_ctor,
577 .base.dtor = nv50_disp_dmac_dtor,
578 .base.init = nv50_disp_core_init,
579 .base.fini = nv50_disp_core_fini,
580 .base.map = nv50_disp_chan_map,
581 .base.ntfy = nv50_disp_chan_ntfy,
582 .base.rd32 = nv50_disp_chan_rd32,
583 .base.wr32 = nv50_disp_chan_wr32,
584 .chid = 0,
585 .attach = nv50_disp_dmac_object_attach,
586 .detach = nv50_disp_dmac_object_detach,
589 /*******************************************************************************
590 * EVO sync channel objects
591 ******************************************************************************/
593 static const struct nv50_disp_mthd_list
594 nv50_disp_base_mthd_base = {
595 .mthd = 0x0000,
596 .addr = 0x000000,
597 .data = {
598 { 0x0080, 0x000000 },
599 { 0x0084, 0x0008c4 },
600 { 0x0088, 0x0008d0 },
601 { 0x008c, 0x0008dc },
602 { 0x0090, 0x0008e4 },
603 { 0x0094, 0x610884 },
604 { 0x00a0, 0x6108a0 },
605 { 0x00a4, 0x610878 },
606 { 0x00c0, 0x61086c },
607 { 0x00e0, 0x610858 },
608 { 0x00e4, 0x610860 },
609 { 0x00e8, 0x6108ac },
610 { 0x00ec, 0x6108b4 },
611 { 0x0100, 0x610894 },
612 { 0x0110, 0x6108bc },
613 { 0x0114, 0x61088c },
618 const struct nv50_disp_mthd_list
619 nv50_disp_base_mthd_image = {
620 .mthd = 0x0400,
621 .addr = 0x000000,
622 .data = {
623 { 0x0800, 0x6108f0 },
624 { 0x0804, 0x6108fc },
625 { 0x0808, 0x61090c },
626 { 0x080c, 0x610914 },
627 { 0x0810, 0x610904 },
632 static const struct nv50_disp_mthd_chan
633 nv50_disp_base_mthd_chan = {
634 .name = "Base",
635 .addr = 0x000540,
636 .data = {
637 { "Global", 1, &nv50_disp_base_mthd_base },
638 { "Image", 2, &nv50_disp_base_mthd_image },
644 nv50_disp_base_ctor(struct nvkm_object *parent,
645 struct nvkm_object *engine,
646 struct nvkm_oclass *oclass, void *data, u32 size,
647 struct nvkm_object **pobject)
649 union {
650 struct nv50_disp_base_channel_dma_v0 v0;
651 } *args = data;
652 struct nv50_disp_priv *priv = (void *)engine;
653 struct nv50_disp_dmac *dmac;
654 int ret;
656 nv_ioctl(parent, "create disp base channel dma size %d\n", size);
657 if (nvif_unpack(args->v0, 0, 0, false)) {
658 nv_ioctl(parent, "create disp base channel dma vers %d "
659 "pushbuf %08x head %d\n",
660 args->v0.version, args->v0.pushbuf, args->v0.head);
661 if (args->v0.head > priv->head.nr)
662 return -EINVAL;
663 } else
664 return ret;
666 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
667 args->v0.head, sizeof(*dmac),
668 (void **)&dmac);
669 *pobject = nv_object(dmac);
670 if (ret)
671 return ret;
673 return 0;
676 struct nv50_disp_chan_impl
677 nv50_disp_base_ofuncs = {
678 .base.ctor = nv50_disp_base_ctor,
679 .base.dtor = nv50_disp_dmac_dtor,
680 .base.init = nv50_disp_dmac_init,
681 .base.fini = nv50_disp_dmac_fini,
682 .base.ntfy = nv50_disp_chan_ntfy,
683 .base.map = nv50_disp_chan_map,
684 .base.rd32 = nv50_disp_chan_rd32,
685 .base.wr32 = nv50_disp_chan_wr32,
686 .chid = 1,
687 .attach = nv50_disp_dmac_object_attach,
688 .detach = nv50_disp_dmac_object_detach,
691 /*******************************************************************************
692 * EVO overlay channel objects
693 ******************************************************************************/
695 const struct nv50_disp_mthd_list
696 nv50_disp_ovly_mthd_base = {
697 .mthd = 0x0000,
698 .addr = 0x000000,
699 .data = {
700 { 0x0080, 0x000000 },
701 { 0x0084, 0x0009a0 },
702 { 0x0088, 0x0009c0 },
703 { 0x008c, 0x0009c8 },
704 { 0x0090, 0x6109b4 },
705 { 0x0094, 0x610970 },
706 { 0x00a0, 0x610998 },
707 { 0x00a4, 0x610964 },
708 { 0x00c0, 0x610958 },
709 { 0x00e0, 0x6109a8 },
710 { 0x00e4, 0x6109d0 },
711 { 0x00e8, 0x6109d8 },
712 { 0x0100, 0x61094c },
713 { 0x0104, 0x610984 },
714 { 0x0108, 0x61098c },
715 { 0x0800, 0x6109f8 },
716 { 0x0808, 0x610a08 },
717 { 0x080c, 0x610a10 },
718 { 0x0810, 0x610a00 },
723 static const struct nv50_disp_mthd_chan
724 nv50_disp_ovly_mthd_chan = {
725 .name = "Overlay",
726 .addr = 0x000540,
727 .data = {
728 { "Global", 1, &nv50_disp_ovly_mthd_base },
734 nv50_disp_ovly_ctor(struct nvkm_object *parent,
735 struct nvkm_object *engine,
736 struct nvkm_oclass *oclass, void *data, u32 size,
737 struct nvkm_object **pobject)
739 union {
740 struct nv50_disp_overlay_channel_dma_v0 v0;
741 } *args = data;
742 struct nv50_disp_priv *priv = (void *)engine;
743 struct nv50_disp_dmac *dmac;
744 int ret;
746 nv_ioctl(parent, "create disp overlay channel dma size %d\n", size);
747 if (nvif_unpack(args->v0, 0, 0, false)) {
748 nv_ioctl(parent, "create disp overlay channel dma vers %d "
749 "pushbuf %08x head %d\n",
750 args->v0.version, args->v0.pushbuf, args->v0.head);
751 if (args->v0.head > priv->head.nr)
752 return -EINVAL;
753 } else
754 return ret;
756 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
757 args->v0.head, sizeof(*dmac),
758 (void **)&dmac);
759 *pobject = nv_object(dmac);
760 if (ret)
761 return ret;
763 return 0;
766 struct nv50_disp_chan_impl
767 nv50_disp_ovly_ofuncs = {
768 .base.ctor = nv50_disp_ovly_ctor,
769 .base.dtor = nv50_disp_dmac_dtor,
770 .base.init = nv50_disp_dmac_init,
771 .base.fini = nv50_disp_dmac_fini,
772 .base.ntfy = nv50_disp_chan_ntfy,
773 .base.map = nv50_disp_chan_map,
774 .base.rd32 = nv50_disp_chan_rd32,
775 .base.wr32 = nv50_disp_chan_wr32,
776 .chid = 3,
777 .attach = nv50_disp_dmac_object_attach,
778 .detach = nv50_disp_dmac_object_detach,
781 /*******************************************************************************
782 * EVO PIO channel base class
783 ******************************************************************************/
785 static int
786 nv50_disp_pioc_create_(struct nvkm_object *parent,
787 struct nvkm_object *engine,
788 struct nvkm_oclass *oclass, int head,
789 int length, void **pobject)
791 return nv50_disp_chan_create_(parent, engine, oclass, head,
792 length, pobject);
795 void
796 nv50_disp_pioc_dtor(struct nvkm_object *object)
798 struct nv50_disp_pioc *pioc = (void *)object;
799 nv50_disp_chan_destroy(&pioc->base);
802 static int
803 nv50_disp_pioc_init(struct nvkm_object *object)
805 struct nv50_disp_priv *priv = (void *)object->engine;
806 struct nv50_disp_pioc *pioc = (void *)object;
807 int chid = pioc->base.chid;
808 int ret;
810 ret = nv50_disp_chan_init(&pioc->base);
811 if (ret)
812 return ret;
814 nv_wr32(priv, 0x610200 + (chid * 0x10), 0x00002000);
815 if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00000000, 0x00000000)) {
816 nv_error(pioc, "timeout0: 0x%08x\n",
817 nv_rd32(priv, 0x610200 + (chid * 0x10)));
818 return -EBUSY;
821 nv_wr32(priv, 0x610200 + (chid * 0x10), 0x00000001);
822 if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00030000, 0x00010000)) {
823 nv_error(pioc, "timeout1: 0x%08x\n",
824 nv_rd32(priv, 0x610200 + (chid * 0x10)));
825 return -EBUSY;
828 return 0;
831 static int
832 nv50_disp_pioc_fini(struct nvkm_object *object, bool suspend)
834 struct nv50_disp_priv *priv = (void *)object->engine;
835 struct nv50_disp_pioc *pioc = (void *)object;
836 int chid = pioc->base.chid;
838 nv_mask(priv, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000);
839 if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00030000, 0x00000000)) {
840 nv_error(pioc, "timeout: 0x%08x\n",
841 nv_rd32(priv, 0x610200 + (chid * 0x10)));
842 if (suspend)
843 return -EBUSY;
846 return nv50_disp_chan_fini(&pioc->base, suspend);
849 /*******************************************************************************
850 * EVO immediate overlay channel objects
851 ******************************************************************************/
854 nv50_disp_oimm_ctor(struct nvkm_object *parent,
855 struct nvkm_object *engine,
856 struct nvkm_oclass *oclass, void *data, u32 size,
857 struct nvkm_object **pobject)
859 union {
860 struct nv50_disp_overlay_v0 v0;
861 } *args = data;
862 struct nv50_disp_priv *priv = (void *)engine;
863 struct nv50_disp_pioc *pioc;
864 int ret;
866 nv_ioctl(parent, "create disp overlay size %d\n", size);
867 if (nvif_unpack(args->v0, 0, 0, false)) {
868 nv_ioctl(parent, "create disp overlay vers %d head %d\n",
869 args->v0.version, args->v0.head);
870 if (args->v0.head > priv->head.nr)
871 return -EINVAL;
872 } else
873 return ret;
875 ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
876 sizeof(*pioc), (void **)&pioc);
877 *pobject = nv_object(pioc);
878 if (ret)
879 return ret;
881 return 0;
884 struct nv50_disp_chan_impl
885 nv50_disp_oimm_ofuncs = {
886 .base.ctor = nv50_disp_oimm_ctor,
887 .base.dtor = nv50_disp_pioc_dtor,
888 .base.init = nv50_disp_pioc_init,
889 .base.fini = nv50_disp_pioc_fini,
890 .base.ntfy = nv50_disp_chan_ntfy,
891 .base.map = nv50_disp_chan_map,
892 .base.rd32 = nv50_disp_chan_rd32,
893 .base.wr32 = nv50_disp_chan_wr32,
894 .chid = 5,
897 /*******************************************************************************
898 * EVO cursor channel objects
899 ******************************************************************************/
902 nv50_disp_curs_ctor(struct nvkm_object *parent,
903 struct nvkm_object *engine,
904 struct nvkm_oclass *oclass, void *data, u32 size,
905 struct nvkm_object **pobject)
907 union {
908 struct nv50_disp_cursor_v0 v0;
909 } *args = data;
910 struct nv50_disp_priv *priv = (void *)engine;
911 struct nv50_disp_pioc *pioc;
912 int ret;
914 nv_ioctl(parent, "create disp cursor size %d\n", size);
915 if (nvif_unpack(args->v0, 0, 0, false)) {
916 nv_ioctl(parent, "create disp cursor vers %d head %d\n",
917 args->v0.version, args->v0.head);
918 if (args->v0.head > priv->head.nr)
919 return -EINVAL;
920 } else
921 return ret;
923 ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
924 sizeof(*pioc), (void **)&pioc);
925 *pobject = nv_object(pioc);
926 if (ret)
927 return ret;
929 return 0;
932 struct nv50_disp_chan_impl
933 nv50_disp_curs_ofuncs = {
934 .base.ctor = nv50_disp_curs_ctor,
935 .base.dtor = nv50_disp_pioc_dtor,
936 .base.init = nv50_disp_pioc_init,
937 .base.fini = nv50_disp_pioc_fini,
938 .base.ntfy = nv50_disp_chan_ntfy,
939 .base.map = nv50_disp_chan_map,
940 .base.rd32 = nv50_disp_chan_rd32,
941 .base.wr32 = nv50_disp_chan_wr32,
942 .chid = 7,
945 /*******************************************************************************
946 * Base display object
947 ******************************************************************************/
950 nv50_disp_main_scanoutpos(NV50_DISP_MTHD_V0)
952 const u32 blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
953 const u32 blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
954 const u32 total = nv_rd32(priv, 0x610afc + (head * 0x540));
955 union {
956 struct nv04_disp_scanoutpos_v0 v0;
957 } *args = data;
958 int ret;
960 nv_ioctl(object, "disp scanoutpos size %d\n", size);
961 if (nvif_unpack(args->v0, 0, 0, false)) {
962 nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
963 args->v0.vblanke = (blanke & 0xffff0000) >> 16;
964 args->v0.hblanke = (blanke & 0x0000ffff);
965 args->v0.vblanks = (blanks & 0xffff0000) >> 16;
966 args->v0.hblanks = (blanks & 0x0000ffff);
967 args->v0.vtotal = ( total & 0xffff0000) >> 16;
968 args->v0.htotal = ( total & 0x0000ffff);
969 args->v0.time[0] = ktime_to_ns(ktime_get());
970 args->v0.vline = /* vline read locks hline */
971 nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
972 args->v0.time[1] = ktime_to_ns(ktime_get());
973 args->v0.hline =
974 nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
975 } else
976 return ret;
978 return 0;
982 nv50_disp_main_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
984 const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
985 union {
986 struct nv50_disp_mthd_v0 v0;
987 struct nv50_disp_mthd_v1 v1;
988 } *args = data;
989 struct nv50_disp_priv *priv = (void *)object->engine;
990 struct nvkm_output *outp = NULL;
991 struct nvkm_output *temp;
992 u16 type, mask = 0;
993 int head, ret;
995 if (mthd != NV50_DISP_MTHD)
996 return -EINVAL;
998 nv_ioctl(object, "disp mthd size %d\n", size);
999 if (nvif_unpack(args->v0, 0, 0, true)) {
1000 nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
1001 args->v0.version, args->v0.method, args->v0.head);
1002 mthd = args->v0.method;
1003 head = args->v0.head;
1004 } else
1005 if (nvif_unpack(args->v1, 1, 1, true)) {
1006 nv_ioctl(object, "disp mthd vers %d mthd %02x "
1007 "type %04x mask %04x\n",
1008 args->v1.version, args->v1.method,
1009 args->v1.hasht, args->v1.hashm);
1010 mthd = args->v1.method;
1011 type = args->v1.hasht;
1012 mask = args->v1.hashm;
1013 head = ffs((mask >> 8) & 0x0f) - 1;
1014 } else
1015 return ret;
1017 if (head < 0 || head >= priv->head.nr)
1018 return -ENXIO;
1020 if (mask) {
1021 list_for_each_entry(temp, &priv->base.outp, head) {
1022 if ((temp->info.hasht == type) &&
1023 (temp->info.hashm & mask) == mask) {
1024 outp = temp;
1025 break;
1028 if (outp == NULL)
1029 return -ENXIO;
1032 switch (mthd) {
1033 case NV50_DISP_SCANOUTPOS:
1034 return impl->head.scanoutpos(object, priv, data, size, head);
1035 default:
1036 break;
1039 switch (mthd * !!outp) {
1040 case NV50_DISP_MTHD_V1_DAC_PWR:
1041 return priv->dac.power(object, priv, data, size, head, outp);
1042 case NV50_DISP_MTHD_V1_DAC_LOAD:
1043 return priv->dac.sense(object, priv, data, size, head, outp);
1044 case NV50_DISP_MTHD_V1_SOR_PWR:
1045 return priv->sor.power(object, priv, data, size, head, outp);
1046 case NV50_DISP_MTHD_V1_SOR_HDA_ELD:
1047 if (!priv->sor.hda_eld)
1048 return -ENODEV;
1049 return priv->sor.hda_eld(object, priv, data, size, head, outp);
1050 case NV50_DISP_MTHD_V1_SOR_HDMI_PWR:
1051 if (!priv->sor.hdmi)
1052 return -ENODEV;
1053 return priv->sor.hdmi(object, priv, data, size, head, outp);
1054 case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: {
1055 union {
1056 struct nv50_disp_sor_lvds_script_v0 v0;
1057 } *args = data;
1058 nv_ioctl(object, "disp sor lvds script size %d\n", size);
1059 if (nvif_unpack(args->v0, 0, 0, false)) {
1060 nv_ioctl(object, "disp sor lvds script "
1061 "vers %d name %04x\n",
1062 args->v0.version, args->v0.script);
1063 priv->sor.lvdsconf = args->v0.script;
1064 return 0;
1065 } else
1066 return ret;
1068 break;
1069 case NV50_DISP_MTHD_V1_SOR_DP_PWR: {
1070 struct nvkm_output_dp *outpdp = (void *)outp;
1071 union {
1072 struct nv50_disp_sor_dp_pwr_v0 v0;
1073 } *args = data;
1074 nv_ioctl(object, "disp sor dp pwr size %d\n", size);
1075 if (nvif_unpack(args->v0, 0, 0, false)) {
1076 nv_ioctl(object, "disp sor dp pwr vers %d state %d\n",
1077 args->v0.version, args->v0.state);
1078 if (args->v0.state == 0) {
1079 nvkm_notify_put(&outpdp->irq);
1080 ((struct nvkm_output_dp_impl *)nv_oclass(outp))
1081 ->lnk_pwr(outpdp, 0);
1082 atomic_set(&outpdp->lt.done, 0);
1083 return 0;
1084 } else
1085 if (args->v0.state != 0) {
1086 nvkm_output_dp_train(&outpdp->base, 0, true);
1087 return 0;
1089 } else
1090 return ret;
1092 break;
1093 case NV50_DISP_MTHD_V1_PIOR_PWR:
1094 if (!priv->pior.power)
1095 return -ENODEV;
1096 return priv->pior.power(object, priv, data, size, head, outp);
1097 default:
1098 break;
1101 return -EINVAL;
1105 nv50_disp_main_ctor(struct nvkm_object *parent,
1106 struct nvkm_object *engine,
1107 struct nvkm_oclass *oclass, void *data, u32 size,
1108 struct nvkm_object **pobject)
1110 struct nv50_disp_priv *priv = (void *)engine;
1111 struct nv50_disp_base *base;
1112 int ret;
1114 ret = nvkm_parent_create(parent, engine, oclass, 0,
1115 priv->sclass, 0, &base);
1116 *pobject = nv_object(base);
1117 if (ret)
1118 return ret;
1120 return nvkm_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
1121 &base->ramht);
1124 void
1125 nv50_disp_main_dtor(struct nvkm_object *object)
1127 struct nv50_disp_base *base = (void *)object;
1128 nvkm_ramht_ref(NULL, &base->ramht);
1129 nvkm_parent_destroy(&base->base);
1132 static int
1133 nv50_disp_main_init(struct nvkm_object *object)
1135 struct nv50_disp_priv *priv = (void *)object->engine;
1136 struct nv50_disp_base *base = (void *)object;
1137 int ret, i;
1138 u32 tmp;
1140 ret = nvkm_parent_init(&base->base);
1141 if (ret)
1142 return ret;
1144 /* The below segments of code copying values from one register to
1145 * another appear to inform EVO of the display capabilities or
1146 * something similar. NFI what the 0x614004 caps are for..
1148 tmp = nv_rd32(priv, 0x614004);
1149 nv_wr32(priv, 0x610184, tmp);
1151 /* ... CRTC caps */
1152 for (i = 0; i < priv->head.nr; i++) {
1153 tmp = nv_rd32(priv, 0x616100 + (i * 0x800));
1154 nv_wr32(priv, 0x610190 + (i * 0x10), tmp);
1155 tmp = nv_rd32(priv, 0x616104 + (i * 0x800));
1156 nv_wr32(priv, 0x610194 + (i * 0x10), tmp);
1157 tmp = nv_rd32(priv, 0x616108 + (i * 0x800));
1158 nv_wr32(priv, 0x610198 + (i * 0x10), tmp);
1159 tmp = nv_rd32(priv, 0x61610c + (i * 0x800));
1160 nv_wr32(priv, 0x61019c + (i * 0x10), tmp);
1163 /* ... DAC caps */
1164 for (i = 0; i < priv->dac.nr; i++) {
1165 tmp = nv_rd32(priv, 0x61a000 + (i * 0x800));
1166 nv_wr32(priv, 0x6101d0 + (i * 0x04), tmp);
1169 /* ... SOR caps */
1170 for (i = 0; i < priv->sor.nr; i++) {
1171 tmp = nv_rd32(priv, 0x61c000 + (i * 0x800));
1172 nv_wr32(priv, 0x6101e0 + (i * 0x04), tmp);
1175 /* ... PIOR caps */
1176 for (i = 0; i < priv->pior.nr; i++) {
1177 tmp = nv_rd32(priv, 0x61e000 + (i * 0x800));
1178 nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp);
1181 /* steal display away from vbios, or something like that */
1182 if (nv_rd32(priv, 0x610024) & 0x00000100) {
1183 nv_wr32(priv, 0x610024, 0x00000100);
1184 nv_mask(priv, 0x6194e8, 0x00000001, 0x00000000);
1185 if (!nv_wait(priv, 0x6194e8, 0x00000002, 0x00000000)) {
1186 nv_error(priv, "timeout acquiring display\n");
1187 return -EBUSY;
1191 /* point at display engine memory area (hash table, objects) */
1192 nv_wr32(priv, 0x610010, (nv_gpuobj(base->ramht)->addr >> 8) | 9);
1194 /* enable supervisor interrupts, disable everything else */
1195 nv_wr32(priv, 0x61002c, 0x00000370);
1196 nv_wr32(priv, 0x610028, 0x00000000);
1197 return 0;
1200 static int
1201 nv50_disp_main_fini(struct nvkm_object *object, bool suspend)
1203 struct nv50_disp_priv *priv = (void *)object->engine;
1204 struct nv50_disp_base *base = (void *)object;
1206 /* disable all interrupts */
1207 nv_wr32(priv, 0x610024, 0x00000000);
1208 nv_wr32(priv, 0x610020, 0x00000000);
1210 return nvkm_parent_fini(&base->base, suspend);
1213 struct nvkm_ofuncs
1214 nv50_disp_main_ofuncs = {
1215 .ctor = nv50_disp_main_ctor,
1216 .dtor = nv50_disp_main_dtor,
1217 .init = nv50_disp_main_init,
1218 .fini = nv50_disp_main_fini,
1219 .mthd = nv50_disp_main_mthd,
1220 .ntfy = nvkm_disp_ntfy,
1223 static struct nvkm_oclass
1224 nv50_disp_main_oclass[] = {
1225 { NV50_DISP, &nv50_disp_main_ofuncs },
1229 static struct nvkm_oclass
1230 nv50_disp_sclass[] = {
1231 { NV50_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base },
1232 { NV50_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base },
1233 { NV50_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
1234 { NV50_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
1235 { NV50_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
1239 /*******************************************************************************
1240 * Display context, tracks instmem allocation and prevents more than one
1241 * client using the display hardware at any time.
1242 ******************************************************************************/
1244 static int
1245 nv50_disp_data_ctor(struct nvkm_object *parent,
1246 struct nvkm_object *engine,
1247 struct nvkm_oclass *oclass, void *data, u32 size,
1248 struct nvkm_object **pobject)
1250 struct nv50_disp_priv *priv = (void *)engine;
1251 struct nvkm_engctx *ectx;
1252 int ret = -EBUSY;
1254 /* no context needed for channel objects... */
1255 if (nv_mclass(parent) != NV_DEVICE) {
1256 atomic_inc(&parent->refcount);
1257 *pobject = parent;
1258 return 1;
1261 /* allocate display hardware to client */
1262 mutex_lock(&nv_subdev(priv)->mutex);
1263 if (list_empty(&nv_engine(priv)->contexts)) {
1264 ret = nvkm_engctx_create(parent, engine, oclass, NULL, 0x10000,
1265 0x10000, NVOBJ_FLAG_HEAP, &ectx);
1266 *pobject = nv_object(ectx);
1268 mutex_unlock(&nv_subdev(priv)->mutex);
1269 return ret;
1272 struct nvkm_oclass
1273 nv50_disp_cclass = {
1274 .handle = NV_ENGCTX(DISP, 0x50),
1275 .ofuncs = &(struct nvkm_ofuncs) {
1276 .ctor = nv50_disp_data_ctor,
1277 .dtor = _nvkm_engctx_dtor,
1278 .init = _nvkm_engctx_init,
1279 .fini = _nvkm_engctx_fini,
1280 .rd32 = _nvkm_engctx_rd32,
1281 .wr32 = _nvkm_engctx_wr32,
1285 /*******************************************************************************
1286 * Display engine implementation
1287 ******************************************************************************/
1289 static void
1290 nv50_disp_vblank_fini(struct nvkm_event *event, int type, int head)
1292 struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank);
1293 nv_mask(disp, 0x61002c, (4 << head), 0);
1296 static void
1297 nv50_disp_vblank_init(struct nvkm_event *event, int type, int head)
1299 struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank);
1300 nv_mask(disp, 0x61002c, (4 << head), (4 << head));
1303 const struct nvkm_event_func
1304 nv50_disp_vblank_func = {
1305 .ctor = nvkm_disp_vblank_ctor,
1306 .init = nv50_disp_vblank_init,
1307 .fini = nv50_disp_vblank_fini,
1310 static const struct nvkm_enum
1311 nv50_disp_intr_error_type[] = {
1312 { 3, "ILLEGAL_MTHD" },
1313 { 4, "INVALID_VALUE" },
1314 { 5, "INVALID_STATE" },
1315 { 7, "INVALID_HANDLE" },
1319 static const struct nvkm_enum
1320 nv50_disp_intr_error_code[] = {
1321 { 0x00, "" },
1325 static void
1326 nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid)
1328 struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
1329 u32 data = nv_rd32(priv, 0x610084 + (chid * 0x08));
1330 u32 addr = nv_rd32(priv, 0x610080 + (chid * 0x08));
1331 u32 code = (addr & 0x00ff0000) >> 16;
1332 u32 type = (addr & 0x00007000) >> 12;
1333 u32 mthd = (addr & 0x00000ffc);
1334 const struct nvkm_enum *ec, *et;
1335 char ecunk[6], etunk[6];
1337 et = nvkm_enum_find(nv50_disp_intr_error_type, type);
1338 if (!et)
1339 snprintf(etunk, sizeof(etunk), "UNK%02X", type);
1341 ec = nvkm_enum_find(nv50_disp_intr_error_code, code);
1342 if (!ec)
1343 snprintf(ecunk, sizeof(ecunk), "UNK%02X", code);
1345 nv_error(priv, "%s [%s] chid %d mthd 0x%04x data 0x%08x\n",
1346 et ? et->name : etunk, ec ? ec->name : ecunk,
1347 chid, mthd, data);
1349 if (chid == 0) {
1350 switch (mthd) {
1351 case 0x0080:
1352 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
1353 impl->mthd.core);
1354 break;
1355 default:
1356 break;
1358 } else
1359 if (chid <= 2) {
1360 switch (mthd) {
1361 case 0x0080:
1362 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
1363 impl->mthd.base);
1364 break;
1365 default:
1366 break;
1368 } else
1369 if (chid <= 4) {
1370 switch (mthd) {
1371 case 0x0080:
1372 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 3,
1373 impl->mthd.ovly);
1374 break;
1375 default:
1376 break;
1380 nv_wr32(priv, 0x610020, 0x00010000 << chid);
1381 nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);
1384 static struct nvkm_output *
1385 exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
1386 u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
1387 struct nvbios_outp *info)
1389 struct nvkm_bios *bios = nvkm_bios(priv);
1390 struct nvkm_output *outp;
1391 u16 mask, type;
1393 if (or < 4) {
1394 type = DCB_OUTPUT_ANALOG;
1395 mask = 0;
1396 } else
1397 if (or < 8) {
1398 switch (ctrl & 0x00000f00) {
1399 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
1400 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
1401 case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break;
1402 case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break;
1403 case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break;
1404 case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
1405 default:
1406 nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
1407 return NULL;
1409 or -= 4;
1410 } else {
1411 or = or - 8;
1412 type = 0x0010;
1413 mask = 0;
1414 switch (ctrl & 0x00000f00) {
1415 case 0x00000000: type |= priv->pior.type[or]; break;
1416 default:
1417 nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl);
1418 return NULL;
1422 mask = 0x00c0 & (mask << 6);
1423 mask |= 0x0001 << or;
1424 mask |= 0x0100 << head;
1426 list_for_each_entry(outp, &priv->base.outp, head) {
1427 if ((outp->info.hasht & 0xff) == type &&
1428 (outp->info.hashm & mask) == mask) {
1429 *data = nvbios_outp_match(bios, outp->info.hasht,
1430 outp->info.hashm,
1431 ver, hdr, cnt, len, info);
1432 if (!*data)
1433 return NULL;
1434 return outp;
1438 return NULL;
1441 static struct nvkm_output *
1442 exec_script(struct nv50_disp_priv *priv, int head, int id)
1444 struct nvkm_bios *bios = nvkm_bios(priv);
1445 struct nvkm_output *outp;
1446 struct nvbios_outp info;
1447 u8 ver, hdr, cnt, len;
1448 u32 data, ctrl = 0;
1449 u32 reg;
1450 int i;
1452 /* DAC */
1453 for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++)
1454 ctrl = nv_rd32(priv, 0x610b5c + (i * 8));
1456 /* SOR */
1457 if (!(ctrl & (1 << head))) {
1458 if (nv_device(priv)->chipset < 0x90 ||
1459 nv_device(priv)->chipset == 0x92 ||
1460 nv_device(priv)->chipset == 0xa0) {
1461 reg = 0x610b74;
1462 } else {
1463 reg = 0x610798;
1465 for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++)
1466 ctrl = nv_rd32(priv, reg + (i * 8));
1467 i += 4;
1470 /* PIOR */
1471 if (!(ctrl & (1 << head))) {
1472 for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++)
1473 ctrl = nv_rd32(priv, 0x610b84 + (i * 8));
1474 i += 8;
1477 if (!(ctrl & (1 << head)))
1478 return NULL;
1479 i--;
1481 outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
1482 if (outp) {
1483 struct nvbios_init init = {
1484 .subdev = nv_subdev(priv),
1485 .bios = bios,
1486 .offset = info.script[id],
1487 .outp = &outp->info,
1488 .crtc = head,
1489 .execute = 1,
1492 nvbios_exec(&init);
1495 return outp;
1498 static struct nvkm_output *
1499 exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf)
1501 struct nvkm_bios *bios = nvkm_bios(priv);
1502 struct nvkm_output *outp;
1503 struct nvbios_outp info1;
1504 struct nvbios_ocfg info2;
1505 u8 ver, hdr, cnt, len;
1506 u32 data, ctrl = 0;
1507 u32 reg;
1508 int i;
1510 /* DAC */
1511 for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++)
1512 ctrl = nv_rd32(priv, 0x610b58 + (i * 8));
1514 /* SOR */
1515 if (!(ctrl & (1 << head))) {
1516 if (nv_device(priv)->chipset < 0x90 ||
1517 nv_device(priv)->chipset == 0x92 ||
1518 nv_device(priv)->chipset == 0xa0) {
1519 reg = 0x610b70;
1520 } else {
1521 reg = 0x610794;
1523 for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++)
1524 ctrl = nv_rd32(priv, reg + (i * 8));
1525 i += 4;
1528 /* PIOR */
1529 if (!(ctrl & (1 << head))) {
1530 for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++)
1531 ctrl = nv_rd32(priv, 0x610b80 + (i * 8));
1532 i += 8;
1535 if (!(ctrl & (1 << head)))
1536 return NULL;
1537 i--;
1539 outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
1540 if (!outp)
1541 return NULL;
1543 if (outp->info.location == 0) {
1544 switch (outp->info.type) {
1545 case DCB_OUTPUT_TMDS:
1546 *conf = (ctrl & 0x00000f00) >> 8;
1547 if (pclk >= 165000)
1548 *conf |= 0x0100;
1549 break;
1550 case DCB_OUTPUT_LVDS:
1551 *conf = priv->sor.lvdsconf;
1552 break;
1553 case DCB_OUTPUT_DP:
1554 *conf = (ctrl & 0x00000f00) >> 8;
1555 break;
1556 case DCB_OUTPUT_ANALOG:
1557 default:
1558 *conf = 0x00ff;
1559 break;
1561 } else {
1562 *conf = (ctrl & 0x00000f00) >> 8;
1563 pclk = pclk / 2;
1566 data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
1567 if (data && id < 0xff) {
1568 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
1569 if (data) {
1570 struct nvbios_init init = {
1571 .subdev = nv_subdev(priv),
1572 .bios = bios,
1573 .offset = data,
1574 .outp = &outp->info,
1575 .crtc = head,
1576 .execute = 1,
1579 nvbios_exec(&init);
1583 return outp;
1586 static void
1587 nv50_disp_intr_unk10_0(struct nv50_disp_priv *priv, int head)
1589 exec_script(priv, head, 1);
1592 static void
1593 nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head)
1595 struct nvkm_output *outp = exec_script(priv, head, 2);
1597 /* the binary driver does this outside of the supervisor handling
1598 * (after the third supervisor from a detach). we (currently?)
1599 * allow both detach/attach to happen in the same set of
1600 * supervisor interrupts, so it would make sense to execute this
1601 * (full power down?) script after all the detach phases of the
1602 * supervisor handling. like with training if needed from the
1603 * second supervisor, nvidia doesn't do this, so who knows if it's
1604 * entirely safe, but it does appear to work..
1606 * without this script being run, on some configurations i've
1607 * seen, switching from DP to TMDS on a DP connector may result
1608 * in a blank screen (SOR_PWR off/on can restore it)
1610 if (outp && outp->info.type == DCB_OUTPUT_DP) {
1611 struct nvkm_output_dp *outpdp = (void *)outp;
1612 struct nvbios_init init = {
1613 .subdev = nv_subdev(priv),
1614 .bios = nvkm_bios(priv),
1615 .outp = &outp->info,
1616 .crtc = head,
1617 .offset = outpdp->info.script[4],
1618 .execute = 1,
1621 nvbios_exec(&init);
1622 atomic_set(&outpdp->lt.done, 0);
1626 static void
1627 nv50_disp_intr_unk20_1(struct nv50_disp_priv *priv, int head)
1629 struct nvkm_devinit *devinit = nvkm_devinit(priv);
1630 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
1631 if (pclk)
1632 devinit->pll_set(devinit, PLL_VPLL0 + head, pclk);
1635 static void
1636 nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv, int head,
1637 struct dcb_output *outp, u32 pclk)
1639 const int link = !(outp->sorconf.link & 1);
1640 const int or = ffs(outp->or) - 1;
1641 const u32 soff = ( or * 0x800);
1642 const u32 loff = (link * 0x080) + soff;
1643 const u32 ctrl = nv_rd32(priv, 0x610794 + (or * 8));
1644 const u32 symbol = 100000;
1645 const s32 vactive = nv_rd32(priv, 0x610af8 + (head * 0x540)) & 0xffff;
1646 const s32 vblanke = nv_rd32(priv, 0x610ae8 + (head * 0x540)) & 0xffff;
1647 const s32 vblanks = nv_rd32(priv, 0x610af0 + (head * 0x540)) & 0xffff;
1648 u32 dpctrl = nv_rd32(priv, 0x61c10c + loff);
1649 u32 clksor = nv_rd32(priv, 0x614300 + soff);
1650 int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0;
1651 int TU, VTUi, VTUf, VTUa;
1652 u64 link_data_rate, link_ratio, unk;
1653 u32 best_diff = 64 * symbol;
1654 u32 link_nr, link_bw, bits;
1655 u64 value;
1657 link_bw = (clksor & 0x000c0000) ? 270000 : 162000;
1658 link_nr = hweight32(dpctrl & 0x000f0000);
1660 /* symbols/hblank - algorithm taken from comments in tegra driver */
1661 value = vblanke + vactive - vblanks - 7;
1662 value = value * link_bw;
1663 do_div(value, pclk);
1664 value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr);
1665 nv_mask(priv, 0x61c1e8 + soff, 0x0000ffff, value);
1667 /* symbols/vblank - algorithm taken from comments in tegra driver */
1668 value = vblanks - vblanke - 25;
1669 value = value * link_bw;
1670 do_div(value, pclk);
1671 value = value - ((36 / link_nr) + 3) - 1;
1672 nv_mask(priv, 0x61c1ec + soff, 0x00ffffff, value);
1674 /* watermark / activesym */
1675 if ((ctrl & 0xf0000) == 0x60000) bits = 30;
1676 else if ((ctrl & 0xf0000) == 0x50000) bits = 24;
1677 else bits = 18;
1679 link_data_rate = (pclk * bits / 8) / link_nr;
1681 /* calculate ratio of packed data rate to link symbol rate */
1682 link_ratio = link_data_rate * symbol;
1683 do_div(link_ratio, link_bw);
1685 for (TU = 64; TU >= 32; TU--) {
1686 /* calculate average number of valid symbols in each TU */
1687 u32 tu_valid = link_ratio * TU;
1688 u32 calc, diff;
1690 /* find a hw representation for the fraction.. */
1691 VTUi = tu_valid / symbol;
1692 calc = VTUi * symbol;
1693 diff = tu_valid - calc;
1694 if (diff) {
1695 if (diff >= (symbol / 2)) {
1696 VTUf = symbol / (symbol - diff);
1697 if (symbol - (VTUf * diff))
1698 VTUf++;
1700 if (VTUf <= 15) {
1701 VTUa = 1;
1702 calc += symbol - (symbol / VTUf);
1703 } else {
1704 VTUa = 0;
1705 VTUf = 1;
1706 calc += symbol;
1708 } else {
1709 VTUa = 0;
1710 VTUf = min((int)(symbol / diff), 15);
1711 calc += symbol / VTUf;
1714 diff = calc - tu_valid;
1715 } else {
1716 /* no remainder, but the hw doesn't like the fractional
1717 * part to be zero. decrement the integer part and
1718 * have the fraction add a whole symbol back
1720 VTUa = 0;
1721 VTUf = 1;
1722 VTUi--;
1725 if (diff < best_diff) {
1726 best_diff = diff;
1727 bestTU = TU;
1728 bestVTUa = VTUa;
1729 bestVTUf = VTUf;
1730 bestVTUi = VTUi;
1731 if (diff == 0)
1732 break;
1736 if (!bestTU) {
1737 nv_error(priv, "unable to find suitable dp config\n");
1738 return;
1741 /* XXX close to vbios numbers, but not right */
1742 unk = (symbol - link_ratio) * bestTU;
1743 unk *= link_ratio;
1744 do_div(unk, symbol);
1745 do_div(unk, symbol);
1746 unk += 6;
1748 nv_mask(priv, 0x61c10c + loff, 0x000001fc, bestTU << 2);
1749 nv_mask(priv, 0x61c128 + loff, 0x010f7f3f, bestVTUa << 24 |
1750 bestVTUf << 16 |
1751 bestVTUi << 8 | unk);
1754 static void
1755 nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
1757 struct nvkm_output *outp;
1758 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
1759 u32 hval, hreg = 0x614200 + (head * 0x800);
1760 u32 oval, oreg;
1761 u32 mask, conf;
1763 outp = exec_clkcmp(priv, head, 0xff, pclk, &conf);
1764 if (!outp)
1765 return;
1767 /* we allow both encoder attach and detach operations to occur
1768 * within a single supervisor (ie. modeset) sequence. the
1769 * encoder detach scripts quite often switch off power to the
1770 * lanes, which requires the link to be re-trained.
1772 * this is not generally an issue as the sink "must" (heh)
1773 * signal an irq when it's lost sync so the driver can
1774 * re-train.
1776 * however, on some boards, if one does not configure at least
1777 * the gpu side of the link *before* attaching, then various
1778 * things can go horribly wrong (PDISP disappearing from mmio,
1779 * third supervisor never happens, etc).
1781 * the solution is simply to retrain here, if necessary. last
1782 * i checked, the binary driver userspace does not appear to
1783 * trigger this situation (it forces an UPDATE between steps).
1785 if (outp->info.type == DCB_OUTPUT_DP) {
1786 u32 soff = (ffs(outp->info.or) - 1) * 0x08;
1787 u32 ctrl, datarate;
1789 if (outp->info.location == 0) {
1790 ctrl = nv_rd32(priv, 0x610794 + soff);
1791 soff = 1;
1792 } else {
1793 ctrl = nv_rd32(priv, 0x610b80 + soff);
1794 soff = 2;
1797 switch ((ctrl & 0x000f0000) >> 16) {
1798 case 6: datarate = pclk * 30; break;
1799 case 5: datarate = pclk * 24; break;
1800 case 2:
1801 default:
1802 datarate = pclk * 18;
1803 break;
1806 if (nvkm_output_dp_train(outp, datarate / soff, true))
1807 ERR("link not trained before attach\n");
1810 exec_clkcmp(priv, head, 0, pclk, &conf);
1812 if (!outp->info.location && outp->info.type == DCB_OUTPUT_ANALOG) {
1813 oreg = 0x614280 + (ffs(outp->info.or) - 1) * 0x800;
1814 oval = 0x00000000;
1815 hval = 0x00000000;
1816 mask = 0xffffffff;
1817 } else
1818 if (!outp->info.location) {
1819 if (outp->info.type == DCB_OUTPUT_DP)
1820 nv50_disp_intr_unk20_2_dp(priv, head, &outp->info, pclk);
1821 oreg = 0x614300 + (ffs(outp->info.or) - 1) * 0x800;
1822 oval = (conf & 0x0100) ? 0x00000101 : 0x00000000;
1823 hval = 0x00000000;
1824 mask = 0x00000707;
1825 } else {
1826 oreg = 0x614380 + (ffs(outp->info.or) - 1) * 0x800;
1827 oval = 0x00000001;
1828 hval = 0x00000001;
1829 mask = 0x00000707;
1832 nv_mask(priv, hreg, 0x0000000f, hval);
1833 nv_mask(priv, oreg, mask, oval);
1836 /* If programming a TMDS output on a SOR that can also be configured for
1837 * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off.
1839 * It looks like the VBIOS TMDS scripts make an attempt at this, however,
1840 * the VBIOS scripts on at least one board I have only switch it off on
1841 * link 0, causing a blank display if the output has previously been
1842 * programmed for DisplayPort.
1844 static void
1845 nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv,
1846 struct dcb_output *outp)
1848 struct nvkm_bios *bios = nvkm_bios(priv);
1849 const int link = !(outp->sorconf.link & 1);
1850 const int or = ffs(outp->or) - 1;
1851 const u32 loff = (or * 0x800) + (link * 0x80);
1852 const u16 mask = (outp->sorconf.link << 6) | outp->or;
1853 struct dcb_output match;
1854 u8 ver, hdr;
1856 if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, &match))
1857 nv_mask(priv, 0x61c10c + loff, 0x00000001, 0x00000000);
1860 static void
1861 nv50_disp_intr_unk40_0(struct nv50_disp_priv *priv, int head)
1863 struct nvkm_output *outp;
1864 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
1865 u32 conf;
1867 outp = exec_clkcmp(priv, head, 1, pclk, &conf);
1868 if (!outp)
1869 return;
1871 if (outp->info.location == 0 && outp->info.type == DCB_OUTPUT_TMDS)
1872 nv50_disp_intr_unk40_0_tmds(priv, &outp->info);
1875 void
1876 nv50_disp_intr_supervisor(struct work_struct *work)
1878 struct nv50_disp_priv *priv =
1879 container_of(work, struct nv50_disp_priv, supervisor);
1880 struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
1881 u32 super = nv_rd32(priv, 0x610030);
1882 int head;
1884 nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super);
1886 if (priv->super & 0x00000010) {
1887 nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);
1888 for (head = 0; head < priv->head.nr; head++) {
1889 if (!(super & (0x00000020 << head)))
1890 continue;
1891 if (!(super & (0x00000080 << head)))
1892 continue;
1893 nv50_disp_intr_unk10_0(priv, head);
1895 } else
1896 if (priv->super & 0x00000020) {
1897 for (head = 0; head < priv->head.nr; head++) {
1898 if (!(super & (0x00000080 << head)))
1899 continue;
1900 nv50_disp_intr_unk20_0(priv, head);
1902 for (head = 0; head < priv->head.nr; head++) {
1903 if (!(super & (0x00000200 << head)))
1904 continue;
1905 nv50_disp_intr_unk20_1(priv, head);
1907 for (head = 0; head < priv->head.nr; head++) {
1908 if (!(super & (0x00000080 << head)))
1909 continue;
1910 nv50_disp_intr_unk20_2(priv, head);
1912 } else
1913 if (priv->super & 0x00000040) {
1914 for (head = 0; head < priv->head.nr; head++) {
1915 if (!(super & (0x00000080 << head)))
1916 continue;
1917 nv50_disp_intr_unk40_0(priv, head);
1921 nv_wr32(priv, 0x610030, 0x80000000);
1924 void
1925 nv50_disp_intr(struct nvkm_subdev *subdev)
1927 struct nv50_disp_priv *priv = (void *)subdev;
1928 u32 intr0 = nv_rd32(priv, 0x610020);
1929 u32 intr1 = nv_rd32(priv, 0x610024);
1931 while (intr0 & 0x001f0000) {
1932 u32 chid = __ffs(intr0 & 0x001f0000) - 16;
1933 nv50_disp_intr_error(priv, chid);
1934 intr0 &= ~(0x00010000 << chid);
1937 while (intr0 & 0x0000001f) {
1938 u32 chid = __ffs(intr0 & 0x0000001f);
1939 nv50_disp_chan_uevent_send(priv, chid);
1940 intr0 &= ~(0x00000001 << chid);
1943 if (intr1 & 0x00000004) {
1944 nvkm_disp_vblank(&priv->base, 0);
1945 nv_wr32(priv, 0x610024, 0x00000004);
1946 intr1 &= ~0x00000004;
1949 if (intr1 & 0x00000008) {
1950 nvkm_disp_vblank(&priv->base, 1);
1951 nv_wr32(priv, 0x610024, 0x00000008);
1952 intr1 &= ~0x00000008;
1955 if (intr1 & 0x00000070) {
1956 priv->super = (intr1 & 0x00000070);
1957 schedule_work(&priv->supervisor);
1958 nv_wr32(priv, 0x610024, priv->super);
1959 intr1 &= ~0x00000070;
1963 static int
1964 nv50_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
1965 struct nvkm_oclass *oclass, void *data, u32 size,
1966 struct nvkm_object **pobject)
1968 struct nv50_disp_priv *priv;
1969 int ret;
1971 ret = nvkm_disp_create(parent, engine, oclass, 2, "PDISP",
1972 "display", &priv);
1973 *pobject = nv_object(priv);
1974 if (ret)
1975 return ret;
1977 ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &priv->uevent);
1978 if (ret)
1979 return ret;
1981 nv_engine(priv)->sclass = nv50_disp_main_oclass;
1982 nv_engine(priv)->cclass = &nv50_disp_cclass;
1983 nv_subdev(priv)->intr = nv50_disp_intr;
1984 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
1985 priv->sclass = nv50_disp_sclass;
1986 priv->head.nr = 2;
1987 priv->dac.nr = 3;
1988 priv->sor.nr = 2;
1989 priv->pior.nr = 3;
1990 priv->dac.power = nv50_dac_power;
1991 priv->dac.sense = nv50_dac_sense;
1992 priv->sor.power = nv50_sor_power;
1993 priv->pior.power = nv50_pior_power;
1994 return 0;
1997 struct nvkm_oclass *
1998 nv50_disp_outp_sclass[] = {
1999 &nv50_pior_dp_impl.base.base,
2000 NULL
2003 struct nvkm_oclass *
2004 nv50_disp_oclass = &(struct nv50_disp_impl) {
2005 .base.base.handle = NV_ENGINE(DISP, 0x50),
2006 .base.base.ofuncs = &(struct nvkm_ofuncs) {
2007 .ctor = nv50_disp_ctor,
2008 .dtor = _nvkm_disp_dtor,
2009 .init = _nvkm_disp_init,
2010 .fini = _nvkm_disp_fini,
2012 .base.vblank = &nv50_disp_vblank_func,
2013 .base.outp = nv50_disp_outp_sclass,
2014 .mthd.core = &nv50_disp_core_mthd_chan,
2015 .mthd.base = &nv50_disp_base_mthd_chan,
2016 .mthd.ovly = &nv50_disp_ovly_mthd_chan,
2017 .mthd.prev = 0x000004,
2018 .head.scanoutpos = nv50_disp_main_scanoutpos,
2019 }.base.base;