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.
25 #include <core/object.h>
26 #include <core/parent.h>
27 #include <core/handle.h>
28 #include <core/class.h>
29 #include <core/enum.h>
31 #include <subdev/bios.h>
32 #include <subdev/bios/dcb.h>
33 #include <subdev/bios/disp.h>
34 #include <subdev/bios/init.h>
35 #include <subdev/bios/pll.h>
36 #include <subdev/devinit.h>
37 #include <subdev/timer.h>
38 #include <subdev/fb.h>
42 /*******************************************************************************
43 * EVO channel base class
44 ******************************************************************************/
47 nv50_disp_chan_create_(struct nouveau_object
*parent
,
48 struct nouveau_object
*engine
,
49 struct nouveau_oclass
*oclass
, int chid
,
50 int length
, void **pobject
)
52 struct nv50_disp_base
*base
= (void *)parent
;
53 struct nv50_disp_chan
*chan
;
56 if (base
->chan
& (1 << chid
))
58 base
->chan
|= (1 << chid
);
60 ret
= nouveau_namedb_create_(parent
, engine
, oclass
, 0, NULL
,
61 (1ULL << NVDEV_ENGINE_DMAOBJ
),
72 nv50_disp_chan_destroy(struct nv50_disp_chan
*chan
)
74 struct nv50_disp_base
*base
= (void *)nv_object(chan
)->parent
;
75 base
->chan
&= ~(1 << chan
->chid
);
76 nouveau_namedb_destroy(&chan
->base
);
80 nv50_disp_chan_rd32(struct nouveau_object
*object
, u64 addr
)
82 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
83 struct nv50_disp_chan
*chan
= (void *)object
;
84 return nv_rd32(priv
, 0x640000 + (chan
->chid
* 0x1000) + addr
);
88 nv50_disp_chan_wr32(struct nouveau_object
*object
, u64 addr
, u32 data
)
90 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
91 struct nv50_disp_chan
*chan
= (void *)object
;
92 nv_wr32(priv
, 0x640000 + (chan
->chid
* 0x1000) + addr
, data
);
95 /*******************************************************************************
96 * EVO DMA channel base class
97 ******************************************************************************/
100 nv50_disp_dmac_object_attach(struct nouveau_object
*parent
,
101 struct nouveau_object
*object
, u32 name
)
103 struct nv50_disp_base
*base
= (void *)parent
->parent
;
104 struct nv50_disp_chan
*chan
= (void *)parent
;
105 u32 addr
= nv_gpuobj(object
)->node
->offset
;
106 u32 chid
= chan
->chid
;
107 u32 data
= (chid
<< 28) | (addr
<< 10) | chid
;
108 return nouveau_ramht_insert(base
->ramht
, chid
, name
, data
);
112 nv50_disp_dmac_object_detach(struct nouveau_object
*parent
, int cookie
)
114 struct nv50_disp_base
*base
= (void *)parent
->parent
;
115 nouveau_ramht_remove(base
->ramht
, cookie
);
119 nv50_disp_dmac_create_(struct nouveau_object
*parent
,
120 struct nouveau_object
*engine
,
121 struct nouveau_oclass
*oclass
, u32 pushbuf
, int chid
,
122 int length
, void **pobject
)
124 struct nv50_disp_dmac
*dmac
;
127 ret
= nv50_disp_chan_create_(parent
, engine
, oclass
, chid
,
133 dmac
->pushdma
= (void *)nouveau_handle_ref(parent
, pushbuf
);
137 switch (nv_mclass(dmac
->pushdma
)) {
140 if (dmac
->pushdma
->limit
- dmac
->pushdma
->start
!= 0xfff)
143 switch (dmac
->pushdma
->target
) {
144 case NV_MEM_TARGET_VRAM
:
145 dmac
->push
= 0x00000000 | dmac
->pushdma
->start
>> 8;
147 case NV_MEM_TARGET_PCI_NOSNOOP
:
148 dmac
->push
= 0x00000003 | dmac
->pushdma
->start
>> 8;
162 nv50_disp_dmac_dtor(struct nouveau_object
*object
)
164 struct nv50_disp_dmac
*dmac
= (void *)object
;
165 nouveau_object_ref(NULL
, (struct nouveau_object
**)&dmac
->pushdma
);
166 nv50_disp_chan_destroy(&dmac
->base
);
170 nv50_disp_dmac_init(struct nouveau_object
*object
)
172 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
173 struct nv50_disp_dmac
*dmac
= (void *)object
;
174 int chid
= dmac
->base
.chid
;
177 ret
= nv50_disp_chan_init(&dmac
->base
);
181 /* enable error reporting */
182 nv_mask(priv
, 0x610028, 0x00010001 << chid
, 0x00010001 << chid
);
184 /* initialise channel for dma command submission */
185 nv_wr32(priv
, 0x610204 + (chid
* 0x0010), dmac
->push
);
186 nv_wr32(priv
, 0x610208 + (chid
* 0x0010), 0x00010000);
187 nv_wr32(priv
, 0x61020c + (chid
* 0x0010), chid
);
188 nv_mask(priv
, 0x610200 + (chid
* 0x0010), 0x00000010, 0x00000010);
189 nv_wr32(priv
, 0x640000 + (chid
* 0x1000), 0x00000000);
190 nv_wr32(priv
, 0x610200 + (chid
* 0x0010), 0x00000013);
192 /* wait for it to go inactive */
193 if (!nv_wait(priv
, 0x610200 + (chid
* 0x10), 0x80000000, 0x00000000)) {
194 nv_error(dmac
, "init timeout, 0x%08x\n",
195 nv_rd32(priv
, 0x610200 + (chid
* 0x10)));
203 nv50_disp_dmac_fini(struct nouveau_object
*object
, bool suspend
)
205 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
206 struct nv50_disp_dmac
*dmac
= (void *)object
;
207 int chid
= dmac
->base
.chid
;
209 /* deactivate channel */
210 nv_mask(priv
, 0x610200 + (chid
* 0x0010), 0x00001010, 0x00001000);
211 nv_mask(priv
, 0x610200 + (chid
* 0x0010), 0x00000003, 0x00000000);
212 if (!nv_wait(priv
, 0x610200 + (chid
* 0x10), 0x001e0000, 0x00000000)) {
213 nv_error(dmac
, "fini timeout, 0x%08x\n",
214 nv_rd32(priv
, 0x610200 + (chid
* 0x10)));
219 /* disable error reporting */
220 nv_mask(priv
, 0x610028, 0x00010001 << chid
, 0x00000000 << chid
);
222 return nv50_disp_chan_fini(&dmac
->base
, suspend
);
225 /*******************************************************************************
226 * EVO master channel object
227 ******************************************************************************/
230 nv50_disp_mthd_list(struct nv50_disp_priv
*priv
, int debug
, u32 base
, int c
,
231 const struct nv50_disp_mthd_list
*list
, int inst
)
233 struct nouveau_object
*disp
= nv_object(priv
);
236 for (i
= 0; list
->data
[i
].mthd
; i
++) {
237 if (list
->data
[i
].addr
) {
238 u32 next
= nv_rd32(priv
, list
->data
[i
].addr
+ base
+ 0);
239 u32 prev
= nv_rd32(priv
, list
->data
[i
].addr
+ base
+ c
);
240 u32 mthd
= list
->data
[i
].mthd
+ (list
->mthd
* inst
);
241 const char *name
= list
->data
[i
].name
;
245 snprintf(mods
, sizeof(mods
), "-> 0x%08x", next
);
247 snprintf(mods
, sizeof(mods
), "%13c", ' ');
249 nv_printk_(disp
, debug
, "\t0x%04x: 0x%08x %s%s%s\n",
250 mthd
, prev
, mods
, name
? " // " : "",
257 nv50_disp_mthd_chan(struct nv50_disp_priv
*priv
, int debug
, int head
,
258 const struct nv50_disp_mthd_chan
*chan
)
260 struct nouveau_object
*disp
= nv_object(priv
);
261 const struct nv50_disp_impl
*impl
= (void *)disp
->oclass
;
262 const struct nv50_disp_mthd_list
*list
;
265 if (debug
> nv_subdev(priv
)->debug
)
268 for (i
= 0; (list
= chan
->data
[i
].mthd
) != NULL
; i
++) {
269 u32 base
= head
* chan
->addr
;
270 for (j
= 0; j
< chan
->data
[i
].nr
; j
++, base
+= list
->addr
) {
271 const char *cname
= chan
->name
;
272 const char *sname
= "";
273 char cname_
[16], sname_
[16];
276 snprintf(cname_
, sizeof(cname_
), "%s %d",
281 if (chan
->data
[i
].nr
> 1) {
282 snprintf(sname_
, sizeof(sname_
), " - %s %d",
283 chan
->data
[i
].name
, j
);
287 nv_printk_(disp
, debug
, "%s%s:\n", cname
, sname
);
288 nv50_disp_mthd_list(priv
, debug
, base
, impl
->mthd
.prev
,
294 const struct nv50_disp_mthd_list
295 nv50_disp_mast_mthd_base
= {
299 { 0x0080, 0x000000 },
300 { 0x0084, 0x610bb8 },
301 { 0x0088, 0x610b9c },
302 { 0x008c, 0x000000 },
307 static const struct nv50_disp_mthd_list
308 nv50_disp_mast_mthd_dac
= {
312 { 0x0400, 0x610b58 },
313 { 0x0404, 0x610bdc },
314 { 0x0420, 0x610828 },
319 const struct nv50_disp_mthd_list
320 nv50_disp_mast_mthd_sor
= {
324 { 0x0600, 0x610b70 },
329 const struct nv50_disp_mthd_list
330 nv50_disp_mast_mthd_pior
= {
334 { 0x0700, 0x610b80 },
339 static const struct nv50_disp_mthd_list
340 nv50_disp_mast_mthd_head
= {
344 { 0x0800, 0x610ad8 },
345 { 0x0804, 0x610ad0 },
346 { 0x0808, 0x610a48 },
347 { 0x080c, 0x610a78 },
348 { 0x0810, 0x610ac0 },
349 { 0x0814, 0x610af8 },
350 { 0x0818, 0x610b00 },
351 { 0x081c, 0x610ae8 },
352 { 0x0820, 0x610af0 },
353 { 0x0824, 0x610b08 },
354 { 0x0828, 0x610b10 },
355 { 0x082c, 0x610a68 },
356 { 0x0830, 0x610a60 },
357 { 0x0834, 0x000000 },
358 { 0x0838, 0x610a40 },
359 { 0x0840, 0x610a24 },
360 { 0x0844, 0x610a2c },
361 { 0x0848, 0x610aa8 },
362 { 0x084c, 0x610ab0 },
363 { 0x0860, 0x610a84 },
364 { 0x0864, 0x610a90 },
365 { 0x0868, 0x610b18 },
366 { 0x086c, 0x610b20 },
367 { 0x0870, 0x610ac8 },
368 { 0x0874, 0x610a38 },
369 { 0x0880, 0x610a58 },
370 { 0x0884, 0x610a9c },
371 { 0x08a0, 0x610a70 },
372 { 0x08a4, 0x610a50 },
373 { 0x08a8, 0x610ae0 },
374 { 0x08c0, 0x610b28 },
375 { 0x08c4, 0x610b30 },
376 { 0x08c8, 0x610b40 },
377 { 0x08d4, 0x610b38 },
378 { 0x08d8, 0x610b48 },
379 { 0x08dc, 0x610b50 },
380 { 0x0900, 0x610a18 },
381 { 0x0904, 0x610ab8 },
386 static const struct nv50_disp_mthd_chan
387 nv50_disp_mast_mthd_chan
= {
391 { "Global", 1, &nv50_disp_mast_mthd_base
},
392 { "DAC", 3, &nv50_disp_mast_mthd_dac
},
393 { "SOR", 2, &nv50_disp_mast_mthd_sor
},
394 { "PIOR", 3, &nv50_disp_mast_mthd_pior
},
395 { "HEAD", 2, &nv50_disp_mast_mthd_head
},
401 nv50_disp_mast_ctor(struct nouveau_object
*parent
,
402 struct nouveau_object
*engine
,
403 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
404 struct nouveau_object
**pobject
)
406 struct nv50_display_mast_class
*args
= data
;
407 struct nv50_disp_dmac
*mast
;
410 if (size
< sizeof(*args
))
413 ret
= nv50_disp_dmac_create_(parent
, engine
, oclass
, args
->pushbuf
,
414 0, sizeof(*mast
), (void **)&mast
);
415 *pobject
= nv_object(mast
);
419 nv_parent(mast
)->object_attach
= nv50_disp_dmac_object_attach
;
420 nv_parent(mast
)->object_detach
= nv50_disp_dmac_object_detach
;
425 nv50_disp_mast_init(struct nouveau_object
*object
)
427 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
428 struct nv50_disp_dmac
*mast
= (void *)object
;
431 ret
= nv50_disp_chan_init(&mast
->base
);
435 /* enable error reporting */
436 nv_mask(priv
, 0x610028, 0x00010001, 0x00010001);
438 /* attempt to unstick channel from some unknown state */
439 if ((nv_rd32(priv
, 0x610200) & 0x009f0000) == 0x00020000)
440 nv_mask(priv
, 0x610200, 0x00800000, 0x00800000);
441 if ((nv_rd32(priv
, 0x610200) & 0x003f0000) == 0x00030000)
442 nv_mask(priv
, 0x610200, 0x00600000, 0x00600000);
444 /* initialise channel for dma command submission */
445 nv_wr32(priv
, 0x610204, mast
->push
);
446 nv_wr32(priv
, 0x610208, 0x00010000);
447 nv_wr32(priv
, 0x61020c, 0x00000000);
448 nv_mask(priv
, 0x610200, 0x00000010, 0x00000010);
449 nv_wr32(priv
, 0x640000, 0x00000000);
450 nv_wr32(priv
, 0x610200, 0x01000013);
452 /* wait for it to go inactive */
453 if (!nv_wait(priv
, 0x610200, 0x80000000, 0x00000000)) {
454 nv_error(mast
, "init: 0x%08x\n", nv_rd32(priv
, 0x610200));
462 nv50_disp_mast_fini(struct nouveau_object
*object
, bool suspend
)
464 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
465 struct nv50_disp_dmac
*mast
= (void *)object
;
467 /* deactivate channel */
468 nv_mask(priv
, 0x610200, 0x00000010, 0x00000000);
469 nv_mask(priv
, 0x610200, 0x00000003, 0x00000000);
470 if (!nv_wait(priv
, 0x610200, 0x001e0000, 0x00000000)) {
471 nv_error(mast
, "fini: 0x%08x\n", nv_rd32(priv
, 0x610200));
476 /* disable error reporting */
477 nv_mask(priv
, 0x610028, 0x00010001, 0x00000000);
479 return nv50_disp_chan_fini(&mast
->base
, suspend
);
482 struct nouveau_ofuncs
483 nv50_disp_mast_ofuncs
= {
484 .ctor
= nv50_disp_mast_ctor
,
485 .dtor
= nv50_disp_dmac_dtor
,
486 .init
= nv50_disp_mast_init
,
487 .fini
= nv50_disp_mast_fini
,
488 .rd32
= nv50_disp_chan_rd32
,
489 .wr32
= nv50_disp_chan_wr32
,
492 /*******************************************************************************
493 * EVO sync channel objects
494 ******************************************************************************/
496 static const struct nv50_disp_mthd_list
497 nv50_disp_sync_mthd_base
= {
501 { 0x0080, 0x000000 },
502 { 0x0084, 0x0008c4 },
503 { 0x0088, 0x0008d0 },
504 { 0x008c, 0x0008dc },
505 { 0x0090, 0x0008e4 },
506 { 0x0094, 0x610884 },
507 { 0x00a0, 0x6108a0 },
508 { 0x00a4, 0x610878 },
509 { 0x00c0, 0x61086c },
510 { 0x00e0, 0x610858 },
511 { 0x00e4, 0x610860 },
512 { 0x00e8, 0x6108ac },
513 { 0x00ec, 0x6108b4 },
514 { 0x0100, 0x610894 },
515 { 0x0110, 0x6108bc },
516 { 0x0114, 0x61088c },
521 const struct nv50_disp_mthd_list
522 nv50_disp_sync_mthd_image
= {
526 { 0x0800, 0x6108f0 },
527 { 0x0804, 0x6108fc },
528 { 0x0808, 0x61090c },
529 { 0x080c, 0x610914 },
530 { 0x0810, 0x610904 },
535 static const struct nv50_disp_mthd_chan
536 nv50_disp_sync_mthd_chan
= {
540 { "Global", 1, &nv50_disp_sync_mthd_base
},
541 { "Image", 2, &nv50_disp_sync_mthd_image
},
547 nv50_disp_sync_ctor(struct nouveau_object
*parent
,
548 struct nouveau_object
*engine
,
549 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
550 struct nouveau_object
**pobject
)
552 struct nv50_display_sync_class
*args
= data
;
553 struct nv50_disp_dmac
*dmac
;
556 if (size
< sizeof(*args
) || args
->head
> 1)
559 ret
= nv50_disp_dmac_create_(parent
, engine
, oclass
, args
->pushbuf
,
560 1 + args
->head
, sizeof(*dmac
),
562 *pobject
= nv_object(dmac
);
566 nv_parent(dmac
)->object_attach
= nv50_disp_dmac_object_attach
;
567 nv_parent(dmac
)->object_detach
= nv50_disp_dmac_object_detach
;
571 struct nouveau_ofuncs
572 nv50_disp_sync_ofuncs
= {
573 .ctor
= nv50_disp_sync_ctor
,
574 .dtor
= nv50_disp_dmac_dtor
,
575 .init
= nv50_disp_dmac_init
,
576 .fini
= nv50_disp_dmac_fini
,
577 .rd32
= nv50_disp_chan_rd32
,
578 .wr32
= nv50_disp_chan_wr32
,
581 /*******************************************************************************
582 * EVO overlay channel objects
583 ******************************************************************************/
585 const struct nv50_disp_mthd_list
586 nv50_disp_ovly_mthd_base
= {
590 { 0x0080, 0x000000 },
591 { 0x0084, 0x0009a0 },
592 { 0x0088, 0x0009c0 },
593 { 0x008c, 0x0009c8 },
594 { 0x0090, 0x6109b4 },
595 { 0x0094, 0x610970 },
596 { 0x00a0, 0x610998 },
597 { 0x00a4, 0x610964 },
598 { 0x00c0, 0x610958 },
599 { 0x00e0, 0x6109a8 },
600 { 0x00e4, 0x6109d0 },
601 { 0x00e8, 0x6109d8 },
602 { 0x0100, 0x61094c },
603 { 0x0104, 0x610984 },
604 { 0x0108, 0x61098c },
605 { 0x0800, 0x6109f8 },
606 { 0x0808, 0x610a08 },
607 { 0x080c, 0x610a10 },
608 { 0x0810, 0x610a00 },
613 static const struct nv50_disp_mthd_chan
614 nv50_disp_ovly_mthd_chan
= {
618 { "Global", 1, &nv50_disp_ovly_mthd_base
},
624 nv50_disp_ovly_ctor(struct nouveau_object
*parent
,
625 struct nouveau_object
*engine
,
626 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
627 struct nouveau_object
**pobject
)
629 struct nv50_display_ovly_class
*args
= data
;
630 struct nv50_disp_dmac
*dmac
;
633 if (size
< sizeof(*args
) || args
->head
> 1)
636 ret
= nv50_disp_dmac_create_(parent
, engine
, oclass
, args
->pushbuf
,
637 3 + args
->head
, sizeof(*dmac
),
639 *pobject
= nv_object(dmac
);
643 nv_parent(dmac
)->object_attach
= nv50_disp_dmac_object_attach
;
644 nv_parent(dmac
)->object_detach
= nv50_disp_dmac_object_detach
;
648 struct nouveau_ofuncs
649 nv50_disp_ovly_ofuncs
= {
650 .ctor
= nv50_disp_ovly_ctor
,
651 .dtor
= nv50_disp_dmac_dtor
,
652 .init
= nv50_disp_dmac_init
,
653 .fini
= nv50_disp_dmac_fini
,
654 .rd32
= nv50_disp_chan_rd32
,
655 .wr32
= nv50_disp_chan_wr32
,
658 /*******************************************************************************
659 * EVO PIO channel base class
660 ******************************************************************************/
663 nv50_disp_pioc_create_(struct nouveau_object
*parent
,
664 struct nouveau_object
*engine
,
665 struct nouveau_oclass
*oclass
, int chid
,
666 int length
, void **pobject
)
668 return nv50_disp_chan_create_(parent
, engine
, oclass
, chid
,
673 nv50_disp_pioc_dtor(struct nouveau_object
*object
)
675 struct nv50_disp_pioc
*pioc
= (void *)object
;
676 nv50_disp_chan_destroy(&pioc
->base
);
680 nv50_disp_pioc_init(struct nouveau_object
*object
)
682 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
683 struct nv50_disp_pioc
*pioc
= (void *)object
;
684 int chid
= pioc
->base
.chid
;
687 ret
= nv50_disp_chan_init(&pioc
->base
);
691 nv_wr32(priv
, 0x610200 + (chid
* 0x10), 0x00002000);
692 if (!nv_wait(priv
, 0x610200 + (chid
* 0x10), 0x00000000, 0x00000000)) {
693 nv_error(pioc
, "timeout0: 0x%08x\n",
694 nv_rd32(priv
, 0x610200 + (chid
* 0x10)));
698 nv_wr32(priv
, 0x610200 + (chid
* 0x10), 0x00000001);
699 if (!nv_wait(priv
, 0x610200 + (chid
* 0x10), 0x00030000, 0x00010000)) {
700 nv_error(pioc
, "timeout1: 0x%08x\n",
701 nv_rd32(priv
, 0x610200 + (chid
* 0x10)));
709 nv50_disp_pioc_fini(struct nouveau_object
*object
, bool suspend
)
711 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
712 struct nv50_disp_pioc
*pioc
= (void *)object
;
713 int chid
= pioc
->base
.chid
;
715 nv_mask(priv
, 0x610200 + (chid
* 0x10), 0x00000001, 0x00000000);
716 if (!nv_wait(priv
, 0x610200 + (chid
* 0x10), 0x00030000, 0x00000000)) {
717 nv_error(pioc
, "timeout: 0x%08x\n",
718 nv_rd32(priv
, 0x610200 + (chid
* 0x10)));
723 return nv50_disp_chan_fini(&pioc
->base
, suspend
);
726 /*******************************************************************************
727 * EVO immediate overlay channel objects
728 ******************************************************************************/
731 nv50_disp_oimm_ctor(struct nouveau_object
*parent
,
732 struct nouveau_object
*engine
,
733 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
734 struct nouveau_object
**pobject
)
736 struct nv50_display_oimm_class
*args
= data
;
737 struct nv50_disp_pioc
*pioc
;
740 if (size
< sizeof(*args
) || args
->head
> 1)
743 ret
= nv50_disp_pioc_create_(parent
, engine
, oclass
, 5 + args
->head
,
744 sizeof(*pioc
), (void **)&pioc
);
745 *pobject
= nv_object(pioc
);
752 struct nouveau_ofuncs
753 nv50_disp_oimm_ofuncs
= {
754 .ctor
= nv50_disp_oimm_ctor
,
755 .dtor
= nv50_disp_pioc_dtor
,
756 .init
= nv50_disp_pioc_init
,
757 .fini
= nv50_disp_pioc_fini
,
758 .rd32
= nv50_disp_chan_rd32
,
759 .wr32
= nv50_disp_chan_wr32
,
762 /*******************************************************************************
763 * EVO cursor channel objects
764 ******************************************************************************/
767 nv50_disp_curs_ctor(struct nouveau_object
*parent
,
768 struct nouveau_object
*engine
,
769 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
770 struct nouveau_object
**pobject
)
772 struct nv50_display_curs_class
*args
= data
;
773 struct nv50_disp_pioc
*pioc
;
776 if (size
< sizeof(*args
) || args
->head
> 1)
779 ret
= nv50_disp_pioc_create_(parent
, engine
, oclass
, 7 + args
->head
,
780 sizeof(*pioc
), (void **)&pioc
);
781 *pobject
= nv_object(pioc
);
788 struct nouveau_ofuncs
789 nv50_disp_curs_ofuncs
= {
790 .ctor
= nv50_disp_curs_ctor
,
791 .dtor
= nv50_disp_pioc_dtor
,
792 .init
= nv50_disp_pioc_init
,
793 .fini
= nv50_disp_pioc_fini
,
794 .rd32
= nv50_disp_chan_rd32
,
795 .wr32
= nv50_disp_chan_wr32
,
798 /*******************************************************************************
799 * Base display object
800 ******************************************************************************/
803 nv50_disp_base_scanoutpos(struct nouveau_object
*object
, u32 mthd
,
804 void *data
, u32 size
)
806 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
807 struct nv04_display_scanoutpos
*args
= data
;
808 const int head
= (mthd
& NV50_DISP_MTHD_HEAD
);
809 u32 blanke
, blanks
, total
;
811 if (size
< sizeof(*args
) || head
>= priv
->head
.nr
)
813 blanke
= nv_rd32(priv
, 0x610aec + (head
* 0x540));
814 blanks
= nv_rd32(priv
, 0x610af4 + (head
* 0x540));
815 total
= nv_rd32(priv
, 0x610afc + (head
* 0x540));
817 args
->vblanke
= (blanke
& 0xffff0000) >> 16;
818 args
->hblanke
= (blanke
& 0x0000ffff);
819 args
->vblanks
= (blanks
& 0xffff0000) >> 16;
820 args
->hblanks
= (blanks
& 0x0000ffff);
821 args
->vtotal
= ( total
& 0xffff0000) >> 16;
822 args
->htotal
= ( total
& 0x0000ffff);
824 args
->time
[0] = ktime_to_ns(ktime_get());
825 args
->vline
= nv_rd32(priv
, 0x616340 + (head
* 0x800)) & 0xffff;
826 args
->time
[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
827 args
->hline
= nv_rd32(priv
, 0x616344 + (head
* 0x800)) & 0xffff;
832 nv50_disp_base_vblank_enable(struct nouveau_event
*event
, int type
, int head
)
834 nv_mask(event
->priv
, 0x61002c, (4 << head
), (4 << head
));
838 nv50_disp_base_vblank_disable(struct nouveau_event
*event
, int type
, int head
)
840 nv_mask(event
->priv
, 0x61002c, (4 << head
), 0);
844 nv50_disp_base_ctor(struct nouveau_object
*parent
,
845 struct nouveau_object
*engine
,
846 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
847 struct nouveau_object
**pobject
)
849 struct nv50_disp_priv
*priv
= (void *)engine
;
850 struct nv50_disp_base
*base
;
853 ret
= nouveau_parent_create(parent
, engine
, oclass
, 0,
854 priv
->sclass
, 0, &base
);
855 *pobject
= nv_object(base
);
859 priv
->base
.vblank
->priv
= priv
;
860 priv
->base
.vblank
->enable
= nv50_disp_base_vblank_enable
;
861 priv
->base
.vblank
->disable
= nv50_disp_base_vblank_disable
;
862 return nouveau_ramht_new(nv_object(base
), nv_object(base
), 0x1000, 0,
867 nv50_disp_base_dtor(struct nouveau_object
*object
)
869 struct nv50_disp_base
*base
= (void *)object
;
870 nouveau_ramht_ref(NULL
, &base
->ramht
);
871 nouveau_parent_destroy(&base
->base
);
875 nv50_disp_base_init(struct nouveau_object
*object
)
877 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
878 struct nv50_disp_base
*base
= (void *)object
;
882 ret
= nouveau_parent_init(&base
->base
);
886 /* The below segments of code copying values from one register to
887 * another appear to inform EVO of the display capabilities or
888 * something similar. NFI what the 0x614004 caps are for..
890 tmp
= nv_rd32(priv
, 0x614004);
891 nv_wr32(priv
, 0x610184, tmp
);
894 for (i
= 0; i
< priv
->head
.nr
; i
++) {
895 tmp
= nv_rd32(priv
, 0x616100 + (i
* 0x800));
896 nv_wr32(priv
, 0x610190 + (i
* 0x10), tmp
);
897 tmp
= nv_rd32(priv
, 0x616104 + (i
* 0x800));
898 nv_wr32(priv
, 0x610194 + (i
* 0x10), tmp
);
899 tmp
= nv_rd32(priv
, 0x616108 + (i
* 0x800));
900 nv_wr32(priv
, 0x610198 + (i
* 0x10), tmp
);
901 tmp
= nv_rd32(priv
, 0x61610c + (i
* 0x800));
902 nv_wr32(priv
, 0x61019c + (i
* 0x10), tmp
);
906 for (i
= 0; i
< priv
->dac
.nr
; i
++) {
907 tmp
= nv_rd32(priv
, 0x61a000 + (i
* 0x800));
908 nv_wr32(priv
, 0x6101d0 + (i
* 0x04), tmp
);
912 for (i
= 0; i
< priv
->sor
.nr
; i
++) {
913 tmp
= nv_rd32(priv
, 0x61c000 + (i
* 0x800));
914 nv_wr32(priv
, 0x6101e0 + (i
* 0x04), tmp
);
918 for (i
= 0; i
< priv
->pior
.nr
; i
++) {
919 tmp
= nv_rd32(priv
, 0x61e000 + (i
* 0x800));
920 nv_wr32(priv
, 0x6101f0 + (i
* 0x04), tmp
);
923 /* steal display away from vbios, or something like that */
924 if (nv_rd32(priv
, 0x610024) & 0x00000100) {
925 nv_wr32(priv
, 0x610024, 0x00000100);
926 nv_mask(priv
, 0x6194e8, 0x00000001, 0x00000000);
927 if (!nv_wait(priv
, 0x6194e8, 0x00000002, 0x00000000)) {
928 nv_error(priv
, "timeout acquiring display\n");
933 /* point at display engine memory area (hash table, objects) */
934 nv_wr32(priv
, 0x610010, (nv_gpuobj(base
->ramht
)->addr
>> 8) | 9);
936 /* enable supervisor interrupts, disable everything else */
937 nv_wr32(priv
, 0x61002c, 0x00000370);
938 nv_wr32(priv
, 0x610028, 0x00000000);
943 nv50_disp_base_fini(struct nouveau_object
*object
, bool suspend
)
945 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
946 struct nv50_disp_base
*base
= (void *)object
;
948 /* disable all interrupts */
949 nv_wr32(priv
, 0x610024, 0x00000000);
950 nv_wr32(priv
, 0x610020, 0x00000000);
952 return nouveau_parent_fini(&base
->base
, suspend
);
955 struct nouveau_ofuncs
956 nv50_disp_base_ofuncs
= {
957 .ctor
= nv50_disp_base_ctor
,
958 .dtor
= nv50_disp_base_dtor
,
959 .init
= nv50_disp_base_init
,
960 .fini
= nv50_disp_base_fini
,
963 static struct nouveau_omthds
964 nv50_disp_base_omthds
[] = {
965 { HEAD_MTHD(NV50_DISP_SCANOUTPOS
) , nv50_disp_base_scanoutpos
},
966 { SOR_MTHD(NV50_DISP_SOR_PWR
) , nv50_sor_mthd
},
967 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT
) , nv50_sor_mthd
},
968 { DAC_MTHD(NV50_DISP_DAC_PWR
) , nv50_dac_mthd
},
969 { DAC_MTHD(NV50_DISP_DAC_LOAD
) , nv50_dac_mthd
},
970 { PIOR_MTHD(NV50_DISP_PIOR_PWR
) , nv50_pior_mthd
},
971 { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR
) , nv50_pior_mthd
},
972 { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR
) , nv50_pior_mthd
},
976 static struct nouveau_oclass
977 nv50_disp_base_oclass
[] = {
978 { NV50_DISP_CLASS
, &nv50_disp_base_ofuncs
, nv50_disp_base_omthds
},
982 static struct nouveau_oclass
983 nv50_disp_sclass
[] = {
984 { NV50_DISP_MAST_CLASS
, &nv50_disp_mast_ofuncs
},
985 { NV50_DISP_SYNC_CLASS
, &nv50_disp_sync_ofuncs
},
986 { NV50_DISP_OVLY_CLASS
, &nv50_disp_ovly_ofuncs
},
987 { NV50_DISP_OIMM_CLASS
, &nv50_disp_oimm_ofuncs
},
988 { NV50_DISP_CURS_CLASS
, &nv50_disp_curs_ofuncs
},
992 /*******************************************************************************
993 * Display context, tracks instmem allocation and prevents more than one
994 * client using the display hardware at any time.
995 ******************************************************************************/
998 nv50_disp_data_ctor(struct nouveau_object
*parent
,
999 struct nouveau_object
*engine
,
1000 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
1001 struct nouveau_object
**pobject
)
1003 struct nv50_disp_priv
*priv
= (void *)engine
;
1004 struct nouveau_engctx
*ectx
;
1007 /* no context needed for channel objects... */
1008 if (nv_mclass(parent
) != NV_DEVICE_CLASS
) {
1009 atomic_inc(&parent
->refcount
);
1014 /* allocate display hardware to client */
1015 mutex_lock(&nv_subdev(priv
)->mutex
);
1016 if (list_empty(&nv_engine(priv
)->contexts
)) {
1017 ret
= nouveau_engctx_create(parent
, engine
, oclass
, NULL
,
1019 NVOBJ_FLAG_HEAP
, &ectx
);
1020 *pobject
= nv_object(ectx
);
1022 mutex_unlock(&nv_subdev(priv
)->mutex
);
1026 struct nouveau_oclass
1027 nv50_disp_cclass
= {
1028 .handle
= NV_ENGCTX(DISP
, 0x50),
1029 .ofuncs
= &(struct nouveau_ofuncs
) {
1030 .ctor
= nv50_disp_data_ctor
,
1031 .dtor
= _nouveau_engctx_dtor
,
1032 .init
= _nouveau_engctx_init
,
1033 .fini
= _nouveau_engctx_fini
,
1034 .rd32
= _nouveau_engctx_rd32
,
1035 .wr32
= _nouveau_engctx_wr32
,
1039 /*******************************************************************************
1040 * Display engine implementation
1041 ******************************************************************************/
1043 static const struct nouveau_enum
1044 nv50_disp_intr_error_type
[] = {
1045 { 3, "ILLEGAL_MTHD" },
1046 { 4, "INVALID_VALUE" },
1047 { 5, "INVALID_STATE" },
1048 { 7, "INVALID_HANDLE" },
1052 static const struct nouveau_enum
1053 nv50_disp_intr_error_code
[] = {
1059 nv50_disp_intr_error(struct nv50_disp_priv
*priv
, int chid
)
1061 struct nv50_disp_impl
*impl
= (void *)nv_object(priv
)->oclass
;
1062 u32 data
= nv_rd32(priv
, 0x610084 + (chid
* 0x08));
1063 u32 addr
= nv_rd32(priv
, 0x610080 + (chid
* 0x08));
1064 u32 code
= (addr
& 0x00ff0000) >> 16;
1065 u32 type
= (addr
& 0x00007000) >> 12;
1066 u32 mthd
= (addr
& 0x00000ffc);
1067 const struct nouveau_enum
*ec
, *et
;
1068 char ecunk
[6], etunk
[6];
1070 et
= nouveau_enum_find(nv50_disp_intr_error_type
, type
);
1072 snprintf(etunk
, sizeof(etunk
), "UNK%02X", type
);
1074 ec
= nouveau_enum_find(nv50_disp_intr_error_code
, code
);
1076 snprintf(ecunk
, sizeof(ecunk
), "UNK%02X", code
);
1078 nv_error(priv
, "%s [%s] chid %d mthd 0x%04x data 0x%08x\n",
1079 et
? et
->name
: etunk
, ec
? ec
->name
: ecunk
,
1085 nv50_disp_mthd_chan(priv
, NV_DBG_ERROR
, chid
- 0,
1095 nv50_disp_mthd_chan(priv
, NV_DBG_ERROR
, chid
- 1,
1105 nv50_disp_mthd_chan(priv
, NV_DBG_ERROR
, chid
- 3,
1113 nv_wr32(priv
, 0x610020, 0x00010000 << chid
);
1114 nv_wr32(priv
, 0x610080 + (chid
* 0x08), 0x90000000);
1117 static struct nvkm_output
*
1118 exec_lookup(struct nv50_disp_priv
*priv
, int head
, int or, u32 ctrl
,
1119 u32
*data
, u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
,
1120 struct nvbios_outp
*info
)
1122 struct nouveau_bios
*bios
= nouveau_bios(priv
);
1123 struct nvkm_output
*outp
;
1127 type
= DCB_OUTPUT_ANALOG
;
1131 switch (ctrl
& 0x00000f00) {
1132 case 0x00000000: type
= DCB_OUTPUT_LVDS
; mask
= 1; break;
1133 case 0x00000100: type
= DCB_OUTPUT_TMDS
; mask
= 1; break;
1134 case 0x00000200: type
= DCB_OUTPUT_TMDS
; mask
= 2; break;
1135 case 0x00000500: type
= DCB_OUTPUT_TMDS
; mask
= 3; break;
1136 case 0x00000800: type
= DCB_OUTPUT_DP
; mask
= 1; break;
1137 case 0x00000900: type
= DCB_OUTPUT_DP
; mask
= 2; break;
1139 nv_error(priv
, "unknown SOR mc 0x%08x\n", ctrl
);
1147 switch (ctrl
& 0x00000f00) {
1148 case 0x00000000: type
|= priv
->pior
.type
[or]; break;
1150 nv_error(priv
, "unknown PIOR mc 0x%08x\n", ctrl
);
1155 mask
= 0x00c0 & (mask
<< 6);
1156 mask
|= 0x0001 << or;
1157 mask
|= 0x0100 << head
;
1159 list_for_each_entry(outp
, &priv
->base
.outp
, head
) {
1160 if ((outp
->info
.hasht
& 0xff) == type
&&
1161 (outp
->info
.hashm
& mask
) == mask
) {
1162 *data
= nvbios_outp_match(bios
, outp
->info
.hasht
,
1164 ver
, hdr
, cnt
, len
, info
);
1175 exec_script(struct nv50_disp_priv
*priv
, int head
, int id
)
1177 struct nouveau_bios
*bios
= nouveau_bios(priv
);
1178 struct nvkm_output
*outp
;
1179 struct nvbios_outp info
;
1180 u8 ver
, hdr
, cnt
, len
;
1186 for (i
= 0; !(ctrl
& (1 << head
)) && i
< priv
->dac
.nr
; i
++)
1187 ctrl
= nv_rd32(priv
, 0x610b5c + (i
* 8));
1190 if (!(ctrl
& (1 << head
))) {
1191 if (nv_device(priv
)->chipset
< 0x90 ||
1192 nv_device(priv
)->chipset
== 0x92 ||
1193 nv_device(priv
)->chipset
== 0xa0) {
1198 for (i
= 0; !(ctrl
& (1 << head
)) && i
< priv
->sor
.nr
; i
++)
1199 ctrl
= nv_rd32(priv
, reg
+ (i
* 8));
1204 if (!(ctrl
& (1 << head
))) {
1205 for (i
= 0; !(ctrl
& (1 << head
)) && i
< priv
->pior
.nr
; i
++)
1206 ctrl
= nv_rd32(priv
, 0x610b84 + (i
* 8));
1210 if (!(ctrl
& (1 << head
)))
1214 outp
= exec_lookup(priv
, head
, i
, ctrl
, &data
, &ver
, &hdr
, &cnt
, &len
, &info
);
1216 struct nvbios_init init
= {
1217 .subdev
= nv_subdev(priv
),
1219 .offset
= info
.script
[id
],
1220 .outp
= &outp
->info
,
1225 return nvbios_exec(&init
) == 0;
1231 static struct nvkm_output
*
1232 exec_clkcmp(struct nv50_disp_priv
*priv
, int head
, int id
, u32 pclk
, u32
*conf
)
1234 struct nouveau_bios
*bios
= nouveau_bios(priv
);
1235 struct nvkm_output
*outp
;
1236 struct nvbios_outp info1
;
1237 struct nvbios_ocfg info2
;
1238 u8 ver
, hdr
, cnt
, len
;
1244 for (i
= 0; !(ctrl
& (1 << head
)) && i
< priv
->dac
.nr
; i
++)
1245 ctrl
= nv_rd32(priv
, 0x610b58 + (i
* 8));
1248 if (!(ctrl
& (1 << head
))) {
1249 if (nv_device(priv
)->chipset
< 0x90 ||
1250 nv_device(priv
)->chipset
== 0x92 ||
1251 nv_device(priv
)->chipset
== 0xa0) {
1256 for (i
= 0; !(ctrl
& (1 << head
)) && i
< priv
->sor
.nr
; i
++)
1257 ctrl
= nv_rd32(priv
, reg
+ (i
* 8));
1262 if (!(ctrl
& (1 << head
))) {
1263 for (i
= 0; !(ctrl
& (1 << head
)) && i
< priv
->pior
.nr
; i
++)
1264 ctrl
= nv_rd32(priv
, 0x610b80 + (i
* 8));
1268 if (!(ctrl
& (1 << head
)))
1272 outp
= exec_lookup(priv
, head
, i
, ctrl
, &data
, &ver
, &hdr
, &cnt
, &len
, &info1
);
1276 if (outp
->info
.location
== 0) {
1277 switch (outp
->info
.type
) {
1278 case DCB_OUTPUT_TMDS
:
1279 *conf
= (ctrl
& 0x00000f00) >> 8;
1283 case DCB_OUTPUT_LVDS
:
1284 *conf
= priv
->sor
.lvdsconf
;
1287 *conf
= (ctrl
& 0x00000f00) >> 8;
1289 case DCB_OUTPUT_ANALOG
:
1295 *conf
= (ctrl
& 0x00000f00) >> 8;
1299 data
= nvbios_ocfg_match(bios
, data
, *conf
, &ver
, &hdr
, &cnt
, &len
, &info2
);
1300 if (data
&& id
< 0xff) {
1301 data
= nvbios_oclk_match(bios
, info2
.clkcmp
[id
], pclk
);
1303 struct nvbios_init init
= {
1304 .subdev
= nv_subdev(priv
),
1307 .outp
= &outp
->info
,
1320 nv50_disp_intr_unk10_0(struct nv50_disp_priv
*priv
, int head
)
1322 exec_script(priv
, head
, 1);
1326 nv50_disp_intr_unk20_0(struct nv50_disp_priv
*priv
, int head
)
1328 exec_script(priv
, head
, 2);
1332 nv50_disp_intr_unk20_1(struct nv50_disp_priv
*priv
, int head
)
1334 struct nouveau_devinit
*devinit
= nouveau_devinit(priv
);
1335 u32 pclk
= nv_rd32(priv
, 0x610ad0 + (head
* 0x540)) & 0x3fffff;
1337 devinit
->pll_set(devinit
, PLL_VPLL0
+ head
, pclk
);
1341 nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv
*priv
,
1342 struct dcb_output
*outp
, u32 pclk
)
1344 const int link
= !(outp
->sorconf
.link
& 1);
1345 const int or = ffs(outp
->or) - 1;
1346 const u32 soff
= ( or * 0x800);
1347 const u32 loff
= (link
* 0x080) + soff
;
1348 const u32 ctrl
= nv_rd32(priv
, 0x610794 + (or * 8));
1349 const u32 symbol
= 100000;
1350 u32 dpctrl
= nv_rd32(priv
, 0x61c10c + loff
) & 0x0000f0000;
1351 u32 clksor
= nv_rd32(priv
, 0x614300 + soff
);
1352 int bestTU
= 0, bestVTUi
= 0, bestVTUf
= 0, bestVTUa
= 0;
1353 int TU
, VTUi
, VTUf
, VTUa
;
1354 u64 link_data_rate
, link_ratio
, unk
;
1355 u32 best_diff
= 64 * symbol
;
1356 u32 link_nr
, link_bw
, bits
, r
;
1358 /* calculate packed data rate for each lane */
1359 if (dpctrl
> 0x00030000) link_nr
= 4;
1360 else if (dpctrl
> 0x00010000) link_nr
= 2;
1363 if (clksor
& 0x000c0000)
1368 if ((ctrl
& 0xf0000) == 0x60000) bits
= 30;
1369 else if ((ctrl
& 0xf0000) == 0x50000) bits
= 24;
1372 link_data_rate
= (pclk
* bits
/ 8) / link_nr
;
1374 /* calculate ratio of packed data rate to link symbol rate */
1375 link_ratio
= link_data_rate
* symbol
;
1376 r
= do_div(link_ratio
, link_bw
);
1378 for (TU
= 64; TU
>= 32; TU
--) {
1379 /* calculate average number of valid symbols in each TU */
1380 u32 tu_valid
= link_ratio
* TU
;
1383 /* find a hw representation for the fraction.. */
1384 VTUi
= tu_valid
/ symbol
;
1385 calc
= VTUi
* symbol
;
1386 diff
= tu_valid
- calc
;
1388 if (diff
>= (symbol
/ 2)) {
1389 VTUf
= symbol
/ (symbol
- diff
);
1390 if (symbol
- (VTUf
* diff
))
1395 calc
+= symbol
- (symbol
/ VTUf
);
1403 VTUf
= min((int)(symbol
/ diff
), 15);
1404 calc
+= symbol
/ VTUf
;
1407 diff
= calc
- tu_valid
;
1409 /* no remainder, but the hw doesn't like the fractional
1410 * part to be zero. decrement the integer part and
1411 * have the fraction add a whole symbol back
1418 if (diff
< best_diff
) {
1430 nv_error(priv
, "unable to find suitable dp config\n");
1434 /* XXX close to vbios numbers, but not right */
1435 unk
= (symbol
- link_ratio
) * bestTU
;
1437 r
= do_div(unk
, symbol
);
1438 r
= do_div(unk
, symbol
);
1441 nv_mask(priv
, 0x61c10c + loff
, 0x000001fc, bestTU
<< 2);
1442 nv_mask(priv
, 0x61c128 + loff
, 0x010f7f3f, bestVTUa
<< 24 |
1444 bestVTUi
<< 8 | unk
);
1448 nv50_disp_intr_unk20_2(struct nv50_disp_priv
*priv
, int head
)
1450 struct nvkm_output
*outp
;
1451 u32 pclk
= nv_rd32(priv
, 0x610ad0 + (head
* 0x540)) & 0x3fffff;
1452 u32 hval
, hreg
= 0x614200 + (head
* 0x800);
1456 outp
= exec_clkcmp(priv
, head
, 0xff, pclk
, &conf
);
1460 if (outp
->info
.location
== 0 && outp
->info
.type
== DCB_OUTPUT_DP
) {
1461 u32 soff
= (ffs(outp
->info
.or) - 1) * 0x08;
1462 u32 ctrl
= nv_rd32(priv
, 0x610794 + soff
);
1465 switch ((ctrl
& 0x000f0000) >> 16) {
1466 case 6: datarate
= pclk
* 30 / 8; break;
1467 case 5: datarate
= pclk
* 24 / 8; break;
1470 datarate
= pclk
* 18 / 8;
1474 nouveau_dp_train(&priv
->base
, priv
->sor
.dp
,
1475 &outp
->info
, head
, datarate
);
1478 exec_clkcmp(priv
, head
, 0, pclk
, &conf
);
1480 if (!outp
->info
.location
&& outp
->info
.type
== DCB_OUTPUT_ANALOG
) {
1481 oreg
= 0x614280 + (ffs(outp
->info
.or) - 1) * 0x800;
1486 if (!outp
->info
.location
) {
1487 if (outp
->info
.type
== DCB_OUTPUT_DP
)
1488 nv50_disp_intr_unk20_2_dp(priv
, &outp
->info
, pclk
);
1489 oreg
= 0x614300 + (ffs(outp
->info
.or) - 1) * 0x800;
1490 oval
= (conf
& 0x0100) ? 0x00000101 : 0x00000000;
1494 oreg
= 0x614380 + (ffs(outp
->info
.or) - 1) * 0x800;
1500 nv_mask(priv
, hreg
, 0x0000000f, hval
);
1501 nv_mask(priv
, oreg
, mask
, oval
);
1504 /* If programming a TMDS output on a SOR that can also be configured for
1505 * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off.
1507 * It looks like the VBIOS TMDS scripts make an attempt at this, however,
1508 * the VBIOS scripts on at least one board I have only switch it off on
1509 * link 0, causing a blank display if the output has previously been
1510 * programmed for DisplayPort.
1513 nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv
*priv
, struct dcb_output
*outp
)
1515 struct nouveau_bios
*bios
= nouveau_bios(priv
);
1516 const int link
= !(outp
->sorconf
.link
& 1);
1517 const int or = ffs(outp
->or) - 1;
1518 const u32 loff
= (or * 0x800) + (link
* 0x80);
1519 const u16 mask
= (outp
->sorconf
.link
<< 6) | outp
->or;
1522 if (dcb_outp_match(bios
, DCB_OUTPUT_DP
, mask
, &ver
, &hdr
, outp
))
1523 nv_mask(priv
, 0x61c10c + loff
, 0x00000001, 0x00000000);
1527 nv50_disp_intr_unk40_0(struct nv50_disp_priv
*priv
, int head
)
1529 struct nvkm_output
*outp
;
1530 u32 pclk
= nv_rd32(priv
, 0x610ad0 + (head
* 0x540)) & 0x3fffff;
1533 outp
= exec_clkcmp(priv
, head
, 1, pclk
, &conf
);
1537 if (outp
->info
.location
== 0 && outp
->info
.type
== DCB_OUTPUT_TMDS
)
1538 nv50_disp_intr_unk40_0_tmds(priv
, &outp
->info
);
1540 if (outp
->info
.location
== 1 && outp
->info
.type
== DCB_OUTPUT_DP
) {
1541 u32 soff
= (ffs(outp
->info
.or) - 1) * 0x08;
1542 u32 ctrl
= nv_rd32(priv
, 0x610b84 + soff
);
1545 switch ((ctrl
& 0x000f0000) >> 16) {
1546 case 6: datarate
= pclk
* 30 / 8; break;
1547 case 5: datarate
= pclk
* 24 / 8; break;
1550 datarate
= pclk
* 18 / 8;
1554 nouveau_dp_train(&priv
->base
, priv
->pior
.dp
,
1555 &outp
->info
, head
, datarate
);
1560 nv50_disp_intr_supervisor(struct work_struct
*work
)
1562 struct nv50_disp_priv
*priv
=
1563 container_of(work
, struct nv50_disp_priv
, supervisor
);
1564 struct nv50_disp_impl
*impl
= (void *)nv_object(priv
)->oclass
;
1565 u32 super
= nv_rd32(priv
, 0x610030);
1568 nv_debug(priv
, "supervisor 0x%08x 0x%08x\n", priv
->super
, super
);
1570 if (priv
->super
& 0x00000010) {
1571 nv50_disp_mthd_chan(priv
, NV_DBG_DEBUG
, 0, impl
->mthd
.core
);
1572 for (head
= 0; head
< priv
->head
.nr
; head
++) {
1573 if (!(super
& (0x00000020 << head
)))
1575 if (!(super
& (0x00000080 << head
)))
1577 nv50_disp_intr_unk10_0(priv
, head
);
1580 if (priv
->super
& 0x00000020) {
1581 for (head
= 0; head
< priv
->head
.nr
; head
++) {
1582 if (!(super
& (0x00000080 << head
)))
1584 nv50_disp_intr_unk20_0(priv
, head
);
1586 for (head
= 0; head
< priv
->head
.nr
; head
++) {
1587 if (!(super
& (0x00000200 << head
)))
1589 nv50_disp_intr_unk20_1(priv
, head
);
1591 for (head
= 0; head
< priv
->head
.nr
; head
++) {
1592 if (!(super
& (0x00000080 << head
)))
1594 nv50_disp_intr_unk20_2(priv
, head
);
1597 if (priv
->super
& 0x00000040) {
1598 for (head
= 0; head
< priv
->head
.nr
; head
++) {
1599 if (!(super
& (0x00000080 << head
)))
1601 nv50_disp_intr_unk40_0(priv
, head
);
1605 nv_wr32(priv
, 0x610030, 0x80000000);
1609 nv50_disp_intr(struct nouveau_subdev
*subdev
)
1611 struct nv50_disp_priv
*priv
= (void *)subdev
;
1612 u32 intr0
= nv_rd32(priv
, 0x610020);
1613 u32 intr1
= nv_rd32(priv
, 0x610024);
1615 while (intr0
& 0x001f0000) {
1616 u32 chid
= __ffs(intr0
& 0x001f0000) - 16;
1617 nv50_disp_intr_error(priv
, chid
);
1618 intr0
&= ~(0x00010000 << chid
);
1621 if (intr1
& 0x00000004) {
1622 nouveau_event_trigger(priv
->base
.vblank
, 1, 0);
1623 nv_wr32(priv
, 0x610024, 0x00000004);
1624 intr1
&= ~0x00000004;
1627 if (intr1
& 0x00000008) {
1628 nouveau_event_trigger(priv
->base
.vblank
, 1, 1);
1629 nv_wr32(priv
, 0x610024, 0x00000008);
1630 intr1
&= ~0x00000008;
1633 if (intr1
& 0x00000070) {
1634 priv
->super
= (intr1
& 0x00000070);
1635 schedule_work(&priv
->supervisor
);
1636 nv_wr32(priv
, 0x610024, priv
->super
);
1637 intr1
&= ~0x00000070;
1642 nv50_disp_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
1643 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
1644 struct nouveau_object
**pobject
)
1646 struct nv50_disp_priv
*priv
;
1649 ret
= nouveau_disp_create(parent
, engine
, oclass
, 2, "PDISP",
1651 *pobject
= nv_object(priv
);
1655 nv_engine(priv
)->sclass
= nv50_disp_base_oclass
;
1656 nv_engine(priv
)->cclass
= &nv50_disp_cclass
;
1657 nv_subdev(priv
)->intr
= nv50_disp_intr
;
1658 INIT_WORK(&priv
->supervisor
, nv50_disp_intr_supervisor
);
1659 priv
->sclass
= nv50_disp_sclass
;
1664 priv
->dac
.power
= nv50_dac_power
;
1665 priv
->dac
.sense
= nv50_dac_sense
;
1666 priv
->sor
.power
= nv50_sor_power
;
1667 priv
->pior
.power
= nv50_pior_power
;
1668 priv
->pior
.dp
= &nv50_pior_dp_func
;
1672 struct nouveau_oclass
*
1673 nv50_disp_outp_sclass
[] = {
1674 &nv50_pior_dp_impl
.base
.base
,
1678 struct nouveau_oclass
*
1679 nv50_disp_oclass
= &(struct nv50_disp_impl
) {
1680 .base
.base
.handle
= NV_ENGINE(DISP
, 0x50),
1681 .base
.base
.ofuncs
= &(struct nouveau_ofuncs
) {
1682 .ctor
= nv50_disp_ctor
,
1683 .dtor
= _nouveau_disp_dtor
,
1684 .init
= _nouveau_disp_init
,
1685 .fini
= _nouveau_disp_fini
,
1687 .base
.outp
= nv50_disp_outp_sclass
,
1688 .mthd
.core
= &nv50_disp_mast_mthd_chan
,
1689 .mthd
.base
= &nv50_disp_sync_mthd_chan
,
1690 .mthd
.ovly
= &nv50_disp_ovly_mthd_chan
,
1691 .mthd
.prev
= 0x000004,