1/* 2 * Copyright (C) 2008 Maarten Maathuis. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 */ 26 27#include <drm/drmP.h> 28#include <drm/drm_crtc_helper.h> 29 30#include <nvif/class.h> 31 32#include "nouveau_fbcon.h" 33#include "dispnv04/hw.h" 34#include "nouveau_crtc.h" 35#include "nouveau_dma.h" 36#include "nouveau_gem.h" 37#include "nouveau_connector.h" 38#include "nv50_display.h" 39 40#include "nouveau_fence.h" 41 42#include <nvif/event.h> 43 44static int 45nouveau_display_vblank_handler(struct nvif_notify *notify) 46{ 47 struct nouveau_crtc *nv_crtc = 48 container_of(notify, typeof(*nv_crtc), vblank); 49 drm_handle_vblank(nv_crtc->base.dev, nv_crtc->index); 50 return NVIF_NOTIFY_KEEP; 51} 52 53int 54nouveau_display_vblank_enable(struct drm_device *dev, unsigned int pipe) 55{ 56 struct drm_crtc *crtc; 57 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 58 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 59 if (nv_crtc->index == pipe) { 60 nvif_notify_get(&nv_crtc->vblank); 61 return 0; 62 } 63 } 64 return -EINVAL; 65} 66 67void 68nouveau_display_vblank_disable(struct drm_device *dev, unsigned int pipe) 69{ 70 struct drm_crtc *crtc; 71 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 72 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 73 if (nv_crtc->index == pipe) { 74 nvif_notify_put(&nv_crtc->vblank); 75 return; 76 } 77 } 78} 79 80static inline int 81calc(int blanks, int blanke, int total, int line) 82{ 83 if (blanke >= blanks) { 84 if (line >= blanks) 85 line -= total; 86 } else { 87 if (line >= blanks) 88 line -= total; 89 line -= blanke + 1; 90 } 91 return line; 92} 93 94int 95nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, 96 ktime_t *stime, ktime_t *etime) 97{ 98 struct { 99 struct nv04_disp_mthd_v0 base; 100 struct nv04_disp_scanoutpos_v0 scan; 101 } args = { 102 .base.method = NV04_DISP_SCANOUTPOS, 103 .base.head = nouveau_crtc(crtc)->index, 104 }; 105 struct nouveau_display *disp = nouveau_display(crtc->dev); 106 struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; 107 int ret, retry = 1; 108 109 do { 110 ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args)); 111 if (ret != 0) 112 return 0; 113 114 if (args.scan.vline) { 115 ret |= DRM_SCANOUTPOS_ACCURATE; 116 ret |= DRM_SCANOUTPOS_VALID; 117 break; 118 } 119 120 if (retry) ndelay(vblank->linedur_ns); 121 } while (retry--); 122 123 *hpos = args.scan.hline; 124 *vpos = calc(args.scan.vblanks, args.scan.vblanke, 125 args.scan.vtotal, args.scan.vline); 126 if (stime) *stime = ns_to_ktime(args.scan.time[0]); 127 if (etime) *etime = ns_to_ktime(args.scan.time[1]); 128 129 if (*vpos < 0) 130 ret |= DRM_SCANOUTPOS_IN_VBLANK; 131 return ret; 132} 133 134int 135nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe, 136 unsigned int flags, int *vpos, int *hpos, 137 ktime_t *stime, ktime_t *etime, 138 const struct drm_display_mode *mode) 139{ 140 struct drm_crtc *crtc; 141 142 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 143 if (nouveau_crtc(crtc)->index == pipe) { 144 return nouveau_display_scanoutpos_head(crtc, vpos, hpos, 145 stime, etime); 146 } 147 } 148 149 return 0; 150} 151 152int 153nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe, 154 int *max_error, struct timeval *time, unsigned flags) 155{ 156 struct drm_crtc *crtc; 157 158 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 159 if (nouveau_crtc(crtc)->index == pipe) { 160 return drm_calc_vbltimestamp_from_scanoutpos(dev, 161 pipe, max_error, time, flags, 162 &crtc->hwmode); 163 } 164 } 165 166 return -EINVAL; 167} 168 169static void 170nouveau_display_vblank_fini(struct drm_device *dev) 171{ 172 struct drm_crtc *crtc; 173 174 drm_vblank_cleanup(dev); 175 176 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 177 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 178 nvif_notify_fini(&nv_crtc->vblank); 179 } 180} 181 182static int 183nouveau_display_vblank_init(struct drm_device *dev) 184{ 185 struct nouveau_display *disp = nouveau_display(dev); 186 struct drm_crtc *crtc; 187 int ret; 188 189 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 190 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 191 ret = nvif_notify_init(&disp->disp, 192 nouveau_display_vblank_handler, false, 193 NV04_DISP_NTFY_VBLANK, 194 &(struct nvif_notify_head_req_v0) { 195 .head = nv_crtc->index, 196 }, 197 sizeof(struct nvif_notify_head_req_v0), 198 sizeof(struct nvif_notify_head_rep_v0), 199 &nv_crtc->vblank); 200 if (ret) { 201 nouveau_display_vblank_fini(dev); 202 return ret; 203 } 204 } 205 206 ret = drm_vblank_init(dev, dev->mode_config.num_crtc); 207 if (ret) { 208 nouveau_display_vblank_fini(dev); 209 return ret; 210 } 211 212 return 0; 213} 214 215static void 216nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) 217{ 218 struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); 219 struct nouveau_display *disp = nouveau_display(drm_fb->dev); 220 221 if (disp->fb_dtor) 222 disp->fb_dtor(drm_fb); 223 224 if (fb->nvbo) 225 drm_gem_object_unreference_unlocked(&fb->nvbo->gem); 226 227 drm_framebuffer_cleanup(drm_fb); 228 kfree(fb); 229} 230 231static int 232nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb, 233 struct drm_file *file_priv, 234 unsigned int *handle) 235{ 236 struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); 237 238 return drm_gem_handle_create(file_priv, &fb->nvbo->gem, handle); 239} 240 241static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { 242 .destroy = nouveau_user_framebuffer_destroy, 243 .create_handle = nouveau_user_framebuffer_create_handle, 244}; 245 246int 247nouveau_framebuffer_init(struct drm_device *dev, 248 struct nouveau_framebuffer *nv_fb, 249 struct drm_mode_fb_cmd2 *mode_cmd, 250 struct nouveau_bo *nvbo) 251{ 252 struct nouveau_display *disp = nouveau_display(dev); 253 struct drm_framebuffer *fb = &nv_fb->base; 254 int ret; 255 256 drm_helper_mode_fill_fb_struct(fb, mode_cmd); 257 nv_fb->nvbo = nvbo; 258 259 ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs); 260 if (ret) 261 return ret; 262 263 if (disp->fb_ctor) { 264 ret = disp->fb_ctor(fb); 265 if (ret) 266 disp->fb_dtor(fb); 267 } 268 269 return ret; 270} 271 272static struct drm_framebuffer * 273nouveau_user_framebuffer_create(struct drm_device *dev, 274 struct drm_file *file_priv, 275 struct drm_mode_fb_cmd2 *mode_cmd) 276{ 277 struct nouveau_framebuffer *nouveau_fb; 278 struct drm_gem_object *gem; 279 int ret = -ENOMEM; 280 281 gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); 282 if (!gem) 283 return ERR_PTR(-ENOENT); 284 285 nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); 286 if (!nouveau_fb) 287 goto err_unref; 288 289 ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem)); 290 if (ret) 291 goto err; 292 293 return &nouveau_fb->base; 294 295err: 296 kfree(nouveau_fb); 297err_unref: 298 drm_gem_object_unreference(gem); 299 return ERR_PTR(ret); 300} 301 302static const struct drm_mode_config_funcs nouveau_mode_config_funcs = { 303 .fb_create = nouveau_user_framebuffer_create, 304 .output_poll_changed = nouveau_fbcon_output_poll_changed, 305}; 306 307 308struct nouveau_drm_prop_enum_list { 309 u8 gen_mask; 310 int type; 311 char *name; 312}; 313 314static struct nouveau_drm_prop_enum_list underscan[] = { 315 { 6, UNDERSCAN_AUTO, "auto" }, 316 { 6, UNDERSCAN_OFF, "off" }, 317 { 6, UNDERSCAN_ON, "on" }, 318 {} 319}; 320 321static struct nouveau_drm_prop_enum_list dither_mode[] = { 322 { 7, DITHERING_MODE_AUTO, "auto" }, 323 { 7, DITHERING_MODE_OFF, "off" }, 324 { 1, DITHERING_MODE_ON, "on" }, 325 { 6, DITHERING_MODE_STATIC2X2, "static 2x2" }, 326 { 6, DITHERING_MODE_DYNAMIC2X2, "dynamic 2x2" }, 327 { 4, DITHERING_MODE_TEMPORAL, "temporal" }, 328 {} 329}; 330 331static struct nouveau_drm_prop_enum_list dither_depth[] = { 332 { 6, DITHERING_DEPTH_AUTO, "auto" }, 333 { 6, DITHERING_DEPTH_6BPC, "6 bpc" }, 334 { 6, DITHERING_DEPTH_8BPC, "8 bpc" }, 335 {} 336}; 337 338#define PROP_ENUM(p,gen,n,list) do { \ 339 struct nouveau_drm_prop_enum_list *l = (list); \ 340 int c = 0; \ 341 while (l->gen_mask) { \ 342 if (l->gen_mask & (1 << (gen))) \ 343 c++; \ 344 l++; \ 345 } \ 346 if (c) { \ 347 p = drm_property_create(dev, DRM_MODE_PROP_ENUM, n, c); \ 348 l = (list); \ 349 c = 0; \ 350 while (p && l->gen_mask) { \ 351 if (l->gen_mask & (1 << (gen))) { \ 352 drm_property_add_enum(p, c, l->type, l->name); \ 353 c++; \ 354 } \ 355 l++; \ 356 } \ 357 } \ 358} while(0) 359 360int 361nouveau_display_init(struct drm_device *dev) 362{ 363 struct nouveau_display *disp = nouveau_display(dev); 364 struct nouveau_drm *drm = nouveau_drm(dev); 365 struct drm_connector *connector; 366 int ret; 367 368 ret = disp->init(dev); 369 if (ret) 370 return ret; 371 372 /* enable polling for external displays */ 373 drm_kms_helper_poll_enable(dev); 374 375 /* enable hotplug interrupts */ 376 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 377 struct nouveau_connector *conn = nouveau_connector(connector); 378 nvif_notify_get(&conn->hpd); 379 } 380 381 /* enable flip completion events */ 382 nvif_notify_get(&drm->flip); 383 return ret; 384} 385 386void 387nouveau_display_fini(struct drm_device *dev) 388{ 389 struct nouveau_display *disp = nouveau_display(dev); 390 struct nouveau_drm *drm = nouveau_drm(dev); 391 struct drm_connector *connector; 392 int head; 393 394 /* Make sure that drm and hw vblank irqs get properly disabled. */ 395 for (head = 0; head < dev->mode_config.num_crtc; head++) 396 drm_vblank_off(dev, head); 397 398 /* disable flip completion events */ 399 nvif_notify_put(&drm->flip); 400 401 /* disable hotplug interrupts */ 402 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 403 struct nouveau_connector *conn = nouveau_connector(connector); 404 nvif_notify_put(&conn->hpd); 405 } 406 407 drm_kms_helper_poll_disable(dev); 408 disp->fini(dev); 409} 410 411static void 412nouveau_display_create_properties(struct drm_device *dev) 413{ 414 struct nouveau_display *disp = nouveau_display(dev); 415 int gen; 416 417 if (disp->disp.oclass < NV50_DISP) 418 gen = 0; 419 else 420 if (disp->disp.oclass < GF110_DISP) 421 gen = 1; 422 else 423 gen = 2; 424 425 PROP_ENUM(disp->dithering_mode, gen, "dithering mode", dither_mode); 426 PROP_ENUM(disp->dithering_depth, gen, "dithering depth", dither_depth); 427 PROP_ENUM(disp->underscan_property, gen, "underscan", underscan); 428 429 disp->underscan_hborder_property = 430 drm_property_create_range(dev, 0, "underscan hborder", 0, 128); 431 432 disp->underscan_vborder_property = 433 drm_property_create_range(dev, 0, "underscan vborder", 0, 128); 434 435 if (gen < 1) 436 return; 437 438 /* -90..+90 */ 439 disp->vibrant_hue_property = 440 drm_property_create_range(dev, 0, "vibrant hue", 0, 180); 441 442 /* -100..+100 */ 443 disp->color_vibrance_property = 444 drm_property_create_range(dev, 0, "color vibrance", 0, 200); 445} 446 447int 448nouveau_display_create(struct drm_device *dev) 449{ 450 struct nouveau_drm *drm = nouveau_drm(dev); 451 struct nvkm_device *device = nvxx_device(&drm->device); 452 struct nouveau_display *disp; 453 int ret; 454 455 disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); 456 if (!disp) 457 return -ENOMEM; 458 459 drm_mode_config_init(dev); 460 drm_mode_create_scaling_mode_property(dev); 461 drm_mode_create_dvi_i_properties(dev); 462 463 dev->mode_config.funcs = &nouveau_mode_config_funcs; 464 dev->mode_config.fb_base = device->func->resource_addr(device, 1); 465 466 dev->mode_config.min_width = 0; 467 dev->mode_config.min_height = 0; 468 if (drm->device.info.family < NV_DEVICE_INFO_V0_CELSIUS) { 469 dev->mode_config.max_width = 2048; 470 dev->mode_config.max_height = 2048; 471 } else 472 if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) { 473 dev->mode_config.max_width = 4096; 474 dev->mode_config.max_height = 4096; 475 } else 476 if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI) { 477 dev->mode_config.max_width = 8192; 478 dev->mode_config.max_height = 8192; 479 } else { 480 dev->mode_config.max_width = 16384; 481 dev->mode_config.max_height = 16384; 482 } 483 484 dev->mode_config.preferred_depth = 24; 485 dev->mode_config.prefer_shadow = 1; 486 487 if (drm->device.info.chipset < 0x11) 488 dev->mode_config.async_page_flip = false; 489 else 490 dev->mode_config.async_page_flip = true; 491 492 drm_kms_helper_poll_init(dev); 493 drm_kms_helper_poll_disable(dev); 494 495 if (nouveau_modeset != 2 && drm->vbios.dcb.entries) { 496 static const u16 oclass[] = { 497 GM204_DISP, 498 GM107_DISP, 499 GK110_DISP, 500 GK104_DISP, 501 GF110_DISP, 502 GT214_DISP, 503 GT206_DISP, 504 GT200_DISP, 505 G82_DISP, 506 NV50_DISP, 507 NV04_DISP, 508 }; 509 int i; 510 511 for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) { 512 ret = nvif_object_init(&drm->device.object, 0, 513 oclass[i], NULL, 0, &disp->disp); 514 } 515 516 if (ret == 0) { 517 nouveau_display_create_properties(dev); 518 if (disp->disp.oclass < NV50_DISP) 519 ret = nv04_display_create(dev); 520 else 521 ret = nv50_display_create(dev); 522 } 523 } else { 524 ret = 0; 525 } 526 527 if (ret) 528 goto disp_create_err; 529 530 if (dev->mode_config.num_crtc) { 531 ret = nouveau_display_vblank_init(dev); 532 if (ret) 533 goto vblank_err; 534 } 535 536 nouveau_backlight_init(dev); 537 return 0; 538 539vblank_err: 540 disp->dtor(dev); 541disp_create_err: 542 drm_kms_helper_poll_fini(dev); 543 drm_mode_config_cleanup(dev); 544 return ret; 545} 546 547void 548nouveau_display_destroy(struct drm_device *dev) 549{ 550 struct nouveau_display *disp = nouveau_display(dev); 551 552 nouveau_backlight_exit(dev); 553 nouveau_display_vblank_fini(dev); 554 555 drm_kms_helper_poll_fini(dev); 556 drm_mode_config_cleanup(dev); 557 558 if (disp->dtor) 559 disp->dtor(dev); 560 561 nvif_object_fini(&disp->disp); 562 563 nouveau_drm(dev)->display = NULL; 564 kfree(disp); 565} 566 567int 568nouveau_display_suspend(struct drm_device *dev, bool runtime) 569{ 570 struct drm_crtc *crtc; 571 572 nouveau_display_fini(dev); 573 574 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 575 struct nouveau_framebuffer *nouveau_fb; 576 577 nouveau_fb = nouveau_framebuffer(crtc->primary->fb); 578 if (!nouveau_fb || !nouveau_fb->nvbo) 579 continue; 580 581 nouveau_bo_unpin(nouveau_fb->nvbo); 582 } 583 584 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 585 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 586 if (nv_crtc->cursor.nvbo) { 587 if (nv_crtc->cursor.set_offset) 588 nouveau_bo_unmap(nv_crtc->cursor.nvbo); 589 nouveau_bo_unpin(nv_crtc->cursor.nvbo); 590 } 591 } 592 593 return 0; 594} 595 596void 597nouveau_display_resume(struct drm_device *dev, bool runtime) 598{ 599 struct nouveau_drm *drm = nouveau_drm(dev); 600 struct drm_crtc *crtc; 601 int ret, head; 602 603 /* re-pin fb/cursors */ 604 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 605 struct nouveau_framebuffer *nouveau_fb; 606 607 nouveau_fb = nouveau_framebuffer(crtc->primary->fb); 608 if (!nouveau_fb || !nouveau_fb->nvbo) 609 continue; 610 611 ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM, true); 612 if (ret) 613 NV_ERROR(drm, "Could not pin framebuffer\n"); 614 } 615 616 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 617 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 618 if (!nv_crtc->cursor.nvbo) 619 continue; 620 621 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, true); 622 if (!ret && nv_crtc->cursor.set_offset) 623 ret = nouveau_bo_map(nv_crtc->cursor.nvbo); 624 if (ret) 625 NV_ERROR(drm, "Could not pin/map cursor.\n"); 626 } 627 628 nouveau_display_init(dev); 629 630 /* Force CLUT to get re-loaded during modeset */ 631 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 632 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 633 634 nv_crtc->lut.depth = 0; 635 } 636 637 /* This should ensure we don't hit a locking problem when someone 638 * wakes us up via a connector. We should never go into suspend 639 * while the display is on anyways. 640 */ 641 if (runtime) 642 return; 643 644 drm_helper_resume_force_mode(dev); 645 646 /* Make sure that drm and hw vblank irqs get resumed if needed. */ 647 for (head = 0; head < dev->mode_config.num_crtc; head++) 648 drm_vblank_on(dev, head); 649 650 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 651 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 652 653 if (!nv_crtc->cursor.nvbo) 654 continue; 655 656 if (nv_crtc->cursor.set_offset) 657 nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset); 658 nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, 659 nv_crtc->cursor_saved_y); 660 } 661} 662 663static int 664nouveau_page_flip_emit(struct nouveau_channel *chan, 665 struct nouveau_bo *old_bo, 666 struct nouveau_bo *new_bo, 667 struct nouveau_page_flip_state *s, 668 struct nouveau_fence **pfence) 669{ 670 struct nouveau_fence_chan *fctx = chan->fence; 671 struct nouveau_drm *drm = chan->drm; 672 struct drm_device *dev = drm->dev; 673 unsigned long flags; 674 int ret; 675 676 /* Queue it to the pending list */ 677 spin_lock_irqsave(&dev->event_lock, flags); 678 list_add_tail(&s->head, &fctx->flip); 679 spin_unlock_irqrestore(&dev->event_lock, flags); 680 681 /* Synchronize with the old framebuffer */ 682 ret = nouveau_fence_sync(old_bo, chan, false, false); 683 if (ret) 684 goto fail; 685 686 /* Emit the pageflip */ 687 ret = RING_SPACE(chan, 2); 688 if (ret) 689 goto fail; 690 691 if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI) 692 BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); 693 else 694 BEGIN_NVC0(chan, FermiSw, NV_SW_PAGE_FLIP, 1); 695 OUT_RING (chan, 0x00000000); 696 FIRE_RING (chan); 697 698 ret = nouveau_fence_new(chan, false, pfence); 699 if (ret) 700 goto fail; 701 702 return 0; 703fail: 704 spin_lock_irqsave(&dev->event_lock, flags); 705 list_del(&s->head); 706 spin_unlock_irqrestore(&dev->event_lock, flags); 707 return ret; 708} 709 710int 711nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, 712 struct drm_pending_vblank_event *event, u32 flags) 713{ 714 const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1; 715 struct drm_device *dev = crtc->dev; 716 struct nouveau_drm *drm = nouveau_drm(dev); 717 struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo; 718 struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; 719 struct nouveau_page_flip_state *s; 720 struct nouveau_channel *chan; 721 struct nouveau_cli *cli; 722 struct nouveau_fence *fence; 723 int ret; 724 725 chan = drm->channel; 726 if (!chan) 727 return -ENODEV; 728 cli = (void *)chan->user.client; 729 730 s = kzalloc(sizeof(*s), GFP_KERNEL); 731 if (!s) 732 return -ENOMEM; 733 734 if (new_bo != old_bo) { 735 ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM, true); 736 if (ret) 737 goto fail_free; 738 } 739 740 mutex_lock(&cli->mutex); 741 ret = ttm_bo_reserve(&new_bo->bo, true, false, false, NULL); 742 if (ret) 743 goto fail_unpin; 744 745 /* synchronise rendering channel with the kernel's channel */ 746 ret = nouveau_fence_sync(new_bo, chan, false, true); 747 if (ret) { 748 ttm_bo_unreserve(&new_bo->bo); 749 goto fail_unpin; 750 } 751 752 if (new_bo != old_bo) { 753 ttm_bo_unreserve(&new_bo->bo); 754 755 ret = ttm_bo_reserve(&old_bo->bo, true, false, false, NULL); 756 if (ret) 757 goto fail_unpin; 758 } 759 760 /* Initialize a page flip struct */ 761 *s = (struct nouveau_page_flip_state) 762 { { }, event, nouveau_crtc(crtc)->index, 763 fb->bits_per_pixel, fb->pitches[0], crtc->x, crtc->y, 764 new_bo->bo.offset }; 765 766 /* Keep vblanks on during flip, for the target crtc of this flip */ 767 drm_vblank_get(dev, nouveau_crtc(crtc)->index); 768 769 /* Emit a page flip */ 770 if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { 771 ret = nv50_display_flip_next(crtc, fb, chan, swap_interval); 772 if (ret) 773 goto fail_unreserve; 774 } else { 775 struct nv04_display *dispnv04 = nv04_display(dev); 776 int head = nouveau_crtc(crtc)->index; 777 778 if (swap_interval) { 779 ret = RING_SPACE(chan, 8); 780 if (ret) 781 goto fail_unreserve; 782 783 BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1); 784 OUT_RING (chan, 0); 785 BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1); 786 OUT_RING (chan, head); 787 BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1); 788 OUT_RING (chan, 0); 789 BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1); 790 OUT_RING (chan, 0); 791 } 792 793 nouveau_bo_ref(new_bo, &dispnv04->image[head]); 794 } 795 796 ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); 797 if (ret) 798 goto fail_unreserve; 799 mutex_unlock(&cli->mutex); 800 801 /* Update the crtc struct and cleanup */ 802 crtc->primary->fb = fb; 803 804 nouveau_bo_fence(old_bo, fence, false); 805 ttm_bo_unreserve(&old_bo->bo); 806 if (old_bo != new_bo) 807 nouveau_bo_unpin(old_bo); 808 nouveau_fence_unref(&fence); 809 return 0; 810 811fail_unreserve: 812 drm_vblank_put(dev, nouveau_crtc(crtc)->index); 813 ttm_bo_unreserve(&old_bo->bo); 814fail_unpin: 815 mutex_unlock(&cli->mutex); 816 if (old_bo != new_bo) 817 nouveau_bo_unpin(new_bo); 818fail_free: 819 kfree(s); 820 return ret; 821} 822 823int 824nouveau_finish_page_flip(struct nouveau_channel *chan, 825 struct nouveau_page_flip_state *ps) 826{ 827 struct nouveau_fence_chan *fctx = chan->fence; 828 struct nouveau_drm *drm = chan->drm; 829 struct drm_device *dev = drm->dev; 830 struct nouveau_page_flip_state *s; 831 unsigned long flags; 832 833 spin_lock_irqsave(&dev->event_lock, flags); 834 835 if (list_empty(&fctx->flip)) { 836 NV_ERROR(drm, "unexpected pageflip\n"); 837 spin_unlock_irqrestore(&dev->event_lock, flags); 838 return -EINVAL; 839 } 840 841 s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head); 842 if (s->event) { 843 if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) { 844 drm_arm_vblank_event(dev, s->crtc, s->event); 845 } else { 846 drm_send_vblank_event(dev, s->crtc, s->event); 847 848 /* Give up ownership of vblank for page-flipped crtc */ 849 drm_vblank_put(dev, s->crtc); 850 } 851 } 852 else { 853 /* Give up ownership of vblank for page-flipped crtc */ 854 drm_vblank_put(dev, s->crtc); 855 } 856 857 list_del(&s->head); 858 if (ps) 859 *ps = *s; 860 kfree(s); 861 862 spin_unlock_irqrestore(&dev->event_lock, flags); 863 return 0; 864} 865 866int 867nouveau_flip_complete(struct nvif_notify *notify) 868{ 869 struct nouveau_drm *drm = container_of(notify, typeof(*drm), flip); 870 struct nouveau_channel *chan = drm->channel; 871 struct nouveau_page_flip_state state; 872 873 if (!nouveau_finish_page_flip(chan, &state)) { 874 if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) { 875 nv_set_crtc_base(drm->dev, state.crtc, state.offset + 876 state.y * state.pitch + 877 state.x * state.bpp / 8); 878 } 879 } 880 881 return NVIF_NOTIFY_KEEP; 882} 883 884int 885nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, 886 struct drm_mode_create_dumb *args) 887{ 888 struct nouveau_bo *bo; 889 uint32_t domain; 890 int ret; 891 892 args->pitch = roundup(args->width * (args->bpp / 8), 256); 893 args->size = args->pitch * args->height; 894 args->size = roundup(args->size, PAGE_SIZE); 895 896 /* Use VRAM if there is any ; otherwise fallback to system memory */ 897 if (nouveau_drm(dev)->device.info.ram_size != 0) 898 domain = NOUVEAU_GEM_DOMAIN_VRAM; 899 else 900 domain = NOUVEAU_GEM_DOMAIN_GART; 901 902 ret = nouveau_gem_new(dev, args->size, 0, domain, 0, 0, &bo); 903 if (ret) 904 return ret; 905 906 ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle); 907 drm_gem_object_unreference_unlocked(&bo->gem); 908 return ret; 909} 910 911int 912nouveau_display_dumb_map_offset(struct drm_file *file_priv, 913 struct drm_device *dev, 914 uint32_t handle, uint64_t *poffset) 915{ 916 struct drm_gem_object *gem; 917 918 gem = drm_gem_object_lookup(dev, file_priv, handle); 919 if (gem) { 920 struct nouveau_bo *bo = nouveau_gem_object(gem); 921 *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node); 922 drm_gem_object_unreference_unlocked(gem); 923 return 0; 924 } 925 926 return -ENOENT; 927} 928