]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
drm/nouveau/disp/nv50-: implement a common supervisor 1.0
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nvkm / engine / disp / gf119.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 "ior.h"
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
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)
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) {
70                         *data = nvbios_outp_match(bios, outp->info.hasht, mask,
71                                                   ver, hdr, cnt, len, info);
72                         if (!*data)
73                                 return NULL;
74                         return outp;
75                 }
76         }
77
78         return NULL;
79 }
80
81 static struct nvkm_output *
82 exec_script(struct nv50_disp *disp, int head, int id)
83 {
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;
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 = {
105                         .subdev = subdev,
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
119 static struct nvkm_output *
120 exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
121 {
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;
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
145         *conf = (ctrl & 0x00000f00) >> 8;
146         switch (outp->info.type) {
147         case DCB_OUTPUT_TMDS:
148                 if (*conf == 5)
149                         *conf |= 0x0100;
150                 break;
151         case DCB_OUTPUT_LVDS:
152                 *conf |= disp->sor.lvdsconf;
153                 break;
154         default:
155                 break;
156         }
157
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);
162                 if (data) {
163                         struct nvbios_init init = {
164                                 .subdev = subdev,
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
179 static void
180 gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head)
181 {
182         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
183         struct nvkm_output *outp = exec_script(disp, head, 2);
184
185         /* see note in nv50_disp_intr_unk20_0() */
186         if (outp && outp->info.type == DCB_OUTPUT_DP) {
187                 struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
188                 if (!outpdp->lt.mst) {
189                         struct nvbios_init init = {
190                                 .subdev = subdev,
191                                 .bios = subdev->device->bios,
192                                 .outp = &outp->info,
193                                 .crtc = head,
194                                 .offset = outpdp->info.script[4],
195                                 .execute = 1,
196                         };
197
198                         atomic_set(&outpdp->lt.done, 0);
199                         nvbios_exec(&init);
200                 }
201         }
202 }
203
204 static void
205 gf119_disp_intr_unk2_1(struct nv50_disp *disp, int head)
206 {
207         struct nvkm_device *device = disp->base.engine.subdev.device;
208         struct nvkm_devinit *devinit = device->devinit;
209         u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
210         if (pclk)
211                 nvkm_devinit_pll_set(devinit, PLL_VPLL0 + head, pclk);
212         nvkm_wr32(device, 0x612200 + (head * 0x800), 0x00000000);
213 }
214
215 static void
216 gf119_disp_intr_unk2_2_tu(struct nv50_disp *disp, int head,
217                           struct dcb_output *outp)
218 {
219         struct nvkm_device *device = disp->base.engine.subdev.device;
220         const int or = ffs(outp->or) - 1;
221         const u32 ctrl = nvkm_rd32(device, 0x660200 + (or   * 0x020));
222         const u32 conf = nvkm_rd32(device, 0x660404 + (head * 0x300));
223         const s32 vactive = nvkm_rd32(device, 0x660414 + (head * 0x300)) & 0xffff;
224         const s32 vblanke = nvkm_rd32(device, 0x66041c + (head * 0x300)) & 0xffff;
225         const s32 vblanks = nvkm_rd32(device, 0x660420 + (head * 0x300)) & 0xffff;
226         const u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
227         const u32 link = ((ctrl & 0xf00) == 0x800) ? 0 : 1;
228         const u32 hoff = (head * 0x800);
229         const u32 soff = (  or * 0x800);
230         const u32 loff = (link * 0x080) + soff;
231         const u32 symbol = 100000;
232         const u32 TU = 64;
233         u32 dpctrl = nvkm_rd32(device, 0x61c10c + loff);
234         u32 clksor = nvkm_rd32(device, 0x612300 + soff);
235         u32 datarate, link_nr, link_bw, bits;
236         u64 ratio, value;
237
238         link_nr  = hweight32(dpctrl & 0x000f0000);
239         link_bw  = (clksor & 0x007c0000) >> 18;
240         link_bw *= 27000;
241
242         /* symbols/hblank - algorithm taken from comments in tegra driver */
243         value = vblanke + vactive - vblanks - 7;
244         value = value * link_bw;
245         do_div(value, pclk);
246         value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr);
247         nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, value);
248
249         /* symbols/vblank - algorithm taken from comments in tegra driver */
250         value = vblanks - vblanke - 25;
251         value = value * link_bw;
252         do_div(value, pclk);
253         value = value - ((36 / link_nr) + 3) - 1;
254         nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, value);
255
256         /* watermark */
257         if      ((conf & 0x3c0) == 0x180) bits = 30;
258         else if ((conf & 0x3c0) == 0x140) bits = 24;
259         else                              bits = 18;
260         datarate = (pclk * bits) / 8;
261
262         ratio  = datarate;
263         ratio *= symbol;
264         do_div(ratio, link_nr * link_bw);
265
266         value  = (symbol - ratio) * TU;
267         value *= ratio;
268         do_div(value, symbol);
269         do_div(value, symbol);
270
271         value += 5;
272         value |= 0x08000000;
273
274         nvkm_wr32(device, 0x616610 + hoff, value);
275 }
276
277 static void
278 gf119_disp_intr_unk2_2(struct nv50_disp *disp, int head)
279 {
280         struct nvkm_device *device = disp->base.engine.subdev.device;
281         struct nvkm_output *outp;
282         u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
283         u32 conf, addr, data;
284
285         outp = exec_clkcmp(disp, head, 0xff, pclk, &conf);
286         if (!outp)
287                 return;
288
289         /* see note in nv50_disp_intr_unk20_2() */
290         if (outp->info.type == DCB_OUTPUT_DP) {
291                 u32 sync = nvkm_rd32(device, 0x660404 + (head * 0x300));
292                 switch ((sync & 0x000003c0) >> 6) {
293                 case 6: pclk = pclk * 30; break;
294                 case 5: pclk = pclk * 24; break;
295                 case 2:
296                 default:
297                         pclk = pclk * 18;
298                         break;
299                 }
300
301                 if (nvkm_output_dp_train(outp, pclk))
302                         OUTP_ERR(outp, "link not trained before attach");
303         }
304
305         exec_clkcmp(disp, head, 0, pclk, &conf);
306
307         if (outp->info.type == DCB_OUTPUT_ANALOG) {
308                 addr = 0x612280 + (ffs(outp->info.or) - 1) * 0x800;
309                 data = 0x00000000;
310         } else {
311                 addr = 0x612300 + (ffs(outp->info.or) - 1) * 0x800;
312                 data = (conf & 0x0100) ? 0x00000101 : 0x00000000;
313                 switch (outp->info.type) {
314                 case DCB_OUTPUT_TMDS:
315                         nvkm_mask(device, addr, 0x007c0000, 0x00280000);
316                         break;
317                 case DCB_OUTPUT_DP:
318                         gf119_disp_intr_unk2_2_tu(disp, head, &outp->info);
319                         break;
320                 default:
321                         break;
322                 }
323         }
324
325         nvkm_mask(device, addr, 0x00000707, data);
326 }
327
328 static void
329 gf119_disp_intr_unk4_0(struct nv50_disp *disp, int head)
330 {
331         struct nvkm_device *device = disp->base.engine.subdev.device;
332         u32 pclk = nvkm_rd32(device, 0x660450 + (head * 0x300)) / 1000;
333         u32 conf;
334
335         exec_clkcmp(disp, head, 1, pclk, &conf);
336 }
337
338 void
339 gf119_disp_super(struct work_struct *work)
340 {
341         struct nv50_disp *disp =
342                 container_of(work, struct nv50_disp, supervisor);
343         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
344         struct nvkm_device *device = subdev->device;
345         struct nvkm_head *head;
346         u32 mask[4];
347
348         nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super));
349         list_for_each_entry(head, &disp->base.head, head) {
350                 mask[head->id] = nvkm_rd32(device, 0x6101d4 + (head->id * 0x800));
351                 HEAD_DBG(head, "%08x", mask[head->id]);
352         }
353
354         if (disp->super & 0x00000001) {
355                 nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG);
356                 nv50_disp_super_1(disp);
357                 list_for_each_entry(head, &disp->base.head, head) {
358                         if (!(mask[head->id] & 0x00001000))
359                                 continue;
360                         nv50_disp_super_1_0(disp, head);
361                 }
362         } else
363         if (disp->super & 0x00000002) {
364                 list_for_each_entry(head, &disp->base.head, head) {
365                         if (!(mask[head->id] & 0x00001000))
366                                 continue;
367                         nvkm_debug(subdev, "supervisor 2.0 - head %d\n", head->id);
368                         gf119_disp_intr_unk2_0(disp, head->id);
369                 }
370                 nvkm_outp_route(&disp->base);
371                 list_for_each_entry(head, &disp->base.head, head) {
372                         if (!(mask[head->id] & 0x00010000))
373                                 continue;
374                         nvkm_debug(subdev, "supervisor 2.1 - head %d\n", head->id);
375                         gf119_disp_intr_unk2_1(disp, head->id);
376                 }
377                 list_for_each_entry(head, &disp->base.head, head) {
378                         if (!(mask[head->id] & 0x00001000))
379                                 continue;
380                         nvkm_debug(subdev, "supervisor 2.2 - head %d\n", head->id);
381                         gf119_disp_intr_unk2_2(disp, head->id);
382                 }
383         } else
384         if (disp->super & 0x00000004) {
385                 list_for_each_entry(head, &disp->base.head, head) {
386                         if (!(mask[head->id] & 0x00001000))
387                                 continue;
388                         nvkm_debug(subdev, "supervisor 3.0 - head %d\n", head->id);
389                         gf119_disp_intr_unk4_0(disp, head->id);
390                 }
391         }
392
393         list_for_each_entry(head, &disp->base.head, head)
394                 nvkm_wr32(device, 0x6101d4 + (head->id * 0x800), 0x00000000);
395         nvkm_wr32(device, 0x6101d0, 0x80000000);
396 }
397
398 void
399 gf119_disp_intr_error(struct nv50_disp *disp, int chid)
400 {
401         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
402         struct nvkm_device *device = subdev->device;
403         u32 mthd = nvkm_rd32(device, 0x6101f0 + (chid * 12));
404         u32 data = nvkm_rd32(device, 0x6101f4 + (chid * 12));
405         u32 unkn = nvkm_rd32(device, 0x6101f8 + (chid * 12));
406
407         nvkm_error(subdev, "chid %d mthd %04x data %08x %08x %08x\n",
408                    chid, (mthd & 0x0000ffc), data, mthd, unkn);
409
410         if (chid < ARRAY_SIZE(disp->chan)) {
411                 switch (mthd & 0xffc) {
412                 case 0x0080:
413                         nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR);
414                         break;
415                 default:
416                         break;
417                 }
418         }
419
420         nvkm_wr32(device, 0x61009c, (1 << chid));
421         nvkm_wr32(device, 0x6101f0 + (chid * 12), 0x90000000);
422 }
423
424 void
425 gf119_disp_intr(struct nv50_disp *disp)
426 {
427         struct nvkm_subdev *subdev = &disp->base.engine.subdev;
428         struct nvkm_device *device = subdev->device;
429         struct nvkm_head *head;
430         u32 intr = nvkm_rd32(device, 0x610088);
431
432         if (intr & 0x00000001) {
433                 u32 stat = nvkm_rd32(device, 0x61008c);
434                 while (stat) {
435                         int chid = __ffs(stat); stat &= ~(1 << chid);
436                         nv50_disp_chan_uevent_send(disp, chid);
437                         nvkm_wr32(device, 0x61008c, 1 << chid);
438                 }
439                 intr &= ~0x00000001;
440         }
441
442         if (intr & 0x00000002) {
443                 u32 stat = nvkm_rd32(device, 0x61009c);
444                 int chid = ffs(stat) - 1;
445                 if (chid >= 0)
446                         disp->func->intr_error(disp, chid);
447                 intr &= ~0x00000002;
448         }
449
450         if (intr & 0x00100000) {
451                 u32 stat = nvkm_rd32(device, 0x6100ac);
452                 if (stat & 0x00000007) {
453                         disp->super = (stat & 0x00000007);
454                         queue_work(disp->wq, &disp->supervisor);
455                         nvkm_wr32(device, 0x6100ac, disp->super);
456                         stat &= ~0x00000007;
457                 }
458
459                 if (stat) {
460                         nvkm_warn(subdev, "intr24 %08x\n", stat);
461                         nvkm_wr32(device, 0x6100ac, stat);
462                 }
463
464                 intr &= ~0x00100000;
465         }
466
467         list_for_each_entry(head, &disp->base.head, head) {
468                 const u32 hoff = head->id * 0x800;
469                 u32 mask = 0x01000000 << head->id;
470                 if (mask & intr) {
471                         u32 stat = nvkm_rd32(device, 0x6100bc + hoff);
472                         if (stat & 0x00000001)
473                                 nvkm_disp_vblank(&disp->base, head->id);
474                         nvkm_mask(device, 0x6100bc + hoff, 0, 0);
475                         nvkm_rd32(device, 0x6100c0 + hoff);
476                 }
477         }
478 }
479
480 int
481 gf119_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device,
482                 int index, struct nvkm_disp **pdisp)
483 {
484         u32 heads = nvkm_rd32(device, 0x022448);
485         return nv50_disp_new_(func, device, index, heads, pdisp);
486 }
487
488 static const struct nv50_disp_func
489 gf119_disp = {
490         .intr = gf119_disp_intr,
491         .intr_error = gf119_disp_intr_error,
492         .uevent = &gf119_disp_chan_uevent,
493         .super = gf119_disp_super,
494         .root = &gf119_disp_root_oclass,
495         .head.new = gf119_head_new,
496         .dac = { .nr = 3, .new = gf119_dac_new },
497         .sor = { .nr = 4, .new = gf119_sor_new },
498 };
499
500 int
501 gf119_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
502 {
503         return gf119_disp_new_(&gf119_disp, device, index, pdisp);
504 }