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.
27 #include <core/client.h>
28 #include <core/enum.h>
29 #include <core/gpuobj.h>
30 #include <subdev/bios.h>
31 #include <subdev/bios/disp.h>
32 #include <subdev/bios/init.h>
33 #include <subdev/bios/pll.h>
34 #include <subdev/devinit.h>
37 nv50_disp_vblank_fini(struct nvkm_event
*event
, int type
, int head
)
39 struct nvkm_disp
*disp
= container_of(event
, typeof(*disp
), vblank
);
40 struct nvkm_device
*device
= disp
->engine
.subdev
.device
;
41 nvkm_mask(device
, 0x61002c, (4 << head
), 0);
45 nv50_disp_vblank_init(struct nvkm_event
*event
, int type
, int head
)
47 struct nvkm_disp
*disp
= container_of(event
, typeof(*disp
), vblank
);
48 struct nvkm_device
*device
= disp
->engine
.subdev
.device
;
49 nvkm_mask(device
, 0x61002c, (4 << head
), (4 << head
));
52 const struct nvkm_event_func
53 nv50_disp_vblank_func
= {
54 .ctor
= nvkm_disp_vblank_ctor
,
55 .init
= nv50_disp_vblank_init
,
56 .fini
= nv50_disp_vblank_fini
,
59 static const struct nvkm_enum
60 nv50_disp_intr_error_type
[] = {
61 { 3, "ILLEGAL_MTHD" },
62 { 4, "INVALID_VALUE" },
63 { 5, "INVALID_STATE" },
64 { 7, "INVALID_HANDLE" },
68 static const struct nvkm_enum
69 nv50_disp_intr_error_code
[] = {
75 nv50_disp_intr_error(struct nv50_disp
*disp
, int chid
)
77 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
78 struct nvkm_device
*device
= subdev
->device
;
79 u32 data
= nvkm_rd32(device
, 0x610084 + (chid
* 0x08));
80 u32 addr
= nvkm_rd32(device
, 0x610080 + (chid
* 0x08));
81 u32 code
= (addr
& 0x00ff0000) >> 16;
82 u32 type
= (addr
& 0x00007000) >> 12;
83 u32 mthd
= (addr
& 0x00000ffc);
84 const struct nvkm_enum
*ec
, *et
;
86 et
= nvkm_enum_find(nv50_disp_intr_error_type
, type
);
87 ec
= nvkm_enum_find(nv50_disp_intr_error_code
, code
);
90 "ERROR %d [%s] %02x [%s] chid %d mthd %04x data %08x\n",
91 type
, et
? et
->name
: "", code
, ec
? ec
->name
: "",
94 if (chid
< ARRAY_SIZE(disp
->chan
)) {
97 nv50_disp_chan_mthd(disp
->chan
[chid
], NV_DBG_ERROR
);
104 nvkm_wr32(device
, 0x610020, 0x00010000 << chid
);
105 nvkm_wr32(device
, 0x610080 + (chid
* 0x08), 0x90000000);
108 static struct nvkm_output
*
109 exec_lookup(struct nv50_disp
*disp
, int head
, int or, u32 ctrl
,
110 u32
*data
, u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
,
111 struct nvbios_outp
*info
)
113 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
114 struct nvkm_bios
*bios
= subdev
->device
->bios
;
115 struct nvkm_output
*outp
;
119 type
= DCB_OUTPUT_ANALOG
;
123 switch (ctrl
& 0x00000f00) {
124 case 0x00000000: type
= DCB_OUTPUT_LVDS
; mask
= 1; break;
125 case 0x00000100: type
= DCB_OUTPUT_TMDS
; mask
= 1; break;
126 case 0x00000200: type
= DCB_OUTPUT_TMDS
; mask
= 2; break;
127 case 0x00000500: type
= DCB_OUTPUT_TMDS
; mask
= 3; break;
128 case 0x00000800: type
= DCB_OUTPUT_DP
; mask
= 1; break;
129 case 0x00000900: type
= DCB_OUTPUT_DP
; mask
= 2; break;
131 nvkm_error(subdev
, "unknown SOR mc %08x\n", ctrl
);
139 switch (ctrl
& 0x00000f00) {
140 case 0x00000000: type
|= disp
->pior
.type
[or]; break;
142 nvkm_error(subdev
, "unknown PIOR mc %08x\n", ctrl
);
147 mask
= 0x00c0 & (mask
<< 6);
148 mask
|= 0x0001 << or;
149 mask
|= 0x0100 << head
;
151 list_for_each_entry(outp
, &disp
->base
.outp
, head
) {
152 if ((outp
->info
.hasht
& 0xff) == type
&&
153 (outp
->info
.hashm
& mask
) == mask
) {
154 *data
= nvbios_outp_match(bios
, outp
->info
.hasht
,
156 ver
, hdr
, cnt
, len
, info
);
166 static struct nvkm_output
*
167 exec_script(struct nv50_disp
*disp
, int head
, int id
)
169 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
170 struct nvkm_bios
*bios
= device
->bios
;
171 struct nvkm_output
*outp
;
172 struct nvbios_outp info
;
173 u8 ver
, hdr
, cnt
, len
;
179 for (i
= 0; !(ctrl
& (1 << head
)) && i
< disp
->dac
.nr
; i
++)
180 ctrl
= nvkm_rd32(device
, 0x610b5c + (i
* 8));
183 if (!(ctrl
& (1 << head
))) {
184 if (nv_device(disp
)->chipset
< 0x90 ||
185 nv_device(disp
)->chipset
== 0x92 ||
186 nv_device(disp
)->chipset
== 0xa0) {
191 for (i
= 0; !(ctrl
& (1 << head
)) && i
< disp
->sor
.nr
; i
++)
192 ctrl
= nvkm_rd32(device
, reg
+ (i
* 8));
197 if (!(ctrl
& (1 << head
))) {
198 for (i
= 0; !(ctrl
& (1 << head
)) && i
< disp
->pior
.nr
; i
++)
199 ctrl
= nvkm_rd32(device
, 0x610b84 + (i
* 8));
203 if (!(ctrl
& (1 << head
)))
207 outp
= exec_lookup(disp
, head
, i
, ctrl
, &data
, &ver
, &hdr
, &cnt
, &len
, &info
);
209 struct nvbios_init init
= {
210 .subdev
= nv_subdev(disp
),
212 .offset
= info
.script
[id
],
224 static struct nvkm_output
*
225 exec_clkcmp(struct nv50_disp
*disp
, int head
, int id
, u32 pclk
, u32
*conf
)
227 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
228 struct nvkm_bios
*bios
= device
->bios
;
229 struct nvkm_output
*outp
;
230 struct nvbios_outp info1
;
231 struct nvbios_ocfg info2
;
232 u8 ver
, hdr
, cnt
, len
;
238 for (i
= 0; !(ctrl
& (1 << head
)) && i
< disp
->dac
.nr
; i
++)
239 ctrl
= nvkm_rd32(device
, 0x610b58 + (i
* 8));
242 if (!(ctrl
& (1 << head
))) {
243 if (nv_device(disp
)->chipset
< 0x90 ||
244 nv_device(disp
)->chipset
== 0x92 ||
245 nv_device(disp
)->chipset
== 0xa0) {
250 for (i
= 0; !(ctrl
& (1 << head
)) && i
< disp
->sor
.nr
; i
++)
251 ctrl
= nvkm_rd32(device
, reg
+ (i
* 8));
256 if (!(ctrl
& (1 << head
))) {
257 for (i
= 0; !(ctrl
& (1 << head
)) && i
< disp
->pior
.nr
; i
++)
258 ctrl
= nvkm_rd32(device
, 0x610b80 + (i
* 8));
262 if (!(ctrl
& (1 << head
)))
266 outp
= exec_lookup(disp
, head
, i
, ctrl
, &data
, &ver
, &hdr
, &cnt
, &len
, &info1
);
270 if (outp
->info
.location
== 0) {
271 switch (outp
->info
.type
) {
272 case DCB_OUTPUT_TMDS
:
273 *conf
= (ctrl
& 0x00000f00) >> 8;
277 case DCB_OUTPUT_LVDS
:
278 *conf
= disp
->sor
.lvdsconf
;
281 *conf
= (ctrl
& 0x00000f00) >> 8;
283 case DCB_OUTPUT_ANALOG
:
289 *conf
= (ctrl
& 0x00000f00) >> 8;
293 data
= nvbios_ocfg_match(bios
, data
, *conf
, &ver
, &hdr
, &cnt
, &len
, &info2
);
294 if (data
&& id
< 0xff) {
295 data
= nvbios_oclk_match(bios
, info2
.clkcmp
[id
], pclk
);
297 struct nvbios_init init
= {
298 .subdev
= nv_subdev(disp
),
314 nv50_disp_intr_unk10_0(struct nv50_disp
*disp
, int head
)
316 exec_script(disp
, head
, 1);
320 nv50_disp_intr_unk20_0(struct nv50_disp
*disp
, int head
)
322 struct nvkm_output
*outp
= exec_script(disp
, head
, 2);
324 /* the binary driver does this outside of the supervisor handling
325 * (after the third supervisor from a detach). we (currently?)
326 * allow both detach/attach to happen in the same set of
327 * supervisor interrupts, so it would make sense to execute this
328 * (full power down?) script after all the detach phases of the
329 * supervisor handling. like with training if needed from the
330 * second supervisor, nvidia doesn't do this, so who knows if it's
331 * entirely safe, but it does appear to work..
333 * without this script being run, on some configurations i've
334 * seen, switching from DP to TMDS on a DP connector may result
335 * in a blank screen (SOR_PWR off/on can restore it)
337 if (outp
&& outp
->info
.type
== DCB_OUTPUT_DP
) {
338 struct nvkm_output_dp
*outpdp
= nvkm_output_dp(outp
);
339 struct nvbios_init init
= {
340 .subdev
= nv_subdev(disp
),
341 .bios
= nvkm_bios(disp
),
344 .offset
= outpdp
->info
.script
[4],
349 atomic_set(&outpdp
->lt
.done
, 0);
354 nv50_disp_intr_unk20_1(struct nv50_disp
*disp
, int head
)
356 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
357 struct nvkm_devinit
*devinit
= device
->devinit
;
358 u32 pclk
= nvkm_rd32(device
, 0x610ad0 + (head
* 0x540)) & 0x3fffff;
360 devinit
->pll_set(devinit
, PLL_VPLL0
+ head
, pclk
);
364 nv50_disp_intr_unk20_2_dp(struct nv50_disp
*disp
, int head
,
365 struct dcb_output
*outp
, u32 pclk
)
367 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
368 struct nvkm_device
*device
= subdev
->device
;
369 const int link
= !(outp
->sorconf
.link
& 1);
370 const int or = ffs(outp
->or) - 1;
371 const u32 soff
= ( or * 0x800);
372 const u32 loff
= (link
* 0x080) + soff
;
373 const u32 ctrl
= nvkm_rd32(device
, 0x610794 + (or * 8));
374 const u32 symbol
= 100000;
375 const s32 vactive
= nvkm_rd32(device
, 0x610af8 + (head
* 0x540)) & 0xffff;
376 const s32 vblanke
= nvkm_rd32(device
, 0x610ae8 + (head
* 0x540)) & 0xffff;
377 const s32 vblanks
= nvkm_rd32(device
, 0x610af0 + (head
* 0x540)) & 0xffff;
378 u32 dpctrl
= nvkm_rd32(device
, 0x61c10c + loff
);
379 u32 clksor
= nvkm_rd32(device
, 0x614300 + soff
);
380 int bestTU
= 0, bestVTUi
= 0, bestVTUf
= 0, bestVTUa
= 0;
381 int TU
, VTUi
, VTUf
, VTUa
;
382 u64 link_data_rate
, link_ratio
, unk
;
383 u32 best_diff
= 64 * symbol
;
384 u32 link_nr
, link_bw
, bits
;
387 link_bw
= (clksor
& 0x000c0000) ? 270000 : 162000;
388 link_nr
= hweight32(dpctrl
& 0x000f0000);
390 /* symbols/hblank - algorithm taken from comments in tegra driver */
391 value
= vblanke
+ vactive
- vblanks
- 7;
392 value
= value
* link_bw
;
394 value
= value
- (3 * !!(dpctrl
& 0x00004000)) - (12 / link_nr
);
395 nvkm_mask(device
, 0x61c1e8 + soff
, 0x0000ffff, value
);
397 /* symbols/vblank - algorithm taken from comments in tegra driver */
398 value
= vblanks
- vblanke
- 25;
399 value
= value
* link_bw
;
401 value
= value
- ((36 / link_nr
) + 3) - 1;
402 nvkm_mask(device
, 0x61c1ec + soff
, 0x00ffffff, value
);
404 /* watermark / activesym */
405 if ((ctrl
& 0xf0000) == 0x60000) bits
= 30;
406 else if ((ctrl
& 0xf0000) == 0x50000) bits
= 24;
409 link_data_rate
= (pclk
* bits
/ 8) / link_nr
;
411 /* calculate ratio of packed data rate to link symbol rate */
412 link_ratio
= link_data_rate
* symbol
;
413 do_div(link_ratio
, link_bw
);
415 for (TU
= 64; TU
>= 32; TU
--) {
416 /* calculate average number of valid symbols in each TU */
417 u32 tu_valid
= link_ratio
* TU
;
420 /* find a hw representation for the fraction.. */
421 VTUi
= tu_valid
/ symbol
;
422 calc
= VTUi
* symbol
;
423 diff
= tu_valid
- calc
;
425 if (diff
>= (symbol
/ 2)) {
426 VTUf
= symbol
/ (symbol
- diff
);
427 if (symbol
- (VTUf
* diff
))
432 calc
+= symbol
- (symbol
/ VTUf
);
440 VTUf
= min((int)(symbol
/ diff
), 15);
441 calc
+= symbol
/ VTUf
;
444 diff
= calc
- tu_valid
;
446 /* no remainder, but the hw doesn't like the fractional
447 * part to be zero. decrement the integer part and
448 * have the fraction add a whole symbol back
455 if (diff
< best_diff
) {
467 nvkm_error(subdev
, "unable to find suitable dp config\n");
471 /* XXX close to vbios numbers, but not right */
472 unk
= (symbol
- link_ratio
) * bestTU
;
478 nvkm_mask(device
, 0x61c10c + loff
, 0x000001fc, bestTU
<< 2);
479 nvkm_mask(device
, 0x61c128 + loff
, 0x010f7f3f, bestVTUa
<< 24 |
481 bestVTUi
<< 8 | unk
);
485 nv50_disp_intr_unk20_2(struct nv50_disp
*disp
, int head
)
487 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
488 struct nvkm_output
*outp
;
489 u32 pclk
= nvkm_rd32(device
, 0x610ad0 + (head
* 0x540)) & 0x3fffff;
490 u32 hval
, hreg
= 0x614200 + (head
* 0x800);
494 outp
= exec_clkcmp(disp
, head
, 0xff, pclk
, &conf
);
498 /* we allow both encoder attach and detach operations to occur
499 * within a single supervisor (ie. modeset) sequence. the
500 * encoder detach scripts quite often switch off power to the
501 * lanes, which requires the link to be re-trained.
503 * this is not generally an issue as the sink "must" (heh)
504 * signal an irq when it's lost sync so the driver can
507 * however, on some boards, if one does not configure at least
508 * the gpu side of the link *before* attaching, then various
509 * things can go horribly wrong (PDISP disappearing from mmio,
510 * third supervisor never happens, etc).
512 * the solution is simply to retrain here, if necessary. last
513 * i checked, the binary driver userspace does not appear to
514 * trigger this situation (it forces an UPDATE between steps).
516 if (outp
->info
.type
== DCB_OUTPUT_DP
) {
517 u32 soff
= (ffs(outp
->info
.or) - 1) * 0x08;
520 if (outp
->info
.location
== 0) {
521 ctrl
= nvkm_rd32(device
, 0x610794 + soff
);
524 ctrl
= nvkm_rd32(device
, 0x610b80 + soff
);
528 switch ((ctrl
& 0x000f0000) >> 16) {
529 case 6: datarate
= pclk
* 30; break;
530 case 5: datarate
= pclk
* 24; break;
533 datarate
= pclk
* 18;
537 if (nvkm_output_dp_train(outp
, datarate
/ soff
, true))
538 OUTP_ERR(outp
, "link not trained before attach");
541 exec_clkcmp(disp
, head
, 0, pclk
, &conf
);
543 if (!outp
->info
.location
&& outp
->info
.type
== DCB_OUTPUT_ANALOG
) {
544 oreg
= 0x614280 + (ffs(outp
->info
.or) - 1) * 0x800;
549 if (!outp
->info
.location
) {
550 if (outp
->info
.type
== DCB_OUTPUT_DP
)
551 nv50_disp_intr_unk20_2_dp(disp
, head
, &outp
->info
, pclk
);
552 oreg
= 0x614300 + (ffs(outp
->info
.or) - 1) * 0x800;
553 oval
= (conf
& 0x0100) ? 0x00000101 : 0x00000000;
557 oreg
= 0x614380 + (ffs(outp
->info
.or) - 1) * 0x800;
563 nvkm_mask(device
, hreg
, 0x0000000f, hval
);
564 nvkm_mask(device
, oreg
, mask
, oval
);
567 /* If programming a TMDS output on a SOR that can also be configured for
568 * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off.
570 * It looks like the VBIOS TMDS scripts make an attempt at this, however,
571 * the VBIOS scripts on at least one board I have only switch it off on
572 * link 0, causing a blank display if the output has previously been
573 * programmed for DisplayPort.
576 nv50_disp_intr_unk40_0_tmds(struct nv50_disp
*disp
,
577 struct dcb_output
*outp
)
579 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
580 struct nvkm_bios
*bios
= device
->bios
;
581 const int link
= !(outp
->sorconf
.link
& 1);
582 const int or = ffs(outp
->or) - 1;
583 const u32 loff
= (or * 0x800) + (link
* 0x80);
584 const u16 mask
= (outp
->sorconf
.link
<< 6) | outp
->or;
585 struct dcb_output match
;
588 if (dcb_outp_match(bios
, DCB_OUTPUT_DP
, mask
, &ver
, &hdr
, &match
))
589 nvkm_mask(device
, 0x61c10c + loff
, 0x00000001, 0x00000000);
593 nv50_disp_intr_unk40_0(struct nv50_disp
*disp
, int head
)
595 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
596 struct nvkm_output
*outp
;
597 u32 pclk
= nvkm_rd32(device
, 0x610ad0 + (head
* 0x540)) & 0x3fffff;
600 outp
= exec_clkcmp(disp
, head
, 1, pclk
, &conf
);
604 if (outp
->info
.location
== 0 && outp
->info
.type
== DCB_OUTPUT_TMDS
)
605 nv50_disp_intr_unk40_0_tmds(disp
, &outp
->info
);
609 nv50_disp_intr_supervisor(struct work_struct
*work
)
611 struct nv50_disp
*disp
=
612 container_of(work
, struct nv50_disp
, supervisor
);
613 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
614 struct nvkm_device
*device
= subdev
->device
;
615 u32 super
= nvkm_rd32(device
, 0x610030);
618 nvkm_debug(subdev
, "supervisor %08x %08x\n", disp
->super
, super
);
620 if (disp
->super
& 0x00000010) {
621 nv50_disp_chan_mthd(disp
->chan
[0], NV_DBG_DEBUG
);
622 for (head
= 0; head
< disp
->head
.nr
; head
++) {
623 if (!(super
& (0x00000020 << head
)))
625 if (!(super
& (0x00000080 << head
)))
627 nv50_disp_intr_unk10_0(disp
, head
);
630 if (disp
->super
& 0x00000020) {
631 for (head
= 0; head
< disp
->head
.nr
; head
++) {
632 if (!(super
& (0x00000080 << head
)))
634 nv50_disp_intr_unk20_0(disp
, head
);
636 for (head
= 0; head
< disp
->head
.nr
; head
++) {
637 if (!(super
& (0x00000200 << head
)))
639 nv50_disp_intr_unk20_1(disp
, head
);
641 for (head
= 0; head
< disp
->head
.nr
; head
++) {
642 if (!(super
& (0x00000080 << head
)))
644 nv50_disp_intr_unk20_2(disp
, head
);
647 if (disp
->super
& 0x00000040) {
648 for (head
= 0; head
< disp
->head
.nr
; head
++) {
649 if (!(super
& (0x00000080 << head
)))
651 nv50_disp_intr_unk40_0(disp
, head
);
655 nvkm_wr32(device
, 0x610030, 0x80000000);
659 nv50_disp_intr(struct nvkm_subdev
*subdev
)
661 struct nv50_disp
*disp
= (void *)subdev
;
662 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
663 u32 intr0
= nvkm_rd32(device
, 0x610020);
664 u32 intr1
= nvkm_rd32(device
, 0x610024);
666 while (intr0
& 0x001f0000) {
667 u32 chid
= __ffs(intr0
& 0x001f0000) - 16;
668 nv50_disp_intr_error(disp
, chid
);
669 intr0
&= ~(0x00010000 << chid
);
672 while (intr0
& 0x0000001f) {
673 u32 chid
= __ffs(intr0
& 0x0000001f);
674 nv50_disp_chan_uevent_send(disp
, chid
);
675 intr0
&= ~(0x00000001 << chid
);
678 if (intr1
& 0x00000004) {
679 nvkm_disp_vblank(&disp
->base
, 0);
680 nvkm_wr32(device
, 0x610024, 0x00000004);
683 if (intr1
& 0x00000008) {
684 nvkm_disp_vblank(&disp
->base
, 1);
685 nvkm_wr32(device
, 0x610024, 0x00000008);
688 if (intr1
& 0x00000070) {
689 disp
->super
= (intr1
& 0x00000070);
690 schedule_work(&disp
->supervisor
);
691 nvkm_wr32(device
, 0x610024, disp
->super
);
695 static const struct nvkm_disp_func
697 .root
= &nv50_disp_root_oclass
,
701 nv50_disp_ctor(struct nvkm_object
*parent
, struct nvkm_object
*engine
,
702 struct nvkm_oclass
*oclass
, void *data
, u32 size
,
703 struct nvkm_object
**pobject
)
705 struct nv50_disp
*disp
;
708 ret
= nvkm_disp_create(parent
, engine
, oclass
, 2, "PDISP",
710 *pobject
= nv_object(disp
);
714 disp
->base
.func
= &nv50_disp
;
716 ret
= nvkm_event_init(&nv50_disp_chan_uevent
, 1, 9, &disp
->uevent
);
720 nv_subdev(disp
)->intr
= nv50_disp_intr
;
721 INIT_WORK(&disp
->supervisor
, nv50_disp_intr_supervisor
);
726 disp
->dac
.power
= nv50_dac_power
;
727 disp
->dac
.sense
= nv50_dac_sense
;
728 disp
->sor
.power
= nv50_sor_power
;
729 disp
->pior
.power
= nv50_pior_power
;
734 nv50_disp_oclass
= &(struct nv50_disp_impl
) {
735 .base
.base
.handle
= NV_ENGINE(DISP
, 0x50),
736 .base
.base
.ofuncs
= &(struct nvkm_ofuncs
) {
737 .ctor
= nv50_disp_ctor
,
738 .dtor
= _nvkm_disp_dtor
,
739 .init
= _nvkm_disp_init
,
740 .fini
= _nvkm_disp_fini
,
742 .base
.outp
.internal
.crt
= nv50_dac_output_new
,
743 .base
.outp
.internal
.tmds
= nv50_sor_output_new
,
744 .base
.outp
.internal
.lvds
= nv50_sor_output_new
,
745 .base
.outp
.external
.tmds
= nv50_pior_output_new
,
746 .base
.outp
.external
.dp
= nv50_pior_dp_new
,
747 .base
.vblank
= &nv50_disp_vblank_func
,
748 .head
.scanoutpos
= nv50_disp_root_scanoutpos
,