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 <subdev/bios.h>
28 #include <subdev/bios/disp.h>
29 #include <subdev/bios/init.h>
30 #include <subdev/bios/pll.h>
31 #include <subdev/devinit.h>
34 gf119_disp_vblank_init(struct nv50_disp
*disp
, int head
)
36 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
37 nvkm_mask(device
, 0x6100c0 + (head
* 0x800), 0x00000001, 0x00000001);
41 gf119_disp_vblank_fini(struct nv50_disp
*disp
, int head
)
43 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
44 nvkm_mask(device
, 0x6100c0 + (head
* 0x800), 0x00000001, 0x00000000);
47 static struct nvkm_output
*
48 exec_lookup(struct nv50_disp
*disp
, int head
, int or, u32 ctrl
,
49 u32
*data
, u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
,
50 struct nvbios_outp
*info
)
52 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
53 struct nvkm_bios
*bios
= subdev
->device
->bios
;
54 struct nvkm_output
*outp
;
58 type
= DCB_OUTPUT_ANALOG
;
62 switch (ctrl
& 0x00000f00) {
63 case 0x00000000: type
= DCB_OUTPUT_LVDS
; mask
= 1; break;
64 case 0x00000100: type
= DCB_OUTPUT_TMDS
; mask
= 1; break;
65 case 0x00000200: type
= DCB_OUTPUT_TMDS
; mask
= 2; break;
66 case 0x00000500: type
= DCB_OUTPUT_TMDS
; mask
= 3; break;
67 case 0x00000800: type
= DCB_OUTPUT_DP
; mask
= 1; break;
68 case 0x00000900: type
= DCB_OUTPUT_DP
; mask
= 2; break;
70 nvkm_error(subdev
, "unknown SOR mc %08x\n", ctrl
);
75 mask
= 0x00c0 & (mask
<< 6);
77 mask
|= 0x0100 << head
;
80 list_for_each_entry(outp
, &disp
->base
.outp
, head
) {
81 if ((outp
->info
.hasht
& 0xff) == type
&&
82 (outp
->info
.hashm
& mask
) == mask
) {
83 *data
= nvbios_outp_match(bios
, outp
->info
.hasht
,
85 ver
, hdr
, cnt
, len
, info
);
95 static struct nvkm_output
*
96 exec_script(struct nv50_disp
*disp
, int head
, int id
)
98 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
99 struct nvkm_device
*device
= subdev
->device
;
100 struct nvkm_bios
*bios
= device
->bios
;
101 struct nvkm_output
*outp
;
102 struct nvbios_outp info
;
103 u8 ver
, hdr
, cnt
, len
;
107 for (or = 0; !(ctrl
& (1 << head
)) && or < 8; or++) {
108 ctrl
= nvkm_rd32(device
, 0x640180 + (or * 0x20));
109 if (ctrl
& (1 << head
))
116 outp
= exec_lookup(disp
, head
, or, ctrl
, &data
, &ver
, &hdr
, &cnt
, &len
, &info
);
118 struct nvbios_init init
= {
121 .offset
= info
.script
[id
],
133 static struct nvkm_output
*
134 exec_clkcmp(struct nv50_disp
*disp
, int head
, int id
, u32 pclk
, u32
*conf
)
136 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
137 struct nvkm_device
*device
= subdev
->device
;
138 struct nvkm_bios
*bios
= device
->bios
;
139 struct nvkm_output
*outp
;
140 struct nvbios_outp info1
;
141 struct nvbios_ocfg info2
;
142 u8 ver
, hdr
, cnt
, len
;
146 for (or = 0; !(ctrl
& (1 << head
)) && or < 8; or++) {
147 ctrl
= nvkm_rd32(device
, 0x660180 + (or * 0x20));
148 if (ctrl
& (1 << head
))
155 outp
= exec_lookup(disp
, head
, or, ctrl
, &data
, &ver
, &hdr
, &cnt
, &len
, &info1
);
159 *conf
= (ctrl
& 0x00000f00) >> 8;
160 switch (outp
->info
.type
) {
161 case DCB_OUTPUT_TMDS
:
165 case DCB_OUTPUT_LVDS
:
166 *conf
|= disp
->sor
.lvdsconf
;
172 data
= nvbios_ocfg_match(bios
, data
, *conf
& 0xff, *conf
>> 8,
173 &ver
, &hdr
, &cnt
, &len
, &info2
);
174 if (data
&& id
< 0xff) {
175 data
= nvbios_oclk_match(bios
, info2
.clkcmp
[id
], pclk
);
177 struct nvbios_init init
= {
194 gf119_disp_intr_unk1_0(struct nv50_disp
*disp
, int head
)
196 exec_script(disp
, head
, 1);
200 gf119_disp_intr_unk2_0(struct nv50_disp
*disp
, int head
)
202 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
203 struct nvkm_output
*outp
= exec_script(disp
, head
, 2);
205 /* see note in nv50_disp_intr_unk20_0() */
206 if (outp
&& outp
->info
.type
== DCB_OUTPUT_DP
) {
207 struct nvkm_output_dp
*outpdp
= nvkm_output_dp(outp
);
208 struct nvbios_init init
= {
210 .bios
= subdev
->device
->bios
,
213 .offset
= outpdp
->info
.script
[4],
218 atomic_set(&outpdp
->lt
.done
, 0);
223 gf119_disp_intr_unk2_1(struct nv50_disp
*disp
, int head
)
225 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
226 struct nvkm_devinit
*devinit
= device
->devinit
;
227 u32 pclk
= nvkm_rd32(device
, 0x660450 + (head
* 0x300)) / 1000;
229 nvkm_devinit_pll_set(devinit
, PLL_VPLL0
+ head
, pclk
);
230 nvkm_wr32(device
, 0x612200 + (head
* 0x800), 0x00000000);
234 gf119_disp_intr_unk2_2_tu(struct nv50_disp
*disp
, int head
,
235 struct dcb_output
*outp
)
237 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
238 const int or = ffs(outp
->or) - 1;
239 const u32 ctrl
= nvkm_rd32(device
, 0x660200 + (or * 0x020));
240 const u32 conf
= nvkm_rd32(device
, 0x660404 + (head
* 0x300));
241 const s32 vactive
= nvkm_rd32(device
, 0x660414 + (head
* 0x300)) & 0xffff;
242 const s32 vblanke
= nvkm_rd32(device
, 0x66041c + (head
* 0x300)) & 0xffff;
243 const s32 vblanks
= nvkm_rd32(device
, 0x660420 + (head
* 0x300)) & 0xffff;
244 const u32 pclk
= nvkm_rd32(device
, 0x660450 + (head
* 0x300)) / 1000;
245 const u32 link
= ((ctrl
& 0xf00) == 0x800) ? 0 : 1;
246 const u32 hoff
= (head
* 0x800);
247 const u32 soff
= ( or * 0x800);
248 const u32 loff
= (link
* 0x080) + soff
;
249 const u32 symbol
= 100000;
251 u32 dpctrl
= nvkm_rd32(device
, 0x61c10c + loff
);
252 u32 clksor
= nvkm_rd32(device
, 0x612300 + soff
);
253 u32 datarate
, link_nr
, link_bw
, bits
;
256 link_nr
= hweight32(dpctrl
& 0x000f0000);
257 link_bw
= (clksor
& 0x007c0000) >> 18;
260 /* symbols/hblank - algorithm taken from comments in tegra driver */
261 value
= vblanke
+ vactive
- vblanks
- 7;
262 value
= value
* link_bw
;
264 value
= value
- (3 * !!(dpctrl
& 0x00004000)) - (12 / link_nr
);
265 nvkm_mask(device
, 0x616620 + hoff
, 0x0000ffff, value
);
267 /* symbols/vblank - algorithm taken from comments in tegra driver */
268 value
= vblanks
- vblanke
- 25;
269 value
= value
* link_bw
;
271 value
= value
- ((36 / link_nr
) + 3) - 1;
272 nvkm_mask(device
, 0x616624 + hoff
, 0x00ffffff, value
);
275 if ((conf
& 0x3c0) == 0x180) bits
= 30;
276 else if ((conf
& 0x3c0) == 0x140) bits
= 24;
278 datarate
= (pclk
* bits
) / 8;
282 do_div(ratio
, link_nr
* link_bw
);
284 value
= (symbol
- ratio
) * TU
;
286 do_div(value
, symbol
);
287 do_div(value
, symbol
);
292 nvkm_wr32(device
, 0x616610 + hoff
, value
);
296 gf119_disp_intr_unk2_2(struct nv50_disp
*disp
, int head
)
298 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
299 struct nvkm_output
*outp
;
300 u32 pclk
= nvkm_rd32(device
, 0x660450 + (head
* 0x300)) / 1000;
301 u32 conf
, addr
, data
;
303 outp
= exec_clkcmp(disp
, head
, 0xff, pclk
, &conf
);
307 /* see note in nv50_disp_intr_unk20_2() */
308 if (outp
->info
.type
== DCB_OUTPUT_DP
) {
309 u32 sync
= nvkm_rd32(device
, 0x660404 + (head
* 0x300));
310 switch ((sync
& 0x000003c0) >> 6) {
311 case 6: pclk
= pclk
* 30; break;
312 case 5: pclk
= pclk
* 24; break;
319 if (nvkm_output_dp_train(outp
, pclk
, true))
320 OUTP_ERR(outp
, "link not trained before attach");
322 if (disp
->func
->sor
.magic
)
323 disp
->func
->sor
.magic(outp
);
326 exec_clkcmp(disp
, head
, 0, pclk
, &conf
);
328 if (outp
->info
.type
== DCB_OUTPUT_ANALOG
) {
329 addr
= 0x612280 + (ffs(outp
->info
.or) - 1) * 0x800;
332 addr
= 0x612300 + (ffs(outp
->info
.or) - 1) * 0x800;
333 data
= (conf
& 0x0100) ? 0x00000101 : 0x00000000;
334 switch (outp
->info
.type
) {
335 case DCB_OUTPUT_TMDS
:
336 nvkm_mask(device
, addr
, 0x007c0000, 0x00280000);
339 gf119_disp_intr_unk2_2_tu(disp
, head
, &outp
->info
);
346 nvkm_mask(device
, addr
, 0x00000707, data
);
350 gf119_disp_intr_unk4_0(struct nv50_disp
*disp
, int head
)
352 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
353 u32 pclk
= nvkm_rd32(device
, 0x660450 + (head
* 0x300)) / 1000;
356 exec_clkcmp(disp
, head
, 1, pclk
, &conf
);
360 gf119_disp_intr_supervisor(struct work_struct
*work
)
362 struct nv50_disp
*disp
=
363 container_of(work
, struct nv50_disp
, supervisor
);
364 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
365 struct nvkm_device
*device
= subdev
->device
;
369 nvkm_debug(subdev
, "supervisor %d\n", ffs(disp
->super
));
370 for (head
= 0; head
< disp
->base
.head
.nr
; head
++) {
371 mask
[head
] = nvkm_rd32(device
, 0x6101d4 + (head
* 0x800));
372 nvkm_debug(subdev
, "head %d: %08x\n", head
, mask
[head
]);
375 if (disp
->super
& 0x00000001) {
376 nv50_disp_chan_mthd(disp
->chan
[0], NV_DBG_DEBUG
);
377 for (head
= 0; head
< disp
->base
.head
.nr
; head
++) {
378 if (!(mask
[head
] & 0x00001000))
380 nvkm_debug(subdev
, "supervisor 1.0 - head %d\n", head
);
381 gf119_disp_intr_unk1_0(disp
, head
);
384 if (disp
->super
& 0x00000002) {
385 for (head
= 0; head
< disp
->base
.head
.nr
; head
++) {
386 if (!(mask
[head
] & 0x00001000))
388 nvkm_debug(subdev
, "supervisor 2.0 - head %d\n", head
);
389 gf119_disp_intr_unk2_0(disp
, head
);
391 for (head
= 0; head
< disp
->base
.head
.nr
; head
++) {
392 if (!(mask
[head
] & 0x00010000))
394 nvkm_debug(subdev
, "supervisor 2.1 - head %d\n", head
);
395 gf119_disp_intr_unk2_1(disp
, head
);
397 for (head
= 0; head
< disp
->base
.head
.nr
; head
++) {
398 if (!(mask
[head
] & 0x00001000))
400 nvkm_debug(subdev
, "supervisor 2.2 - head %d\n", head
);
401 gf119_disp_intr_unk2_2(disp
, head
);
404 if (disp
->super
& 0x00000004) {
405 for (head
= 0; head
< disp
->base
.head
.nr
; head
++) {
406 if (!(mask
[head
] & 0x00001000))
408 nvkm_debug(subdev
, "supervisor 3.0 - head %d\n", head
);
409 gf119_disp_intr_unk4_0(disp
, head
);
413 for (head
= 0; head
< disp
->base
.head
.nr
; head
++)
414 nvkm_wr32(device
, 0x6101d4 + (head
* 0x800), 0x00000000);
415 nvkm_wr32(device
, 0x6101d0, 0x80000000);
419 gf119_disp_intr_error(struct nv50_disp
*disp
, int chid
)
421 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
422 struct nvkm_device
*device
= subdev
->device
;
423 u32 mthd
= nvkm_rd32(device
, 0x6101f0 + (chid
* 12));
424 u32 data
= nvkm_rd32(device
, 0x6101f4 + (chid
* 12));
425 u32 unkn
= nvkm_rd32(device
, 0x6101f8 + (chid
* 12));
427 nvkm_error(subdev
, "chid %d mthd %04x data %08x %08x %08x\n",
428 chid
, (mthd
& 0x0000ffc), data
, mthd
, unkn
);
430 if (chid
< ARRAY_SIZE(disp
->chan
)) {
431 switch (mthd
& 0xffc) {
433 nv50_disp_chan_mthd(disp
->chan
[chid
], NV_DBG_ERROR
);
440 nvkm_wr32(device
, 0x61009c, (1 << chid
));
441 nvkm_wr32(device
, 0x6101f0 + (chid
* 12), 0x90000000);
445 gf119_disp_intr(struct nv50_disp
*disp
)
447 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
448 struct nvkm_device
*device
= subdev
->device
;
449 u32 intr
= nvkm_rd32(device
, 0x610088);
452 if (intr
& 0x00000001) {
453 u32 stat
= nvkm_rd32(device
, 0x61008c);
455 int chid
= __ffs(stat
); stat
&= ~(1 << chid
);
456 nv50_disp_chan_uevent_send(disp
, chid
);
457 nvkm_wr32(device
, 0x61008c, 1 << chid
);
462 if (intr
& 0x00000002) {
463 u32 stat
= nvkm_rd32(device
, 0x61009c);
464 int chid
= ffs(stat
) - 1;
466 gf119_disp_intr_error(disp
, chid
);
470 if (intr
& 0x00100000) {
471 u32 stat
= nvkm_rd32(device
, 0x6100ac);
472 if (stat
& 0x00000007) {
473 disp
->super
= (stat
& 0x00000007);
474 schedule_work(&disp
->supervisor
);
475 nvkm_wr32(device
, 0x6100ac, disp
->super
);
480 nvkm_warn(subdev
, "intr24 %08x\n", stat
);
481 nvkm_wr32(device
, 0x6100ac, stat
);
487 for (i
= 0; i
< disp
->base
.head
.nr
; i
++) {
488 u32 mask
= 0x01000000 << i
;
490 u32 stat
= nvkm_rd32(device
, 0x6100bc + (i
* 0x800));
491 if (stat
& 0x00000001)
492 nvkm_disp_vblank(&disp
->base
, i
);
493 nvkm_mask(device
, 0x6100bc + (i
* 0x800), 0, 0);
494 nvkm_rd32(device
, 0x6100c0 + (i
* 0x800));
500 gf119_disp_new_(const struct nv50_disp_func
*func
, struct nvkm_device
*device
,
501 int index
, struct nvkm_disp
**pdisp
)
503 u32 heads
= nvkm_rd32(device
, 0x022448);
504 return nv50_disp_new_(func
, device
, index
, heads
, pdisp
);
507 static const struct nv50_disp_func
509 .intr
= gf119_disp_intr
,
510 .uevent
= &gf119_disp_chan_uevent
,
511 .super
= gf119_disp_intr_supervisor
,
512 .root
= &gf119_disp_root_oclass
,
513 .head
.vblank_init
= gf119_disp_vblank_init
,
514 .head
.vblank_fini
= gf119_disp_vblank_fini
,
515 .head
.scanoutpos
= gf119_disp_root_scanoutpos
,
516 .outp
.internal
.crt
= nv50_dac_output_new
,
517 .outp
.internal
.tmds
= nv50_sor_output_new
,
518 .outp
.internal
.lvds
= nv50_sor_output_new
,
519 .outp
.internal
.dp
= gf119_sor_dp_new
,
521 .dac
.power
= nv50_dac_power
,
522 .dac
.sense
= nv50_dac_sense
,
524 .sor
.power
= nv50_sor_power
,
525 .sor
.hda_eld
= gf119_hda_eld
,
526 .sor
.hdmi
= gf119_hdmi_ctrl
,
530 gf119_disp_new(struct nvkm_device
*device
, int index
, struct nvkm_disp
**pdisp
)
532 return gf119_disp_new_(&gf119_disp
, device
, index
, pdisp
);