]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
drm/nouveau/disp: common implementation of scanoutpos method in nvkm_head
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nvkm / engine / disp / nv50.c
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"
25 #include "head.h"
26 #include "rootnv50.h"
27
28 #include <core/client.h>
29 #include <core/enum.h>
30 #include <core/gpuobj.h>
31 #include <subdev/bios.h>
32 #include <subdev/bios/disp.h>
33 #include <subdev/bios/init.h>
34 #include <subdev/bios/pll.h>
35 #include <subdev/devinit.h>
36 #include <subdev/timer.h>
37
38 static const struct nvkm_disp_oclass *
39 nv50_disp_root_(struct nvkm_disp *base)
40 {
41         return nv50_disp(base)->func->root;
42 }
43
44 static int
45 nv50_disp_outp_internal_crt_(struct nvkm_disp *base, int index,
46                              struct dcb_output *dcb, struct nvkm_output **poutp)
47 {
48         struct nv50_disp *disp = nv50_disp(base);
49         return disp->func->outp.internal.crt(base, index, dcb, poutp);
50 }
51
52 static int
53 nv50_disp_outp_internal_tmds_(struct nvkm_disp *base, int index,
54                               struct dcb_output *dcb,
55                               struct nvkm_output **poutp)
56 {
57         struct nv50_disp *disp = nv50_disp(base);
58         return disp->func->outp.internal.tmds(base, index, dcb, poutp);
59 }
60
61 static int
62 nv50_disp_outp_internal_lvds_(struct nvkm_disp *base, int index,
63                               struct dcb_output *dcb,
64                               struct nvkm_output **poutp)
65 {
66         struct nv50_disp *disp = nv50_disp(base);
67         return disp->func->outp.internal.lvds(base, index, dcb, poutp);
68 }
69
70 static int
71 nv50_disp_outp_internal_dp_(struct nvkm_disp *base, int index,
72                             struct dcb_output *dcb, struct nvkm_output **poutp)
73 {
74         struct nv50_disp *disp = nv50_disp(base);
75         if (disp->func->outp.internal.dp)
76                 return disp->func->outp.internal.dp(base, index, dcb, poutp);
77         return -ENODEV;
78 }
79
80 static int
81 nv50_disp_outp_external_tmds_(struct nvkm_disp *base, int index,
82                               struct dcb_output *dcb,
83                               struct nvkm_output **poutp)
84 {
85         struct nv50_disp *disp = nv50_disp(base);
86         if (disp->func->outp.external.tmds)
87                 return disp->func->outp.external.tmds(base, index, dcb, poutp);
88         return -ENODEV;
89 }
90
91 static int
92 nv50_disp_outp_external_dp_(struct nvkm_disp *base, int index,
93                             struct dcb_output *dcb, struct nvkm_output **poutp)
94 {
95         struct nv50_disp *disp = nv50_disp(base);
96         if (disp->func->outp.external.dp)
97                 return disp->func->outp.external.dp(base, index, dcb, poutp);
98         return -ENODEV;
99 }
100
101 static void
102 nv50_disp_intr_(struct nvkm_disp *base)
103 {
104         struct nv50_disp *disp = nv50_disp(base);
105         disp->func->intr(disp);
106 }
107
108 static void *
109 nv50_disp_dtor_(struct nvkm_disp *base)
110 {
111         struct nv50_disp *disp = nv50_disp(base);
112         nvkm_event_fini(&disp->uevent);
113         return disp;
114 }
115
116 static const struct nvkm_disp_func
117 nv50_disp_ = {
118         .dtor = nv50_disp_dtor_,
119         .intr = nv50_disp_intr_,
120         .root = nv50_disp_root_,
121         .outp.internal.crt = nv50_disp_outp_internal_crt_,
122         .outp.internal.tmds = nv50_disp_outp_internal_tmds_,
123         .outp.internal.lvds = nv50_disp_outp_internal_lvds_,
124         .outp.internal.dp = nv50_disp_outp_internal_dp_,
125         .outp.external.tmds = nv50_disp_outp_external_tmds_,
126         .outp.external.dp = nv50_disp_outp_external_dp_,
127 };
128
129 int
130 nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
131                int index, int heads, struct nvkm_disp **pdisp)
132 {
133         struct nv50_disp *disp;
134         int ret, i;
135
136         if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL)))
137                 return -ENOMEM;
138         INIT_WORK(&disp->supervisor, func->super);
139         disp->func = func;
140         *pdisp = &disp->base;
141
142         ret = nvkm_disp_ctor(&nv50_disp_, device, index, &disp->base);
143         if (ret)
144                 return ret;
145
146         for (i = 0; func->head.new && i < heads; i++) {
147                 ret = func->head.new(&disp->base, i);
148                 if (ret)
149                         return ret;
150         }
151
152         return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent);
153 }
154
155 static struct nvkm_output *
156 exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
157             u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
158             struct nvbios_outp *info)
159 {
160         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
161         struct nvkm_bios *bios = subdev->device->bios;
162         struct nvkm_output *outp;
163         u16 mask, type;
164
165         if (or < 4) {
166                 type = DCB_OUTPUT_ANALOG;
167                 mask = 0;
168         } else
169         if (or < 8) {
170                 switch (ctrl & 0x00000f00) {
171                 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
172                 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
173                 case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break;
174                 case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break;
175                 case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break;
176                 case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
177                 default:
178                         nvkm_error(subdev, "unknown SOR mc %08x\n", ctrl);
179                         return NULL;
180                 }
181                 or  -= 4;
182         } else {
183                 or   = or - 8;
184                 type = 0x0010;
185                 mask = 0;
186                 switch (ctrl & 0x00000f00) {
187                 case 0x00000000: type |= disp->pior.type[or]; break;
188                 default:
189                         nvkm_error(subdev, "unknown PIOR mc %08x\n", ctrl);
190                         return NULL;
191                 }
192         }
193
194         mask  = 0x00c0 & (mask << 6);
195         mask |= 0x0001 << or;
196         mask |= 0x0100 << head;
197
198         list_for_each_entry(outp, &disp->base.outp, head) {
199                 if ((outp->info.hasht & 0xff) == type &&
200                     (outp->info.hashm & mask) == mask) {
201                         *data = nvbios_outp_match(bios, outp->info.hasht, mask,
202                                                   ver, hdr, cnt, len, info);
203                         if (!*data)
204                                 return NULL;
205                         return outp;
206                 }
207         }
208
209         return NULL;
210 }
211
212 static struct nvkm_output *
213 exec_script(struct nv50_disp *disp, int head, int id)
214 {
215         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
216         struct nvkm_device *device = subdev->device;
217         struct nvkm_bios *bios = device->bios;
218         struct nvkm_output *outp;
219         struct nvbios_outp info;
220         u8  ver, hdr, cnt, len;
221         u32 data, ctrl = 0;
222         u32 reg;
223         int i;
224
225         /* DAC */
226         for (i = 0; !(ctrl & (1 << head)) && i < disp->func->dac.nr; i++)
227                 ctrl = nvkm_rd32(device, 0x610b5c + (i * 8));
228
229         /* SOR */
230         if (!(ctrl & (1 << head))) {
231                 if (device->chipset  < 0x90 ||
232                     device->chipset == 0x92 ||
233                     device->chipset == 0xa0) {
234                         reg = 0x610b74;
235                 } else {
236                         reg = 0x610798;
237                 }
238                 for (i = 0; !(ctrl & (1 << head)) && i < disp->func->sor.nr; i++)
239                         ctrl = nvkm_rd32(device, reg + (i * 8));
240                 i += 4;
241         }
242
243         /* PIOR */
244         if (!(ctrl & (1 << head))) {
245                 for (i = 0; !(ctrl & (1 << head)) && i < disp->func->pior.nr; i++)
246                         ctrl = nvkm_rd32(device, 0x610b84 + (i * 8));
247                 i += 8;
248         }
249
250         if (!(ctrl & (1 << head)))
251                 return NULL;
252         i--;
253
254         outp = exec_lookup(disp, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
255         if (outp) {
256                 struct nvbios_init init = {
257                         .subdev = subdev,
258                         .bios = bios,
259                         .offset = info.script[id],
260                         .outp = &outp->info,
261                         .crtc = head,
262                         .execute = 1,
263                 };
264
265                 nvbios_exec(&init);
266         }
267
268         return outp;
269 }
270
271 static struct nvkm_output *
272 exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
273 {
274         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
275         struct nvkm_device *device = subdev->device;
276         struct nvkm_bios *bios = device->bios;
277         struct nvkm_output *outp;
278         struct nvbios_outp info1;
279         struct nvbios_ocfg info2;
280         u8  ver, hdr, cnt, len;
281         u32 data, ctrl = 0;
282         u32 reg;
283         int i;
284
285         /* DAC */
286         for (i = 0; !(ctrl & (1 << head)) && i < disp->func->dac.nr; i++)
287                 ctrl = nvkm_rd32(device, 0x610b58 + (i * 8));
288
289         /* SOR */
290         if (!(ctrl & (1 << head))) {
291                 if (device->chipset  < 0x90 ||
292                     device->chipset == 0x92 ||
293                     device->chipset == 0xa0) {
294                         reg = 0x610b70;
295                 } else {
296                         reg = 0x610794;
297                 }
298                 for (i = 0; !(ctrl & (1 << head)) && i < disp->func->sor.nr; i++)
299                         ctrl = nvkm_rd32(device, reg + (i * 8));
300                 i += 4;
301         }
302
303         /* PIOR */
304         if (!(ctrl & (1 << head))) {
305                 for (i = 0; !(ctrl & (1 << head)) && i < disp->func->pior.nr; i++)
306                         ctrl = nvkm_rd32(device, 0x610b80 + (i * 8));
307                 i += 8;
308         }
309
310         if (!(ctrl & (1 << head)))
311                 return NULL;
312         i--;
313
314         outp = exec_lookup(disp, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
315         if (!outp)
316                 return NULL;
317
318         *conf = (ctrl & 0x00000f00) >> 8;
319         if (outp->info.location == 0) {
320                 switch (outp->info.type) {
321                 case DCB_OUTPUT_TMDS:
322                         if (*conf == 5)
323                                 *conf |= 0x0100;
324                         break;
325                 case DCB_OUTPUT_LVDS:
326                         *conf |= disp->sor.lvdsconf;
327                         break;
328                 default:
329                         break;
330                 }
331         } else {
332                 *conf = (ctrl & 0x00000f00) >> 8;
333                 pclk = pclk / 2;
334         }
335
336         data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
337                                  &ver, &hdr, &cnt, &len, &info2);
338         if (data && id < 0xff) {
339                 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
340                 if (data) {
341                         struct nvbios_init init = {
342                                 .subdev = subdev,
343                                 .bios = bios,
344                                 .offset = data,
345                                 .outp = &outp->info,
346                                 .crtc = head,
347                                 .execute = 1,
348                         };
349
350                         nvbios_exec(&init);
351                 }
352         }
353
354         return outp;
355 }
356
357 /* If programming a TMDS output on a SOR that can also be configured for
358  * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off.
359  *
360  * It looks like the VBIOS TMDS scripts make an attempt at this, however,
361  * the VBIOS scripts on at least one board I have only switch it off on
362  * link 0, causing a blank display if the output has previously been
363  * programmed for DisplayPort.
364  */
365 static void
366 nv50_disp_intr_unk40_0_tmds(struct nv50_disp *disp,
367                             struct dcb_output *outp)
368 {
369         struct nvkm_device *device = disp->base.engine.subdev.device;
370         struct nvkm_bios *bios = device->bios;
371         const int link = !(outp->sorconf.link & 1);
372         const int   or = ffs(outp->or) - 1;
373         const u32 loff = (or * 0x800) + (link * 0x80);
374         const u16 mask = (outp->sorconf.link << 6) | outp->or;
375         struct dcb_output match;
376         u8  ver, hdr;
377
378         if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, &match))
379                 nvkm_mask(device, 0x61c10c + loff, 0x00000001, 0x00000000);
380 }
381
382 static void
383 nv50_disp_intr_unk40_0(struct nv50_disp *disp, int head)
384 {
385         struct nvkm_device *device = disp->base.engine.subdev.device;
386         struct nvkm_output *outp;
387         u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
388         u32 conf;
389
390         outp = exec_clkcmp(disp, head, 1, pclk, &conf);
391         if (!outp)
392                 return;
393
394         if (outp->info.location == 0 && outp->info.type == DCB_OUTPUT_TMDS)
395                 nv50_disp_intr_unk40_0_tmds(disp, &outp->info);
396         nv50_disp_dptmds_war_3(disp, &outp->info);
397 }
398
399 static void
400 nv50_disp_intr_unk20_2_dp(struct nv50_disp *disp, int head,
401                           struct dcb_output *outp, u32 pclk)
402 {
403         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
404         struct nvkm_device *device = subdev->device;
405         const int link = !(outp->sorconf.link & 1);
406         const int   or = ffs(outp->or) - 1;
407         const u32 soff = (  or * 0x800);
408         const u32 loff = (link * 0x080) + soff;
409         const u32 ctrl = nvkm_rd32(device, 0x610794 + (or * 8));
410         const u32 symbol = 100000;
411         const s32 vactive = nvkm_rd32(device, 0x610af8 + (head * 0x540)) & 0xffff;
412         const s32 vblanke = nvkm_rd32(device, 0x610ae8 + (head * 0x540)) & 0xffff;
413         const s32 vblanks = nvkm_rd32(device, 0x610af0 + (head * 0x540)) & 0xffff;
414         u32 dpctrl = nvkm_rd32(device, 0x61c10c + loff);
415         u32 clksor = nvkm_rd32(device, 0x614300 + soff);
416         int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0;
417         int TU, VTUi, VTUf, VTUa;
418         u64 link_data_rate, link_ratio, unk;
419         u32 best_diff = 64 * symbol;
420         u32 link_nr, link_bw, bits;
421         u64 value;
422
423         link_bw = (clksor & 0x000c0000) ? 270000 : 162000;
424         link_nr = hweight32(dpctrl & 0x000f0000);
425
426         /* symbols/hblank - algorithm taken from comments in tegra driver */
427         value = vblanke + vactive - vblanks - 7;
428         value = value * link_bw;
429         do_div(value, pclk);
430         value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr);
431         nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, value);
432
433         /* symbols/vblank - algorithm taken from comments in tegra driver */
434         value = vblanks - vblanke - 25;
435         value = value * link_bw;
436         do_div(value, pclk);
437         value = value - ((36 / link_nr) + 3) - 1;
438         nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, value);
439
440         /* watermark / activesym */
441         if      ((ctrl & 0xf0000) == 0x60000) bits = 30;
442         else if ((ctrl & 0xf0000) == 0x50000) bits = 24;
443         else                                  bits = 18;
444
445         link_data_rate = (pclk * bits / 8) / link_nr;
446
447         /* calculate ratio of packed data rate to link symbol rate */
448         link_ratio = link_data_rate * symbol;
449         do_div(link_ratio, link_bw);
450
451         for (TU = 64; TU >= 32; TU--) {
452                 /* calculate average number of valid symbols in each TU */
453                 u32 tu_valid = link_ratio * TU;
454                 u32 calc, diff;
455
456                 /* find a hw representation for the fraction.. */
457                 VTUi = tu_valid / symbol;
458                 calc = VTUi * symbol;
459                 diff = tu_valid - calc;
460                 if (diff) {
461                         if (diff >= (symbol / 2)) {
462                                 VTUf = symbol / (symbol - diff);
463                                 if (symbol - (VTUf * diff))
464                                         VTUf++;
465
466                                 if (VTUf <= 15) {
467                                         VTUa  = 1;
468                                         calc += symbol - (symbol / VTUf);
469                                 } else {
470                                         VTUa  = 0;
471                                         VTUf  = 1;
472                                         calc += symbol;
473                                 }
474                         } else {
475                                 VTUa  = 0;
476                                 VTUf  = min((int)(symbol / diff), 15);
477                                 calc += symbol / VTUf;
478                         }
479
480                         diff = calc - tu_valid;
481                 } else {
482                         /* no remainder, but the hw doesn't like the fractional
483                          * part to be zero.  decrement the integer part and
484                          * have the fraction add a whole symbol back
485                          */
486                         VTUa = 0;
487                         VTUf = 1;
488                         VTUi--;
489                 }
490
491                 if (diff < best_diff) {
492                         best_diff = diff;
493                         bestTU = TU;
494                         bestVTUa = VTUa;
495                         bestVTUf = VTUf;
496                         bestVTUi = VTUi;
497                         if (diff == 0)
498                                 break;
499                 }
500         }
501
502         if (!bestTU) {
503                 nvkm_error(subdev, "unable to find suitable dp config\n");
504                 return;
505         }
506
507         /* XXX close to vbios numbers, but not right */
508         unk  = (symbol - link_ratio) * bestTU;
509         unk *= link_ratio;
510         do_div(unk, symbol);
511         do_div(unk, symbol);
512         unk += 6;
513
514         nvkm_mask(device, 0x61c10c + loff, 0x000001fc, bestTU << 2);
515         nvkm_mask(device, 0x61c128 + loff, 0x010f7f3f, bestVTUa << 24 |
516                                                    bestVTUf << 16 |
517                                                    bestVTUi << 8 | unk);
518 }
519
520 static void
521 nv50_disp_intr_unk20_2(struct nv50_disp *disp, int head)
522 {
523         struct nvkm_device *device = disp->base.engine.subdev.device;
524         struct nvkm_output *outp;
525         u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
526         u32 hval, hreg = 0x614200 + (head * 0x800);
527         u32 oval, oreg;
528         u32 mask, conf;
529
530         outp = exec_clkcmp(disp, head, 0xff, pclk, &conf);
531         if (!outp)
532                 return;
533
534         /* we allow both encoder attach and detach operations to occur
535          * within a single supervisor (ie. modeset) sequence.  the
536          * encoder detach scripts quite often switch off power to the
537          * lanes, which requires the link to be re-trained.
538          *
539          * this is not generally an issue as the sink "must" (heh)
540          * signal an irq when it's lost sync so the driver can
541          * re-train.
542          *
543          * however, on some boards, if one does not configure at least
544          * the gpu side of the link *before* attaching, then various
545          * things can go horribly wrong (PDISP disappearing from mmio,
546          * third supervisor never happens, etc).
547          *
548          * the solution is simply to retrain here, if necessary.  last
549          * i checked, the binary driver userspace does not appear to
550          * trigger this situation (it forces an UPDATE between steps).
551          */
552         if (outp->info.type == DCB_OUTPUT_DP) {
553                 u32 soff = (ffs(outp->info.or) - 1) * 0x08;
554                 u32 ctrl, datarate;
555
556                 if (outp->info.location == 0) {
557                         ctrl = nvkm_rd32(device, 0x610794 + soff);
558                         soff = 1;
559                 } else {
560                         ctrl = nvkm_rd32(device, 0x610b80 + soff);
561                         soff = 2;
562                 }
563
564                 switch ((ctrl & 0x000f0000) >> 16) {
565                 case 6: datarate = pclk * 30; break;
566                 case 5: datarate = pclk * 24; break;
567                 case 2:
568                 default:
569                         datarate = pclk * 18;
570                         break;
571                 }
572
573                 if (nvkm_output_dp_train(outp, datarate / soff))
574                         OUTP_ERR(outp, "link not trained before attach");
575         }
576
577         exec_clkcmp(disp, head, 0, pclk, &conf);
578
579         if (!outp->info.location && outp->info.type == DCB_OUTPUT_ANALOG) {
580                 oreg = 0x614280 + (ffs(outp->info.or) - 1) * 0x800;
581                 oval = 0x00000000;
582                 hval = 0x00000000;
583                 mask = 0xffffffff;
584         } else
585         if (!outp->info.location) {
586                 if (outp->info.type == DCB_OUTPUT_DP)
587                         nv50_disp_intr_unk20_2_dp(disp, head, &outp->info, pclk);
588                 oreg = 0x614300 + (ffs(outp->info.or) - 1) * 0x800;
589                 oval = (conf & 0x0100) ? 0x00000101 : 0x00000000;
590                 hval = 0x00000000;
591                 mask = 0x00000707;
592         } else {
593                 oreg = 0x614380 + (ffs(outp->info.or) - 1) * 0x800;
594                 oval = 0x00000001;
595                 hval = 0x00000001;
596                 mask = 0x00000707;
597         }
598
599         nvkm_mask(device, hreg, 0x0000000f, hval);
600         nvkm_mask(device, oreg, mask, oval);
601
602         nv50_disp_dptmds_war_2(disp, &outp->info);
603 }
604
605 static void
606 nv50_disp_intr_unk20_1(struct nv50_disp *disp, int head)
607 {
608         struct nvkm_device *device = disp->base.engine.subdev.device;
609         struct nvkm_devinit *devinit = device->devinit;
610         u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
611         if (pclk)
612                 nvkm_devinit_pll_set(devinit, PLL_VPLL0 + head, pclk);
613 }
614
615 static void
616 nv50_disp_intr_unk20_0(struct nv50_disp *disp, int head)
617 {
618         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
619         struct nvkm_output *outp = exec_script(disp, head, 2);
620
621         /* the binary driver does this outside of the supervisor handling
622          * (after the third supervisor from a detach).  we (currently?)
623          * allow both detach/attach to happen in the same set of
624          * supervisor interrupts, so it would make sense to execute this
625          * (full power down?) script after all the detach phases of the
626          * supervisor handling.  like with training if needed from the
627          * second supervisor, nvidia doesn't do this, so who knows if it's
628          * entirely safe, but it does appear to work..
629          *
630          * without this script being run, on some configurations i've
631          * seen, switching from DP to TMDS on a DP connector may result
632          * in a blank screen (SOR_PWR off/on can restore it)
633          */
634         if (outp && outp->info.type == DCB_OUTPUT_DP) {
635                 struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
636                 struct nvbios_init init = {
637                         .subdev = subdev,
638                         .bios = subdev->device->bios,
639                         .outp = &outp->info,
640                         .crtc = head,
641                         .offset = outpdp->info.script[4],
642                         .execute = 1,
643                 };
644
645                 nvkm_notify_put(&outpdp->irq);
646                 nvbios_exec(&init);
647                 atomic_set(&outpdp->lt.done, 0);
648         }
649 }
650
651 static void
652 nv50_disp_intr_unk10_0(struct nv50_disp *disp, int head)
653 {
654         exec_script(disp, head, 1);
655 }
656
657 void
658 nv50_disp_super(struct work_struct *work)
659 {
660         struct nv50_disp *disp =
661                 container_of(work, struct nv50_disp, supervisor);
662         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
663         struct nvkm_device *device = subdev->device;
664         struct nvkm_head *head;
665         u32 super = nvkm_rd32(device, 0x610030);
666
667         nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super, super);
668
669         if (disp->super & 0x00000010) {
670                 nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG);
671                 list_for_each_entry(head, &disp->base.head, head) {
672                         if (!(super & (0x00000020 << head->id)))
673                                 continue;
674                         if (!(super & (0x00000080 << head->id)))
675                                 continue;
676                         nv50_disp_intr_unk10_0(disp, head->id);
677                 }
678         } else
679         if (disp->super & 0x00000020) {
680                 list_for_each_entry(head, &disp->base.head, head) {
681                         if (!(super & (0x00000080 << head->id)))
682                                 continue;
683                         nv50_disp_intr_unk20_0(disp, head->id);
684                 }
685                 list_for_each_entry(head, &disp->base.head, head) {
686                         if (!(super & (0x00000200 << head->id)))
687                                 continue;
688                         nv50_disp_intr_unk20_1(disp, head->id);
689                 }
690                 list_for_each_entry(head, &disp->base.head, head) {
691                         if (!(super & (0x00000080 << head->id)))
692                                 continue;
693                         nv50_disp_intr_unk20_2(disp, head->id);
694                 }
695         } else
696         if (disp->super & 0x00000040) {
697                 list_for_each_entry(head, &disp->base.head, head) {
698                         if (!(super & (0x00000080 << head->id)))
699                                 continue;
700                         nv50_disp_intr_unk40_0(disp, head->id);
701                 }
702                 nv50_disp_update_sppll1(disp);
703         }
704
705         nvkm_wr32(device, 0x610030, 0x80000000);
706 }
707
708 static const struct nvkm_enum
709 nv50_disp_intr_error_type[] = {
710         { 3, "ILLEGAL_MTHD" },
711         { 4, "INVALID_VALUE" },
712         { 5, "INVALID_STATE" },
713         { 7, "INVALID_HANDLE" },
714         {}
715 };
716
717 static const struct nvkm_enum
718 nv50_disp_intr_error_code[] = {
719         { 0x00, "" },
720         {}
721 };
722
723 static void
724 nv50_disp_intr_error(struct nv50_disp *disp, int chid)
725 {
726         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
727         struct nvkm_device *device = subdev->device;
728         u32 data = nvkm_rd32(device, 0x610084 + (chid * 0x08));
729         u32 addr = nvkm_rd32(device, 0x610080 + (chid * 0x08));
730         u32 code = (addr & 0x00ff0000) >> 16;
731         u32 type = (addr & 0x00007000) >> 12;
732         u32 mthd = (addr & 0x00000ffc);
733         const struct nvkm_enum *ec, *et;
734
735         et = nvkm_enum_find(nv50_disp_intr_error_type, type);
736         ec = nvkm_enum_find(nv50_disp_intr_error_code, code);
737
738         nvkm_error(subdev,
739                    "ERROR %d [%s] %02x [%s] chid %d mthd %04x data %08x\n",
740                    type, et ? et->name : "", code, ec ? ec->name : "",
741                    chid, mthd, data);
742
743         if (chid < ARRAY_SIZE(disp->chan)) {
744                 switch (mthd) {
745                 case 0x0080:
746                         nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR);
747                         break;
748                 default:
749                         break;
750                 }
751         }
752
753         nvkm_wr32(device, 0x610020, 0x00010000 << chid);
754         nvkm_wr32(device, 0x610080 + (chid * 0x08), 0x90000000);
755 }
756
757 void
758 nv50_disp_intr(struct nv50_disp *disp)
759 {
760         struct nvkm_device *device = disp->base.engine.subdev.device;
761         u32 intr0 = nvkm_rd32(device, 0x610020);
762         u32 intr1 = nvkm_rd32(device, 0x610024);
763
764         while (intr0 & 0x001f0000) {
765                 u32 chid = __ffs(intr0 & 0x001f0000) - 16;
766                 nv50_disp_intr_error(disp, chid);
767                 intr0 &= ~(0x00010000 << chid);
768         }
769
770         while (intr0 & 0x0000001f) {
771                 u32 chid = __ffs(intr0 & 0x0000001f);
772                 nv50_disp_chan_uevent_send(disp, chid);
773                 intr0 &= ~(0x00000001 << chid);
774         }
775
776         if (intr1 & 0x00000004) {
777                 nvkm_disp_vblank(&disp->base, 0);
778                 nvkm_wr32(device, 0x610024, 0x00000004);
779         }
780
781         if (intr1 & 0x00000008) {
782                 nvkm_disp_vblank(&disp->base, 1);
783                 nvkm_wr32(device, 0x610024, 0x00000008);
784         }
785
786         if (intr1 & 0x00000070) {
787                 disp->super = (intr1 & 0x00000070);
788                 schedule_work(&disp->supervisor);
789                 nvkm_wr32(device, 0x610024, disp->super);
790         }
791 }
792
793 static const struct nv50_disp_func
794 nv50_disp = {
795         .intr = nv50_disp_intr,
796         .uevent = &nv50_disp_chan_uevent,
797         .super = nv50_disp_super,
798         .root = &nv50_disp_root_oclass,
799         .head.new = nv50_head_new,
800         .outp.internal.crt = nv50_dac_output_new,
801         .outp.internal.tmds = nv50_sor_output_new,
802         .outp.internal.lvds = nv50_sor_output_new,
803         .outp.external.tmds = nv50_pior_output_new,
804         .outp.external.dp = nv50_pior_dp_new,
805         .dac.nr = 3,
806         .dac.power = nv50_dac_power,
807         .dac.sense = nv50_dac_sense,
808         .sor.nr = 2,
809         .sor.power = nv50_sor_power,
810         .pior.nr = 3,
811         .pior.power = nv50_pior_power,
812 };
813
814 int
815 nv50_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
816 {
817         return nv50_disp_new_(&nv50_disp, device, index, 2, pdisp);
818 }