1/* 2 * Copyright 2007 Ben Skeggs 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 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23#include "nv_include.h" 24 25#include "hwdefs/nv_object.xml.h" 26#include "hwdefs/nv_m2mf.xml.h" 27#include "hwdefs/nv01_2d.xml.h" 28#include "hwdefs/nv50_2d.xml.h" 29#include "nv04_accel.h" 30 31Bool 32nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, int bpp, 33 int usage_hint, int *pitch, struct nouveau_bo **bo) 34{ 35 NVPtr pNv = NVPTR(scrn); 36 Bool scanout = (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT); 37 Bool tiled = (usage_hint & NOUVEAU_CREATE_PIXMAP_TILED); 38 Bool shared = FALSE; 39 union nouveau_bo_config cfg = {}; 40 int flags = NOUVEAU_BO_MAP | (bpp >= 8 ? NOUVEAU_BO_VRAM : 0); 41 int cpp = bpp / 8, ret; 42 43#ifdef NOUVEAU_PIXMAP_SHARING 44 shared = ((usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED); 45#endif 46 47 flags = NOUVEAU_BO_MAP; 48 if (bpp >= 8) 49 flags |= shared ? NOUVEAU_BO_GART : NOUVEAU_BO_VRAM; 50 51 if (scanout && pNv->tiled_scanout) 52 tiled = TRUE; 53 54 if (pNv->Architecture >= NV_TESLA) { 55 if (!scanout && bpp >= 8 && !shared) 56 tiled = TRUE; 57 58 *pitch = NOUVEAU_ALIGN(width * cpp, !tiled ? 256 : 64); 59 } else { 60 *pitch = NOUVEAU_ALIGN(width * cpp, 64); 61 } 62 63 if (tiled) { 64 if (pNv->Architecture >= NV_FERMI) { 65 if (height > 64) cfg.nvc0.tile_mode = 0x040; 66 else if (height > 32) cfg.nvc0.tile_mode = 0x030; 67 else if (height > 16) cfg.nvc0.tile_mode = 0x020; 68 else if (height > 8) cfg.nvc0.tile_mode = 0x010; 69 else cfg.nvc0.tile_mode = 0x000; 70 71 if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) 72 cfg.nvc0.memtype = (bpp == 16) ? 0x01 : 0x11; 73 else 74 cfg.nvc0.memtype = 0xfe; 75 76 height = NOUVEAU_ALIGN(height, 77 NVC0_TILE_HEIGHT(cfg.nvc0.tile_mode)); 78 } else if (pNv->Architecture >= NV_TESLA) { 79 if (height > 32) cfg.nv50.tile_mode = 0x040; 80 else if (height > 16) cfg.nv50.tile_mode = 0x030; 81 else if (height > 8) cfg.nv50.tile_mode = 0x020; 82 else if (height > 4) cfg.nv50.tile_mode = 0x010; 83 else cfg.nv50.tile_mode = 0x000; 84 85 if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) 86 cfg.nv50.memtype = (bpp == 16) ? 0x16c : 0x128; 87 else if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT) 88 cfg.nv50.memtype = (bpp == 16) ? 0x070 : 0x07a; 89 else 90 cfg.nv50.memtype = 0x070; 91 92 height = NOUVEAU_ALIGN(height, 93 NV50_TILE_HEIGHT(cfg.nv50.tile_mode)); 94 } else { 95 int pitch_align = max( 96 pNv->dev->chipset >= 0x40 ? 1024 : 256, 97 round_down_pow2(*pitch / 4)); 98 99 *pitch = NOUVEAU_ALIGN(*pitch, pitch_align); 100 cfg.nv04.surf_pitch = *pitch; 101 } 102 } 103 104 if (pNv->Architecture < NV_TESLA) { 105 if (bpp == 16) 106 cfg.nv04.surf_flags |= NV04_BO_16BPP; 107 if (bpp == 32) 108 cfg.nv04.surf_flags |= NV04_BO_32BPP; 109 if (usage_hint & NOUVEAU_CREATE_PIXMAP_ZETA) 110 cfg.nv04.surf_flags |= NV04_BO_ZETA; 111 } 112 113 if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT) 114 flags |= NOUVEAU_BO_CONTIG; 115 116 ret = nouveau_bo_new(pNv->dev, flags, 0, *pitch * height, &cfg, bo); 117 if (ret) { 118 ErrorF("failure to allocate surface %dx%d@%d (pitch %d): %d\n", width, height, bpp, *pitch, ret); 119 return FALSE; 120 } 121 122 return TRUE; 123} 124 125void 126NV11SyncToVBlank(PixmapPtr ppix, BoxPtr box) 127{ 128 ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); 129 NVPtr pNv = NVPTR(pScrn); 130 struct nouveau_pushbuf *push = pNv->pushbuf; 131 int head; 132 xf86CrtcPtr crtc; 133 134 if (!nouveau_exa_pixmap_is_onscreen(ppix)) 135 return; 136 137 crtc = nouveau_pick_best_crtc(pScrn, box->x1, box->y1, 138 box->x2 - box->x1, 139 box->y2 - box->y1); 140 if (!crtc) 141 return; 142 143 if (!PUSH_SPACE(push, 8)) 144 return; 145 146 head = drmmode_head(crtc); 147 148 BEGIN_NV04(push, NV15_BLIT(FLIP_INCR_WRITE), 1); 149 PUSH_DATA (push, 0); 150 BEGIN_NV04(push, NV15_BLIT(FLIP_CRTC_INCR_READ), 1); 151 PUSH_DATA (push, head); 152 BEGIN_NV04(push, SUBC_BLIT(0x00000100), 1); 153 PUSH_DATA (push, 0); 154 BEGIN_NV04(push, NV15_BLIT(FLIP_WAIT), 1); 155 PUSH_DATA (push, 0); 156} 157 158static Bool 159NVAccelInitDmaNotifier0(ScrnInfoPtr pScrn) 160{ 161 NVPtr pNv = NVPTR(pScrn); 162 struct nouveau_object *chan = pNv->channel; 163 struct nv04_notify ntfy = { .length = 32 }; 164 165 if (nouveau_object_new(chan, NvDmaNotifier0, NOUVEAU_NOTIFIER_CLASS, 166 &ntfy, sizeof(ntfy), &pNv->notify0)) 167 return FALSE; 168 169 return TRUE; 170} 171 172static Bool 173NVAccelInitNull(ScrnInfoPtr pScrn) 174{ 175 NVPtr pNv = NVPTR(pScrn); 176 177 if (nouveau_object_new(pNv->channel, NvNullObject, NV01_NULL_CLASS, 178 NULL, 0, &pNv->NvNull)) 179 return FALSE; 180 181 return TRUE; 182} 183 184static Bool 185NVAccelInitContextSurfaces(ScrnInfoPtr pScrn) 186{ 187 NVPtr pNv = NVPTR(pScrn); 188 struct nouveau_pushbuf *push = pNv->pushbuf; 189 struct nv04_fifo *fifo = pNv->channel->data; 190 uint32_t class; 191 192 class = (pNv->Architecture >= NV_ARCH_10) ? NV10_SURFACE_2D_CLASS : 193 NV04_SURFACE_2D_CLASS; 194 195 if (nouveau_object_new(pNv->channel, NvContextSurfaces, class, 196 NULL, 0, &pNv->NvContextSurfaces)) 197 return FALSE; 198 199 if (!PUSH_SPACE(push, 8)) 200 return FALSE; 201 202 BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1); 203 PUSH_DATA (push, pNv->NvContextSurfaces->handle); 204 BEGIN_NV04(push, NV04_SF2D(DMA_NOTIFY), 1); 205 PUSH_DATA (push, pNv->NvNull->handle); 206 BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2); 207 PUSH_DATA (push, fifo->vram); 208 PUSH_DATA (push, fifo->vram); 209 return TRUE; 210} 211 212static Bool 213NVAccelInitContextBeta1(ScrnInfoPtr pScrn) 214{ 215 NVPtr pNv = NVPTR(pScrn); 216 struct nouveau_pushbuf *push = pNv->pushbuf; 217 218 if (nouveau_object_new(pNv->channel, NvContextBeta1, NV01_BETA_CLASS, 219 NULL, 0, &pNv->NvContextBeta1)) 220 return FALSE; 221 222 if (!PUSH_SPACE(push, 4)) 223 return FALSE; 224 225 BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 226 PUSH_DATA (push, pNv->NvContextBeta1->handle); 227 BEGIN_NV04(push, NV01_BETA(BETA_1D31), 1); /*alpha factor*/ 228 PUSH_DATA (push, 0xff << 23); 229 return TRUE; 230} 231 232 233static Bool 234NVAccelInitContextBeta4(ScrnInfoPtr pScrn) 235{ 236 NVPtr pNv = NVPTR(pScrn); 237 struct nouveau_pushbuf *push = pNv->pushbuf; 238 239 if (nouveau_object_new(pNv->channel, NvContextBeta4, NV04_BETA4_CLASS, 240 NULL, 0, &pNv->NvContextBeta4)) 241 return FALSE; 242 243 if (!PUSH_SPACE(push, 4)) 244 return FALSE; 245 246 BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 247 PUSH_DATA (push, pNv->NvContextBeta4->handle); 248 BEGIN_NV04(push, NV04_BETA4(BETA_FACTOR), 1); /*RGBA factor*/ 249 PUSH_DATA (push, 0xffff0000); 250 return TRUE; 251} 252 253Bool 254NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret) 255{ 256 switch (pPix->drawable.bitsPerPixel) { 257 case 32: 258 *fmt_ret = NV04_SURFACE_2D_FORMAT_A8R8G8B8; 259 break; 260 case 24: 261 *fmt_ret = NV04_SURFACE_2D_FORMAT_X8R8G8B8_Z8R8G8B8; 262 break; 263 case 16: 264 if (pPix->drawable.depth == 16) 265 *fmt_ret = NV04_SURFACE_2D_FORMAT_R5G6B5; 266 else 267 *fmt_ret = NV04_SURFACE_2D_FORMAT_X1R5G5B5_Z1R5G5B5; 268 break; 269 case 8: 270 *fmt_ret = NV04_SURFACE_2D_FORMAT_Y8; 271 break; 272 default: 273 return FALSE; 274 } 275 276 return TRUE; 277} 278 279Bool 280NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPict, int *fmt_ret) 281{ 282 switch (pPict->format) { 283 case PICT_a8r8g8b8: 284 *fmt_ret = NV04_SURFACE_2D_FORMAT_A8R8G8B8; 285 break; 286 case PICT_x8r8g8b8: 287 *fmt_ret = NV04_SURFACE_2D_FORMAT_X8R8G8B8_Z8R8G8B8; 288 break; 289 case PICT_r5g6b5: 290 *fmt_ret = NV04_SURFACE_2D_FORMAT_R5G6B5; 291 break; 292 case PICT_a8: 293 *fmt_ret = NV04_SURFACE_2D_FORMAT_Y8; 294 break; 295 default: 296 return FALSE; 297 } 298 299 return TRUE; 300} 301 302/* A copy of exaGetOffscreenPixmap(), since it's private. */ 303PixmapPtr 304NVGetDrawablePixmap(DrawablePtr pDraw) 305{ 306 if (pDraw->type == DRAWABLE_WINDOW) 307 return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw); 308 else 309 return (PixmapPtr) pDraw; 310} 311 312static Bool 313NVAccelInitImagePattern(ScrnInfoPtr pScrn) 314{ 315 NVPtr pNv = NVPTR(pScrn); 316 struct nouveau_pushbuf *push = pNv->pushbuf; 317 318 if (nouveau_object_new(pNv->channel, NvImagePattern, NV04_PATTERN_CLASS, 319 NULL, 0, &pNv->NvImagePattern)) 320 return FALSE; 321 322 if (!PUSH_SPACE(push, 8)) 323 return FALSE; 324 325 BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 326 PUSH_DATA (push, pNv->NvImagePattern->handle); 327 BEGIN_NV04(push, NV01_PATT(DMA_NOTIFY), 1); 328 PUSH_DATA (push, pNv->NvNull->handle); 329 BEGIN_NV04(push, NV01_PATT(MONOCHROME_FORMAT), 3); 330#if X_BYTE_ORDER == X_BIG_ENDIAN 331 PUSH_DATA (push, NV01_PATTERN_MONOCHROME_FORMAT_LE); 332#else 333 PUSH_DATA (push, NV01_PATTERN_MONOCHROME_FORMAT_CGA6); 334#endif 335 PUSH_DATA (push, NV01_PATTERN_MONOCHROME_SHAPE_8X8); 336 PUSH_DATA (push, NV04_PATTERN_PATTERN_SELECT_MONO); 337 338 return TRUE; 339} 340 341static Bool 342NVAccelInitRasterOp(ScrnInfoPtr pScrn) 343{ 344 NVPtr pNv = NVPTR(pScrn); 345 struct nouveau_pushbuf *push = pNv->pushbuf; 346 347 if (nouveau_object_new(pNv->channel, NvRop, NV03_ROP_CLASS, 348 NULL, 0, &pNv->NvRop)) 349 return FALSE; 350 351 if (!PUSH_SPACE(push, 4)) 352 return FALSE; 353 354 BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 355 PUSH_DATA (push, pNv->NvRop->handle); 356 BEGIN_NV04(push, NV01_ROP(DMA_NOTIFY), 1); 357 PUSH_DATA (push, pNv->NvNull->handle); 358 359 pNv->currentRop = ~0; 360 return TRUE; 361} 362 363static Bool 364NVAccelInitRectangle(ScrnInfoPtr pScrn) 365{ 366 NVPtr pNv = NVPTR(pScrn); 367 struct nouveau_pushbuf *push = pNv->pushbuf; 368 369 if (nouveau_object_new(pNv->channel, NvRectangle, NV04_GDI_CLASS, 370 NULL, 0, &pNv->NvRectangle)) 371 return FALSE; 372 373 if (!PUSH_SPACE(push, 16)) 374 return FALSE; 375 376 BEGIN_NV04(push, NV01_SUBC(RECT, OBJECT), 1); 377 PUSH_DATA (push, pNv->NvRectangle->handle); 378 BEGIN_NV04(push, NV04_RECT(DMA_NOTIFY), 1); 379 PUSH_DATA (push, pNv->notify0->handle); 380 BEGIN_NV04(push, NV04_RECT(DMA_FONTS), 1); 381 PUSH_DATA (push, pNv->NvNull->handle); 382 BEGIN_NV04(push, NV04_RECT(SURFACE), 1); 383 PUSH_DATA (push, pNv->NvContextSurfaces->handle); 384 BEGIN_NV04(push, NV04_RECT(ROP), 1); 385 PUSH_DATA (push, pNv->NvRop->handle); 386 BEGIN_NV04(push, NV04_RECT(PATTERN), 1); 387 PUSH_DATA (push, pNv->NvImagePattern->handle); 388 BEGIN_NV04(push, NV04_RECT(OPERATION), 1); 389 PUSH_DATA (push, NV04_GDI_OPERATION_ROP_AND); 390 BEGIN_NV04(push, NV04_RECT(MONOCHROME_FORMAT), 1); 391 /* XXX why putting 1 like renouveau dump, swap the text */ 392#if 1 || X_BYTE_ORDER == X_BIG_ENDIAN 393 PUSH_DATA (push, NV04_GDI_MONOCHROME_FORMAT_LE); 394#else 395 PUSH_DATA (push, NV04_GDI_MONOCHROME_FORMAT_CGA6); 396#endif 397 398 return TRUE; 399} 400 401static Bool 402NVAccelInitImageBlit(ScrnInfoPtr pScrn) 403{ 404 NVPtr pNv = NVPTR(pScrn); 405 struct nouveau_pushbuf *push = pNv->pushbuf; 406 uint32_t class; 407 408 class = (pNv->dev->chipset >= 0x11) ? NV15_BLIT_CLASS : NV04_BLIT_CLASS; 409 410 if (nouveau_object_new(pNv->channel, NvImageBlit, class, 411 NULL, 0, &pNv->NvImageBlit)) 412 return FALSE; 413 414 if (!PUSH_SPACE(push, 16)) 415 return FALSE; 416 417 BEGIN_NV04(push, NV01_SUBC(BLIT, OBJECT), 1); 418 PUSH_DATA (push, pNv->NvImageBlit->handle); 419 BEGIN_NV04(push, NV01_BLIT(DMA_NOTIFY), 1); 420 PUSH_DATA (push, pNv->notify0->handle); 421 BEGIN_NV04(push, NV01_BLIT(COLOR_KEY), 1); 422 PUSH_DATA (push, pNv->NvNull->handle); 423 BEGIN_NV04(push, NV04_BLIT(SURFACES), 1); 424 PUSH_DATA (push, pNv->NvContextSurfaces->handle); 425 BEGIN_NV04(push, NV01_BLIT(CLIP), 3); 426 PUSH_DATA (push, pNv->NvNull->handle); 427 PUSH_DATA (push, pNv->NvImagePattern->handle); 428 PUSH_DATA (push, pNv->NvRop->handle); 429 BEGIN_NV04(push, NV01_BLIT(OPERATION), 1); 430 PUSH_DATA (push, NV01_BLIT_OPERATION_ROP_AND); 431 if (pNv->NvImageBlit->oclass == NV15_BLIT_CLASS) { 432 BEGIN_NV04(push, NV15_BLIT(FLIP_SET_READ), 3); 433 PUSH_DATA (push, 0); 434 PUSH_DATA (push, 1); 435 PUSH_DATA (push, 2); 436 } 437 438 return TRUE; 439} 440 441static Bool 442NVAccelInitScaledImage(ScrnInfoPtr pScrn) 443{ 444 NVPtr pNv = NVPTR(pScrn); 445 struct nouveau_pushbuf *push = pNv->pushbuf; 446 struct nv04_fifo *fifo = pNv->channel->data; 447 uint32_t class; 448 449 switch (pNv->Architecture) { 450 case NV_ARCH_04: 451 class = NV04_SIFM_CLASS; 452 break; 453 case NV_ARCH_10: 454 case NV_ARCH_20: 455 case NV_ARCH_30: 456 class = NV10_SIFM_CLASS; 457 break; 458 case NV_ARCH_40: 459 default: 460 class = NV40_SIFM_CLASS; 461 break; 462 } 463 464 if (nouveau_object_new(pNv->channel, NvScaledImage, class, 465 NULL, 0, &pNv->NvScaledImage)) 466 return FALSE; 467 468 if (!PUSH_SPACE(push, 16)) 469 return FALSE; 470 471 BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 472 PUSH_DATA (push, pNv->NvScaledImage->handle); 473 BEGIN_NV04(push, NV03_SIFM(DMA_NOTIFY), 7); 474 PUSH_DATA (push, pNv->notify0->handle); 475 PUSH_DATA (push, fifo->vram); 476 PUSH_DATA (push, pNv->NvNull->handle); 477 PUSH_DATA (push, pNv->NvNull->handle); 478 PUSH_DATA (push, pNv->NvContextBeta1->handle); 479 PUSH_DATA (push, pNv->NvContextBeta4->handle); 480 PUSH_DATA (push, pNv->NvContextSurfaces->handle); 481 if (pNv->Architecture>=NV_ARCH_10) { 482 BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1); 483 PUSH_DATA (push, NV05_SIFM_COLOR_CONVERSION_DITHER); 484 } 485 BEGIN_NV04(push, NV03_SIFM(OPERATION), 1); 486 PUSH_DATA (push, NV03_SIFM_OPERATION_SRCCOPY); 487 488 return TRUE; 489} 490 491static Bool 492NVAccelInitClipRectangle(ScrnInfoPtr pScrn) 493{ 494 NVPtr pNv = NVPTR(pScrn); 495 struct nouveau_pushbuf *push = pNv->pushbuf; 496 497 if (nouveau_object_new(pNv->channel, NvClipRectangle, NV01_CLIP_CLASS, 498 NULL, 0, &pNv->NvClipRectangle)) 499 return FALSE; 500 501 if (!PUSH_SPACE(push, 4)) 502 return FALSE; 503 504 BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 505 PUSH_DATA (push, pNv->NvClipRectangle->handle); 506 BEGIN_NV04(push, NV01_CLIP(DMA_NOTIFY), 1); 507 PUSH_DATA (push, pNv->NvNull->handle); 508 return TRUE; 509} 510 511static Bool 512NVAccelInitMemFormat(ScrnInfoPtr pScrn) 513{ 514 NVPtr pNv = NVPTR(pScrn); 515 struct nouveau_pushbuf *push = pNv->pushbuf; 516 517 if (nouveau_object_new(pNv->channel, NvMemFormat, NV03_M2MF_CLASS, 518 NULL, 0, &pNv->NvMemFormat)) 519 return FALSE; 520 521 if (!PUSH_SPACE(push, 4)) 522 return FALSE; 523 524 BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1); 525 PUSH_DATA (push, pNv->NvMemFormat->handle); 526 BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1); 527 PUSH_DATA (push, pNv->notify0->handle); 528 return TRUE; 529} 530 531static Bool 532NVAccelInitImageFromCpu(ScrnInfoPtr pScrn) 533{ 534 NVPtr pNv = NVPTR(pScrn); 535 struct nouveau_pushbuf *push = pNv->pushbuf; 536 uint32_t class; 537 538 switch (pNv->Architecture) { 539 case NV_ARCH_04: 540 class = NV04_IFC_CLASS; 541 break; 542 case NV_ARCH_10: 543 case NV_ARCH_20: 544 case NV_ARCH_30: 545 case NV_ARCH_40: 546 default: 547 class = NV10_IFC_CLASS; 548 break; 549 } 550 551 if (nouveau_object_new(pNv->channel, NvImageFromCpu, class, 552 NULL, 0, &pNv->NvImageFromCpu)) 553 return FALSE; 554 555 if (!PUSH_SPACE(push, 16)) 556 return FALSE; 557 558 BEGIN_NV04(push, NV01_SUBC(IFC, OBJECT), 1); 559 PUSH_DATA (push, pNv->NvImageFromCpu->handle); 560 BEGIN_NV04(push, NV01_IFC(DMA_NOTIFY), 1); 561 PUSH_DATA (push, pNv->notify0->handle); 562 BEGIN_NV04(push, NV01_IFC(CLIP), 1); 563 PUSH_DATA (push, pNv->NvNull->handle); 564 BEGIN_NV04(push, NV01_IFC(PATTERN), 1); 565 PUSH_DATA (push, pNv->NvNull->handle); 566 BEGIN_NV04(push, NV01_IFC(ROP), 1); 567 PUSH_DATA (push, pNv->NvNull->handle); 568 if (pNv->Architecture >= NV_ARCH_10) { 569 BEGIN_NV04(push, NV01_IFC(BETA), 1); 570 PUSH_DATA (push, pNv->NvNull->handle); 571 BEGIN_NV04(push, NV04_IFC(BETA4), 1); 572 PUSH_DATA (push, pNv->NvNull->handle); 573 } 574 BEGIN_NV04(push, NV04_IFC(SURFACE), 1); 575 PUSH_DATA (push, pNv->NvContextSurfaces->handle); 576 BEGIN_NV04(push, NV01_IFC(OPERATION), 1); 577 PUSH_DATA (push, NV01_IFC_OPERATION_SRCCOPY); 578 return TRUE; 579} 580 581#define INIT_CONTEXT_OBJECT(name) do { \ 582 ret = NVAccelInit##name(pScrn); \ 583 if (!ret) { \ 584 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \ 585 "Failed to initialise context object: "#name \ 586 " (%d)\n", ret); \ 587 return FALSE; \ 588 } \ 589} while(0) 590 591void 592NVAccelCommonFini(ScrnInfoPtr pScrn) 593{ 594 NVPtr pNv = NVPTR(pScrn); 595 596 nouveau_object_del(&pNv->notify0); 597 nouveau_object_del(&pNv->vblank_sem); 598 599 nouveau_object_del(&pNv->NvContextSurfaces); 600 nouveau_object_del(&pNv->NvContextBeta1); 601 nouveau_object_del(&pNv->NvContextBeta4); 602 nouveau_object_del(&pNv->NvImagePattern); 603 nouveau_object_del(&pNv->NvRop); 604 nouveau_object_del(&pNv->NvRectangle); 605 nouveau_object_del(&pNv->NvImageBlit); 606 nouveau_object_del(&pNv->NvScaledImage); 607 nouveau_object_del(&pNv->NvClipRectangle); 608 nouveau_object_del(&pNv->NvImageFromCpu); 609 nouveau_object_del(&pNv->Nv2D); 610 nouveau_object_del(&pNv->NvMemFormat); 611 nouveau_object_del(&pNv->NvSW); 612 nouveau_object_del(&pNv->Nv3D); 613 nouveau_object_del(&pNv->NvCOPY); 614 615 nouveau_bo_ref(NULL, &pNv->scratch); 616 617 nouveau_bufctx_del(&pNv->bufctx); 618 nouveau_pushbuf_del(&pNv->pushbuf); 619 nouveau_object_del(&pNv->channel); 620} 621 622Bool 623NVAccelCommonInit(ScrnInfoPtr pScrn) 624{ 625 NVPtr pNv = NVPTR(pScrn); 626 struct nv04_fifo nv04_data = { .vram = NvDmaFB, 627 .gart = NvDmaTT }; 628 struct nvc0_fifo nvc0_data = { }; 629 struct nouveau_object *device = &pNv->dev->object; 630 int size, ret; 631 void *data; 632 633 if (pNv->dev->drm_version < 0x01000000 && pNv->dev->chipset >= 0xc0) { 634 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 635 "Fermi acceleration not supported on old kernel\n"); 636 return FALSE; 637 } 638 639 if (pNv->Architecture < NV_FERMI) { 640 data = &nv04_data; 641 size = sizeof(nv04_data); 642 } else { 643 data = &nvc0_data; 644 size = sizeof(nvc0_data); 645 } 646 647 ret = nouveau_object_new(device, 0, NOUVEAU_FIFO_CHANNEL_CLASS, 648 data, size, &pNv->channel); 649 if (ret) { 650 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 651 "Error creating GPU channel: %d\n", ret); 652 return FALSE; 653 } 654 655 ret = nouveau_pushbuf_new(pNv->client, pNv->channel, 4, 32 * 1024, 656 true, &pNv->pushbuf); 657 if (ret) { 658 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 659 "Error allocating DMA push buffer: %d\n",ret); 660 NVAccelCommonFini(pScrn); 661 return FALSE; 662 } 663 664 ret = nouveau_bufctx_new(pNv->client, 1, &pNv->bufctx); 665 if (ret) { 666 NVAccelCommonFini(pScrn); 667 return FALSE; 668 } 669 670 pNv->pushbuf->user_priv = pNv->bufctx; 671 672 /* Scratch buffer */ 673 ret = nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 674 128 * 1024, 128 * 1024, NULL, &pNv->scratch); 675 if (!ret) 676 ret = nouveau_bo_map(pNv->scratch, 0, pNv->client); 677 if (ret) { 678 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 679 "Failed to allocate scratch buffer: %d\n", ret); 680 return FALSE; 681 } 682 683 /* General engine objects */ 684 if (pNv->Architecture < NV_FERMI) { 685 INIT_CONTEXT_OBJECT(DmaNotifier0); 686 INIT_CONTEXT_OBJECT(Null); 687 } 688 689 /* 2D engine */ 690 if (pNv->Architecture < NV_TESLA) { 691 INIT_CONTEXT_OBJECT(ContextSurfaces); 692 INIT_CONTEXT_OBJECT(ContextBeta1); 693 INIT_CONTEXT_OBJECT(ContextBeta4); 694 INIT_CONTEXT_OBJECT(ImagePattern); 695 INIT_CONTEXT_OBJECT(RasterOp); 696 INIT_CONTEXT_OBJECT(Rectangle); 697 INIT_CONTEXT_OBJECT(ImageBlit); 698 INIT_CONTEXT_OBJECT(ScaledImage); 699 INIT_CONTEXT_OBJECT(ClipRectangle); 700 INIT_CONTEXT_OBJECT(ImageFromCpu); 701 } else 702 if (pNv->Architecture < NV_FERMI) { 703 INIT_CONTEXT_OBJECT(2D_NV50); 704 } else { 705 INIT_CONTEXT_OBJECT(2D_NVC0); 706 } 707 708 if (pNv->Architecture < NV_TESLA) 709 INIT_CONTEXT_OBJECT(MemFormat); 710 else 711 if (pNv->Architecture < NV_FERMI) 712 INIT_CONTEXT_OBJECT(M2MF_NV50); 713 else 714 if (pNv->Architecture < NV_KEPLER) 715 INIT_CONTEXT_OBJECT(M2MF_NVC0); 716 else { 717 INIT_CONTEXT_OBJECT(P2MF_NVE0); 718 INIT_CONTEXT_OBJECT(COPY_NVE0); 719 } 720 721 /* 3D init */ 722 switch (pNv->Architecture) { 723 case NV_FERMI: 724 case NV_KEPLER: 725 case NV_MAXWELL: 726 case NV_PASCAL: 727 INIT_CONTEXT_OBJECT(3D_NVC0); 728 break; 729 case NV_TESLA: 730 INIT_CONTEXT_OBJECT(NV50TCL); 731 break; 732 case NV_ARCH_40: 733 INIT_CONTEXT_OBJECT(NV40TCL); 734 break; 735 case NV_ARCH_30: 736 INIT_CONTEXT_OBJECT(NV30TCL); 737 break; 738 case NV_ARCH_20: 739 case NV_ARCH_10: 740 INIT_CONTEXT_OBJECT(NV10TCL); 741 break; 742 default: 743 break; 744 } 745 746 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Channel setup complete.\n"); 747 return TRUE; 748} 749