]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
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.
29 #include <subdev/bios.h>
30 #include <subdev/bios/disp.h>
31 #include <subdev/bios/init.h>
32 #include <subdev/bios/pll.h>
33 #include <subdev/devinit.h>
35 static struct nvkm_output
*
36 exec_lookup(struct nv50_disp
*disp
, int head
, int or, u32 ctrl
,
37 u32
*data
, u8
*ver
, u8
*hdr
, u8
*cnt
, u8
*len
,
38 struct nvbios_outp
*info
)
40 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
41 struct nvkm_bios
*bios
= subdev
->device
->bios
;
42 struct nvkm_output
*outp
;
46 type
= DCB_OUTPUT_ANALOG
;
50 switch (ctrl
& 0x00000f00) {
51 case 0x00000000: type
= DCB_OUTPUT_LVDS
; mask
= 1; break;
52 case 0x00000100: type
= DCB_OUTPUT_TMDS
; mask
= 1; break;
53 case 0x00000200: type
= DCB_OUTPUT_TMDS
; mask
= 2; break;
54 case 0x00000500: type
= DCB_OUTPUT_TMDS
; mask
= 3; break;
55 case 0x00000800: type
= DCB_OUTPUT_DP
; mask
= 1; break;
56 case 0x00000900: type
= DCB_OUTPUT_DP
; mask
= 2; break;
58 nvkm_error(subdev
, "unknown SOR mc %08x\n", ctrl
);
63 mask
= 0x00c0 & (mask
<< 6);
65 mask
|= 0x0100 << head
;
67 list_for_each_entry(outp
, &disp
->base
.outp
, head
) {
68 if ((outp
->info
.hasht
& 0xff) == type
&&
69 (outp
->info
.hashm
& mask
) == mask
) {
70 *data
= nvbios_outp_match(bios
, outp
->info
.hasht
, mask
,
71 ver
, hdr
, cnt
, len
, info
);
81 static struct nvkm_output
*
82 exec_script(struct nv50_disp
*disp
, int head
, int id
)
84 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
85 struct nvkm_device
*device
= subdev
->device
;
86 struct nvkm_bios
*bios
= device
->bios
;
87 struct nvkm_output
*outp
;
88 struct nvbios_outp info
;
89 u8 ver
, hdr
, cnt
, len
;
93 for (or = 0; !(ctrl
& (1 << head
)) && or < 8; or++) {
94 ctrl
= nvkm_rd32(device
, 0x640180 + (or * 0x20));
95 if (ctrl
& (1 << head
))
102 outp
= exec_lookup(disp
, head
, or, ctrl
, &data
, &ver
, &hdr
, &cnt
, &len
, &info
);
104 struct nvbios_init init
= {
107 .offset
= info
.script
[id
],
119 static struct nvkm_output
*
120 exec_clkcmp(struct nv50_disp
*disp
, int head
, int id
, u32 pclk
, u32
*conf
)
122 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
123 struct nvkm_device
*device
= subdev
->device
;
124 struct nvkm_bios
*bios
= device
->bios
;
125 struct nvkm_output
*outp
;
126 struct nvbios_outp info1
;
127 struct nvbios_ocfg info2
;
128 u8 ver
, hdr
, cnt
, len
;
132 for (or = 0; !(ctrl
& (1 << head
)) && or < 8; or++) {
133 ctrl
= nvkm_rd32(device
, 0x660180 + (or * 0x20));
134 if (ctrl
& (1 << head
))
141 outp
= exec_lookup(disp
, head
, or, ctrl
, &data
, &ver
, &hdr
, &cnt
, &len
, &info1
);
145 *conf
= (ctrl
& 0x00000f00) >> 8;
146 switch (outp
->info
.type
) {
147 case DCB_OUTPUT_TMDS
:
151 case DCB_OUTPUT_LVDS
:
152 *conf
|= disp
->sor
.lvdsconf
;
158 data
= nvbios_ocfg_match(bios
, data
, *conf
& 0xff, *conf
>> 8,
159 &ver
, &hdr
, &cnt
, &len
, &info2
);
160 if (data
&& id
< 0xff) {
161 data
= nvbios_oclk_match(bios
, info2
.clkcmp
[id
], pclk
);
163 struct nvbios_init init
= {
180 gf119_disp_intr_unk1_0(struct nv50_disp
*disp
, int head
)
182 exec_script(disp
, head
, 1);
186 gf119_disp_intr_unk2_0(struct nv50_disp
*disp
, int head
)
188 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
189 struct nvkm_output
*outp
= exec_script(disp
, head
, 2);
191 /* see note in nv50_disp_intr_unk20_0() */
192 if (outp
&& outp
->info
.type
== DCB_OUTPUT_DP
) {
193 struct nvkm_output_dp
*outpdp
= nvkm_output_dp(outp
);
194 if (!outpdp
->lt
.mst
) {
195 struct nvbios_init init
= {
197 .bios
= subdev
->device
->bios
,
200 .offset
= outpdp
->info
.script
[4],
204 atomic_set(&outpdp
->lt
.done
, 0);
211 gf119_disp_intr_unk2_1(struct nv50_disp
*disp
, int head
)
213 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
214 struct nvkm_devinit
*devinit
= device
->devinit
;
215 u32 pclk
= nvkm_rd32(device
, 0x660450 + (head
* 0x300)) / 1000;
217 nvkm_devinit_pll_set(devinit
, PLL_VPLL0
+ head
, pclk
);
218 nvkm_wr32(device
, 0x612200 + (head
* 0x800), 0x00000000);
222 gf119_disp_intr_unk2_2_tu(struct nv50_disp
*disp
, int head
,
223 struct dcb_output
*outp
)
225 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
226 const int or = ffs(outp
->or) - 1;
227 const u32 ctrl
= nvkm_rd32(device
, 0x660200 + (or * 0x020));
228 const u32 conf
= nvkm_rd32(device
, 0x660404 + (head
* 0x300));
229 const s32 vactive
= nvkm_rd32(device
, 0x660414 + (head
* 0x300)) & 0xffff;
230 const s32 vblanke
= nvkm_rd32(device
, 0x66041c + (head
* 0x300)) & 0xffff;
231 const s32 vblanks
= nvkm_rd32(device
, 0x660420 + (head
* 0x300)) & 0xffff;
232 const u32 pclk
= nvkm_rd32(device
, 0x660450 + (head
* 0x300)) / 1000;
233 const u32 link
= ((ctrl
& 0xf00) == 0x800) ? 0 : 1;
234 const u32 hoff
= (head
* 0x800);
235 const u32 soff
= ( or * 0x800);
236 const u32 loff
= (link
* 0x080) + soff
;
237 const u32 symbol
= 100000;
239 u32 dpctrl
= nvkm_rd32(device
, 0x61c10c + loff
);
240 u32 clksor
= nvkm_rd32(device
, 0x612300 + soff
);
241 u32 datarate
, link_nr
, link_bw
, bits
;
244 link_nr
= hweight32(dpctrl
& 0x000f0000);
245 link_bw
= (clksor
& 0x007c0000) >> 18;
248 /* symbols/hblank - algorithm taken from comments in tegra driver */
249 value
= vblanke
+ vactive
- vblanks
- 7;
250 value
= value
* link_bw
;
252 value
= value
- (3 * !!(dpctrl
& 0x00004000)) - (12 / link_nr
);
253 nvkm_mask(device
, 0x616620 + hoff
, 0x0000ffff, value
);
255 /* symbols/vblank - algorithm taken from comments in tegra driver */
256 value
= vblanks
- vblanke
- 25;
257 value
= value
* link_bw
;
259 value
= value
- ((36 / link_nr
) + 3) - 1;
260 nvkm_mask(device
, 0x616624 + hoff
, 0x00ffffff, value
);
263 if ((conf
& 0x3c0) == 0x180) bits
= 30;
264 else if ((conf
& 0x3c0) == 0x140) bits
= 24;
266 datarate
= (pclk
* bits
) / 8;
270 do_div(ratio
, link_nr
* link_bw
);
272 value
= (symbol
- ratio
) * TU
;
274 do_div(value
, symbol
);
275 do_div(value
, symbol
);
280 nvkm_wr32(device
, 0x616610 + hoff
, value
);
284 gf119_disp_intr_unk2_2(struct nv50_disp
*disp
, int head
)
286 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
287 struct nvkm_output
*outp
;
288 u32 pclk
= nvkm_rd32(device
, 0x660450 + (head
* 0x300)) / 1000;
289 u32 conf
, addr
, data
;
291 outp
= exec_clkcmp(disp
, head
, 0xff, pclk
, &conf
);
295 /* see note in nv50_disp_intr_unk20_2() */
296 if (outp
->info
.type
== DCB_OUTPUT_DP
) {
297 u32 sync
= nvkm_rd32(device
, 0x660404 + (head
* 0x300));
298 switch ((sync
& 0x000003c0) >> 6) {
299 case 6: pclk
= pclk
* 30; break;
300 case 5: pclk
= pclk
* 24; break;
307 if (nvkm_output_dp_train(outp
, pclk
))
308 OUTP_ERR(outp
, "link not trained before attach");
310 if (disp
->func
->sor
.magic
)
311 disp
->func
->sor
.magic(outp
);
314 exec_clkcmp(disp
, head
, 0, pclk
, &conf
);
316 if (outp
->info
.type
== DCB_OUTPUT_ANALOG
) {
317 addr
= 0x612280 + (ffs(outp
->info
.or) - 1) * 0x800;
320 addr
= 0x612300 + (ffs(outp
->info
.or) - 1) * 0x800;
321 data
= (conf
& 0x0100) ? 0x00000101 : 0x00000000;
322 switch (outp
->info
.type
) {
323 case DCB_OUTPUT_TMDS
:
324 nvkm_mask(device
, addr
, 0x007c0000, 0x00280000);
327 gf119_disp_intr_unk2_2_tu(disp
, head
, &outp
->info
);
334 nvkm_mask(device
, addr
, 0x00000707, data
);
338 gf119_disp_intr_unk4_0(struct nv50_disp
*disp
, int head
)
340 struct nvkm_device
*device
= disp
->base
.engine
.subdev
.device
;
341 u32 pclk
= nvkm_rd32(device
, 0x660450 + (head
* 0x300)) / 1000;
344 exec_clkcmp(disp
, head
, 1, pclk
, &conf
);
348 gf119_disp_super(struct work_struct
*work
)
350 struct nv50_disp
*disp
=
351 container_of(work
, struct nv50_disp
, supervisor
);
352 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
353 struct nvkm_device
*device
= subdev
->device
;
354 struct nvkm_head
*head
;
357 nvkm_debug(subdev
, "supervisor %d\n", ffs(disp
->super
));
358 list_for_each_entry(head
, &disp
->base
.head
, head
) {
359 mask
[head
->id
] = nvkm_rd32(device
, 0x6101d4 + (head
->id
* 0x800));
360 HEAD_DBG(head
, "%08x", mask
[head
->id
]);
363 if (disp
->super
& 0x00000001) {
364 nv50_disp_chan_mthd(disp
->chan
[0], NV_DBG_DEBUG
);
365 nv50_disp_super_1(disp
);
366 list_for_each_entry(head
, &disp
->base
.head
, head
) {
367 if (!(mask
[head
->id
] & 0x00001000))
369 nvkm_debug(subdev
, "supervisor 1.0 - head %d\n", head
->id
);
370 gf119_disp_intr_unk1_0(disp
, head
->id
);
373 if (disp
->super
& 0x00000002) {
374 list_for_each_entry(head
, &disp
->base
.head
, head
) {
375 if (!(mask
[head
->id
] & 0x00001000))
377 nvkm_debug(subdev
, "supervisor 2.0 - head %d\n", head
->id
);
378 gf119_disp_intr_unk2_0(disp
, head
->id
);
380 list_for_each_entry(head
, &disp
->base
.head
, head
) {
381 if (!(mask
[head
->id
] & 0x00010000))
383 nvkm_debug(subdev
, "supervisor 2.1 - head %d\n", head
->id
);
384 gf119_disp_intr_unk2_1(disp
, head
->id
);
386 list_for_each_entry(head
, &disp
->base
.head
, head
) {
387 if (!(mask
[head
->id
] & 0x00001000))
389 nvkm_debug(subdev
, "supervisor 2.2 - head %d\n", head
->id
);
390 gf119_disp_intr_unk2_2(disp
, head
->id
);
393 if (disp
->super
& 0x00000004) {
394 list_for_each_entry(head
, &disp
->base
.head
, head
) {
395 if (!(mask
[head
->id
] & 0x00001000))
397 nvkm_debug(subdev
, "supervisor 3.0 - head %d\n", head
->id
);
398 gf119_disp_intr_unk4_0(disp
, head
->id
);
402 list_for_each_entry(head
, &disp
->base
.head
, head
)
403 nvkm_wr32(device
, 0x6101d4 + (head
->id
* 0x800), 0x00000000);
404 nvkm_wr32(device
, 0x6101d0, 0x80000000);
408 gf119_disp_intr_error(struct nv50_disp
*disp
, int chid
)
410 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
411 struct nvkm_device
*device
= subdev
->device
;
412 u32 mthd
= nvkm_rd32(device
, 0x6101f0 + (chid
* 12));
413 u32 data
= nvkm_rd32(device
, 0x6101f4 + (chid
* 12));
414 u32 unkn
= nvkm_rd32(device
, 0x6101f8 + (chid
* 12));
416 nvkm_error(subdev
, "chid %d mthd %04x data %08x %08x %08x\n",
417 chid
, (mthd
& 0x0000ffc), data
, mthd
, unkn
);
419 if (chid
< ARRAY_SIZE(disp
->chan
)) {
420 switch (mthd
& 0xffc) {
422 nv50_disp_chan_mthd(disp
->chan
[chid
], NV_DBG_ERROR
);
429 nvkm_wr32(device
, 0x61009c, (1 << chid
));
430 nvkm_wr32(device
, 0x6101f0 + (chid
* 12), 0x90000000);
434 gf119_disp_intr(struct nv50_disp
*disp
)
436 struct nvkm_subdev
*subdev
= &disp
->base
.engine
.subdev
;
437 struct nvkm_device
*device
= subdev
->device
;
438 struct nvkm_head
*head
;
439 u32 intr
= nvkm_rd32(device
, 0x610088);
441 if (intr
& 0x00000001) {
442 u32 stat
= nvkm_rd32(device
, 0x61008c);
444 int chid
= __ffs(stat
); stat
&= ~(1 << chid
);
445 nv50_disp_chan_uevent_send(disp
, chid
);
446 nvkm_wr32(device
, 0x61008c, 1 << chid
);
451 if (intr
& 0x00000002) {
452 u32 stat
= nvkm_rd32(device
, 0x61009c);
453 int chid
= ffs(stat
) - 1;
455 disp
->func
->intr_error(disp
, chid
);
459 if (intr
& 0x00100000) {
460 u32 stat
= nvkm_rd32(device
, 0x6100ac);
461 if (stat
& 0x00000007) {
462 disp
->super
= (stat
& 0x00000007);
463 queue_work(disp
->wq
, &disp
->supervisor
);
464 nvkm_wr32(device
, 0x6100ac, disp
->super
);
469 nvkm_warn(subdev
, "intr24 %08x\n", stat
);
470 nvkm_wr32(device
, 0x6100ac, stat
);
476 list_for_each_entry(head
, &disp
->base
.head
, head
) {
477 const u32 hoff
= head
->id
* 0x800;
478 u32 mask
= 0x01000000 << head
->id
;
480 u32 stat
= nvkm_rd32(device
, 0x6100bc + hoff
);
481 if (stat
& 0x00000001)
482 nvkm_disp_vblank(&disp
->base
, head
->id
);
483 nvkm_mask(device
, 0x6100bc + hoff
, 0, 0);
484 nvkm_rd32(device
, 0x6100c0 + hoff
);
490 gf119_disp_new_(const struct nv50_disp_func
*func
, struct nvkm_device
*device
,
491 int index
, struct nvkm_disp
**pdisp
)
493 u32 heads
= nvkm_rd32(device
, 0x022448);
494 return nv50_disp_new_(func
, device
, index
, heads
, pdisp
);
497 static const struct nv50_disp_func
499 .intr
= gf119_disp_intr
,
500 .intr_error
= gf119_disp_intr_error
,
501 .uevent
= &gf119_disp_chan_uevent
,
502 .super
= gf119_disp_super
,
503 .root
= &gf119_disp_root_oclass
,
504 .head
.new = gf119_head_new
,
505 .outp
.internal
.crt
= nv50_dac_output_new
,
506 .outp
.internal
.tmds
= nv50_sor_output_new
,
507 .outp
.internal
.lvds
= nv50_sor_output_new
,
508 .outp
.internal
.dp
= gf119_sor_dp_new
,
510 .dac
.new = gf119_dac_new
,
511 .dac
.sense
= nv50_dac_sense
,
513 .sor
.new = gf119_sor_new
,
514 .sor
.hda_eld
= gf119_hda_eld
,
515 .sor
.hdmi
= gf119_hdmi_ctrl
,
519 gf119_disp_new(struct nvkm_device
*device
, int index
, struct nvkm_disp
**pdisp
)
521 return gf119_disp_new_(&gf119_disp
, device
, index
, pdisp
);