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