1/* 2 * Copyright (C) 2012 Avionic Design GmbH 3 * Copyright (C) 2012-2013 NVIDIA CORPORATION. All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10#include <linux/host1x.h> 11 12#include "drm.h" 13#include "gem.h" 14 15#define DRIVER_NAME "tegra" 16#define DRIVER_DESC "NVIDIA Tegra graphics" 17#define DRIVER_DATE "20120330" 18#define DRIVER_MAJOR 0 19#define DRIVER_MINOR 0 20#define DRIVER_PATCHLEVEL 0 21 22struct tegra_drm_file { 23 struct list_head contexts; 24}; 25 26static int tegra_drm_load(struct drm_device *drm, unsigned long flags) 27{ 28 struct host1x_device *device = to_host1x_device(drm->dev); 29 struct tegra_drm *tegra; 30 int err; 31 32 tegra = kzalloc(sizeof(*tegra), GFP_KERNEL); 33 if (!tegra) 34 return -ENOMEM; 35 36 mutex_init(&tegra->clients_lock); 37 INIT_LIST_HEAD(&tegra->clients); 38 drm->dev_private = tegra; 39 tegra->drm = drm; 40 41 drm_mode_config_init(drm); 42 43 err = tegra_drm_fb_prepare(drm); 44 if (err < 0) 45 return err; 46 47 drm_kms_helper_poll_init(drm); 48 49 err = host1x_device_init(device); 50 if (err < 0) 51 return err; 52 53 /* 54 * We don't use the drm_irq_install() helpers provided by the DRM 55 * core, so we need to set this manually in order to allow the 56 * DRM_IOCTL_WAIT_VBLANK to operate correctly. 57 */ 58 drm->irq_enabled = true; 59 60 err = drm_vblank_init(drm, drm->mode_config.num_crtc); 61 if (err < 0) 62 return err; 63 64 err = tegra_drm_fb_init(drm); 65 if (err < 0) 66 return err; 67 68 return 0; 69} 70 71static int tegra_drm_unload(struct drm_device *drm) 72{ 73 struct host1x_device *device = to_host1x_device(drm->dev); 74 int err; 75 76 drm_kms_helper_poll_fini(drm); 77 tegra_drm_fb_exit(drm); 78 drm_vblank_cleanup(drm); 79 drm_mode_config_cleanup(drm); 80 81 err = host1x_device_exit(device); 82 if (err < 0) 83 return err; 84 85 return 0; 86} 87 88static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp) 89{ 90 struct tegra_drm_file *fpriv; 91 92 fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); 93 if (!fpriv) 94 return -ENOMEM; 95 96 INIT_LIST_HEAD(&fpriv->contexts); 97 filp->driver_priv = fpriv; 98 99 return 0; 100} 101 102static void tegra_drm_context_free(struct tegra_drm_context *context) 103{ 104 context->client->ops->close_channel(context); 105 kfree(context); 106} 107 108static void tegra_drm_lastclose(struct drm_device *drm) 109{ 110#ifdef CONFIG_DRM_TEGRA_FBDEV 111 struct tegra_drm *tegra = drm->dev_private; 112 113 tegra_fbdev_restore_mode(tegra->fbdev); 114#endif 115} 116 117static struct host1x_bo * 118host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle) 119{ 120 struct drm_gem_object *gem; 121 struct tegra_bo *bo; 122 123 gem = drm_gem_object_lookup(drm, file, handle); 124 if (!gem) 125 return NULL; 126 127 mutex_lock(&drm->struct_mutex); 128 drm_gem_object_unreference(gem); 129 mutex_unlock(&drm->struct_mutex); 130 131 bo = to_tegra_bo(gem); 132 return &bo->base; 133} 134 135static int host1x_reloc_copy_from_user(struct host1x_reloc *dest, 136 struct drm_tegra_reloc __user *src, 137 struct drm_device *drm, 138 struct drm_file *file) 139{ 140 u32 cmdbuf, target; 141 int err; 142 143 err = get_user(cmdbuf, &src->cmdbuf.handle); 144 if (err < 0) 145 return err; 146 147 err = get_user(dest->cmdbuf.offset, &src->cmdbuf.offset); 148 if (err < 0) 149 return err; 150 151 err = get_user(target, &src->target.handle); 152 if (err < 0) 153 return err; 154 155 err = get_user(dest->target.offset, &src->cmdbuf.offset); 156 if (err < 0) 157 return err; 158 159 err = get_user(dest->shift, &src->shift); 160 if (err < 0) 161 return err; 162 163 dest->cmdbuf.bo = host1x_bo_lookup(drm, file, cmdbuf); 164 if (!dest->cmdbuf.bo) 165 return -ENOENT; 166 167 dest->target.bo = host1x_bo_lookup(drm, file, target); 168 if (!dest->target.bo) 169 return -ENOENT; 170 171 return 0; 172} 173 174int tegra_drm_submit(struct tegra_drm_context *context, 175 struct drm_tegra_submit *args, struct drm_device *drm, 176 struct drm_file *file) 177{ 178 unsigned int num_cmdbufs = args->num_cmdbufs; 179 unsigned int num_relocs = args->num_relocs; 180 unsigned int num_waitchks = args->num_waitchks; 181 struct drm_tegra_cmdbuf __user *cmdbufs = 182 (void __user *)(uintptr_t)args->cmdbufs; 183 struct drm_tegra_reloc __user *relocs = 184 (void __user *)(uintptr_t)args->relocs; 185 struct drm_tegra_waitchk __user *waitchks = 186 (void __user *)(uintptr_t)args->waitchks; 187 struct drm_tegra_syncpt syncpt; 188 struct host1x_job *job; 189 int err; 190 191 /* We don't yet support other than one syncpt_incr struct per submit */ 192 if (args->num_syncpts != 1) 193 return -EINVAL; 194 195 job = host1x_job_alloc(context->channel, args->num_cmdbufs, 196 args->num_relocs, args->num_waitchks); 197 if (!job) 198 return -ENOMEM; 199 200 job->num_relocs = args->num_relocs; 201 job->num_waitchk = args->num_waitchks; 202 job->client = (u32)args->context; 203 job->class = context->client->base.class; 204 job->serialize = true; 205 206 while (num_cmdbufs) { 207 struct drm_tegra_cmdbuf cmdbuf; 208 struct host1x_bo *bo; 209 210 if (copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf))) { 211 err = -EFAULT; 212 goto fail; 213 } 214 215 bo = host1x_bo_lookup(drm, file, cmdbuf.handle); 216 if (!bo) { 217 err = -ENOENT; 218 goto fail; 219 } 220 221 host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset); 222 num_cmdbufs--; 223 cmdbufs++; 224 } 225 226 /* copy and resolve relocations from submit */ 227 while (num_relocs--) { 228 err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs], 229 &relocs[num_relocs], drm, 230 file); 231 if (err < 0) 232 goto fail; 233 } 234 235 if (copy_from_user(job->waitchk, waitchks, 236 sizeof(*waitchks) * num_waitchks)) { 237 err = -EFAULT; 238 goto fail; 239 } 240 241 if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts, 242 sizeof(syncpt))) { 243 err = -EFAULT; 244 goto fail; 245 } 246 247 job->is_addr_reg = context->client->ops->is_addr_reg; 248 job->syncpt_incrs = syncpt.incrs; 249 job->syncpt_id = syncpt.id; 250 job->timeout = 10000; 251 252 if (args->timeout && args->timeout < 10000) 253 job->timeout = args->timeout; 254 255 err = host1x_job_pin(job, context->client->base.dev); 256 if (err) 257 goto fail; 258 259 err = host1x_job_submit(job); 260 if (err) 261 goto fail_submit; 262 263 args->fence = job->syncpt_end; 264 265 host1x_job_put(job); 266 return 0; 267 268fail_submit: 269 host1x_job_unpin(job); 270fail: 271 host1x_job_put(job); 272 return err; 273} 274 275 276#ifdef CONFIG_DRM_TEGRA_STAGING 277static struct tegra_drm_context *tegra_drm_get_context(__u64 context) 278{ 279 return (struct tegra_drm_context *)(uintptr_t)context; 280} 281 282static bool tegra_drm_file_owns_context(struct tegra_drm_file *file, 283 struct tegra_drm_context *context) 284{ 285 struct tegra_drm_context *ctx; 286 287 list_for_each_entry(ctx, &file->contexts, list) 288 if (ctx == context) 289 return true; 290 291 return false; 292} 293 294static int tegra_gem_create(struct drm_device *drm, void *data, 295 struct drm_file *file) 296{ 297 struct drm_tegra_gem_create *args = data; 298 struct tegra_bo *bo; 299 300 bo = tegra_bo_create_with_handle(file, drm, args->size, args->flags, 301 &args->handle); 302 if (IS_ERR(bo)) 303 return PTR_ERR(bo); 304 305 return 0; 306} 307 308static int tegra_gem_mmap(struct drm_device *drm, void *data, 309 struct drm_file *file) 310{ 311 struct drm_tegra_gem_mmap *args = data; 312 struct drm_gem_object *gem; 313 struct tegra_bo *bo; 314 315 gem = drm_gem_object_lookup(drm, file, args->handle); 316 if (!gem) 317 return -EINVAL; 318 319 bo = to_tegra_bo(gem); 320 321 args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node); 322 323 drm_gem_object_unreference(gem); 324 325 return 0; 326} 327 328static int tegra_syncpt_read(struct drm_device *drm, void *data, 329 struct drm_file *file) 330{ 331 struct host1x *host = dev_get_drvdata(drm->dev->parent); 332 struct drm_tegra_syncpt_read *args = data; 333 struct host1x_syncpt *sp; 334 335 sp = host1x_syncpt_get(host, args->id); 336 if (!sp) 337 return -EINVAL; 338 339 args->value = host1x_syncpt_read_min(sp); 340 return 0; 341} 342 343static int tegra_syncpt_incr(struct drm_device *drm, void *data, 344 struct drm_file *file) 345{ 346 struct host1x *host1x = dev_get_drvdata(drm->dev->parent); 347 struct drm_tegra_syncpt_incr *args = data; 348 struct host1x_syncpt *sp; 349 350 sp = host1x_syncpt_get(host1x, args->id); 351 if (!sp) 352 return -EINVAL; 353 354 return host1x_syncpt_incr(sp); 355} 356 357static int tegra_syncpt_wait(struct drm_device *drm, void *data, 358 struct drm_file *file) 359{ 360 struct host1x *host1x = dev_get_drvdata(drm->dev->parent); 361 struct drm_tegra_syncpt_wait *args = data; 362 struct host1x_syncpt *sp; 363 364 sp = host1x_syncpt_get(host1x, args->id); 365 if (!sp) 366 return -EINVAL; 367 368 return host1x_syncpt_wait(sp, args->thresh, args->timeout, 369 &args->value); 370} 371 372static int tegra_open_channel(struct drm_device *drm, void *data, 373 struct drm_file *file) 374{ 375 struct tegra_drm_file *fpriv = file->driver_priv; 376 struct tegra_drm *tegra = drm->dev_private; 377 struct drm_tegra_open_channel *args = data; 378 struct tegra_drm_context *context; 379 struct tegra_drm_client *client; 380 int err = -ENODEV; 381 382 context = kzalloc(sizeof(*context), GFP_KERNEL); 383 if (!context) 384 return -ENOMEM; 385 386 list_for_each_entry(client, &tegra->clients, list) 387 if (client->base.class == args->client) { 388 err = client->ops->open_channel(client, context); 389 if (err) 390 break; 391 392 list_add(&context->list, &fpriv->contexts); 393 args->context = (uintptr_t)context; 394 context->client = client; 395 return 0; 396 } 397 398 kfree(context); 399 return err; 400} 401 402static int tegra_close_channel(struct drm_device *drm, void *data, 403 struct drm_file *file) 404{ 405 struct tegra_drm_file *fpriv = file->driver_priv; 406 struct drm_tegra_close_channel *args = data; 407 struct tegra_drm_context *context; 408 409 context = tegra_drm_get_context(args->context); 410 411 if (!tegra_drm_file_owns_context(fpriv, context)) 412 return -EINVAL; 413 414 list_del(&context->list); 415 tegra_drm_context_free(context); 416 417 return 0; 418} 419 420static int tegra_get_syncpt(struct drm_device *drm, void *data, 421 struct drm_file *file) 422{ 423 struct tegra_drm_file *fpriv = file->driver_priv; 424 struct drm_tegra_get_syncpt *args = data; 425 struct tegra_drm_context *context; 426 struct host1x_syncpt *syncpt; 427 428 context = tegra_drm_get_context(args->context); 429 430 if (!tegra_drm_file_owns_context(fpriv, context)) 431 return -ENODEV; 432 433 if (args->index >= context->client->base.num_syncpts) 434 return -EINVAL; 435 436 syncpt = context->client->base.syncpts[args->index]; 437 args->id = host1x_syncpt_id(syncpt); 438 439 return 0; 440} 441 442static int tegra_submit(struct drm_device *drm, void *data, 443 struct drm_file *file) 444{ 445 struct tegra_drm_file *fpriv = file->driver_priv; 446 struct drm_tegra_submit *args = data; 447 struct tegra_drm_context *context; 448 449 context = tegra_drm_get_context(args->context); 450 451 if (!tegra_drm_file_owns_context(fpriv, context)) 452 return -ENODEV; 453 454 return context->client->ops->submit(context, args, drm, file); 455} 456 457static int tegra_get_syncpt_base(struct drm_device *drm, void *data, 458 struct drm_file *file) 459{ 460 struct tegra_drm_file *fpriv = file->driver_priv; 461 struct drm_tegra_get_syncpt_base *args = data; 462 struct tegra_drm_context *context; 463 struct host1x_syncpt_base *base; 464 struct host1x_syncpt *syncpt; 465 466 context = tegra_drm_get_context(args->context); 467 468 if (!tegra_drm_file_owns_context(fpriv, context)) 469 return -ENODEV; 470 471 if (args->syncpt >= context->client->base.num_syncpts) 472 return -EINVAL; 473 474 syncpt = context->client->base.syncpts[args->syncpt]; 475 476 base = host1x_syncpt_get_base(syncpt); 477 if (!base) 478 return -ENXIO; 479 480 args->id = host1x_syncpt_base_id(base); 481 482 return 0; 483} 484 485static int tegra_gem_set_tiling(struct drm_device *drm, void *data, 486 struct drm_file *file) 487{ 488 struct drm_tegra_gem_set_tiling *args = data; 489 enum tegra_bo_tiling_mode mode; 490 struct drm_gem_object *gem; 491 unsigned long value = 0; 492 struct tegra_bo *bo; 493 494 switch (args->mode) { 495 case DRM_TEGRA_GEM_TILING_MODE_PITCH: 496 mode = TEGRA_BO_TILING_MODE_PITCH; 497 498 if (args->value != 0) 499 return -EINVAL; 500 501 break; 502 503 case DRM_TEGRA_GEM_TILING_MODE_TILED: 504 mode = TEGRA_BO_TILING_MODE_TILED; 505 506 if (args->value != 0) 507 return -EINVAL; 508 509 break; 510 511 case DRM_TEGRA_GEM_TILING_MODE_BLOCK: 512 mode = TEGRA_BO_TILING_MODE_BLOCK; 513 514 if (args->value > 5) 515 return -EINVAL; 516 517 value = args->value; 518 break; 519 520 default: 521 return -EINVAL; 522 } 523 524 gem = drm_gem_object_lookup(drm, file, args->handle); 525 if (!gem) 526 return -ENOENT; 527 528 bo = to_tegra_bo(gem); 529 530 bo->tiling.mode = mode; 531 bo->tiling.value = value; 532 533 drm_gem_object_unreference(gem); 534 535 return 0; 536} 537 538static int tegra_gem_get_tiling(struct drm_device *drm, void *data, 539 struct drm_file *file) 540{ 541 struct drm_tegra_gem_get_tiling *args = data; 542 struct drm_gem_object *gem; 543 struct tegra_bo *bo; 544 int err = 0; 545 546 gem = drm_gem_object_lookup(drm, file, args->handle); 547 if (!gem) 548 return -ENOENT; 549 550 bo = to_tegra_bo(gem); 551 552 switch (bo->tiling.mode) { 553 case TEGRA_BO_TILING_MODE_PITCH: 554 args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH; 555 args->value = 0; 556 break; 557 558 case TEGRA_BO_TILING_MODE_TILED: 559 args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED; 560 args->value = 0; 561 break; 562 563 case TEGRA_BO_TILING_MODE_BLOCK: 564 args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK; 565 args->value = bo->tiling.value; 566 break; 567 568 default: 569 err = -EINVAL; 570 break; 571 } 572 573 drm_gem_object_unreference(gem); 574 575 return err; 576} 577 578static int tegra_gem_set_flags(struct drm_device *drm, void *data, 579 struct drm_file *file) 580{ 581 struct drm_tegra_gem_set_flags *args = data; 582 struct drm_gem_object *gem; 583 struct tegra_bo *bo; 584 585 if (args->flags & ~DRM_TEGRA_GEM_FLAGS) 586 return -EINVAL; 587 588 gem = drm_gem_object_lookup(drm, file, args->handle); 589 if (!gem) 590 return -ENOENT; 591 592 bo = to_tegra_bo(gem); 593 bo->flags = 0; 594 595 if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP) 596 bo->flags |= TEGRA_BO_BOTTOM_UP; 597 598 drm_gem_object_unreference(gem); 599 600 return 0; 601} 602 603static int tegra_gem_get_flags(struct drm_device *drm, void *data, 604 struct drm_file *file) 605{ 606 struct drm_tegra_gem_get_flags *args = data; 607 struct drm_gem_object *gem; 608 struct tegra_bo *bo; 609 610 gem = drm_gem_object_lookup(drm, file, args->handle); 611 if (!gem) 612 return -ENOENT; 613 614 bo = to_tegra_bo(gem); 615 args->flags = 0; 616 617 if (bo->flags & TEGRA_BO_BOTTOM_UP) 618 args->flags |= DRM_TEGRA_GEM_BOTTOM_UP; 619 620 drm_gem_object_unreference(gem); 621 622 return 0; 623} 624#endif 625 626static const struct drm_ioctl_desc tegra_drm_ioctls[] = { 627#ifdef CONFIG_DRM_TEGRA_STAGING 628 DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED), 629 DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED), 630 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED), 631 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED), 632 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, DRM_UNLOCKED), 633 DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, DRM_UNLOCKED), 634 DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, DRM_UNLOCKED), 635 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED), 636 DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), 637 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED), 638 DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED), 639 DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED), 640 DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, DRM_UNLOCKED), 641 DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, DRM_UNLOCKED), 642#endif 643}; 644 645static const struct file_operations tegra_drm_fops = { 646 .owner = THIS_MODULE, 647 .open = drm_open, 648 .release = drm_release, 649 .unlocked_ioctl = drm_ioctl, 650 .mmap = tegra_drm_mmap, 651 .poll = drm_poll, 652 .read = drm_read, 653#ifdef CONFIG_COMPAT 654 .compat_ioctl = drm_compat_ioctl, 655#endif 656 .llseek = noop_llseek, 657}; 658 659static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe) 660{ 661 struct drm_crtc *crtc; 662 663 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { 664 struct tegra_dc *dc = to_tegra_dc(crtc); 665 666 if (dc->pipe == pipe) 667 return crtc; 668 } 669 670 return NULL; 671} 672 673static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc) 674{ 675 /* TODO: implement real hardware counter using syncpoints */ 676 return drm_vblank_count(dev, crtc); 677} 678 679static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) 680{ 681 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); 682 struct tegra_dc *dc = to_tegra_dc(crtc); 683 684 if (!crtc) 685 return -ENODEV; 686 687 tegra_dc_enable_vblank(dc); 688 689 return 0; 690} 691 692static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe) 693{ 694 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); 695 struct tegra_dc *dc = to_tegra_dc(crtc); 696 697 if (crtc) 698 tegra_dc_disable_vblank(dc); 699} 700 701static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file) 702{ 703 struct tegra_drm_file *fpriv = file->driver_priv; 704 struct tegra_drm_context *context, *tmp; 705 struct drm_crtc *crtc; 706 707 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) 708 tegra_dc_cancel_page_flip(crtc, file); 709 710 list_for_each_entry_safe(context, tmp, &fpriv->contexts, list) 711 tegra_drm_context_free(context); 712 713 kfree(fpriv); 714} 715 716#ifdef CONFIG_DEBUG_FS 717static int tegra_debugfs_framebuffers(struct seq_file *s, void *data) 718{ 719 struct drm_info_node *node = (struct drm_info_node *)s->private; 720 struct drm_device *drm = node->minor->dev; 721 struct drm_framebuffer *fb; 722 723 mutex_lock(&drm->mode_config.fb_lock); 724 725 list_for_each_entry(fb, &drm->mode_config.fb_list, head) { 726 seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n", 727 fb->base.id, fb->width, fb->height, fb->depth, 728 fb->bits_per_pixel, 729 atomic_read(&fb->refcount.refcount)); 730 } 731 732 mutex_unlock(&drm->mode_config.fb_lock); 733 734 return 0; 735} 736 737static struct drm_info_list tegra_debugfs_list[] = { 738 { "framebuffers", tegra_debugfs_framebuffers, 0 }, 739}; 740 741static int tegra_debugfs_init(struct drm_minor *minor) 742{ 743 return drm_debugfs_create_files(tegra_debugfs_list, 744 ARRAY_SIZE(tegra_debugfs_list), 745 minor->debugfs_root, minor); 746} 747 748static void tegra_debugfs_cleanup(struct drm_minor *minor) 749{ 750 drm_debugfs_remove_files(tegra_debugfs_list, 751 ARRAY_SIZE(tegra_debugfs_list), minor); 752} 753#endif 754 755static struct drm_driver tegra_drm_driver = { 756 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, 757 .load = tegra_drm_load, 758 .unload = tegra_drm_unload, 759 .open = tegra_drm_open, 760 .preclose = tegra_drm_preclose, 761 .lastclose = tegra_drm_lastclose, 762 763 .get_vblank_counter = tegra_drm_get_vblank_counter, 764 .enable_vblank = tegra_drm_enable_vblank, 765 .disable_vblank = tegra_drm_disable_vblank, 766 767#if defined(CONFIG_DEBUG_FS) 768 .debugfs_init = tegra_debugfs_init, 769 .debugfs_cleanup = tegra_debugfs_cleanup, 770#endif 771 772 .gem_free_object = tegra_bo_free_object, 773 .gem_vm_ops = &tegra_bo_vm_ops, 774 775 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 776 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 777 .gem_prime_export = tegra_gem_prime_export, 778 .gem_prime_import = tegra_gem_prime_import, 779 780 .dumb_create = tegra_bo_dumb_create, 781 .dumb_map_offset = tegra_bo_dumb_map_offset, 782 .dumb_destroy = drm_gem_dumb_destroy, 783 784 .ioctls = tegra_drm_ioctls, 785 .num_ioctls = ARRAY_SIZE(tegra_drm_ioctls), 786 .fops = &tegra_drm_fops, 787 788 .name = DRIVER_NAME, 789 .desc = DRIVER_DESC, 790 .date = DRIVER_DATE, 791 .major = DRIVER_MAJOR, 792 .minor = DRIVER_MINOR, 793 .patchlevel = DRIVER_PATCHLEVEL, 794}; 795 796int tegra_drm_register_client(struct tegra_drm *tegra, 797 struct tegra_drm_client *client) 798{ 799 mutex_lock(&tegra->clients_lock); 800 list_add_tail(&client->list, &tegra->clients); 801 mutex_unlock(&tegra->clients_lock); 802 803 return 0; 804} 805 806int tegra_drm_unregister_client(struct tegra_drm *tegra, 807 struct tegra_drm_client *client) 808{ 809 mutex_lock(&tegra->clients_lock); 810 list_del_init(&client->list); 811 mutex_unlock(&tegra->clients_lock); 812 813 return 0; 814} 815 816static int host1x_drm_probe(struct host1x_device *dev) 817{ 818 struct drm_driver *driver = &tegra_drm_driver; 819 struct drm_device *drm; 820 int err; 821 822 drm = drm_dev_alloc(driver, &dev->dev); 823 if (!drm) 824 return -ENOMEM; 825 826 drm_dev_set_unique(drm, dev_name(&dev->dev)); 827 dev_set_drvdata(&dev->dev, drm); 828 829 err = drm_dev_register(drm, 0); 830 if (err < 0) 831 goto unref; 832 833 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, 834 driver->major, driver->minor, driver->patchlevel, 835 driver->date, drm->primary->index); 836 837 return 0; 838 839unref: 840 drm_dev_unref(drm); 841 return err; 842} 843 844static int host1x_drm_remove(struct host1x_device *dev) 845{ 846 struct drm_device *drm = dev_get_drvdata(&dev->dev); 847 848 drm_dev_unregister(drm); 849 drm_dev_unref(drm); 850 851 return 0; 852} 853 854static const struct of_device_id host1x_drm_subdevs[] = { 855 { .compatible = "nvidia,tegra20-dc", }, 856 { .compatible = "nvidia,tegra20-hdmi", }, 857 { .compatible = "nvidia,tegra20-gr2d", }, 858 { .compatible = "nvidia,tegra20-gr3d", }, 859 { .compatible = "nvidia,tegra30-dc", }, 860 { .compatible = "nvidia,tegra30-hdmi", }, 861 { .compatible = "nvidia,tegra30-gr2d", }, 862 { .compatible = "nvidia,tegra30-gr3d", }, 863 { .compatible = "nvidia,tegra114-dsi", }, 864 { .compatible = "nvidia,tegra114-hdmi", }, 865 { .compatible = "nvidia,tegra114-gr3d", }, 866 { .compatible = "nvidia,tegra124-dc", }, 867 { .compatible = "nvidia,tegra124-sor", }, 868 { .compatible = "nvidia,tegra124-hdmi", }, 869 { /* sentinel */ } 870}; 871 872static struct host1x_driver host1x_drm_driver = { 873 .name = "drm", 874 .probe = host1x_drm_probe, 875 .remove = host1x_drm_remove, 876 .subdevs = host1x_drm_subdevs, 877}; 878 879static int __init host1x_drm_init(void) 880{ 881 int err; 882 883 err = host1x_driver_register(&host1x_drm_driver); 884 if (err < 0) 885 return err; 886 887 err = platform_driver_register(&tegra_dc_driver); 888 if (err < 0) 889 goto unregister_host1x; 890 891 err = platform_driver_register(&tegra_dsi_driver); 892 if (err < 0) 893 goto unregister_dc; 894 895 err = platform_driver_register(&tegra_sor_driver); 896 if (err < 0) 897 goto unregister_dsi; 898 899 err = platform_driver_register(&tegra_hdmi_driver); 900 if (err < 0) 901 goto unregister_sor; 902 903 err = platform_driver_register(&tegra_dpaux_driver); 904 if (err < 0) 905 goto unregister_hdmi; 906 907 err = platform_driver_register(&tegra_gr2d_driver); 908 if (err < 0) 909 goto unregister_dpaux; 910 911 err = platform_driver_register(&tegra_gr3d_driver); 912 if (err < 0) 913 goto unregister_gr2d; 914 915 return 0; 916 917unregister_gr2d: 918 platform_driver_unregister(&tegra_gr2d_driver); 919unregister_dpaux: 920 platform_driver_unregister(&tegra_dpaux_driver); 921unregister_hdmi: 922 platform_driver_unregister(&tegra_hdmi_driver); 923unregister_sor: 924 platform_driver_unregister(&tegra_sor_driver); 925unregister_dsi: 926 platform_driver_unregister(&tegra_dsi_driver); 927unregister_dc: 928 platform_driver_unregister(&tegra_dc_driver); 929unregister_host1x: 930 host1x_driver_unregister(&host1x_drm_driver); 931 return err; 932} 933module_init(host1x_drm_init); 934 935static void __exit host1x_drm_exit(void) 936{ 937 platform_driver_unregister(&tegra_gr3d_driver); 938 platform_driver_unregister(&tegra_gr2d_driver); 939 platform_driver_unregister(&tegra_dpaux_driver); 940 platform_driver_unregister(&tegra_hdmi_driver); 941 platform_driver_unregister(&tegra_sor_driver); 942 platform_driver_unregister(&tegra_dsi_driver); 943 platform_driver_unregister(&tegra_dc_driver); 944 host1x_driver_unregister(&host1x_drm_driver); 945} 946module_exit(host1x_drm_exit); 947 948MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); 949MODULE_DESCRIPTION("NVIDIA Tegra DRM driver"); 950MODULE_LICENSE("GPL v2"); 951