aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra/drm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tegra/drm.c')
-rw-r--r--drivers/gpu/drm/tegra/drm.c216
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
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
131int tegra_drm_submit(struct tegra_drm_context *context, 174int 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
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}
454#endif 624#endif
455 625
456static const struct drm_ioctl_desc tegra_drm_ioctls[] = { 626static 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