]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
drm/nouveau/disp/dp: determine a failsafe link training rate
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / nouveau / nvkm / engine / disp / gf119.c
CommitLineData
2a7909c0
BS
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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.
21 *
22 * Authors: Ben Skeggs
23 */
24#include "nv50.h"
a1c93078 25#include "head.h"
78f1ad6f 26#include "ior.h"
2a7909c0
BS
27#include "rootnv50.h"
28
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>
34
2a7909c0
BS
35static struct nvkm_output *
36exec_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)
39{
40 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
41 struct nvkm_bios *bios = subdev->device->bios;
42 struct nvkm_output *outp;
43 u16 mask, type;
44
45 if (or < 4) {
46 type = DCB_OUTPUT_ANALOG;
47 mask = 0;
48 } else {
49 or -= 4;
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;
57 default:
58 nvkm_error(subdev, "unknown SOR mc %08x\n", ctrl);
59 return NULL;
60 }
61 }
62
63 mask = 0x00c0 & (mask << 6);
64 mask |= 0x0001 << or;
65 mask |= 0x0100 << head;
66
67 list_for_each_entry(outp, &disp->base.outp, head) {
68 if ((outp->info.hasht & 0xff) == type &&
69 (outp->info.hashm & mask) == mask) {
9a2b8131 70 *data = nvbios_outp_match(bios, outp->info.hasht, mask,
2a7909c0
BS
71 ver, hdr, cnt, len, info);
72 if (!*data)
73 return NULL;
74 return outp;
75 }
76 }
77
78 return NULL;
79}
80
81static struct nvkm_output *
82exec_script(struct nv50_disp *disp, int head, int id)
83{
70aa8670
BS
84 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
85 struct nvkm_device *device = subdev->device;
2a7909c0
BS
86 struct nvkm_bios *bios = device->bios;
87 struct nvkm_output *outp;
88 struct nvbios_outp info;
89 u8 ver, hdr, cnt, len;
90 u32 data, ctrl = 0;
91 int or;
92
93 for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) {
94 ctrl = nvkm_rd32(device, 0x640180 + (or * 0x20));
95 if (ctrl & (1 << head))
96 break;
97 }
98
99 if (or == 8)
100 return NULL;
101
102 outp = exec_lookup(disp, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
103 if (outp) {
104 struct nvbios_init init = {
70aa8670 105 .subdev = subdev,
2a7909c0
BS
106 .bios = bios,
107 .offset = info.script[id],
108 .outp = &outp->info,
109 .crtc = head,
110 .execute = 1,
111 };
112
113 nvbios_exec(&init);
114 }
115
116 return outp;
117}
118
119static struct nvkm_output *
120exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
121{
70aa8670
BS
122 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
123 struct nvkm_device *device = subdev->device;
2a7909c0
BS
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;
129 u32 data, ctrl = 0;
130 int or;
131
132 for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) {
133 ctrl = nvkm_rd32(device, 0x660180 + (or * 0x20));
134 if (ctrl & (1 << head))
135 break;
136 }
137
138 if (or == 8)
139 return NULL;
140
141 outp = exec_lookup(disp, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
142 if (!outp)
143 return NULL;
144
bc9139d2 145 *conf = (ctrl & 0x00000f00) >> 8;
2a7909c0
BS
146 switch (outp->info.type) {
147 case DCB_OUTPUT_TMDS:
16ef53a9 148 if (*conf == 5)
2a7909c0
BS
149 *conf |= 0x0100;
150 break;
151 case DCB_OUTPUT_LVDS:
bc9139d2 152 *conf |= disp->sor.lvdsconf;
2a7909c0 153 break;
2a7909c0 154 default:
2a7909c0
BS
155 break;
156 }
157
bc9139d2
BS
158 data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
159 &ver, &hdr, &cnt, &len, &info2);
2a7909c0
BS
160 if (data && id < 0xff) {
161 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
162 if (data) {
163 struct nvbios_init init = {
70aa8670 164 .subdev = subdev,
2a7909c0
BS
165 .bios = bios,
166 .offset = data,
167 .outp = &outp->info,
168 .crtc = head,
169 .execute = 1,
170 };
171
172 nvbios_exec(&init);
173 }
174 }
175
176 return outp;
177}
178
179static void
180gf119_disp_intr_unk1_0(struct nv50_disp *disp, int head)
181{
182 exec_script(disp, head, 1);
183}
184
185static void
186gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head)
187{
46484438 188 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
2a7909c0
BS
189 struct nvkm_output *outp = exec_script(disp, head, 2);
190
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);
f2a40513
BS
194 if (!outpdp->lt.mst) {
195 struct nvbios_init init = {
196 .subdev = subdev,
197 .bios = subdev->device->bios,
198 .outp = &outp->info,
199 .crtc = head,
200 .offset = outpdp->info.script[4],
201 .execute = 1,
202 };
2a7909c0 203
725fa3ac 204 nvkm_notify_put(&outpdp->irq);
f2a40513
BS
205 nvbios_exec(&init);
206 atomic_set(&outpdp->lt.done, 0);
207 }
2a7909c0
BS
208 }
209}
210
211static void
212gf119_disp_intr_unk2_1(struct nv50_disp *disp, int head)
213{
214 struct nvkm_device *device = disp->base.engine.subdev.device;
215 struct nvkm_devinit *devinit = device->devinit;
216 u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
217 if (pclk)
151abd44 218 nvkm_devinit_pll_set(devinit, PLL_VPLL0 + head, pclk);
2a7909c0
BS
219 nvkm_wr32(device, 0x612200 + (head * 0x800), 0x00000000);
220}
221
222static void
223gf119_disp_intr_unk2_2_tu(struct nv50_disp *disp, int head,
224 struct dcb_output *outp)
225{
226 struct nvkm_device *device = disp->base.engine.subdev.device;
227 const int or = ffs(outp->or) - 1;
228 const u32 ctrl = nvkm_rd32(device, 0x660200 + (or * 0x020));
229 const u32 conf = nvkm_rd32(device, 0x660404 + (head * 0x300));
230 const s32 vactive = nvkm_rd32(device, 0x660414 + (head * 0x300)) & 0xffff;
231 const s32 vblanke = nvkm_rd32(device, 0x66041c + (head * 0x300)) & 0xffff;
232 const s32 vblanks = nvkm_rd32(device, 0x660420 + (head * 0x300)) & 0xffff;
233 const u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
234 const u32 link = ((ctrl & 0xf00) == 0x800) ? 0 : 1;
235 const u32 hoff = (head * 0x800);
236 const u32 soff = ( or * 0x800);
237 const u32 loff = (link * 0x080) + soff;
238 const u32 symbol = 100000;
239 const u32 TU = 64;
240 u32 dpctrl = nvkm_rd32(device, 0x61c10c + loff);
241 u32 clksor = nvkm_rd32(device, 0x612300 + soff);
242 u32 datarate, link_nr, link_bw, bits;
243 u64 ratio, value;
244
245 link_nr = hweight32(dpctrl & 0x000f0000);
246 link_bw = (clksor & 0x007c0000) >> 18;
247 link_bw *= 27000;
248
249 /* symbols/hblank - algorithm taken from comments in tegra driver */
250 value = vblanke + vactive - vblanks - 7;
251 value = value * link_bw;
252 do_div(value, pclk);
253 value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr);
254 nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, value);
255
256 /* symbols/vblank - algorithm taken from comments in tegra driver */
257 value = vblanks - vblanke - 25;
258 value = value * link_bw;
259 do_div(value, pclk);
260 value = value - ((36 / link_nr) + 3) - 1;
261 nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, value);
262
263 /* watermark */
264 if ((conf & 0x3c0) == 0x180) bits = 30;
265 else if ((conf & 0x3c0) == 0x140) bits = 24;
266 else bits = 18;
267 datarate = (pclk * bits) / 8;
268
269 ratio = datarate;
270 ratio *= symbol;
271 do_div(ratio, link_nr * link_bw);
272
273 value = (symbol - ratio) * TU;
274 value *= ratio;
275 do_div(value, symbol);
276 do_div(value, symbol);
277
278 value += 5;
279 value |= 0x08000000;
280
281 nvkm_wr32(device, 0x616610 + hoff, value);
282}
283
284static void
285gf119_disp_intr_unk2_2(struct nv50_disp *disp, int head)
286{
287 struct nvkm_device *device = disp->base.engine.subdev.device;
288 struct nvkm_output *outp;
289 u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
290 u32 conf, addr, data;
291
292 outp = exec_clkcmp(disp, head, 0xff, pclk, &conf);
293 if (!outp)
294 return;
295
296 /* see note in nv50_disp_intr_unk20_2() */
297 if (outp->info.type == DCB_OUTPUT_DP) {
298 u32 sync = nvkm_rd32(device, 0x660404 + (head * 0x300));
299 switch ((sync & 0x000003c0) >> 6) {
300 case 6: pclk = pclk * 30; break;
301 case 5: pclk = pclk * 24; break;
302 case 2:
303 default:
304 pclk = pclk * 18;
305 break;
306 }
307
1f8711ba 308 if (nvkm_output_dp_train(outp, pclk))
2a7909c0
BS
309 OUTP_ERR(outp, "link not trained before attach");
310 } else {
70aa8670
BS
311 if (disp->func->sor.magic)
312 disp->func->sor.magic(outp);
2a7909c0
BS
313 }
314
315 exec_clkcmp(disp, head, 0, pclk, &conf);
316
317 if (outp->info.type == DCB_OUTPUT_ANALOG) {
318 addr = 0x612280 + (ffs(outp->info.or) - 1) * 0x800;
319 data = 0x00000000;
320 } else {
321 addr = 0x612300 + (ffs(outp->info.or) - 1) * 0x800;
322 data = (conf & 0x0100) ? 0x00000101 : 0x00000000;
323 switch (outp->info.type) {
324 case DCB_OUTPUT_TMDS:
325 nvkm_mask(device, addr, 0x007c0000, 0x00280000);
326 break;
327 case DCB_OUTPUT_DP:
328 gf119_disp_intr_unk2_2_tu(disp, head, &outp->info);
329 break;
330 default:
331 break;
332 }
333 }
334
335 nvkm_mask(device, addr, 0x00000707, data);
336}
337
338static void
339gf119_disp_intr_unk4_0(struct nv50_disp *disp, int head)
340{
341 struct nvkm_device *device = disp->base.engine.subdev.device;
342 u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
343 u32 conf;
344
345 exec_clkcmp(disp, head, 1, pclk, &conf);
346}
347
348void
af85389c 349gf119_disp_super(struct work_struct *work)
2a7909c0
BS
350{
351 struct nv50_disp *disp =
352 container_of(work, struct nv50_disp, supervisor);
2a7909c0
BS
353 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
354 struct nvkm_device *device = subdev->device;
a1c93078 355 struct nvkm_head *head;
2a7909c0 356 u32 mask[4];
2a7909c0
BS
357
358 nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super));
a1c93078
BS
359 list_for_each_entry(head, &disp->base.head, head) {
360 mask[head->id] = nvkm_rd32(device, 0x6101d4 + (head->id * 0x800));
361 HEAD_DBG(head, "%08x", mask[head->id]);
2a7909c0
BS
362 }
363
364 if (disp->super & 0x00000001) {
0ce41e3c 365 nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG);
a1c93078
BS
366 list_for_each_entry(head, &disp->base.head, head) {
367 if (!(mask[head->id] & 0x00001000))
2a7909c0 368 continue;
a1c93078
BS
369 nvkm_debug(subdev, "supervisor 1.0 - head %d\n", head->id);
370 gf119_disp_intr_unk1_0(disp, head->id);
2a7909c0
BS
371 }
372 } else
373 if (disp->super & 0x00000002) {
a1c93078
BS
374 list_for_each_entry(head, &disp->base.head, head) {
375 if (!(mask[head->id] & 0x00001000))
2a7909c0 376 continue;
a1c93078
BS
377 nvkm_debug(subdev, "supervisor 2.0 - head %d\n", head->id);
378 gf119_disp_intr_unk2_0(disp, head->id);
2a7909c0 379 }
a1c93078
BS
380 list_for_each_entry(head, &disp->base.head, head) {
381 if (!(mask[head->id] & 0x00010000))
2a7909c0 382 continue;
a1c93078
BS
383 nvkm_debug(subdev, "supervisor 2.1 - head %d\n", head->id);
384 gf119_disp_intr_unk2_1(disp, head->id);
2a7909c0 385 }
a1c93078
BS
386 list_for_each_entry(head, &disp->base.head, head) {
387 if (!(mask[head->id] & 0x00001000))
2a7909c0 388 continue;
a1c93078
BS
389 nvkm_debug(subdev, "supervisor 2.2 - head %d\n", head->id);
390 gf119_disp_intr_unk2_2(disp, head->id);
2a7909c0
BS
391 }
392 } else
393 if (disp->super & 0x00000004) {
a1c93078
BS
394 list_for_each_entry(head, &disp->base.head, head) {
395 if (!(mask[head->id] & 0x00001000))
2a7909c0 396 continue;
a1c93078
BS
397 nvkm_debug(subdev, "supervisor 3.0 - head %d\n", head->id);
398 gf119_disp_intr_unk4_0(disp, head->id);
2a7909c0
BS
399 }
400 }
401
a1c93078
BS
402 list_for_each_entry(head, &disp->base.head, head)
403 nvkm_wr32(device, 0x6101d4 + (head->id * 0x800), 0x00000000);
2a7909c0
BS
404 nvkm_wr32(device, 0x6101d0, 0x80000000);
405}
406
fd47877f 407void
2a7909c0
BS
408gf119_disp_intr_error(struct nv50_disp *disp, int chid)
409{
2a7909c0
BS
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));
415
416 nvkm_error(subdev, "chid %d mthd %04x data %08x %08x %08x\n",
417 chid, (mthd & 0x0000ffc), data, mthd, unkn);
418
0ce41e3c 419 if (chid < ARRAY_SIZE(disp->chan)) {
2a7909c0
BS
420 switch (mthd & 0xffc) {
421 case 0x0080:
0ce41e3c 422 nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR);
2a7909c0
BS
423 break;
424 default:
425 break;
426 }
427 }
428
429 nvkm_wr32(device, 0x61009c, (1 << chid));
430 nvkm_wr32(device, 0x6101f0 + (chid * 12), 0x90000000);
431}
432
433void
70aa8670 434gf119_disp_intr(struct nv50_disp *disp)
2a7909c0 435{
70aa8670 436 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
2a7909c0 437 struct nvkm_device *device = subdev->device;
a1c93078 438 struct nvkm_head *head;
2a7909c0 439 u32 intr = nvkm_rd32(device, 0x610088);
2a7909c0
BS
440
441 if (intr & 0x00000001) {
442 u32 stat = nvkm_rd32(device, 0x61008c);
443 while (stat) {
444 int chid = __ffs(stat); stat &= ~(1 << chid);
445 nv50_disp_chan_uevent_send(disp, chid);
446 nvkm_wr32(device, 0x61008c, 1 << chid);
447 }
448 intr &= ~0x00000001;
449 }
450
451 if (intr & 0x00000002) {
452 u32 stat = nvkm_rd32(device, 0x61009c);
453 int chid = ffs(stat) - 1;
454 if (chid >= 0)
fd47877f 455 disp->func->intr_error(disp, chid);
2a7909c0
BS
456 intr &= ~0x00000002;
457 }
458
459 if (intr & 0x00100000) {
460 u32 stat = nvkm_rd32(device, 0x6100ac);
461 if (stat & 0x00000007) {
462 disp->super = (stat & 0x00000007);
463 schedule_work(&disp->supervisor);
464 nvkm_wr32(device, 0x6100ac, disp->super);
465 stat &= ~0x00000007;
466 }
467
468 if (stat) {
469 nvkm_warn(subdev, "intr24 %08x\n", stat);
470 nvkm_wr32(device, 0x6100ac, stat);
471 }
472
473 intr &= ~0x00100000;
474 }
475
a1c93078
BS
476 list_for_each_entry(head, &disp->base.head, head) {
477 const u32 hoff = head->id * 0x800;
478 u32 mask = 0x01000000 << head->id;
2a7909c0 479 if (mask & intr) {
a1c93078 480 u32 stat = nvkm_rd32(device, 0x6100bc + hoff);
2a7909c0 481 if (stat & 0x00000001)
a1c93078
BS
482 nvkm_disp_vblank(&disp->base, head->id);
483 nvkm_mask(device, 0x6100bc + hoff, 0, 0);
484 nvkm_rd32(device, 0x6100c0 + hoff);
2a7909c0
BS
485 }
486 }
487}
488
70aa8670
BS
489int
490gf119_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
491 int index, struct nvkm_disp **pdisp)
492{
493 u32 heads = nvkm_rd32(device, 0x022448);
494 return nv50_disp_new_(func, device, index, heads, pdisp);
495}
496
497static const struct nv50_disp_func
0ce41e3c 498gf119_disp = {
70aa8670 499 .intr = gf119_disp_intr,
fd47877f 500 .intr_error = gf119_disp_intr_error,
70aa8670 501 .uevent = &gf119_disp_chan_uevent,
af85389c 502 .super = gf119_disp_super,
0ce41e3c 503 .root = &gf119_disp_root_oclass,
a1c93078 504 .head.new = gf119_head_new,
70aa8670
BS
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,
509 .dac.nr = 3,
b3c9c022 510 .dac.new = gf119_dac_new,
70aa8670
BS
511 .dac.power = nv50_dac_power,
512 .dac.sense = nv50_dac_sense,
513 .sor.nr = 4,
78f1ad6f 514 .sor.new = gf119_sor_new,
70aa8670
BS
515 .sor.power = nv50_sor_power,
516 .sor.hda_eld = gf119_hda_eld,
517 .sor.hdmi = gf119_hdmi_ctrl,
0ce41e3c
BS
518};
519
70aa8670
BS
520int
521gf119_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
2a7909c0 522{
70aa8670 523 return gf119_disp_new_(&gf119_disp, device, index, pdisp);
2a7909c0 524}