diff options
Diffstat (limited to 'drivers/gpu/drm/tegra/drm.c')
| -rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 216 |
1 files changed, 195 insertions, 21 deletions
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 3396f9f6a9f7..59736bb810cd 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
| @@ -40,6 +40,12 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) | |||
| 40 | 40 | ||
| 41 | drm_mode_config_init(drm); | 41 | drm_mode_config_init(drm); |
| 42 | 42 | ||
| 43 | err = tegra_drm_fb_prepare(drm); | ||
| 44 | if (err < 0) | ||
| 45 | return err; | ||
| 46 | |||
| 47 | drm_kms_helper_poll_init(drm); | ||
| 48 | |||
| 43 | err = host1x_device_init(device); | 49 | err = host1x_device_init(device); |
| 44 | if (err < 0) | 50 | if (err < 0) |
| 45 | return err; | 51 | return err; |
| @@ -59,8 +65,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) | |||
| 59 | if (err < 0) | 65 | if (err < 0) |
| 60 | return err; | 66 | return err; |
| 61 | 67 | ||
| 62 | drm_kms_helper_poll_init(drm); | ||
| 63 | |||
| 64 | return 0; | 68 | return 0; |
| 65 | } | 69 | } |
| 66 | 70 | ||
| @@ -128,6 +132,45 @@ host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle) | |||
| 128 | return &bo->base; | 132 | return &bo->base; |
| 129 | } | 133 | } |
| 130 | 134 | ||
| 135 | static 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 | |||
| 131 | int tegra_drm_submit(struct tegra_drm_context *context, | 174 | int tegra_drm_submit(struct tegra_drm_context *context, |
| 132 | struct drm_tegra_submit *args, struct drm_device *drm, | 175 | struct drm_tegra_submit *args, struct drm_device *drm, |
| 133 | struct drm_file *file) | 176 | struct drm_file *file) |
| @@ -180,26 +223,13 @@ int tegra_drm_submit(struct tegra_drm_context *context, | |||
| 180 | cmdbufs++; | 223 | cmdbufs++; |
| 181 | } | 224 | } |
| 182 | 225 | ||
| 183 | if (copy_from_user(job->relocarray, relocs, | 226 | /* copy and resolve relocations from submit */ |
| 184 | sizeof(*relocs) * num_relocs)) { | ||
| 185 | err = -EFAULT; | ||
| 186 | goto fail; | ||
| 187 | } | ||
| 188 | |||
| 189 | while (num_relocs--) { | 227 | while (num_relocs--) { |
| 190 | struct host1x_reloc *reloc = &job->relocarray[num_relocs]; | 228 | err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs], |
| 191 | struct host1x_bo *cmdbuf, *target; | 229 | &relocs[num_relocs], drm, |
| 192 | 230 | file); | |
| 193 | cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf); | 231 | if (err < 0) |
| 194 | target = host1x_bo_lookup(drm, file, (u32)reloc->target); | ||
| 195 | |||
| 196 | reloc->cmdbuf = cmdbuf; | ||
| 197 | reloc->target = target; | ||
| 198 | |||
| 199 | if (!reloc->target || !reloc->cmdbuf) { | ||
| 200 | err = -ENOENT; | ||
| 201 | goto fail; | 232 | goto fail; |
| 202 | } | ||
| 203 | } | 233 | } |
| 204 | 234 | ||
| 205 | if (copy_from_user(job->waitchk, waitchks, | 235 | if (copy_from_user(job->waitchk, waitchks, |
| @@ -451,11 +481,151 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data, | |||
| 451 | 481 | ||
| 452 | return 0; | 482 | return 0; |
| 453 | } | 483 | } |
| 484 | |||
| 485 | static 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 | |||
| 538 | static 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 | |||
| 578 | static 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 | |||
| 603 | static 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 | } | ||
| 454 | #endif | 624 | #endif |
| 455 | 625 | ||
| 456 | static const struct drm_ioctl_desc tegra_drm_ioctls[] = { | 626 | static const struct drm_ioctl_desc tegra_drm_ioctls[] = { |
| 457 | #ifdef CONFIG_DRM_TEGRA_STAGING | 627 | #ifdef CONFIG_DRM_TEGRA_STAGING |
| 458 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH), | 628 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED), |
| 459 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED), | 629 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED), |
| 460 | DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED), | 630 | DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED), |
| 461 | DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED), | 631 | DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED), |
| @@ -465,6 +635,10 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = { | |||
| 465 | DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED), | 635 | DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED), |
| 466 | DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), | 636 | DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), |
| 467 | DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, 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), | ||
| 468 | #endif | 642 | #endif |
| 469 | }; | 643 | }; |
| 470 | 644 | ||
