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>
30 #include <engine/software.h>
31 #include <engine/disp.h>
33 #include <subdev/timer.h>
34 #include <subdev/fb.h>
35 #include <subdev/bar.h>
36 #include <subdev/clock.h>
38 #include <subdev/bios.h>
39 #include <subdev/bios/dcb.h>
40 #include <subdev/bios/disp.h>
41 #include <subdev/bios/init.h>
42 #include <subdev/bios/pll.h>
46 /*******************************************************************************
47 * EVO DMA channel base class
48 ******************************************************************************/
51 nvd0_disp_dmac_object_attach(struct nouveau_object
*parent
,
52 struct nouveau_object
*object
, u32 name
)
54 struct nv50_disp_base
*base
= (void *)parent
->parent
;
55 struct nv50_disp_chan
*chan
= (void *)parent
;
56 u32 addr
= nv_gpuobj(object
)->node
->offset
;
57 u32 data
= (chan
->chid
<< 27) | (addr
<< 9) | 0x00000001;
58 return nouveau_ramht_insert(base
->ramht
, chan
->chid
, name
, data
);
62 nvd0_disp_dmac_object_detach(struct nouveau_object
*parent
, int cookie
)
64 struct nv50_disp_base
*base
= (void *)parent
->parent
;
65 nouveau_ramht_remove(base
->ramht
, cookie
);
69 nvd0_disp_dmac_init(struct nouveau_object
*object
)
71 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
72 struct nv50_disp_dmac
*dmac
= (void *)object
;
73 int chid
= dmac
->base
.chid
;
76 ret
= nv50_disp_chan_init(&dmac
->base
);
80 /* enable error reporting */
81 nv_mask(priv
, 0x610090, 0x00000001 << chid
, 0x00000001 << chid
);
82 nv_mask(priv
, 0x6100a0, 0x00000001 << chid
, 0x00000001 << chid
);
84 /* initialise channel for dma command submission */
85 nv_wr32(priv
, 0x610494 + (chid
* 0x0010), dmac
->push
);
86 nv_wr32(priv
, 0x610498 + (chid
* 0x0010), 0x00010000);
87 nv_wr32(priv
, 0x61049c + (chid
* 0x0010), 0x00000001);
88 nv_mask(priv
, 0x610490 + (chid
* 0x0010), 0x00000010, 0x00000010);
89 nv_wr32(priv
, 0x640000 + (chid
* 0x1000), 0x00000000);
90 nv_wr32(priv
, 0x610490 + (chid
* 0x0010), 0x00000013);
92 /* wait for it to go inactive */
93 if (!nv_wait(priv
, 0x610490 + (chid
* 0x10), 0x80000000, 0x00000000)) {
94 nv_error(dmac
, "init: 0x%08x\n",
95 nv_rd32(priv
, 0x610490 + (chid
* 0x10)));
103 nvd0_disp_dmac_fini(struct nouveau_object
*object
, bool suspend
)
105 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
106 struct nv50_disp_dmac
*dmac
= (void *)object
;
107 int chid
= dmac
->base
.chid
;
109 /* deactivate channel */
110 nv_mask(priv
, 0x610490 + (chid
* 0x0010), 0x00001010, 0x00001000);
111 nv_mask(priv
, 0x610490 + (chid
* 0x0010), 0x00000003, 0x00000000);
112 if (!nv_wait(priv
, 0x610490 + (chid
* 0x10), 0x001e0000, 0x00000000)) {
113 nv_error(dmac
, "fini: 0x%08x\n",
114 nv_rd32(priv
, 0x610490 + (chid
* 0x10)));
119 /* disable error reporting */
120 nv_mask(priv
, 0x610090, 0x00000001 << chid
, 0x00000000);
121 nv_mask(priv
, 0x6100a0, 0x00000001 << chid
, 0x00000000);
123 return nv50_disp_chan_fini(&dmac
->base
, suspend
);
126 /*******************************************************************************
127 * EVO master channel object
128 ******************************************************************************/
131 nvd0_disp_mast_ctor(struct nouveau_object
*parent
,
132 struct nouveau_object
*engine
,
133 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
134 struct nouveau_object
**pobject
)
136 struct nv50_display_mast_class
*args
= data
;
137 struct nv50_disp_dmac
*mast
;
140 if (size
< sizeof(*args
))
143 ret
= nv50_disp_dmac_create_(parent
, engine
, oclass
, args
->pushbuf
,
144 0, sizeof(*mast
), (void **)&mast
);
145 *pobject
= nv_object(mast
);
149 nv_parent(mast
)->object_attach
= nvd0_disp_dmac_object_attach
;
150 nv_parent(mast
)->object_detach
= nvd0_disp_dmac_object_detach
;
155 nvd0_disp_mast_init(struct nouveau_object
*object
)
157 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
158 struct nv50_disp_dmac
*mast
= (void *)object
;
161 ret
= nv50_disp_chan_init(&mast
->base
);
165 /* enable error reporting */
166 nv_mask(priv
, 0x610090, 0x00000001, 0x00000001);
167 nv_mask(priv
, 0x6100a0, 0x00000001, 0x00000001);
169 /* initialise channel for dma command submission */
170 nv_wr32(priv
, 0x610494, mast
->push
);
171 nv_wr32(priv
, 0x610498, 0x00010000);
172 nv_wr32(priv
, 0x61049c, 0x00000001);
173 nv_mask(priv
, 0x610490, 0x00000010, 0x00000010);
174 nv_wr32(priv
, 0x640000, 0x00000000);
175 nv_wr32(priv
, 0x610490, 0x01000013);
177 /* wait for it to go inactive */
178 if (!nv_wait(priv
, 0x610490, 0x80000000, 0x00000000)) {
179 nv_error(mast
, "init: 0x%08x\n", nv_rd32(priv
, 0x610490));
187 nvd0_disp_mast_fini(struct nouveau_object
*object
, bool suspend
)
189 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
190 struct nv50_disp_dmac
*mast
= (void *)object
;
192 /* deactivate channel */
193 nv_mask(priv
, 0x610490, 0x00000010, 0x00000000);
194 nv_mask(priv
, 0x610490, 0x00000003, 0x00000000);
195 if (!nv_wait(priv
, 0x610490, 0x001e0000, 0x00000000)) {
196 nv_error(mast
, "fini: 0x%08x\n", nv_rd32(priv
, 0x610490));
201 /* disable error reporting */
202 nv_mask(priv
, 0x610090, 0x00000001, 0x00000000);
203 nv_mask(priv
, 0x6100a0, 0x00000001, 0x00000000);
205 return nv50_disp_chan_fini(&mast
->base
, suspend
);
208 struct nouveau_ofuncs
209 nvd0_disp_mast_ofuncs
= {
210 .ctor
= nvd0_disp_mast_ctor
,
211 .dtor
= nv50_disp_dmac_dtor
,
212 .init
= nvd0_disp_mast_init
,
213 .fini
= nvd0_disp_mast_fini
,
214 .rd32
= nv50_disp_chan_rd32
,
215 .wr32
= nv50_disp_chan_wr32
,
218 /*******************************************************************************
219 * EVO sync channel objects
220 ******************************************************************************/
223 nvd0_disp_sync_ctor(struct nouveau_object
*parent
,
224 struct nouveau_object
*engine
,
225 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
226 struct nouveau_object
**pobject
)
228 struct nv50_display_sync_class
*args
= data
;
229 struct nv50_disp_priv
*priv
= (void *)engine
;
230 struct nv50_disp_dmac
*dmac
;
233 if (size
< sizeof(*data
) || args
->head
>= priv
->head
.nr
)
236 ret
= nv50_disp_dmac_create_(parent
, engine
, oclass
, args
->pushbuf
,
237 1 + args
->head
, sizeof(*dmac
),
239 *pobject
= nv_object(dmac
);
243 nv_parent(dmac
)->object_attach
= nvd0_disp_dmac_object_attach
;
244 nv_parent(dmac
)->object_detach
= nvd0_disp_dmac_object_detach
;
248 struct nouveau_ofuncs
249 nvd0_disp_sync_ofuncs
= {
250 .ctor
= nvd0_disp_sync_ctor
,
251 .dtor
= nv50_disp_dmac_dtor
,
252 .init
= nvd0_disp_dmac_init
,
253 .fini
= nvd0_disp_dmac_fini
,
254 .rd32
= nv50_disp_chan_rd32
,
255 .wr32
= nv50_disp_chan_wr32
,
258 /*******************************************************************************
259 * EVO overlay channel objects
260 ******************************************************************************/
263 nvd0_disp_ovly_ctor(struct nouveau_object
*parent
,
264 struct nouveau_object
*engine
,
265 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
266 struct nouveau_object
**pobject
)
268 struct nv50_display_ovly_class
*args
= data
;
269 struct nv50_disp_priv
*priv
= (void *)engine
;
270 struct nv50_disp_dmac
*dmac
;
273 if (size
< sizeof(*data
) || args
->head
>= priv
->head
.nr
)
276 ret
= nv50_disp_dmac_create_(parent
, engine
, oclass
, args
->pushbuf
,
277 5 + args
->head
, sizeof(*dmac
),
279 *pobject
= nv_object(dmac
);
283 nv_parent(dmac
)->object_attach
= nvd0_disp_dmac_object_attach
;
284 nv_parent(dmac
)->object_detach
= nvd0_disp_dmac_object_detach
;
288 struct nouveau_ofuncs
289 nvd0_disp_ovly_ofuncs
= {
290 .ctor
= nvd0_disp_ovly_ctor
,
291 .dtor
= nv50_disp_dmac_dtor
,
292 .init
= nvd0_disp_dmac_init
,
293 .fini
= nvd0_disp_dmac_fini
,
294 .rd32
= nv50_disp_chan_rd32
,
295 .wr32
= nv50_disp_chan_wr32
,
298 /*******************************************************************************
299 * EVO PIO channel base class
300 ******************************************************************************/
303 nvd0_disp_pioc_create_(struct nouveau_object
*parent
,
304 struct nouveau_object
*engine
,
305 struct nouveau_oclass
*oclass
, int chid
,
306 int length
, void **pobject
)
308 return nv50_disp_chan_create_(parent
, engine
, oclass
, chid
,
313 nvd0_disp_pioc_dtor(struct nouveau_object
*object
)
315 struct nv50_disp_pioc
*pioc
= (void *)object
;
316 nv50_disp_chan_destroy(&pioc
->base
);
320 nvd0_disp_pioc_init(struct nouveau_object
*object
)
322 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
323 struct nv50_disp_pioc
*pioc
= (void *)object
;
324 int chid
= pioc
->base
.chid
;
327 ret
= nv50_disp_chan_init(&pioc
->base
);
331 /* enable error reporting */
332 nv_mask(priv
, 0x610090, 0x00000001 << chid
, 0x00000001 << chid
);
333 nv_mask(priv
, 0x6100a0, 0x00000001 << chid
, 0x00000001 << chid
);
335 /* activate channel */
336 nv_wr32(priv
, 0x610490 + (chid
* 0x10), 0x00000001);
337 if (!nv_wait(priv
, 0x610490 + (chid
* 0x10), 0x00030000, 0x00010000)) {
338 nv_error(pioc
, "init: 0x%08x\n",
339 nv_rd32(priv
, 0x610490 + (chid
* 0x10)));
347 nvd0_disp_pioc_fini(struct nouveau_object
*object
, bool suspend
)
349 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
350 struct nv50_disp_pioc
*pioc
= (void *)object
;
351 int chid
= pioc
->base
.chid
;
353 nv_mask(priv
, 0x610490 + (chid
* 0x10), 0x00000001, 0x00000000);
354 if (!nv_wait(priv
, 0x610490 + (chid
* 0x10), 0x00030000, 0x00000000)) {
355 nv_error(pioc
, "timeout: 0x%08x\n",
356 nv_rd32(priv
, 0x610490 + (chid
* 0x10)));
361 /* disable error reporting */
362 nv_mask(priv
, 0x610090, 0x00000001 << chid
, 0x00000000);
363 nv_mask(priv
, 0x6100a0, 0x00000001 << chid
, 0x00000000);
365 return nv50_disp_chan_fini(&pioc
->base
, suspend
);
368 /*******************************************************************************
369 * EVO immediate overlay channel objects
370 ******************************************************************************/
373 nvd0_disp_oimm_ctor(struct nouveau_object
*parent
,
374 struct nouveau_object
*engine
,
375 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
376 struct nouveau_object
**pobject
)
378 struct nv50_display_oimm_class
*args
= data
;
379 struct nv50_disp_priv
*priv
= (void *)engine
;
380 struct nv50_disp_pioc
*pioc
;
383 if (size
< sizeof(*args
) || args
->head
>= priv
->head
.nr
)
386 ret
= nvd0_disp_pioc_create_(parent
, engine
, oclass
, 9 + args
->head
,
387 sizeof(*pioc
), (void **)&pioc
);
388 *pobject
= nv_object(pioc
);
395 struct nouveau_ofuncs
396 nvd0_disp_oimm_ofuncs
= {
397 .ctor
= nvd0_disp_oimm_ctor
,
398 .dtor
= nvd0_disp_pioc_dtor
,
399 .init
= nvd0_disp_pioc_init
,
400 .fini
= nvd0_disp_pioc_fini
,
401 .rd32
= nv50_disp_chan_rd32
,
402 .wr32
= nv50_disp_chan_wr32
,
405 /*******************************************************************************
406 * EVO cursor channel objects
407 ******************************************************************************/
410 nvd0_disp_curs_ctor(struct nouveau_object
*parent
,
411 struct nouveau_object
*engine
,
412 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
413 struct nouveau_object
**pobject
)
415 struct nv50_display_curs_class
*args
= data
;
416 struct nv50_disp_priv
*priv
= (void *)engine
;
417 struct nv50_disp_pioc
*pioc
;
420 if (size
< sizeof(*args
) || args
->head
>= priv
->head
.nr
)
423 ret
= nvd0_disp_pioc_create_(parent
, engine
, oclass
, 13 + args
->head
,
424 sizeof(*pioc
), (void **)&pioc
);
425 *pobject
= nv_object(pioc
);
432 struct nouveau_ofuncs
433 nvd0_disp_curs_ofuncs
= {
434 .ctor
= nvd0_disp_curs_ctor
,
435 .dtor
= nvd0_disp_pioc_dtor
,
436 .init
= nvd0_disp_pioc_init
,
437 .fini
= nvd0_disp_pioc_fini
,
438 .rd32
= nv50_disp_chan_rd32
,
439 .wr32
= nv50_disp_chan_wr32
,
442 /*******************************************************************************
443 * Base display object
444 ******************************************************************************/
447 nvd0_disp_base_ctor(struct nouveau_object
*parent
,
448 struct nouveau_object
*engine
,
449 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
450 struct nouveau_object
**pobject
)
452 struct nv50_disp_priv
*priv
= (void *)engine
;
453 struct nv50_disp_base
*base
;
456 ret
= nouveau_parent_create(parent
, engine
, oclass
, 0,
457 priv
->sclass
, 0, &base
);
458 *pobject
= nv_object(base
);
462 return nouveau_ramht_new(parent
, parent
, 0x1000, 0, &base
->ramht
);
466 nvd0_disp_base_dtor(struct nouveau_object
*object
)
468 struct nv50_disp_base
*base
= (void *)object
;
469 nouveau_ramht_ref(NULL
, &base
->ramht
);
470 nouveau_parent_destroy(&base
->base
);
474 nvd0_disp_base_init(struct nouveau_object
*object
)
476 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
477 struct nv50_disp_base
*base
= (void *)object
;
481 ret
= nouveau_parent_init(&base
->base
);
485 /* The below segments of code copying values from one register to
486 * another appear to inform EVO of the display capabilities or
491 for (i
= 0; i
< priv
->head
.nr
; i
++) {
492 tmp
= nv_rd32(priv
, 0x616104 + (i
* 0x800));
493 nv_wr32(priv
, 0x6101b4 + (i
* 0x800), tmp
);
494 tmp
= nv_rd32(priv
, 0x616108 + (i
* 0x800));
495 nv_wr32(priv
, 0x6101b8 + (i
* 0x800), tmp
);
496 tmp
= nv_rd32(priv
, 0x61610c + (i
* 0x800));
497 nv_wr32(priv
, 0x6101bc + (i
* 0x800), tmp
);
501 for (i
= 0; i
< priv
->dac
.nr
; i
++) {
502 tmp
= nv_rd32(priv
, 0x61a000 + (i
* 0x800));
503 nv_wr32(priv
, 0x6101c0 + (i
* 0x800), tmp
);
507 for (i
= 0; i
< priv
->sor
.nr
; i
++) {
508 tmp
= nv_rd32(priv
, 0x61c000 + (i
* 0x800));
509 nv_wr32(priv
, 0x6301c4 + (i
* 0x800), tmp
);
512 /* steal display away from vbios, or something like that */
513 if (nv_rd32(priv
, 0x6100ac) & 0x00000100) {
514 nv_wr32(priv
, 0x6100ac, 0x00000100);
515 nv_mask(priv
, 0x6194e8, 0x00000001, 0x00000000);
516 if (!nv_wait(priv
, 0x6194e8, 0x00000002, 0x00000000)) {
517 nv_error(priv
, "timeout acquiring display\n");
522 /* point at display engine memory area (hash table, objects) */
523 nv_wr32(priv
, 0x610010, (nv_gpuobj(object
->parent
)->addr
>> 8) | 9);
525 /* enable supervisor interrupts, disable everything else */
526 nv_wr32(priv
, 0x610090, 0x00000000);
527 nv_wr32(priv
, 0x6100a0, 0x00000000);
528 nv_wr32(priv
, 0x6100b0, 0x00000307);
534 nvd0_disp_base_fini(struct nouveau_object
*object
, bool suspend
)
536 struct nv50_disp_priv
*priv
= (void *)object
->engine
;
537 struct nv50_disp_base
*base
= (void *)object
;
539 /* disable all interrupts */
540 nv_wr32(priv
, 0x6100b0, 0x00000000);
542 return nouveau_parent_fini(&base
->base
, suspend
);
545 struct nouveau_ofuncs
546 nvd0_disp_base_ofuncs
= {
547 .ctor
= nvd0_disp_base_ctor
,
548 .dtor
= nvd0_disp_base_dtor
,
549 .init
= nvd0_disp_base_init
,
550 .fini
= nvd0_disp_base_fini
,
553 static struct nouveau_oclass
554 nvd0_disp_base_oclass
[] = {
555 { NVD0_DISP_CLASS
, &nvd0_disp_base_ofuncs
, nva3_disp_base_omthds
},
559 static struct nouveau_oclass
560 nvd0_disp_sclass
[] = {
561 { NVD0_DISP_MAST_CLASS
, &nvd0_disp_mast_ofuncs
},
562 { NVD0_DISP_SYNC_CLASS
, &nvd0_disp_sync_ofuncs
},
563 { NVD0_DISP_OVLY_CLASS
, &nvd0_disp_ovly_ofuncs
},
564 { NVD0_DISP_OIMM_CLASS
, &nvd0_disp_oimm_ofuncs
},
565 { NVD0_DISP_CURS_CLASS
, &nvd0_disp_curs_ofuncs
},
569 /*******************************************************************************
570 * Display engine implementation
571 ******************************************************************************/
574 exec_lookup(struct nv50_disp_priv
*priv
, int head
, int outp
, u32 ctrl
,
575 struct dcb_output
*dcb
, u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
,
576 struct nvbios_outp
*info
)
578 struct nouveau_bios
*bios
= nouveau_bios(priv
);
583 type
= DCB_OUTPUT_ANALOG
;
587 switch (ctrl
& 0x00000f00) {
588 case 0x00000000: type
= DCB_OUTPUT_LVDS
; mask
= 1; break;
589 case 0x00000100: type
= DCB_OUTPUT_TMDS
; mask
= 1; break;
590 case 0x00000200: type
= DCB_OUTPUT_TMDS
; mask
= 2; break;
591 case 0x00000500: type
= DCB_OUTPUT_TMDS
; mask
= 3; break;
592 case 0x00000800: type
= DCB_OUTPUT_DP
; mask
= 1; break;
593 case 0x00000900: type
= DCB_OUTPUT_DP
; mask
= 2; break;
595 nv_error(priv
, "unknown SOR mc 0x%08x\n", ctrl
);
598 dcb
->sorconf
.link
= mask
;
601 mask
= 0x00c0 & (mask
<< 6);
602 mask
|= 0x0001 << outp
;
603 mask
|= 0x0100 << head
;
605 /* this is a tad special, but for the moment its needed to get
606 * all the dcb data required by the vbios scripts.. will be cleaned
607 * up later as more bits are moved to the core..
609 while ((data
= dcb_outp(bios
, idx
++, ver
, hdr
))) {
610 u32 conn
= nv_ro32(bios
, data
+ 0);
611 u32 conf
= nv_ro32(bios
, data
+ 4);
612 if ((conn
& 0x00300000) ||
613 (conn
& 0x0000000f) != type
||
614 (conn
& 0x0f000000) != (0x01000000 << outp
))
617 if ( (mask
& 0x00c0) && (mask
& 0x00c0) !=
618 ((mask
& 0x00c0) & ((conf
& 0x00000030) << 2)))
623 dcb
->connector
= (conn
& 0x0000f000) >> 12;
625 return nvbios_outp_match(bios
, type
, mask
, ver
, hdr
, cnt
, len
, info
);
632 exec_script(struct nv50_disp_priv
*priv
, int head
, int outp
, u32 ctrl
, int id
)
634 struct nouveau_bios
*bios
= nouveau_bios(priv
);
635 struct nvbios_outp info
;
636 struct dcb_output dcb
;
637 u8 ver
, hdr
, cnt
, len
;
640 data
= exec_lookup(priv
, head
, outp
, ctrl
, &dcb
, &ver
, &hdr
, &cnt
, &len
, &info
);
642 struct nvbios_init init
= {
643 .subdev
= nv_subdev(priv
),
645 .offset
= info
.script
[id
],
651 return nvbios_exec(&init
) == 0;
658 exec_clkcmp(struct nv50_disp_priv
*priv
, int head
, int outp
,
659 u32 ctrl
, u32 conf
, int id
, u32 pclk
)
661 struct nouveau_bios
*bios
= nouveau_bios(priv
);
662 struct nvbios_outp info1
;
663 struct nvbios_ocfg info2
;
664 struct dcb_output dcb
;
665 u8 ver
, hdr
, cnt
, len
;
668 data
= exec_lookup(priv
, head
, outp
, ctrl
, &dcb
, &ver
, &hdr
, &cnt
, &len
, &info1
);
670 data
= nvbios_ocfg_match(bios
, data
, conf
, &ver
, &hdr
, &cnt
, &len
, &info2
);
672 data
= nvbios_oclk_match(bios
, info2
.clkcmp
[id
], pclk
);
674 struct nvbios_init init
= {
675 .subdev
= nv_subdev(priv
),
683 return nvbios_exec(&init
) == 0;
692 nvd0_display_unk1_handler(struct nv50_disp_priv
*priv
, u32 head
, u32 mask
)
696 for (i
= 0; mask
&& i
< 8; i
++) {
697 u32 mcc
= nv_rd32(priv
, 0x640180 + (i
* 0x20));
698 if (mcc
& (1 << head
))
699 exec_script(priv
, head
, i
, mcc
, 1);
702 nv_wr32(priv
, 0x6101d4, 0x00000000);
703 nv_wr32(priv
, 0x6109d4, 0x00000000);
704 nv_wr32(priv
, 0x6101d0, 0x80000000);
708 nvd0_display_unk2_handler(struct nv50_disp_priv
*priv
, u32 head
, u32 mask
)
713 for (i
= 0; mask
&& i
< 8; i
++) {
714 u32 mcc
= nv_rd32(priv
, 0x640180 + (i
* 0x20));
715 if (mcc
& (1 << head
))
716 exec_script(priv
, head
, i
, mcc
, 2);
719 pclk
= nv_rd32(priv
, 0x660450 + (head
* 0x300)) / 1000;
720 nv_debug(priv
, "head %d pclk %d mask 0x%08x\n", head
, pclk
, mask
);
721 if (pclk
&& (mask
& 0x00010000)) {
722 struct nouveau_clock
*clk
= nouveau_clock(priv
);
723 clk
->pll_set(clk
, PLL_VPLL0
+ head
, pclk
);
726 nv_wr32(priv
, 0x612200 + (head
* 0x800), 0x00000000);
728 for (i
= 0; mask
&& i
< 8; i
++) {
729 u32 mcp
= nv_rd32(priv
, 0x660180 + (i
* 0x20));
730 u32 cfg
= nv_rd32(priv
, 0x660184 + (i
* 0x20));
731 if (mcp
& (1 << head
)) {
732 if (exec_clkcmp(priv
, head
, i
, mcp
, cfg
, 0, pclk
)) {
733 u32 addr
, mask
, data
= 0x00000000;
735 addr
= 0x612280 + ((i
- 0) * 0x800);
738 addr
= 0x612300 + ((i
- 4) * 0x800);
740 if (cfg
& 0x00000100)
743 nv_mask(priv
, addr
, mask
, data
);
749 nv_wr32(priv
, 0x6101d4, 0x00000000);
750 nv_wr32(priv
, 0x6109d4, 0x00000000);
751 nv_wr32(priv
, 0x6101d0, 0x80000000);
755 nvd0_display_unk4_handler(struct nv50_disp_priv
*priv
, u32 head
, u32 mask
)
759 pclk
= nv_rd32(priv
, 0x660450 + (head
* 0x300)) / 1000;
761 for (i
= 0; mask
&& i
< 8; i
++) {
762 u32 mcp
= nv_rd32(priv
, 0x660180 + (i
* 0x20));
763 u32 cfg
= nv_rd32(priv
, 0x660184 + (i
* 0x20));
764 if (mcp
& (1 << head
))
765 exec_clkcmp(priv
, head
, i
, mcp
, cfg
, 1, pclk
);
768 nv_wr32(priv
, 0x6101d4, 0x00000000);
769 nv_wr32(priv
, 0x6109d4, 0x00000000);
770 nv_wr32(priv
, 0x6101d0, 0x80000000);
774 nvd0_disp_intr_vblank(struct nv50_disp_priv
*priv
, int crtc
)
776 struct nouveau_bar
*bar
= nouveau_bar(priv
);
777 struct nouveau_disp
*disp
= &priv
->base
;
778 struct nouveau_software_chan
*chan
, *temp
;
781 spin_lock_irqsave(&disp
->vblank
.lock
, flags
);
782 list_for_each_entry_safe(chan
, temp
, &disp
->vblank
.list
, vblank
.head
) {
783 if (chan
->vblank
.crtc
!= crtc
)
786 nv_wr32(priv
, 0x001718, 0x80000000 | chan
->vblank
.channel
);
788 nv_wr32(priv
, 0x06000c, upper_32_bits(chan
->vblank
.offset
));
789 nv_wr32(priv
, 0x060010, lower_32_bits(chan
->vblank
.offset
));
790 nv_wr32(priv
, 0x060014, chan
->vblank
.value
);
792 list_del(&chan
->vblank
.head
);
793 if (disp
->vblank
.put
)
794 disp
->vblank
.put(disp
->vblank
.data
, crtc
);
796 spin_unlock_irqrestore(&disp
->vblank
.lock
, flags
);
798 if (disp
->vblank
.notify
)
799 disp
->vblank
.notify(disp
->vblank
.data
, crtc
);
803 nvd0_disp_intr(struct nouveau_subdev
*subdev
)
805 struct nv50_disp_priv
*priv
= (void *)subdev
;
806 u32 intr
= nv_rd32(priv
, 0x610088);
809 if (intr
& 0x00000001) {
810 u32 stat
= nv_rd32(priv
, 0x61008c);
811 nv_wr32(priv
, 0x61008c, stat
);
815 if (intr
& 0x00000002) {
816 u32 stat
= nv_rd32(priv
, 0x61009c);
817 int chid
= ffs(stat
) - 1;
819 u32 mthd
= nv_rd32(priv
, 0x6101f0 + (chid
* 12));
820 u32 data
= nv_rd32(priv
, 0x6101f4 + (chid
* 12));
821 u32 unkn
= nv_rd32(priv
, 0x6101f8 + (chid
* 12));
823 nv_error(priv
, "chid %d mthd 0x%04x data 0x%08x "
825 chid
, (mthd
& 0x0000ffc), data
, mthd
, unkn
);
826 nv_wr32(priv
, 0x61009c, (1 << chid
));
827 nv_wr32(priv
, 0x6101f0 + (chid
* 12), 0x90000000);
833 if (intr
& 0x00100000) {
834 u32 stat
= nv_rd32(priv
, 0x6100ac);
835 u32 mask
= 0, crtc
= ~0;
837 while (!mask
&& ++crtc
< priv
->head
.nr
)
838 mask
= nv_rd32(priv
, 0x6101d4 + (crtc
* 0x800));
840 if (stat
& 0x00000001) {
841 nv_wr32(priv
, 0x6100ac, 0x00000001);
842 nvd0_display_unk1_handler(priv
, crtc
, mask
);
846 if (stat
& 0x00000002) {
847 nv_wr32(priv
, 0x6100ac, 0x00000002);
848 nvd0_display_unk2_handler(priv
, crtc
, mask
);
852 if (stat
& 0x00000004) {
853 nv_wr32(priv
, 0x6100ac, 0x00000004);
854 nvd0_display_unk4_handler(priv
, crtc
, mask
);
859 nv_info(priv
, "unknown intr24 0x%08x\n", stat
);
860 nv_wr32(priv
, 0x6100ac, stat
);
866 for (i
= 0; i
< priv
->head
.nr
; i
++) {
867 u32 mask
= 0x01000000 << i
;
869 u32 stat
= nv_rd32(priv
, 0x6100bc + (i
* 0x800));
870 if (stat
& 0x00000001)
871 nvd0_disp_intr_vblank(priv
, i
);
872 nv_mask(priv
, 0x6100bc + (i
* 0x800), 0, 0);
873 nv_rd32(priv
, 0x6100c0 + (i
* 0x800));
879 nvd0_disp_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
880 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
881 struct nouveau_object
**pobject
)
883 struct nv50_disp_priv
*priv
;
886 ret
= nouveau_disp_create(parent
, engine
, oclass
, "PDISP",
888 *pobject
= nv_object(priv
);
892 nv_engine(priv
)->sclass
= nvd0_disp_base_oclass
;
893 nv_engine(priv
)->cclass
= &nv50_disp_cclass
;
894 nv_subdev(priv
)->intr
= nvd0_disp_intr
;
895 priv
->sclass
= nvd0_disp_sclass
;
896 priv
->head
.nr
= nv_rd32(priv
, 0x022448);
899 priv
->sor
.dp_train
= nvd0_sor_dp_train
;
900 priv
->sor
.dp_lnkctl
= nvd0_sor_dp_lnkctl
;
901 priv
->sor
.dp_drvctl
= nvd0_sor_dp_drvctl
;
903 INIT_LIST_HEAD(&priv
->base
.vblank
.list
);
904 spin_lock_init(&priv
->base
.vblank
.lock
);
908 struct nouveau_oclass
910 .handle
= NV_ENGINE(DISP
, 0x90),
911 .ofuncs
= &(struct nouveau_ofuncs
) {
912 .ctor
= nvd0_disp_ctor
,
913 .dtor
= _nouveau_disp_dtor
,
914 .init
= _nouveau_disp_init
,
915 .fini
= _nouveau_disp_fini
,