drm/nouveau/device: decouple from engine machinery
[deliverable/linux.git] / drivers / gpu / drm / nouveau / nvkm / engine / disp / nv50.c
CommitLineData
ebb945a9
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 */
878da15a
BS
24#include "nv50.h"
25#include "outp.h"
26#include "outpdp.h"
ebb945a9 27
bf0eb898 28#include <core/client.h>
a1e88736 29#include <core/gpuobj.h>
117e1633 30#include <core/enum.h>
878da15a
BS
31#include <core/handle.h>
32#include <core/ramht.h>
33#include <engine/dmaobj.h>
186ecad2
BS
34#include <subdev/bios.h>
35#include <subdev/bios/dcb.h>
36#include <subdev/bios/disp.h>
37#include <subdev/bios/init.h>
38#include <subdev/bios/pll.h>
88524bc0 39#include <subdev/devinit.h>
370c00f9 40#include <subdev/fb.h>
878da15a 41#include <subdev/timer.h>
446b05a0 42
878da15a
BS
43#include <nvif/class.h>
44#include <nvif/event.h>
45#include <nvif/unpack.h>
70cabe4a
BS
46
47/*******************************************************************************
370c00f9 48 * EVO channel base class
70cabe4a
BS
49 ******************************************************************************/
50
2c04ae01 51static int
878da15a
BS
52nv50_disp_chan_create_(struct nvkm_object *parent,
53 struct nvkm_object *engine,
54 struct nvkm_oclass *oclass, int head,
370c00f9
BS
55 int length, void **pobject)
56{
2c04ae01 57 const struct nv50_disp_chan_impl *impl = (void *)oclass->ofuncs;
370c00f9
BS
58 struct nv50_disp_base *base = (void *)parent;
59 struct nv50_disp_chan *chan;
2c04ae01 60 int chid = impl->chid + head;
370c00f9
BS
61 int ret;
62
63 if (base->chan & (1 << chid))
64 return -EBUSY;
65 base->chan |= (1 << chid);
66
878da15a
BS
67 ret = nvkm_namedb_create_(parent, engine, oclass, 0, NULL,
68 (1ULL << NVDEV_ENGINE_DMAOBJ),
69 length, pobject);
370c00f9
BS
70 chan = *pobject;
71 if (ret)
72 return ret;
370c00f9 73 chan->chid = chid;
2c04ae01
BS
74
75 nv_parent(chan)->object_attach = impl->attach;
76 nv_parent(chan)->object_detach = impl->detach;
370c00f9
BS
77 return 0;
78}
79
2c04ae01 80static void
370c00f9
BS
81nv50_disp_chan_destroy(struct nv50_disp_chan *chan)
82{
83 struct nv50_disp_base *base = (void *)nv_object(chan)->parent;
84 base->chan &= ~(1 << chan->chid);
878da15a 85 nvkm_namedb_destroy(&chan->base);
370c00f9
BS
86}
87
b38a2322
BS
88static void
89nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index)
90{
fd166a18 91 struct nv50_disp *disp = container_of(event, typeof(*disp), uevent);
2fde1f1c
BS
92 struct nvkm_device *device = disp->base.engine.subdev.device;
93 nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000000 << index);
94 nvkm_wr32(device, 0x610020, 0x00000001 << index);
b38a2322
BS
95}
96
97static void
98nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index)
99{
fd166a18 100 struct nv50_disp *disp = container_of(event, typeof(*disp), uevent);
2fde1f1c
BS
101 struct nvkm_device *device = disp->base.engine.subdev.device;
102 nvkm_wr32(device, 0x610020, 0x00000001 << index);
103 nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000001 << index);
b38a2322
BS
104}
105
106void
fd166a18 107nv50_disp_chan_uevent_send(struct nv50_disp *disp, int chid)
b38a2322
BS
108{
109 struct nvif_notify_uevent_rep {
110 } rep;
111
fd166a18 112 nvkm_event_send(&disp->uevent, 1, chid, &rep, sizeof(rep));
b38a2322
BS
113}
114
115int
878da15a 116nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size,
b38a2322
BS
117 struct nvkm_notify *notify)
118{
119 struct nv50_disp_dmac *dmac = (void *)object;
120 union {
121 struct nvif_notify_uevent_req none;
122 } *args = data;
123 int ret;
124
125 if (nvif_unvers(args->none)) {
126 notify->size = sizeof(struct nvif_notify_uevent_rep);
127 notify->types = 1;
128 notify->index = dmac->base.chid;
129 return 0;
130 }
131
132 return ret;
133}
134
135const struct nvkm_event_func
136nv50_disp_chan_uevent = {
137 .ctor = nv50_disp_chan_uevent_ctor,
138 .init = nv50_disp_chan_uevent_init,
139 .fini = nv50_disp_chan_uevent_fini,
140};
141
142int
878da15a 143nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type,
b38a2322
BS
144 struct nvkm_event **pevent)
145{
fd166a18 146 struct nv50_disp *disp = (void *)object->engine;
b38a2322
BS
147 switch (type) {
148 case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT:
fd166a18 149 *pevent = &disp->uevent;
b38a2322
BS
150 return 0;
151 default:
152 break;
153 }
154 return -EINVAL;
155}
156
b76f1529 157int
878da15a 158nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size)
b76f1529
BS
159{
160 struct nv50_disp_chan *chan = (void *)object;
161 *addr = nv_device_resource_start(nv_device(object), 0) +
162 0x640000 + (chan->chid * 0x1000);
163 *size = 0x001000;
164 return 0;
165}
166
370c00f9 167u32
878da15a 168nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr)
70cabe4a 169{
370c00f9 170 struct nv50_disp_chan *chan = (void *)object;
2fde1f1c
BS
171 struct nvkm_device *device = object->engine->subdev.device;
172 return nvkm_rd32(device, 0x640000 + (chan->chid * 0x1000) + addr);
70cabe4a
BS
173}
174
370c00f9 175void
878da15a 176nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data)
70cabe4a 177{
370c00f9 178 struct nv50_disp_chan *chan = (void *)object;
2fde1f1c
BS
179 struct nvkm_device *device = object->engine->subdev.device;
180 nvkm_wr32(device, 0x640000 + (chan->chid * 0x1000) + addr, data);
370c00f9
BS
181}
182
183/*******************************************************************************
184 * EVO DMA channel base class
185 ******************************************************************************/
186
187static int
878da15a
BS
188nv50_disp_dmac_object_attach(struct nvkm_object *parent,
189 struct nvkm_object *object, u32 name)
370c00f9
BS
190{
191 struct nv50_disp_base *base = (void *)parent->parent;
192 struct nv50_disp_chan *chan = (void *)parent;
193 u32 addr = nv_gpuobj(object)->node->offset;
194 u32 chid = chan->chid;
195 u32 data = (chid << 28) | (addr << 10) | chid;
878da15a 196 return nvkm_ramht_insert(base->ramht, chid, name, data);
370c00f9
BS
197}
198
199static void
878da15a 200nv50_disp_dmac_object_detach(struct nvkm_object *parent, int cookie)
370c00f9
BS
201{
202 struct nv50_disp_base *base = (void *)parent->parent;
878da15a 203 nvkm_ramht_remove(base->ramht, cookie);
370c00f9
BS
204}
205
2c04ae01 206static int
878da15a
BS
207nv50_disp_dmac_create_(struct nvkm_object *parent,
208 struct nvkm_object *engine,
209 struct nvkm_oclass *oclass, u32 pushbuf, int head,
370c00f9
BS
210 int length, void **pobject)
211{
212 struct nv50_disp_dmac *dmac;
213 int ret;
214
2c04ae01 215 ret = nv50_disp_chan_create_(parent, engine, oclass, head,
370c00f9
BS
216 length, pobject);
217 dmac = *pobject;
218 if (ret)
219 return ret;
220
878da15a 221 dmac->pushdma = (void *)nvkm_handle_ref(parent, pushbuf);
370c00f9
BS
222 if (!dmac->pushdma)
223 return -ENOENT;
224
225 switch (nv_mclass(dmac->pushdma)) {
226 case 0x0002:
227 case 0x003d:
228 if (dmac->pushdma->limit - dmac->pushdma->start != 0xfff)
229 return -EINVAL;
230
231 switch (dmac->pushdma->target) {
232 case NV_MEM_TARGET_VRAM:
963e9650 233 dmac->push = 0x00000001 | dmac->pushdma->start >> 8;
370c00f9 234 break;
944234d6
BS
235 case NV_MEM_TARGET_PCI_NOSNOOP:
236 dmac->push = 0x00000003 | dmac->pushdma->start >> 8;
237 break;
370c00f9
BS
238 default:
239 return -EINVAL;
240 }
241 break;
242 default:
243 return -EINVAL;
244 }
245
246 return 0;
247}
248
249void
878da15a 250nv50_disp_dmac_dtor(struct nvkm_object *object)
370c00f9
BS
251{
252 struct nv50_disp_dmac *dmac = (void *)object;
878da15a 253 nvkm_object_ref(NULL, (struct nvkm_object **)&dmac->pushdma);
370c00f9
BS
254 nv50_disp_chan_destroy(&dmac->base);
255}
256
257static int
878da15a 258nv50_disp_dmac_init(struct nvkm_object *object)
370c00f9 259{
fd166a18 260 struct nv50_disp *disp = (void *)object->engine;
370c00f9 261 struct nv50_disp_dmac *dmac = (void *)object;
84407824
BS
262 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
263 struct nvkm_device *device = subdev->device;
370c00f9
BS
264 int chid = dmac->base.chid;
265 int ret;
266
267 ret = nv50_disp_chan_init(&dmac->base);
268 if (ret)
269 return ret;
270
271 /* enable error reporting */
2fde1f1c 272 nvkm_mask(device, 0x610028, 0x00010000 << chid, 0x00010000 << chid);
370c00f9
BS
273
274 /* initialise channel for dma command submission */
2fde1f1c
BS
275 nvkm_wr32(device, 0x610204 + (chid * 0x0010), dmac->push);
276 nvkm_wr32(device, 0x610208 + (chid * 0x0010), 0x00010000);
277 nvkm_wr32(device, 0x61020c + (chid * 0x0010), chid);
278 nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010);
279 nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000);
280 nvkm_wr32(device, 0x610200 + (chid * 0x0010), 0x00000013);
370c00f9
BS
281
282 /* wait for it to go inactive */
3a020b4d
BS
283 if (nvkm_msec(device, 2000,
284 if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x80000000))
285 break;
286 ) < 0) {
84407824
BS
287 nvkm_error(subdev, "ch %d init timeout, %08x\n", chid,
288 nvkm_rd32(device, 0x610200 + (chid * 0x10)));
370c00f9
BS
289 return -EBUSY;
290 }
291
292 return 0;
293}
294
295static int
878da15a 296nv50_disp_dmac_fini(struct nvkm_object *object, bool suspend)
370c00f9 297{
fd166a18 298 struct nv50_disp *disp = (void *)object->engine;
370c00f9 299 struct nv50_disp_dmac *dmac = (void *)object;
84407824
BS
300 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
301 struct nvkm_device *device = subdev->device;
370c00f9
BS
302 int chid = dmac->base.chid;
303
304 /* deactivate channel */
2fde1f1c
BS
305 nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00001010, 0x00001000);
306 nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000003, 0x00000000);
3a020b4d
BS
307 if (nvkm_msec(device, 2000,
308 if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x001e0000))
309 break;
310 ) < 0) {
84407824
BS
311 nvkm_error(subdev, "ch %d fini timeout, %08x\n", chid,
312 nvkm_rd32(device, 0x610200 + (chid * 0x10)));
370c00f9
BS
313 if (suspend)
314 return -EBUSY;
315 }
316
b38a2322 317 /* disable error reporting and completion notifications */
2fde1f1c 318 nvkm_mask(device, 0x610028, 0x00010001 << chid, 0x00000000 << chid);
370c00f9
BS
319
320 return nv50_disp_chan_fini(&dmac->base, suspend);
70cabe4a
BS
321}
322
323/*******************************************************************************
324 * EVO master channel object
325 ******************************************************************************/
326
d67d92c0 327static void
fd166a18 328nv50_disp_mthd_list(struct nv50_disp *disp, int debug, u32 base, int c,
d67d92c0
BS
329 const struct nv50_disp_mthd_list *list, int inst)
330{
84407824
BS
331 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
332 struct nvkm_device *device = subdev->device;
d67d92c0
BS
333 int i;
334
335 for (i = 0; list->data[i].mthd; i++) {
336 if (list->data[i].addr) {
2fde1f1c
BS
337 u32 next = nvkm_rd32(device, list->data[i].addr + base + 0);
338 u32 prev = nvkm_rd32(device, list->data[i].addr + base + c);
d67d92c0
BS
339 u32 mthd = list->data[i].mthd + (list->mthd * inst);
340 const char *name = list->data[i].name;
341 char mods[16];
342
343 if (prev != next)
84407824 344 snprintf(mods, sizeof(mods), "-> %08x", next);
d67d92c0
BS
345 else
346 snprintf(mods, sizeof(mods), "%13c", ' ');
347
84407824
BS
348 nvkm_printk_(subdev, debug, info,
349 "\t%04x: %08x %s%s%s\n",
350 mthd, prev, mods, name ? " // " : "",
351 name ? name : "");
d67d92c0
BS
352 }
353 }
354}
355
356void
fd166a18 357nv50_disp_mthd_chan(struct nv50_disp *disp, int debug, int head,
d67d92c0
BS
358 const struct nv50_disp_mthd_chan *chan)
359{
fd166a18
BS
360 struct nvkm_object *object = nv_object(disp);
361 const struct nv50_disp_impl *impl = (void *)object->oclass;
d67d92c0 362 const struct nv50_disp_mthd_list *list;
84407824 363 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
d67d92c0
BS
364 int i, j;
365
fd166a18 366 if (debug > nv_subdev(disp)->debug)
d67d92c0
BS
367 return;
368
369 for (i = 0; (list = chan->data[i].mthd) != NULL; i++) {
370 u32 base = head * chan->addr;
371 for (j = 0; j < chan->data[i].nr; j++, base += list->addr) {
372 const char *cname = chan->name;
373 const char *sname = "";
374 char cname_[16], sname_[16];
375
376 if (chan->addr) {
377 snprintf(cname_, sizeof(cname_), "%s %d",
378 chan->name, head);
379 cname = cname_;
380 }
381
382 if (chan->data[i].nr > 1) {
383 snprintf(sname_, sizeof(sname_), " - %s %d",
384 chan->data[i].name, j);
385 sname = sname_;
386 }
387
84407824 388 nvkm_printk_(subdev, debug, info, "%s%s:\n", cname, sname);
fd166a18 389 nv50_disp_mthd_list(disp, debug, base, impl->mthd.prev,
d67d92c0
BS
390 list, j);
391 }
392 }
393}
394
395const struct nv50_disp_mthd_list
2832271d 396nv50_disp_core_mthd_base = {
d67d92c0
BS
397 .mthd = 0x0000,
398 .addr = 0x000000,
399 .data = {
400 { 0x0080, 0x000000 },
401 { 0x0084, 0x610bb8 },
402 { 0x0088, 0x610b9c },
403 { 0x008c, 0x000000 },
404 {}
405 }
406};
407
408static const struct nv50_disp_mthd_list
2832271d 409nv50_disp_core_mthd_dac = {
d67d92c0
BS
410 .mthd = 0x0080,
411 .addr = 0x000008,
412 .data = {
413 { 0x0400, 0x610b58 },
414 { 0x0404, 0x610bdc },
415 { 0x0420, 0x610828 },
416 {}
417 }
418};
419
420const struct nv50_disp_mthd_list
2832271d 421nv50_disp_core_mthd_sor = {
d67d92c0
BS
422 .mthd = 0x0040,
423 .addr = 0x000008,
424 .data = {
425 { 0x0600, 0x610b70 },
426 {}
427 }
428};
429
430const struct nv50_disp_mthd_list
2832271d 431nv50_disp_core_mthd_pior = {
d67d92c0
BS
432 .mthd = 0x0040,
433 .addr = 0x000008,
434 .data = {
435 { 0x0700, 0x610b80 },
436 {}
437 }
438};
439
440static const struct nv50_disp_mthd_list
2832271d 441nv50_disp_core_mthd_head = {
d67d92c0
BS
442 .mthd = 0x0400,
443 .addr = 0x000540,
444 .data = {
445 { 0x0800, 0x610ad8 },
446 { 0x0804, 0x610ad0 },
447 { 0x0808, 0x610a48 },
448 { 0x080c, 0x610a78 },
449 { 0x0810, 0x610ac0 },
450 { 0x0814, 0x610af8 },
451 { 0x0818, 0x610b00 },
452 { 0x081c, 0x610ae8 },
453 { 0x0820, 0x610af0 },
454 { 0x0824, 0x610b08 },
455 { 0x0828, 0x610b10 },
456 { 0x082c, 0x610a68 },
457 { 0x0830, 0x610a60 },
458 { 0x0834, 0x000000 },
459 { 0x0838, 0x610a40 },
460 { 0x0840, 0x610a24 },
461 { 0x0844, 0x610a2c },
462 { 0x0848, 0x610aa8 },
463 { 0x084c, 0x610ab0 },
464 { 0x0860, 0x610a84 },
465 { 0x0864, 0x610a90 },
466 { 0x0868, 0x610b18 },
467 { 0x086c, 0x610b20 },
468 { 0x0870, 0x610ac8 },
469 { 0x0874, 0x610a38 },
470 { 0x0880, 0x610a58 },
471 { 0x0884, 0x610a9c },
472 { 0x08a0, 0x610a70 },
473 { 0x08a4, 0x610a50 },
474 { 0x08a8, 0x610ae0 },
475 { 0x08c0, 0x610b28 },
476 { 0x08c4, 0x610b30 },
477 { 0x08c8, 0x610b40 },
478 { 0x08d4, 0x610b38 },
479 { 0x08d8, 0x610b48 },
480 { 0x08dc, 0x610b50 },
481 { 0x0900, 0x610a18 },
482 { 0x0904, 0x610ab8 },
483 {}
484 }
485};
486
487static const struct nv50_disp_mthd_chan
2832271d 488nv50_disp_core_mthd_chan = {
d67d92c0
BS
489 .name = "Core",
490 .addr = 0x000000,
491 .data = {
2832271d
BS
492 { "Global", 1, &nv50_disp_core_mthd_base },
493 { "DAC", 3, &nv50_disp_core_mthd_dac },
494 { "SOR", 2, &nv50_disp_core_mthd_sor },
495 { "PIOR", 3, &nv50_disp_core_mthd_pior },
496 { "HEAD", 2, &nv50_disp_core_mthd_head },
d67d92c0
BS
497 {}
498 }
499};
500
2c04ae01 501int
878da15a
BS
502nv50_disp_core_ctor(struct nvkm_object *parent,
503 struct nvkm_object *engine,
504 struct nvkm_oclass *oclass, void *data, u32 size,
505 struct nvkm_object **pobject)
70cabe4a 506{
648d4dfd
BS
507 union {
508 struct nv50_disp_core_channel_dma_v0 v0;
509 } *args = data;
370c00f9 510 struct nv50_disp_dmac *mast;
70cabe4a
BS
511 int ret;
512
53003941 513 nvif_ioctl(parent, "create disp core channel dma size %d\n", size);
648d4dfd 514 if (nvif_unpack(args->v0, 0, 0, false)) {
53003941
BS
515 nvif_ioctl(parent, "create disp core channel dma vers %d "
516 "pushbuf %08x\n",
517 args->v0.version, args->v0.pushbuf);
648d4dfd
BS
518 } else
519 return ret;
370c00f9 520
648d4dfd 521 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
370c00f9
BS
522 0, sizeof(*mast), (void **)&mast);
523 *pobject = nv_object(mast);
70cabe4a
BS
524 if (ret)
525 return ret;
526
527 return 0;
528}
529
70cabe4a 530static int
878da15a 531nv50_disp_core_init(struct nvkm_object *object)
70cabe4a 532{
fd166a18 533 struct nv50_disp *disp = (void *)object->engine;
370c00f9 534 struct nv50_disp_dmac *mast = (void *)object;
84407824
BS
535 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
536 struct nvkm_device *device = subdev->device;
70cabe4a
BS
537 int ret;
538
370c00f9 539 ret = nv50_disp_chan_init(&mast->base);
70cabe4a
BS
540 if (ret)
541 return ret;
542
370c00f9 543 /* enable error reporting */
2fde1f1c 544 nvkm_mask(device, 0x610028, 0x00010000, 0x00010000);
370c00f9
BS
545
546 /* attempt to unstick channel from some unknown state */
2fde1f1c
BS
547 if ((nvkm_rd32(device, 0x610200) & 0x009f0000) == 0x00020000)
548 nvkm_mask(device, 0x610200, 0x00800000, 0x00800000);
549 if ((nvkm_rd32(device, 0x610200) & 0x003f0000) == 0x00030000)
550 nvkm_mask(device, 0x610200, 0x00600000, 0x00600000);
370c00f9
BS
551
552 /* initialise channel for dma command submission */
2fde1f1c
BS
553 nvkm_wr32(device, 0x610204, mast->push);
554 nvkm_wr32(device, 0x610208, 0x00010000);
555 nvkm_wr32(device, 0x61020c, 0x00000000);
556 nvkm_mask(device, 0x610200, 0x00000010, 0x00000010);
557 nvkm_wr32(device, 0x640000, 0x00000000);
558 nvkm_wr32(device, 0x610200, 0x01000013);
370c00f9
BS
559
560 /* wait for it to go inactive */
3a020b4d
BS
561 if (nvkm_msec(device, 2000,
562 if (!(nvkm_rd32(device, 0x610200) & 0x80000000))
563 break;
564 ) < 0) {
84407824
BS
565 nvkm_error(subdev, "core init: %08x\n",
566 nvkm_rd32(device, 0x610200));
370c00f9
BS
567 return -EBUSY;
568 }
569
70cabe4a
BS
570 return 0;
571}
572
573static int
878da15a 574nv50_disp_core_fini(struct nvkm_object *object, bool suspend)
70cabe4a 575{
fd166a18 576 struct nv50_disp *disp = (void *)object->engine;
370c00f9 577 struct nv50_disp_dmac *mast = (void *)object;
84407824
BS
578 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
579 struct nvkm_device *device = subdev->device;
370c00f9
BS
580
581 /* deactivate channel */
2fde1f1c
BS
582 nvkm_mask(device, 0x610200, 0x00000010, 0x00000000);
583 nvkm_mask(device, 0x610200, 0x00000003, 0x00000000);
3a020b4d
BS
584 if (nvkm_msec(device, 2000,
585 if (!(nvkm_rd32(device, 0x610200) & 0x001e0000))
586 break;
587 ) < 0) {
84407824
BS
588 nvkm_error(subdev, "core fini: %08x\n",
589 nvkm_rd32(device, 0x610200));
370c00f9
BS
590 if (suspend)
591 return -EBUSY;
592 }
593
b38a2322 594 /* disable error reporting and completion notifications */
2fde1f1c 595 nvkm_mask(device, 0x610028, 0x00010001, 0x00000000);
370c00f9
BS
596
597 return nv50_disp_chan_fini(&mast->base, suspend);
70cabe4a
BS
598}
599
2c04ae01 600struct nv50_disp_chan_impl
2832271d
BS
601nv50_disp_core_ofuncs = {
602 .base.ctor = nv50_disp_core_ctor,
2c04ae01 603 .base.dtor = nv50_disp_dmac_dtor,
2832271d
BS
604 .base.init = nv50_disp_core_init,
605 .base.fini = nv50_disp_core_fini,
b76f1529 606 .base.map = nv50_disp_chan_map,
b38a2322 607 .base.ntfy = nv50_disp_chan_ntfy,
2c04ae01
BS
608 .base.rd32 = nv50_disp_chan_rd32,
609 .base.wr32 = nv50_disp_chan_wr32,
610 .chid = 0,
611 .attach = nv50_disp_dmac_object_attach,
612 .detach = nv50_disp_dmac_object_detach,
70cabe4a
BS
613};
614
615/*******************************************************************************
370c00f9 616 * EVO sync channel objects
70cabe4a
BS
617 ******************************************************************************/
618
d67d92c0 619static const struct nv50_disp_mthd_list
2832271d 620nv50_disp_base_mthd_base = {
d67d92c0
BS
621 .mthd = 0x0000,
622 .addr = 0x000000,
623 .data = {
624 { 0x0080, 0x000000 },
625 { 0x0084, 0x0008c4 },
626 { 0x0088, 0x0008d0 },
627 { 0x008c, 0x0008dc },
628 { 0x0090, 0x0008e4 },
629 { 0x0094, 0x610884 },
630 { 0x00a0, 0x6108a0 },
631 { 0x00a4, 0x610878 },
632 { 0x00c0, 0x61086c },
633 { 0x00e0, 0x610858 },
634 { 0x00e4, 0x610860 },
635 { 0x00e8, 0x6108ac },
636 { 0x00ec, 0x6108b4 },
637 { 0x0100, 0x610894 },
638 { 0x0110, 0x6108bc },
639 { 0x0114, 0x61088c },
640 {}
641 }
642};
643
644const struct nv50_disp_mthd_list
2832271d 645nv50_disp_base_mthd_image = {
d67d92c0
BS
646 .mthd = 0x0400,
647 .addr = 0x000000,
648 .data = {
649 { 0x0800, 0x6108f0 },
650 { 0x0804, 0x6108fc },
651 { 0x0808, 0x61090c },
652 { 0x080c, 0x610914 },
653 { 0x0810, 0x610904 },
654 {}
655 }
656};
657
658static const struct nv50_disp_mthd_chan
2832271d 659nv50_disp_base_mthd_chan = {
d67d92c0
BS
660 .name = "Base",
661 .addr = 0x000540,
662 .data = {
2832271d
BS
663 { "Global", 1, &nv50_disp_base_mthd_base },
664 { "Image", 2, &nv50_disp_base_mthd_image },
d67d92c0
BS
665 {}
666 }
667};
668
2c04ae01 669int
878da15a
BS
670nv50_disp_base_ctor(struct nvkm_object *parent,
671 struct nvkm_object *engine,
672 struct nvkm_oclass *oclass, void *data, u32 size,
673 struct nvkm_object **pobject)
70cabe4a 674{
648d4dfd
BS
675 union {
676 struct nv50_disp_base_channel_dma_v0 v0;
677 } *args = data;
fd166a18 678 struct nv50_disp *disp = (void *)engine;
370c00f9 679 struct nv50_disp_dmac *dmac;
70cabe4a
BS
680 int ret;
681
53003941 682 nvif_ioctl(parent, "create disp base channel dma size %d\n", size);
648d4dfd 683 if (nvif_unpack(args->v0, 0, 0, false)) {
53003941
BS
684 nvif_ioctl(parent, "create disp base channel dma vers %d "
685 "pushbuf %08x head %d\n",
686 args->v0.version, args->v0.pushbuf, args->v0.head);
fd166a18 687 if (args->v0.head > disp->head.nr)
648d4dfd
BS
688 return -EINVAL;
689 } else
690 return ret;
370c00f9 691
648d4dfd
BS
692 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
693 args->v0.head, sizeof(*dmac),
694 (void **)&dmac);
370c00f9 695 *pobject = nv_object(dmac);
70cabe4a
BS
696 if (ret)
697 return ret;
698
699 return 0;
700}
701
2c04ae01 702struct nv50_disp_chan_impl
2832271d
BS
703nv50_disp_base_ofuncs = {
704 .base.ctor = nv50_disp_base_ctor,
2c04ae01
BS
705 .base.dtor = nv50_disp_dmac_dtor,
706 .base.init = nv50_disp_dmac_init,
707 .base.fini = nv50_disp_dmac_fini,
b38a2322 708 .base.ntfy = nv50_disp_chan_ntfy,
b76f1529 709 .base.map = nv50_disp_chan_map,
2c04ae01
BS
710 .base.rd32 = nv50_disp_chan_rd32,
711 .base.wr32 = nv50_disp_chan_wr32,
712 .chid = 1,
713 .attach = nv50_disp_dmac_object_attach,
714 .detach = nv50_disp_dmac_object_detach,
370c00f9
BS
715};
716
717/*******************************************************************************
718 * EVO overlay channel objects
719 ******************************************************************************/
70cabe4a 720
d67d92c0
BS
721const struct nv50_disp_mthd_list
722nv50_disp_ovly_mthd_base = {
723 .mthd = 0x0000,
724 .addr = 0x000000,
725 .data = {
726 { 0x0080, 0x000000 },
727 { 0x0084, 0x0009a0 },
728 { 0x0088, 0x0009c0 },
729 { 0x008c, 0x0009c8 },
730 { 0x0090, 0x6109b4 },
731 { 0x0094, 0x610970 },
732 { 0x00a0, 0x610998 },
733 { 0x00a4, 0x610964 },
734 { 0x00c0, 0x610958 },
735 { 0x00e0, 0x6109a8 },
736 { 0x00e4, 0x6109d0 },
737 { 0x00e8, 0x6109d8 },
738 { 0x0100, 0x61094c },
739 { 0x0104, 0x610984 },
740 { 0x0108, 0x61098c },
741 { 0x0800, 0x6109f8 },
742 { 0x0808, 0x610a08 },
743 { 0x080c, 0x610a10 },
744 { 0x0810, 0x610a00 },
745 {}
746 }
747};
748
749static const struct nv50_disp_mthd_chan
750nv50_disp_ovly_mthd_chan = {
751 .name = "Overlay",
752 .addr = 0x000540,
753 .data = {
754 { "Global", 1, &nv50_disp_ovly_mthd_base },
755 {}
756 }
757};
758
2c04ae01 759int
878da15a
BS
760nv50_disp_ovly_ctor(struct nvkm_object *parent,
761 struct nvkm_object *engine,
762 struct nvkm_oclass *oclass, void *data, u32 size,
763 struct nvkm_object **pobject)
70cabe4a 764{
648d4dfd
BS
765 union {
766 struct nv50_disp_overlay_channel_dma_v0 v0;
767 } *args = data;
fd166a18 768 struct nv50_disp *disp = (void *)engine;
370c00f9 769 struct nv50_disp_dmac *dmac;
70cabe4a
BS
770 int ret;
771
53003941 772 nvif_ioctl(parent, "create disp overlay channel dma size %d\n", size);
648d4dfd 773 if (nvif_unpack(args->v0, 0, 0, false)) {
53003941
BS
774 nvif_ioctl(parent, "create disp overlay channel dma vers %d "
775 "pushbuf %08x head %d\n",
776 args->v0.version, args->v0.pushbuf, args->v0.head);
fd166a18 777 if (args->v0.head > disp->head.nr)
648d4dfd
BS
778 return -EINVAL;
779 } else
780 return ret;
370c00f9 781
648d4dfd
BS
782 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
783 args->v0.head, sizeof(*dmac),
784 (void **)&dmac);
370c00f9 785 *pobject = nv_object(dmac);
70cabe4a
BS
786 if (ret)
787 return ret;
788
789 return 0;
790}
791
2c04ae01 792struct nv50_disp_chan_impl
370c00f9 793nv50_disp_ovly_ofuncs = {
2c04ae01
BS
794 .base.ctor = nv50_disp_ovly_ctor,
795 .base.dtor = nv50_disp_dmac_dtor,
796 .base.init = nv50_disp_dmac_init,
797 .base.fini = nv50_disp_dmac_fini,
b38a2322 798 .base.ntfy = nv50_disp_chan_ntfy,
b76f1529 799 .base.map = nv50_disp_chan_map,
2c04ae01
BS
800 .base.rd32 = nv50_disp_chan_rd32,
801 .base.wr32 = nv50_disp_chan_wr32,
802 .chid = 3,
803 .attach = nv50_disp_dmac_object_attach,
804 .detach = nv50_disp_dmac_object_detach,
70cabe4a
BS
805};
806
807/*******************************************************************************
370c00f9 808 * EVO PIO channel base class
70cabe4a
BS
809 ******************************************************************************/
810
811static int
878da15a
BS
812nv50_disp_pioc_create_(struct nvkm_object *parent,
813 struct nvkm_object *engine,
814 struct nvkm_oclass *oclass, int head,
370c00f9 815 int length, void **pobject)
70cabe4a 816{
2c04ae01 817 return nv50_disp_chan_create_(parent, engine, oclass, head,
370c00f9
BS
818 length, pobject);
819}
820
2c04ae01 821void
878da15a 822nv50_disp_pioc_dtor(struct nvkm_object *object)
370c00f9
BS
823{
824 struct nv50_disp_pioc *pioc = (void *)object;
825 nv50_disp_chan_destroy(&pioc->base);
826}
827
828static int
878da15a 829nv50_disp_pioc_init(struct nvkm_object *object)
370c00f9 830{
fd166a18 831 struct nv50_disp *disp = (void *)object->engine;
370c00f9 832 struct nv50_disp_pioc *pioc = (void *)object;
84407824
BS
833 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
834 struct nvkm_device *device = subdev->device;
370c00f9 835 int chid = pioc->base.chid;
70cabe4a
BS
836 int ret;
837
370c00f9 838 ret = nv50_disp_chan_init(&pioc->base);
70cabe4a
BS
839 if (ret)
840 return ret;
841
2fde1f1c 842 nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00002000);
3a020b4d
BS
843 if (nvkm_msec(device, 2000,
844 if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000))
845 break;
846 ) < 0) {
84407824
BS
847 nvkm_error(subdev, "ch %d timeout0: %08x\n", chid,
848 nvkm_rd32(device, 0x610200 + (chid * 0x10)));
370c00f9
BS
849 return -EBUSY;
850 }
851
2fde1f1c 852 nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00000001);
3a020b4d
BS
853 if (nvkm_msec(device, 2000,
854 u32 tmp = nvkm_rd32(device, 0x610200 + (chid * 0x10));
855 if ((tmp & 0x00030000) == 0x00010000)
856 break;
857 ) < 0) {
84407824
BS
858 nvkm_error(subdev, "ch %d timeout1: %08x\n", chid,
859 nvkm_rd32(device, 0x610200 + (chid * 0x10)));
370c00f9
BS
860 return -EBUSY;
861 }
862
70cabe4a
BS
863 return 0;
864}
865
370c00f9 866static int
878da15a 867nv50_disp_pioc_fini(struct nvkm_object *object, bool suspend)
70cabe4a 868{
fd166a18 869 struct nv50_disp *disp = (void *)object->engine;
370c00f9 870 struct nv50_disp_pioc *pioc = (void *)object;
84407824
BS
871 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
872 struct nvkm_device *device = subdev->device;
370c00f9
BS
873 int chid = pioc->base.chid;
874
2fde1f1c 875 nvkm_mask(device, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000);
3a020b4d
BS
876 if (nvkm_msec(device, 2000,
877 if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000))
878 break;
879 ) < 0) {
84407824
BS
880 nvkm_error(subdev, "ch %d timeout: %08x\n", chid,
881 nvkm_rd32(device, 0x610200 + (chid * 0x10)));
370c00f9
BS
882 if (suspend)
883 return -EBUSY;
884 }
885
886 return nv50_disp_chan_fini(&pioc->base, suspend);
70cabe4a
BS
887}
888
370c00f9
BS
889/*******************************************************************************
890 * EVO immediate overlay channel objects
891 ******************************************************************************/
892
2c04ae01 893int
878da15a
BS
894nv50_disp_oimm_ctor(struct nvkm_object *parent,
895 struct nvkm_object *engine,
896 struct nvkm_oclass *oclass, void *data, u32 size,
897 struct nvkm_object **pobject)
70cabe4a 898{
648d4dfd
BS
899 union {
900 struct nv50_disp_overlay_v0 v0;
901 } *args = data;
fd166a18 902 struct nv50_disp *disp = (void *)engine;
370c00f9 903 struct nv50_disp_pioc *pioc;
70cabe4a
BS
904 int ret;
905
53003941 906 nvif_ioctl(parent, "create disp overlay size %d\n", size);
648d4dfd 907 if (nvif_unpack(args->v0, 0, 0, false)) {
53003941
BS
908 nvif_ioctl(parent, "create disp overlay vers %d head %d\n",
909 args->v0.version, args->v0.head);
fd166a18 910 if (args->v0.head > disp->head.nr)
648d4dfd
BS
911 return -EINVAL;
912 } else
913 return ret;
370c00f9 914
648d4dfd 915 ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
370c00f9
BS
916 sizeof(*pioc), (void **)&pioc);
917 *pobject = nv_object(pioc);
70cabe4a
BS
918 if (ret)
919 return ret;
920
921 return 0;
922}
923
2c04ae01 924struct nv50_disp_chan_impl
370c00f9 925nv50_disp_oimm_ofuncs = {
2c04ae01
BS
926 .base.ctor = nv50_disp_oimm_ctor,
927 .base.dtor = nv50_disp_pioc_dtor,
928 .base.init = nv50_disp_pioc_init,
929 .base.fini = nv50_disp_pioc_fini,
b38a2322 930 .base.ntfy = nv50_disp_chan_ntfy,
b76f1529 931 .base.map = nv50_disp_chan_map,
2c04ae01
BS
932 .base.rd32 = nv50_disp_chan_rd32,
933 .base.wr32 = nv50_disp_chan_wr32,
934 .chid = 5,
370c00f9
BS
935};
936
937/*******************************************************************************
938 * EVO cursor channel objects
939 ******************************************************************************/
940
2c04ae01 941int
878da15a
BS
942nv50_disp_curs_ctor(struct nvkm_object *parent,
943 struct nvkm_object *engine,
944 struct nvkm_oclass *oclass, void *data, u32 size,
945 struct nvkm_object **pobject)
70cabe4a 946{
648d4dfd
BS
947 union {
948 struct nv50_disp_cursor_v0 v0;
949 } *args = data;
fd166a18 950 struct nv50_disp *disp = (void *)engine;
370c00f9
BS
951 struct nv50_disp_pioc *pioc;
952 int ret;
953
53003941 954 nvif_ioctl(parent, "create disp cursor size %d\n", size);
648d4dfd 955 if (nvif_unpack(args->v0, 0, 0, false)) {
53003941
BS
956 nvif_ioctl(parent, "create disp cursor vers %d head %d\n",
957 args->v0.version, args->v0.head);
fd166a18 958 if (args->v0.head > disp->head.nr)
648d4dfd
BS
959 return -EINVAL;
960 } else
961 return ret;
370c00f9 962
648d4dfd 963 ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
370c00f9
BS
964 sizeof(*pioc), (void **)&pioc);
965 *pobject = nv_object(pioc);
966 if (ret)
967 return ret;
968
969 return 0;
70cabe4a
BS
970}
971
2c04ae01 972struct nv50_disp_chan_impl
370c00f9 973nv50_disp_curs_ofuncs = {
2c04ae01
BS
974 .base.ctor = nv50_disp_curs_ctor,
975 .base.dtor = nv50_disp_pioc_dtor,
976 .base.init = nv50_disp_pioc_init,
977 .base.fini = nv50_disp_pioc_fini,
b38a2322 978 .base.ntfy = nv50_disp_chan_ntfy,
b76f1529 979 .base.map = nv50_disp_chan_map,
2c04ae01
BS
980 .base.rd32 = nv50_disp_chan_rd32,
981 .base.wr32 = nv50_disp_chan_wr32,
982 .chid = 7,
70cabe4a
BS
983};
984
985/*******************************************************************************
986 * Base display object
987 ******************************************************************************/
988
d2fa7d32 989int
2832271d 990nv50_disp_main_scanoutpos(NV50_DISP_MTHD_V0)
d2fa7d32 991{
2fde1f1c
BS
992 struct nvkm_device *device = disp->base.engine.subdev.device;
993 const u32 blanke = nvkm_rd32(device, 0x610aec + (head * 0x540));
994 const u32 blanks = nvkm_rd32(device, 0x610af4 + (head * 0x540));
995 const u32 total = nvkm_rd32(device, 0x610afc + (head * 0x540));
4952b4d3
BS
996 union {
997 struct nv04_disp_scanoutpos_v0 v0;
998 } *args = data;
999 int ret;
1000
53003941 1001 nvif_ioctl(object, "disp scanoutpos size %d\n", size);
4952b4d3 1002 if (nvif_unpack(args->v0, 0, 0, false)) {
53003941
BS
1003 nvif_ioctl(object, "disp scanoutpos vers %d\n",
1004 args->v0.version);
4952b4d3
BS
1005 args->v0.vblanke = (blanke & 0xffff0000) >> 16;
1006 args->v0.hblanke = (blanke & 0x0000ffff);
1007 args->v0.vblanks = (blanks & 0xffff0000) >> 16;
1008 args->v0.hblanks = (blanks & 0x0000ffff);
1009 args->v0.vtotal = ( total & 0xffff0000) >> 16;
1010 args->v0.htotal = ( total & 0x0000ffff);
1011 args->v0.time[0] = ktime_to_ns(ktime_get());
1012 args->v0.vline = /* vline read locks hline */
2fde1f1c 1013 nvkm_rd32(device, 0x616340 + (head * 0x800)) & 0xffff;
4952b4d3
BS
1014 args->v0.time[1] = ktime_to_ns(ktime_get());
1015 args->v0.hline =
2fde1f1c 1016 nvkm_rd32(device, 0x616344 + (head * 0x800)) & 0xffff;
4952b4d3
BS
1017 } else
1018 return ret;
d2fa7d32 1019
d2fa7d32
BS
1020 return 0;
1021}
1022
bf0eb898 1023int
878da15a 1024nv50_disp_main_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
bf0eb898 1025{
4952b4d3 1026 const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
bf0eb898
BS
1027 union {
1028 struct nv50_disp_mthd_v0 v0;
1029 struct nv50_disp_mthd_v1 v1;
1030 } *args = data;
fd166a18 1031 struct nv50_disp *disp = (void *)object->engine;
bf0eb898
BS
1032 struct nvkm_output *outp = NULL;
1033 struct nvkm_output *temp;
1034 u16 type, mask = 0;
1035 int head, ret;
1036
1037 if (mthd != NV50_DISP_MTHD)
1038 return -EINVAL;
1039
53003941 1040 nvif_ioctl(object, "disp mthd size %d\n", size);
bf0eb898 1041 if (nvif_unpack(args->v0, 0, 0, true)) {
53003941
BS
1042 nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
1043 args->v0.version, args->v0.method, args->v0.head);
bf0eb898
BS
1044 mthd = args->v0.method;
1045 head = args->v0.head;
1046 } else
1047 if (nvif_unpack(args->v1, 1, 1, true)) {
53003941
BS
1048 nvif_ioctl(object, "disp mthd vers %d mthd %02x "
1049 "type %04x mask %04x\n",
1050 args->v1.version, args->v1.method,
1051 args->v1.hasht, args->v1.hashm);
bf0eb898
BS
1052 mthd = args->v1.method;
1053 type = args->v1.hasht;
1054 mask = args->v1.hashm;
1055 head = ffs((mask >> 8) & 0x0f) - 1;
1056 } else
1057 return ret;
1058
fd166a18 1059 if (head < 0 || head >= disp->head.nr)
bf0eb898
BS
1060 return -ENXIO;
1061
1062 if (mask) {
fd166a18 1063 list_for_each_entry(temp, &disp->base.outp, head) {
bf0eb898
BS
1064 if ((temp->info.hasht == type) &&
1065 (temp->info.hashm & mask) == mask) {
1066 outp = temp;
1067 break;
1068 }
1069 }
1070 if (outp == NULL)
1071 return -ENXIO;
1072 }
1073
1074 switch (mthd) {
4952b4d3 1075 case NV50_DISP_SCANOUTPOS:
fd166a18 1076 return impl->head.scanoutpos(object, disp, data, size, head);
bf0eb898
BS
1077 default:
1078 break;
1079 }
1080
1081 switch (mthd * !!outp) {
1082 case NV50_DISP_MTHD_V1_DAC_PWR:
fd166a18 1083 return disp->dac.power(object, disp, data, size, head, outp);
c4abd317 1084 case NV50_DISP_MTHD_V1_DAC_LOAD:
fd166a18 1085 return disp->dac.sense(object, disp, data, size, head, outp);
d55b4af9 1086 case NV50_DISP_MTHD_V1_SOR_PWR:
fd166a18 1087 return disp->sor.power(object, disp, data, size, head, outp);
120b0c39 1088 case NV50_DISP_MTHD_V1_SOR_HDA_ELD:
fd166a18 1089 if (!disp->sor.hda_eld)
120b0c39 1090 return -ENODEV;
fd166a18 1091 return disp->sor.hda_eld(object, disp, data, size, head, outp);
e00f2235 1092 case NV50_DISP_MTHD_V1_SOR_HDMI_PWR:
fd166a18 1093 if (!disp->sor.hdmi)
e00f2235 1094 return -ENODEV;
fd166a18 1095 return disp->sor.hdmi(object, disp, data, size, head, outp);
a3761fa2
BS
1096 case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: {
1097 union {
1098 struct nv50_disp_sor_lvds_script_v0 v0;
1099 } *args = data;
53003941 1100 nvif_ioctl(object, "disp sor lvds script size %d\n", size);
a3761fa2 1101 if (nvif_unpack(args->v0, 0, 0, false)) {
53003941
BS
1102 nvif_ioctl(object, "disp sor lvds script "
1103 "vers %d name %04x\n",
1104 args->v0.version, args->v0.script);
fd166a18 1105 disp->sor.lvdsconf = args->v0.script;
a3761fa2
BS
1106 return 0;
1107 } else
1108 return ret;
1109 }
1110 break;
c02ed2bf 1111 case NV50_DISP_MTHD_V1_SOR_DP_PWR: {
f2c906fc 1112 struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
c02ed2bf
BS
1113 union {
1114 struct nv50_disp_sor_dp_pwr_v0 v0;
1115 } *args = data;
53003941 1116 nvif_ioctl(object, "disp sor dp pwr size %d\n", size);
c02ed2bf 1117 if (nvif_unpack(args->v0, 0, 0, false)) {
53003941
BS
1118 nvif_ioctl(object, "disp sor dp pwr vers %d state %d\n",
1119 args->v0.version, args->v0.state);
c02ed2bf
BS
1120 if (args->v0.state == 0) {
1121 nvkm_notify_put(&outpdp->irq);
f2c906fc 1122 outpdp->func->lnk_pwr(outpdp, 0);
c02ed2bf
BS
1123 atomic_set(&outpdp->lt.done, 0);
1124 return 0;
1125 } else
1126 if (args->v0.state != 0) {
1127 nvkm_output_dp_train(&outpdp->base, 0, true);
1128 return 0;
1129 }
1130 } else
1131 return ret;
1132 }
1133 break;
67cb49c4 1134 case NV50_DISP_MTHD_V1_PIOR_PWR:
fd166a18 1135 if (!disp->pior.power)
67cb49c4 1136 return -ENODEV;
fd166a18 1137 return disp->pior.power(object, disp, data, size, head, outp);
bf0eb898
BS
1138 default:
1139 break;
1140 }
1141
1142 return -EINVAL;
1143}
1144
79ca2770 1145int
878da15a
BS
1146nv50_disp_main_ctor(struct nvkm_object *parent,
1147 struct nvkm_object *engine,
1148 struct nvkm_oclass *oclass, void *data, u32 size,
1149 struct nvkm_object **pobject)
70cabe4a 1150{
fd166a18 1151 struct nv50_disp *disp = (void *)engine;
70cabe4a
BS
1152 struct nv50_disp_base *base;
1153 int ret;
1154
878da15a 1155 ret = nvkm_parent_create(parent, engine, oclass, 0,
fd166a18 1156 disp->sclass, 0, &base);
70cabe4a
BS
1157 *pobject = nv_object(base);
1158 if (ret)
1159 return ret;
1160
878da15a
BS
1161 return nvkm_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
1162 &base->ramht);
70cabe4a
BS
1163}
1164
79ca2770 1165void
878da15a 1166nv50_disp_main_dtor(struct nvkm_object *object)
70cabe4a
BS
1167{
1168 struct nv50_disp_base *base = (void *)object;
878da15a
BS
1169 nvkm_ramht_ref(NULL, &base->ramht);
1170 nvkm_parent_destroy(&base->base);
70cabe4a
BS
1171}
1172
1173static int
878da15a 1174nv50_disp_main_init(struct nvkm_object *object)
70cabe4a 1175{
fd166a18 1176 struct nv50_disp *disp = (void *)object->engine;
70cabe4a 1177 struct nv50_disp_base *base = (void *)object;
2fde1f1c 1178 struct nvkm_device *device = disp->base.engine.subdev.device;
ab77214a
BS
1179 int ret, i;
1180 u32 tmp;
70cabe4a 1181
878da15a 1182 ret = nvkm_parent_init(&base->base);
70cabe4a
BS
1183 if (ret)
1184 return ret;
1185
ab77214a
BS
1186 /* The below segments of code copying values from one register to
1187 * another appear to inform EVO of the display capabilities or
1188 * something similar. NFI what the 0x614004 caps are for..
1189 */
2fde1f1c
BS
1190 tmp = nvkm_rd32(device, 0x614004);
1191 nvkm_wr32(device, 0x610184, tmp);
ab77214a
BS
1192
1193 /* ... CRTC caps */
fd166a18 1194 for (i = 0; i < disp->head.nr; i++) {
2fde1f1c
BS
1195 tmp = nvkm_rd32(device, 0x616100 + (i * 0x800));
1196 nvkm_wr32(device, 0x610190 + (i * 0x10), tmp);
1197 tmp = nvkm_rd32(device, 0x616104 + (i * 0x800));
1198 nvkm_wr32(device, 0x610194 + (i * 0x10), tmp);
1199 tmp = nvkm_rd32(device, 0x616108 + (i * 0x800));
1200 nvkm_wr32(device, 0x610198 + (i * 0x10), tmp);
1201 tmp = nvkm_rd32(device, 0x61610c + (i * 0x800));
1202 nvkm_wr32(device, 0x61019c + (i * 0x10), tmp);
ab77214a
BS
1203 }
1204
1205 /* ... DAC caps */
fd166a18 1206 for (i = 0; i < disp->dac.nr; i++) {
2fde1f1c
BS
1207 tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800));
1208 nvkm_wr32(device, 0x6101d0 + (i * 0x04), tmp);
ab77214a
BS
1209 }
1210
1211 /* ... SOR caps */
fd166a18 1212 for (i = 0; i < disp->sor.nr; i++) {
2fde1f1c
BS
1213 tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800));
1214 nvkm_wr32(device, 0x6101e0 + (i * 0x04), tmp);
ab77214a
BS
1215 }
1216
476e84e1 1217 /* ... PIOR caps */
fd166a18 1218 for (i = 0; i < disp->pior.nr; i++) {
2fde1f1c
BS
1219 tmp = nvkm_rd32(device, 0x61e000 + (i * 0x800));
1220 nvkm_wr32(device, 0x6101f0 + (i * 0x04), tmp);
ab77214a
BS
1221 }
1222
446b05a0 1223 /* steal display away from vbios, or something like that */
2fde1f1c
BS
1224 if (nvkm_rd32(device, 0x610024) & 0x00000100) {
1225 nvkm_wr32(device, 0x610024, 0x00000100);
1226 nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000);
3a020b4d
BS
1227 if (nvkm_msec(device, 2000,
1228 if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002))
1229 break;
1230 ) < 0)
446b05a0 1231 return -EBUSY;
446b05a0
BS
1232 }
1233
1234 /* point at display engine memory area (hash table, objects) */
2fde1f1c 1235 nvkm_wr32(device, 0x610010, (nv_gpuobj(base->ramht)->addr >> 8) | 9);
446b05a0
BS
1236
1237 /* enable supervisor interrupts, disable everything else */
2fde1f1c
BS
1238 nvkm_wr32(device, 0x61002c, 0x00000370);
1239 nvkm_wr32(device, 0x610028, 0x00000000);
70cabe4a
BS
1240 return 0;
1241}
1242
1243static int
878da15a 1244nv50_disp_main_fini(struct nvkm_object *object, bool suspend)
70cabe4a 1245{
fd166a18 1246 struct nv50_disp *disp = (void *)object->engine;
70cabe4a 1247 struct nv50_disp_base *base = (void *)object;
2fde1f1c 1248 struct nvkm_device *device = disp->base.engine.subdev.device;
446b05a0
BS
1249
1250 /* disable all interrupts */
2fde1f1c
BS
1251 nvkm_wr32(device, 0x610024, 0x00000000);
1252 nvkm_wr32(device, 0x610020, 0x00000000);
446b05a0 1253
878da15a 1254 return nvkm_parent_fini(&base->base, suspend);
70cabe4a
BS
1255}
1256
878da15a 1257struct nvkm_ofuncs
2832271d
BS
1258nv50_disp_main_ofuncs = {
1259 .ctor = nv50_disp_main_ctor,
1260 .dtor = nv50_disp_main_dtor,
1261 .init = nv50_disp_main_init,
1262 .fini = nv50_disp_main_fini,
1263 .mthd = nv50_disp_main_mthd,
878da15a 1264 .ntfy = nvkm_disp_ntfy,
70cabe4a
BS
1265};
1266
878da15a 1267static struct nvkm_oclass
2832271d
BS
1268nv50_disp_main_oclass[] = {
1269 { NV50_DISP, &nv50_disp_main_ofuncs },
370c00f9 1270 {}
ebb945a9
BS
1271};
1272
878da15a 1273static struct nvkm_oclass
ebb945a9 1274nv50_disp_sclass[] = {
2832271d
BS
1275 { NV50_DISP_CORE_CHANNEL_DMA, &nv50_disp_core_ofuncs.base },
1276 { NV50_DISP_BASE_CHANNEL_DMA, &nv50_disp_base_ofuncs.base },
648d4dfd
BS
1277 { NV50_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
1278 { NV50_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
1279 { NV50_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
70cabe4a 1280 {}
ebb945a9
BS
1281};
1282
70cabe4a
BS
1283/*******************************************************************************
1284 * Display context, tracks instmem allocation and prevents more than one
1285 * client using the display hardware at any time.
1286 ******************************************************************************/
1287
1288static int
878da15a
BS
1289nv50_disp_data_ctor(struct nvkm_object *parent,
1290 struct nvkm_object *engine,
1291 struct nvkm_oclass *oclass, void *data, u32 size,
1292 struct nvkm_object **pobject)
70cabe4a 1293{
fd166a18 1294 struct nv50_disp *disp = (void *)engine;
a1e88736
BS
1295 struct nvkm_gpuobj *gpuobj;
1296 int ret;
70cabe4a 1297
370c00f9 1298 /* no context needed for channel objects... */
586491e6 1299 if (nv_mclass(parent) != NV_DEVICE) {
370c00f9
BS
1300 atomic_inc(&parent->refcount);
1301 *pobject = parent;
43e6e51c 1302 return 1;
370c00f9 1303 }
70cabe4a 1304
370c00f9 1305 /* allocate display hardware to client */
a1e88736
BS
1306 ret = nvkm_gpuobj_create(parent, engine, oclass, 0, NULL,
1307 0x10000, 0x10000, NVOBJ_FLAG_HEAP,
1308 &gpuobj);
1309 *pobject = nv_object(gpuobj);
fd166a18 1310 mutex_lock(&nv_subdev(disp)->mutex);
a1e88736
BS
1311 if (!list_empty(&nv_engine(disp)->contexts))
1312 ret = -EBUSY;
fd166a18 1313 mutex_unlock(&nv_subdev(disp)->mutex);
370c00f9 1314 return ret;
70cabe4a
BS
1315}
1316
878da15a 1317struct nvkm_oclass
70cabe4a 1318nv50_disp_cclass = {
878da15a 1319 .ofuncs = &(struct nvkm_ofuncs) {
70cabe4a 1320 .ctor = nv50_disp_data_ctor,
a1e88736
BS
1321 .dtor = _nvkm_gpuobj_dtor,
1322 .init = _nvkm_gpuobj_init,
1323 .fini = _nvkm_gpuobj_fini,
1324 .rd32 = _nvkm_gpuobj_rd32,
1325 .wr32 = _nvkm_gpuobj_wr32,
70cabe4a
BS
1326 },
1327};
1328
1329/*******************************************************************************
1330 * Display engine implementation
1331 ******************************************************************************/
1332
79ca2770
BS
1333static void
1334nv50_disp_vblank_fini(struct nvkm_event *event, int type, int head)
1335{
878da15a 1336 struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank);
2fde1f1c
BS
1337 struct nvkm_device *device = disp->engine.subdev.device;
1338 nvkm_mask(device, 0x61002c, (4 << head), 0);
79ca2770
BS
1339}
1340
1341static void
1342nv50_disp_vblank_init(struct nvkm_event *event, int type, int head)
1343{
878da15a 1344 struct nvkm_disp *disp = container_of(event, typeof(*disp), vblank);
2fde1f1c
BS
1345 struct nvkm_device *device = disp->engine.subdev.device;
1346 nvkm_mask(device, 0x61002c, (4 << head), (4 << head));
79ca2770
BS
1347}
1348
1349const struct nvkm_event_func
1350nv50_disp_vblank_func = {
878da15a 1351 .ctor = nvkm_disp_vblank_ctor,
79ca2770
BS
1352 .init = nv50_disp_vblank_init,
1353 .fini = nv50_disp_vblank_fini,
1354};
1355
878da15a 1356static const struct nvkm_enum
117e1633
BS
1357nv50_disp_intr_error_type[] = {
1358 { 3, "ILLEGAL_MTHD" },
1359 { 4, "INVALID_VALUE" },
1360 { 5, "INVALID_STATE" },
1361 { 7, "INVALID_HANDLE" },
1362 {}
1363};
186ecad2 1364
878da15a 1365static const struct nvkm_enum
117e1633
BS
1366nv50_disp_intr_error_code[] = {
1367 { 0x00, "" },
1368 {}
1369};
186ecad2 1370
117e1633 1371static void
fd166a18 1372nv50_disp_intr_error(struct nv50_disp *disp, int chid)
117e1633 1373{
fd166a18 1374 struct nv50_disp_impl *impl = (void *)nv_object(disp)->oclass;
84407824
BS
1375 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
1376 struct nvkm_device *device = subdev->device;
2fde1f1c
BS
1377 u32 data = nvkm_rd32(device, 0x610084 + (chid * 0x08));
1378 u32 addr = nvkm_rd32(device, 0x610080 + (chid * 0x08));
117e1633
BS
1379 u32 code = (addr & 0x00ff0000) >> 16;
1380 u32 type = (addr & 0x00007000) >> 12;
1381 u32 mthd = (addr & 0x00000ffc);
878da15a 1382 const struct nvkm_enum *ec, *et;
117e1633 1383
878da15a 1384 et = nvkm_enum_find(nv50_disp_intr_error_type, type);
878da15a 1385 ec = nvkm_enum_find(nv50_disp_intr_error_code, code);
117e1633 1386
84407824
BS
1387 nvkm_error(subdev,
1388 "ERROR %d [%s] %02x [%s] chid %d mthd %04x data %08x\n",
1389 type, et ? et->name : "", code, ec ? ec->name : "",
1390 chid, mthd, data);
117e1633 1391
9cf6ba20
BS
1392 if (chid == 0) {
1393 switch (mthd) {
1394 case 0x0080:
fd166a18 1395 nv50_disp_mthd_chan(disp, NV_DBG_ERROR, chid - 0,
9cf6ba20
BS
1396 impl->mthd.core);
1397 break;
1398 default:
1399 break;
1400 }
1401 } else
1402 if (chid <= 2) {
1403 switch (mthd) {
1404 case 0x0080:
fd166a18 1405 nv50_disp_mthd_chan(disp, NV_DBG_ERROR, chid - 1,
9cf6ba20
BS
1406 impl->mthd.base);
1407 break;
1408 default:
1409 break;
1410 }
1411 } else
1412 if (chid <= 4) {
1413 switch (mthd) {
1414 case 0x0080:
fd166a18 1415 nv50_disp_mthd_chan(disp, NV_DBG_ERROR, chid - 3,
9cf6ba20
BS
1416 impl->mthd.ovly);
1417 break;
1418 default:
1419 break;
1420 }
1421 }
1422
2fde1f1c
BS
1423 nvkm_wr32(device, 0x610020, 0x00010000 << chid);
1424 nvkm_wr32(device, 0x610080 + (chid * 0x08), 0x90000000);
186ecad2
BS
1425}
1426
415f12ef 1427static struct nvkm_output *
fd166a18 1428exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
415f12ef 1429 u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
186ecad2
BS
1430 struct nvbios_outp *info)
1431{
84407824
BS
1432 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
1433 struct nvkm_bios *bios = subdev->device->bios;
415f12ef
BS
1434 struct nvkm_output *outp;
1435 u16 mask, type;
186ecad2 1436
415f12ef 1437 if (or < 4) {
186ecad2
BS
1438 type = DCB_OUTPUT_ANALOG;
1439 mask = 0;
476e84e1 1440 } else
415f12ef 1441 if (or < 8) {
186ecad2
BS
1442 switch (ctrl & 0x00000f00) {
1443 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
1444 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
1445 case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break;
1446 case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break;
1447 case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break;
1448 case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
1449 default:
84407824 1450 nvkm_error(subdev, "unknown SOR mc %08x\n", ctrl);
415f12ef 1451 return NULL;
186ecad2 1452 }
415f12ef 1453 or -= 4;
476e84e1 1454 } else {
415f12ef 1455 or = or - 8;
476e84e1
BS
1456 type = 0x0010;
1457 mask = 0;
1458 switch (ctrl & 0x00000f00) {
fd166a18 1459 case 0x00000000: type |= disp->pior.type[or]; break;
476e84e1 1460 default:
84407824 1461 nvkm_error(subdev, "unknown PIOR mc %08x\n", ctrl);
415f12ef 1462 return NULL;
476e84e1 1463 }
186ecad2
BS
1464 }
1465
1466 mask = 0x00c0 & (mask << 6);
415f12ef 1467 mask |= 0x0001 << or;
186ecad2
BS
1468 mask |= 0x0100 << head;
1469
fd166a18 1470 list_for_each_entry(outp, &disp->base.outp, head) {
415f12ef
BS
1471 if ((outp->info.hasht & 0xff) == type &&
1472 (outp->info.hashm & mask) == mask) {
1473 *data = nvbios_outp_match(bios, outp->info.hasht,
1474 outp->info.hashm,
1475 ver, hdr, cnt, len, info);
1476 if (!*data)
1477 return NULL;
1478 return outp;
1479 }
1480 }
476e84e1 1481
415f12ef 1482 return NULL;
186ecad2
BS
1483}
1484
1ae5a62b 1485static struct nvkm_output *
fd166a18 1486exec_script(struct nv50_disp *disp, int head, int id)
186ecad2 1487{
2fde1f1c
BS
1488 struct nvkm_device *device = disp->base.engine.subdev.device;
1489 struct nvkm_bios *bios = device->bios;
415f12ef 1490 struct nvkm_output *outp;
186ecad2 1491 struct nvbios_outp info;
186ecad2 1492 u8 ver, hdr, cnt, len;
415f12ef 1493 u32 data, ctrl = 0;
b969fa52 1494 u32 reg;
186ecad2
BS
1495 int i;
1496
476e84e1 1497 /* DAC */
fd166a18 1498 for (i = 0; !(ctrl & (1 << head)) && i < disp->dac.nr; i++)
2fde1f1c 1499 ctrl = nvkm_rd32(device, 0x610b5c + (i * 8));
186ecad2 1500
476e84e1 1501 /* SOR */
c684cef7 1502 if (!(ctrl & (1 << head))) {
fd166a18
BS
1503 if (nv_device(disp)->chipset < 0x90 ||
1504 nv_device(disp)->chipset == 0x92 ||
1505 nv_device(disp)->chipset == 0xa0) {
b969fa52 1506 reg = 0x610b74;
c684cef7 1507 } else {
b969fa52 1508 reg = 0x610798;
c684cef7 1509 }
fd166a18 1510 for (i = 0; !(ctrl & (1 << head)) && i < disp->sor.nr; i++)
2fde1f1c 1511 ctrl = nvkm_rd32(device, reg + (i * 8));
b969fa52 1512 i += 4;
186ecad2
BS
1513 }
1514
476e84e1
BS
1515 /* PIOR */
1516 if (!(ctrl & (1 << head))) {
fd166a18 1517 for (i = 0; !(ctrl & (1 << head)) && i < disp->pior.nr; i++)
2fde1f1c 1518 ctrl = nvkm_rd32(device, 0x610b84 + (i * 8));
476e84e1
BS
1519 i += 8;
1520 }
1521
186ecad2 1522 if (!(ctrl & (1 << head)))
1ae5a62b 1523 return NULL;
c684cef7 1524 i--;
186ecad2 1525
fd166a18 1526 outp = exec_lookup(disp, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
415f12ef 1527 if (outp) {
186ecad2 1528 struct nvbios_init init = {
fd166a18 1529 .subdev = nv_subdev(disp),
186ecad2
BS
1530 .bios = bios,
1531 .offset = info.script[id],
415f12ef 1532 .outp = &outp->info,
186ecad2
BS
1533 .crtc = head,
1534 .execute = 1,
1535 };
1536
1ae5a62b 1537 nvbios_exec(&init);
186ecad2
BS
1538 }
1539
1ae5a62b 1540 return outp;
186ecad2
BS
1541}
1542
415f12ef 1543static struct nvkm_output *
fd166a18 1544exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
186ecad2 1545{
2fde1f1c
BS
1546 struct nvkm_device *device = disp->base.engine.subdev.device;
1547 struct nvkm_bios *bios = device->bios;
415f12ef 1548 struct nvkm_output *outp;
186ecad2
BS
1549 struct nvbios_outp info1;
1550 struct nvbios_ocfg info2;
1551 u8 ver, hdr, cnt, len;
415f12ef 1552 u32 data, ctrl = 0;
b969fa52 1553 u32 reg;
186ecad2
BS
1554 int i;
1555
476e84e1 1556 /* DAC */
fd166a18 1557 for (i = 0; !(ctrl & (1 << head)) && i < disp->dac.nr; i++)
2fde1f1c 1558 ctrl = nvkm_rd32(device, 0x610b58 + (i * 8));
186ecad2 1559
476e84e1 1560 /* SOR */
c684cef7 1561 if (!(ctrl & (1 << head))) {
fd166a18
BS
1562 if (nv_device(disp)->chipset < 0x90 ||
1563 nv_device(disp)->chipset == 0x92 ||
1564 nv_device(disp)->chipset == 0xa0) {
b969fa52 1565 reg = 0x610b70;
c684cef7 1566 } else {
b969fa52 1567 reg = 0x610794;
c684cef7 1568 }
fd166a18 1569 for (i = 0; !(ctrl & (1 << head)) && i < disp->sor.nr; i++)
2fde1f1c 1570 ctrl = nvkm_rd32(device, reg + (i * 8));
b969fa52 1571 i += 4;
186ecad2
BS
1572 }
1573
476e84e1
BS
1574 /* PIOR */
1575 if (!(ctrl & (1 << head))) {
fd166a18 1576 for (i = 0; !(ctrl & (1 << head)) && i < disp->pior.nr; i++)
2fde1f1c 1577 ctrl = nvkm_rd32(device, 0x610b80 + (i * 8));
476e84e1
BS
1578 i += 8;
1579 }
1580
186ecad2 1581 if (!(ctrl & (1 << head)))
415f12ef 1582 return NULL;
c684cef7 1583 i--;
186ecad2 1584
fd166a18 1585 outp = exec_lookup(disp, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
ba5e01b0 1586 if (!outp)
415f12ef 1587 return NULL;
186ecad2 1588
415f12ef
BS
1589 if (outp->info.location == 0) {
1590 switch (outp->info.type) {
476e84e1 1591 case DCB_OUTPUT_TMDS:
415f12ef 1592 *conf = (ctrl & 0x00000f00) >> 8;
476e84e1 1593 if (pclk >= 165000)
415f12ef 1594 *conf |= 0x0100;
476e84e1
BS
1595 break;
1596 case DCB_OUTPUT_LVDS:
fd166a18 1597 *conf = disp->sor.lvdsconf;
476e84e1
BS
1598 break;
1599 case DCB_OUTPUT_DP:
415f12ef 1600 *conf = (ctrl & 0x00000f00) >> 8;
476e84e1
BS
1601 break;
1602 case DCB_OUTPUT_ANALOG:
1603 default:
415f12ef 1604 *conf = 0x00ff;
476e84e1
BS
1605 break;
1606 }
1607 } else {
415f12ef 1608 *conf = (ctrl & 0x00000f00) >> 8;
476e84e1 1609 pclk = pclk / 2;
186ecad2
BS
1610 }
1611
415f12ef 1612 data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
0a0afd28 1613 if (data && id < 0xff) {
186ecad2
BS
1614 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
1615 if (data) {
1616 struct nvbios_init init = {
fd166a18 1617 .subdev = nv_subdev(disp),
186ecad2
BS
1618 .bios = bios,
1619 .offset = data,
415f12ef 1620 .outp = &outp->info,
186ecad2
BS
1621 .crtc = head,
1622 .execute = 1,
1623 };
1624
46c13c13 1625 nvbios_exec(&init);
186ecad2
BS
1626 }
1627 }
1628
415f12ef 1629 return outp;
186ecad2
BS
1630}
1631
1632static void
fd166a18 1633nv50_disp_intr_unk10_0(struct nv50_disp *disp, int head)
186ecad2 1634{
fd166a18 1635 exec_script(disp, head, 1);
16d4c031 1636}
186ecad2 1637
16d4c031 1638static void
fd166a18 1639nv50_disp_intr_unk20_0(struct nv50_disp *disp, int head)
16d4c031 1640{
fd166a18 1641 struct nvkm_output *outp = exec_script(disp, head, 2);
1ae5a62b
BS
1642
1643 /* the binary driver does this outside of the supervisor handling
1644 * (after the third supervisor from a detach). we (currently?)
1645 * allow both detach/attach to happen in the same set of
1646 * supervisor interrupts, so it would make sense to execute this
1647 * (full power down?) script after all the detach phases of the
1648 * supervisor handling. like with training if needed from the
1649 * second supervisor, nvidia doesn't do this, so who knows if it's
1650 * entirely safe, but it does appear to work..
1651 *
1652 * without this script being run, on some configurations i've
1653 * seen, switching from DP to TMDS on a DP connector may result
1654 * in a blank screen (SOR_PWR off/on can restore it)
1655 */
1656 if (outp && outp->info.type == DCB_OUTPUT_DP) {
f2c906fc 1657 struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
1ae5a62b 1658 struct nvbios_init init = {
fd166a18
BS
1659 .subdev = nv_subdev(disp),
1660 .bios = nvkm_bios(disp),
1ae5a62b
BS
1661 .outp = &outp->info,
1662 .crtc = head,
1663 .offset = outpdp->info.script[4],
1664 .execute = 1,
1665 };
1666
1667 nvbios_exec(&init);
1668 atomic_set(&outpdp->lt.done, 0);
1669 }
186ecad2
BS
1670}
1671
1672static void
fd166a18 1673nv50_disp_intr_unk20_1(struct nv50_disp *disp, int head)
16d4c031 1674{
2fde1f1c
BS
1675 struct nvkm_device *device = disp->base.engine.subdev.device;
1676 struct nvkm_devinit *devinit = device->devinit;
1677 u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
16d4c031 1678 if (pclk)
88524bc0 1679 devinit->pll_set(devinit, PLL_VPLL0 + head, pclk);
16d4c031
BS
1680}
1681
1682static void
fd166a18 1683nv50_disp_intr_unk20_2_dp(struct nv50_disp *disp, int head,
16d4c031 1684 struct dcb_output *outp, u32 pclk)
186ecad2 1685{
84407824
BS
1686 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
1687 struct nvkm_device *device = subdev->device;
186ecad2
BS
1688 const int link = !(outp->sorconf.link & 1);
1689 const int or = ffs(outp->or) - 1;
1690 const u32 soff = ( or * 0x800);
1691 const u32 loff = (link * 0x080) + soff;
2fde1f1c 1692 const u32 ctrl = nvkm_rd32(device, 0x610794 + (or * 8));
186ecad2 1693 const u32 symbol = 100000;
2fde1f1c
BS
1694 const s32 vactive = nvkm_rd32(device, 0x610af8 + (head * 0x540)) & 0xffff;
1695 const s32 vblanke = nvkm_rd32(device, 0x610ae8 + (head * 0x540)) & 0xffff;
1696 const s32 vblanks = nvkm_rd32(device, 0x610af0 + (head * 0x540)) & 0xffff;
1697 u32 dpctrl = nvkm_rd32(device, 0x61c10c + loff);
1698 u32 clksor = nvkm_rd32(device, 0x614300 + soff);
186ecad2
BS
1699 int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0;
1700 int TU, VTUi, VTUf, VTUa;
1701 u64 link_data_rate, link_ratio, unk;
1702 u32 best_diff = 64 * symbol;
c354080d 1703 u32 link_nr, link_bw, bits;
9506140f
BS
1704 u64 value;
1705
1706 link_bw = (clksor & 0x000c0000) ? 270000 : 162000;
1707 link_nr = hweight32(dpctrl & 0x000f0000);
1708
1709 /* symbols/hblank - algorithm taken from comments in tegra driver */
1710 value = vblanke + vactive - vblanks - 7;
1711 value = value * link_bw;
1712 do_div(value, pclk);
1713 value = value - (3 * !!(dpctrl & 0x00004000)) - (12 / link_nr);
2fde1f1c 1714 nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, value);
9506140f
BS
1715
1716 /* symbols/vblank - algorithm taken from comments in tegra driver */
1717 value = vblanks - vblanke - 25;
1718 value = value * link_bw;
1719 do_div(value, pclk);
1720 value = value - ((36 / link_nr) + 3) - 1;
2fde1f1c 1721 nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, value);
9506140f
BS
1722
1723 /* watermark / activesym */
bf2c886a
BS
1724 if ((ctrl & 0xf0000) == 0x60000) bits = 30;
1725 else if ((ctrl & 0xf0000) == 0x50000) bits = 24;
1726 else bits = 18;
1727
186ecad2
BS
1728 link_data_rate = (pclk * bits / 8) / link_nr;
1729
1730 /* calculate ratio of packed data rate to link symbol rate */
1731 link_ratio = link_data_rate * symbol;
c354080d 1732 do_div(link_ratio, link_bw);
186ecad2
BS
1733
1734 for (TU = 64; TU >= 32; TU--) {
1735 /* calculate average number of valid symbols in each TU */
1736 u32 tu_valid = link_ratio * TU;
1737 u32 calc, diff;
1738
1739 /* find a hw representation for the fraction.. */
1740 VTUi = tu_valid / symbol;
1741 calc = VTUi * symbol;
1742 diff = tu_valid - calc;
1743 if (diff) {
1744 if (diff >= (symbol / 2)) {
1745 VTUf = symbol / (symbol - diff);
1746 if (symbol - (VTUf * diff))
1747 VTUf++;
1748
1749 if (VTUf <= 15) {
1750 VTUa = 1;
1751 calc += symbol - (symbol / VTUf);
1752 } else {
1753 VTUa = 0;
1754 VTUf = 1;
1755 calc += symbol;
1756 }
1757 } else {
1758 VTUa = 0;
1759 VTUf = min((int)(symbol / diff), 15);
1760 calc += symbol / VTUf;
1761 }
1762
1763 diff = calc - tu_valid;
1764 } else {
1765 /* no remainder, but the hw doesn't like the fractional
1766 * part to be zero. decrement the integer part and
1767 * have the fraction add a whole symbol back
1768 */
1769 VTUa = 0;
1770 VTUf = 1;
1771 VTUi--;
1772 }
1773
1774 if (diff < best_diff) {
1775 best_diff = diff;
1776 bestTU = TU;
1777 bestVTUa = VTUa;
1778 bestVTUf = VTUf;
1779 bestVTUi = VTUi;
1780 if (diff == 0)
1781 break;
1782 }
1783 }
1784
1785 if (!bestTU) {
84407824 1786 nvkm_error(subdev, "unable to find suitable dp config\n");
186ecad2
BS
1787 return;
1788 }
1789
1790 /* XXX close to vbios numbers, but not right */
1791 unk = (symbol - link_ratio) * bestTU;
1792 unk *= link_ratio;
c354080d
BS
1793 do_div(unk, symbol);
1794 do_div(unk, symbol);
186ecad2
BS
1795 unk += 6;
1796
2fde1f1c
BS
1797 nvkm_mask(device, 0x61c10c + loff, 0x000001fc, bestTU << 2);
1798 nvkm_mask(device, 0x61c128 + loff, 0x010f7f3f, bestVTUa << 24 |
186ecad2
BS
1799 bestVTUf << 16 |
1800 bestVTUi << 8 | unk);
1801}
1802
1803static void
fd166a18 1804nv50_disp_intr_unk20_2(struct nv50_disp *disp, int head)
186ecad2 1805{
2fde1f1c 1806 struct nvkm_device *device = disp->base.engine.subdev.device;
415f12ef 1807 struct nvkm_output *outp;
2fde1f1c 1808 u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
16d4c031
BS
1809 u32 hval, hreg = 0x614200 + (head * 0x800);
1810 u32 oval, oreg;
415f12ef 1811 u32 mask, conf;
0a0afd28 1812
fd166a18 1813 outp = exec_clkcmp(disp, head, 0xff, pclk, &conf);
415f12ef
BS
1814 if (!outp)
1815 return;
186ecad2 1816
55f083c3
BS
1817 /* we allow both encoder attach and detach operations to occur
1818 * within a single supervisor (ie. modeset) sequence. the
1819 * encoder detach scripts quite often switch off power to the
1820 * lanes, which requires the link to be re-trained.
1821 *
1822 * this is not generally an issue as the sink "must" (heh)
1823 * signal an irq when it's lost sync so the driver can
1824 * re-train.
1825 *
1826 * however, on some boards, if one does not configure at least
1827 * the gpu side of the link *before* attaching, then various
1828 * things can go horribly wrong (PDISP disappearing from mmio,
1829 * third supervisor never happens, etc).
1830 *
1831 * the solution is simply to retrain here, if necessary. last
1832 * i checked, the binary driver userspace does not appear to
1833 * trigger this situation (it forces an UPDATE between steps).
1834 */
b17932c0 1835 if (outp->info.type == DCB_OUTPUT_DP) {
415f12ef 1836 u32 soff = (ffs(outp->info.or) - 1) * 0x08;
b17932c0
BS
1837 u32 ctrl, datarate;
1838
1839 if (outp->info.location == 0) {
2fde1f1c 1840 ctrl = nvkm_rd32(device, 0x610794 + soff);
b17932c0
BS
1841 soff = 1;
1842 } else {
2fde1f1c 1843 ctrl = nvkm_rd32(device, 0x610b80 + soff);
b17932c0
BS
1844 soff = 2;
1845 }
415f12ef
BS
1846
1847 switch ((ctrl & 0x000f0000) >> 16) {
0713b451
BS
1848 case 6: datarate = pclk * 30; break;
1849 case 5: datarate = pclk * 24; break;
415f12ef
BS
1850 case 2:
1851 default:
0713b451 1852 datarate = pclk * 18;
415f12ef 1853 break;
186ecad2 1854 }
186ecad2 1855
55f083c3 1856 if (nvkm_output_dp_train(outp, datarate / soff, true))
f2c906fc 1857 OUTP_ERR(outp, "link not trained before attach");
415f12ef
BS
1858 }
1859
fd166a18 1860 exec_clkcmp(disp, head, 0, pclk, &conf);
415f12ef
BS
1861
1862 if (!outp->info.location && outp->info.type == DCB_OUTPUT_ANALOG) {
1863 oreg = 0x614280 + (ffs(outp->info.or) - 1) * 0x800;
1864 oval = 0x00000000;
1865 hval = 0x00000000;
1866 mask = 0xffffffff;
1867 } else
1868 if (!outp->info.location) {
1869 if (outp->info.type == DCB_OUTPUT_DP)
fd166a18 1870 nv50_disp_intr_unk20_2_dp(disp, head, &outp->info, pclk);
415f12ef
BS
1871 oreg = 0x614300 + (ffs(outp->info.or) - 1) * 0x800;
1872 oval = (conf & 0x0100) ? 0x00000101 : 0x00000000;
1873 hval = 0x00000000;
1874 mask = 0x00000707;
1875 } else {
1876 oreg = 0x614380 + (ffs(outp->info.or) - 1) * 0x800;
1877 oval = 0x00000001;
1878 hval = 0x00000001;
1879 mask = 0x00000707;
16d4c031 1880 }
415f12ef 1881
2fde1f1c
BS
1882 nvkm_mask(device, hreg, 0x0000000f, hval);
1883 nvkm_mask(device, oreg, mask, oval);
186ecad2
BS
1884}
1885
1886/* If programming a TMDS output on a SOR that can also be configured for
1887 * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off.
1888 *
1889 * It looks like the VBIOS TMDS scripts make an attempt at this, however,
1890 * the VBIOS scripts on at least one board I have only switch it off on
1891 * link 0, causing a blank display if the output has previously been
1892 * programmed for DisplayPort.
1893 */
1894static void
fd166a18 1895nv50_disp_intr_unk40_0_tmds(struct nv50_disp *disp,
878da15a 1896 struct dcb_output *outp)
186ecad2 1897{
2fde1f1c
BS
1898 struct nvkm_device *device = disp->base.engine.subdev.device;
1899 struct nvkm_bios *bios = device->bios;
186ecad2
BS
1900 const int link = !(outp->sorconf.link & 1);
1901 const int or = ffs(outp->or) - 1;
1902 const u32 loff = (or * 0x800) + (link * 0x80);
1903 const u16 mask = (outp->sorconf.link << 6) | outp->or;
5838ae61 1904 struct dcb_output match;
186ecad2
BS
1905 u8 ver, hdr;
1906
5838ae61 1907 if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, &match))
2fde1f1c 1908 nvkm_mask(device, 0x61c10c + loff, 0x00000001, 0x00000000);
186ecad2
BS
1909}
1910
1911static void
fd166a18 1912nv50_disp_intr_unk40_0(struct nv50_disp *disp, int head)
186ecad2 1913{
2fde1f1c 1914 struct nvkm_device *device = disp->base.engine.subdev.device;
415f12ef 1915 struct nvkm_output *outp;
2fde1f1c 1916 u32 pclk = nvkm_rd32(device, 0x610ad0 + (head * 0x540)) & 0x3fffff;
415f12ef 1917 u32 conf;
16d4c031 1918
fd166a18 1919 outp = exec_clkcmp(disp, head, 1, pclk, &conf);
415f12ef
BS
1920 if (!outp)
1921 return;
1922
1923 if (outp->info.location == 0 && outp->info.type == DCB_OUTPUT_TMDS)
fd166a18 1924 nv50_disp_intr_unk40_0_tmds(disp, &outp->info);
186ecad2
BS
1925}
1926
5cc027f6
BS
1927void
1928nv50_disp_intr_supervisor(struct work_struct *work)
186ecad2 1929{
fd166a18
BS
1930 struct nv50_disp *disp =
1931 container_of(work, struct nv50_disp, supervisor);
1932 struct nv50_disp_impl *impl = (void *)nv_object(disp)->oclass;
84407824
BS
1933 struct nvkm_subdev *subdev = &disp->base.engine.subdev;
1934 struct nvkm_device *device = subdev->device;
2fde1f1c 1935 u32 super = nvkm_rd32(device, 0x610030);
16d4c031 1936 int head;
186ecad2 1937
84407824 1938 nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super, super);
186ecad2 1939
fd166a18
BS
1940 if (disp->super & 0x00000010) {
1941 nv50_disp_mthd_chan(disp, NV_DBG_DEBUG, 0, impl->mthd.core);
1942 for (head = 0; head < disp->head.nr; head++) {
16d4c031
BS
1943 if (!(super & (0x00000020 << head)))
1944 continue;
1945 if (!(super & (0x00000080 << head)))
1946 continue;
fd166a18 1947 nv50_disp_intr_unk10_0(disp, head);
16d4c031
BS
1948 }
1949 } else
fd166a18
BS
1950 if (disp->super & 0x00000020) {
1951 for (head = 0; head < disp->head.nr; head++) {
16d4c031
BS
1952 if (!(super & (0x00000080 << head)))
1953 continue;
fd166a18 1954 nv50_disp_intr_unk20_0(disp, head);
16d4c031 1955 }
fd166a18 1956 for (head = 0; head < disp->head.nr; head++) {
16d4c031
BS
1957 if (!(super & (0x00000200 << head)))
1958 continue;
fd166a18 1959 nv50_disp_intr_unk20_1(disp, head);
16d4c031 1960 }
fd166a18 1961 for (head = 0; head < disp->head.nr; head++) {
16d4c031
BS
1962 if (!(super & (0x00000080 << head)))
1963 continue;
fd166a18 1964 nv50_disp_intr_unk20_2(disp, head);
16d4c031
BS
1965 }
1966 } else
fd166a18
BS
1967 if (disp->super & 0x00000040) {
1968 for (head = 0; head < disp->head.nr; head++) {
16d4c031
BS
1969 if (!(super & (0x00000080 << head)))
1970 continue;
fd166a18 1971 nv50_disp_intr_unk40_0(disp, head);
16d4c031
BS
1972 }
1973 }
1974
2fde1f1c 1975 nvkm_wr32(device, 0x610030, 0x80000000);
186ecad2
BS
1976}
1977
70cabe4a 1978void
878da15a 1979nv50_disp_intr(struct nvkm_subdev *subdev)
ebb945a9 1980{
fd166a18 1981 struct nv50_disp *disp = (void *)subdev;
2fde1f1c
BS
1982 struct nvkm_device *device = disp->base.engine.subdev.device;
1983 u32 intr0 = nvkm_rd32(device, 0x610020);
1984 u32 intr1 = nvkm_rd32(device, 0x610024);
ebb945a9 1985
117e1633
BS
1986 while (intr0 & 0x001f0000) {
1987 u32 chid = __ffs(intr0 & 0x001f0000) - 16;
fd166a18 1988 nv50_disp_intr_error(disp, chid);
117e1633 1989 intr0 &= ~(0x00010000 << chid);
186ecad2
BS
1990 }
1991
b38a2322
BS
1992 while (intr0 & 0x0000001f) {
1993 u32 chid = __ffs(intr0 & 0x0000001f);
fd166a18 1994 nv50_disp_chan_uevent_send(disp, chid);
b38a2322
BS
1995 intr0 &= ~(0x00000001 << chid);
1996 }
1997
186ecad2 1998 if (intr1 & 0x00000004) {
fd166a18 1999 nvkm_disp_vblank(&disp->base, 0);
2fde1f1c 2000 nvkm_wr32(device, 0x610024, 0x00000004);
ebb945a9
BS
2001 }
2002
186ecad2 2003 if (intr1 & 0x00000008) {
fd166a18 2004 nvkm_disp_vblank(&disp->base, 1);
2fde1f1c 2005 nvkm_wr32(device, 0x610024, 0x00000008);
ebb945a9
BS
2006 }
2007
186ecad2 2008 if (intr1 & 0x00000070) {
fd166a18
BS
2009 disp->super = (intr1 & 0x00000070);
2010 schedule_work(&disp->supervisor);
2fde1f1c 2011 nvkm_wr32(device, 0x610024, disp->super);
186ecad2 2012 }
ebb945a9
BS
2013}
2014
2015static int
878da15a
BS
2016nv50_disp_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
2017 struct nvkm_oclass *oclass, void *data, u32 size,
2018 struct nvkm_object **pobject)
ebb945a9 2019{
fd166a18 2020 struct nv50_disp *disp;
ebb945a9
BS
2021 int ret;
2022
878da15a 2023 ret = nvkm_disp_create(parent, engine, oclass, 2, "PDISP",
fd166a18
BS
2024 "display", &disp);
2025 *pobject = nv_object(disp);
ebb945a9
BS
2026 if (ret)
2027 return ret;
2028
fd166a18 2029 ret = nvkm_event_init(&nv50_disp_chan_uevent, 1, 9, &disp->uevent);
b38a2322
BS
2030 if (ret)
2031 return ret;
2032
fd166a18
BS
2033 nv_engine(disp)->sclass = nv50_disp_main_oclass;
2034 nv_engine(disp)->cclass = &nv50_disp_cclass;
2035 nv_subdev(disp)->intr = nv50_disp_intr;
2036 INIT_WORK(&disp->supervisor, nv50_disp_intr_supervisor);
2037 disp->sclass = nv50_disp_sclass;
2038 disp->head.nr = 2;
2039 disp->dac.nr = 3;
2040 disp->sor.nr = 2;
2041 disp->pior.nr = 3;
2042 disp->dac.power = nv50_dac_power;
2043 disp->dac.sense = nv50_dac_sense;
2044 disp->sor.power = nv50_sor_power;
2045 disp->pior.power = nv50_pior_power;
ebb945a9
BS
2046 return 0;
2047}
2048
878da15a 2049struct nvkm_oclass *
a8f8b489
BS
2050nv50_disp_oclass = &(struct nv50_disp_impl) {
2051 .base.base.handle = NV_ENGINE(DISP, 0x50),
878da15a 2052 .base.base.ofuncs = &(struct nvkm_ofuncs) {
ebb945a9 2053 .ctor = nv50_disp_ctor,
878da15a
BS
2054 .dtor = _nvkm_disp_dtor,
2055 .init = _nvkm_disp_init,
2056 .fini = _nvkm_disp_fini,
ebb945a9 2057 },
f2c906fc
BS
2058 .base.outp.internal.crt = nv50_dac_output_new,
2059 .base.outp.internal.tmds = nv50_sor_output_new,
2060 .base.outp.internal.lvds = nv50_sor_output_new,
2061 .base.outp.external.tmds = nv50_pior_output_new,
2062 .base.outp.external.dp = nv50_pior_dp_new,
79ca2770 2063 .base.vblank = &nv50_disp_vblank_func,
2832271d
BS
2064 .mthd.core = &nv50_disp_core_mthd_chan,
2065 .mthd.base = &nv50_disp_base_mthd_chan,
d67d92c0
BS
2066 .mthd.ovly = &nv50_disp_ovly_mthd_chan,
2067 .mthd.prev = 0x000004,
2832271d 2068 .head.scanoutpos = nv50_disp_main_scanoutpos,
a8f8b489 2069}.base.base;
This page took 0.284848 seconds and 5 git commands to generate.