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