aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_object.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-06-23 19:48:08 -0400
committerDave Airlie <airlied@redhat.com>2009-07-29 01:42:18 -0400
commite024e11070a0a0dc7163ce1ec2da354a638bdbed (patch)
treeadd483e7428f91da6f3c26be702aa45e6d69b694 /drivers/gpu/drm/radeon/radeon_object.c
parentc836e862803b2aa2bd9a354e151316d2b42c44ec (diff)
drm/radeon/kms: add initial colortiling support.
This adds new set/get tiling interfaces where the pitch and macro/micro tiling enables can be set. Along with a flag to decide if this object should have a surface when mapped. The only thing we need to allocate with a mapped surface should be the frontbuffer. Note rotate scanout shouldn't require one, and back/depth shouldn't either, though mesa needs some fixes. It fixes the TTM interfaces along Thomas's suggestions, and I've tested the surface stealing code with two X servers and not seen any lockdep issues. I've stopped tiling the fbcon frontbuffer, as I don't see there being any advantage other than testing, I've left the testing commands in there, just flip the fb_tiled to true in radeon_fb.c Open: Can we integrate endian swapping in with this? Future features: texture tiling - need to relocate texture registers TXOFFSET* with tiling info. This also merges Michel's cleanup surfaces regs at init time patch even though it makes sense on its own, this patch really relies on it. Some PowerMac firmwares set up a tiling surface at the beginning of VRAM which messes us up otherwise. that patch is: Signed-off-by: Michel Dänzer <daenzer@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_object.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index bac0d06c52ac..d5b1fd562d88 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -44,6 +44,9 @@ struct radeon_object {
44 uint64_t gpu_addr; 44 uint64_t gpu_addr;
45 void *kptr; 45 void *kptr;
46 bool is_iomem; 46 bool is_iomem;
47 uint32_t tiling_flags;
48 uint32_t pitch;
49 int surface_reg;
47}; 50};
48 51
49int radeon_ttm_init(struct radeon_device *rdev); 52int radeon_ttm_init(struct radeon_device *rdev);
@@ -70,6 +73,7 @@ static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj)
70 73
71 robj = container_of(tobj, struct radeon_object, tobj); 74 robj = container_of(tobj, struct radeon_object, tobj);
72 list_del_init(&robj->list); 75 list_del_init(&robj->list);
76 radeon_object_clear_surface_reg(robj);
73 kfree(robj); 77 kfree(robj);
74} 78}
75 79
@@ -141,6 +145,7 @@ int radeon_object_create(struct radeon_device *rdev,
141 } 145 }
142 robj->rdev = rdev; 146 robj->rdev = rdev;
143 robj->gobj = gobj; 147 robj->gobj = gobj;
148 robj->surface_reg = -1;
144 INIT_LIST_HEAD(&robj->list); 149 INIT_LIST_HEAD(&robj->list);
145 150
146 flags = radeon_object_flags_from_domain(domain); 151 flags = radeon_object_flags_from_domain(domain);
@@ -435,6 +440,7 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
435 radeon_object_gpu_addr(robj); 440 radeon_object_gpu_addr(robj);
436 } 441 }
437 lobj->gpu_offset = robj->gpu_addr; 442 lobj->gpu_offset = robj->gpu_addr;
443 lobj->tiling_flags = robj->tiling_flags;
438 if (fence) { 444 if (fence) {
439 old_fence = (struct radeon_fence *)robj->tobj.sync_obj; 445 old_fence = (struct radeon_fence *)robj->tobj.sync_obj;
440 robj->tobj.sync_obj = radeon_fence_ref(fence); 446 robj->tobj.sync_obj = radeon_fence_ref(fence);
@@ -479,3 +485,127 @@ unsigned long radeon_object_size(struct radeon_object *robj)
479{ 485{
480 return robj->tobj.num_pages << PAGE_SHIFT; 486 return robj->tobj.num_pages << PAGE_SHIFT;
481} 487}
488
489int radeon_object_get_surface_reg(struct radeon_object *robj)
490{
491 struct radeon_device *rdev = robj->rdev;
492 struct radeon_surface_reg *reg;
493 struct radeon_object *old_object;
494 int steal;
495 int i;
496
497 if (!robj->tiling_flags)
498 return 0;
499
500 if (robj->surface_reg >= 0) {
501 reg = &rdev->surface_regs[robj->surface_reg];
502 i = robj->surface_reg;
503 goto out;
504 }
505
506 steal = -1;
507 for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
508
509 reg = &rdev->surface_regs[i];
510 if (!reg->robj)
511 break;
512
513 old_object = reg->robj;
514 if (old_object->pin_count == 0)
515 steal = i;
516 }
517
518 /* if we are all out */
519 if (i == RADEON_GEM_MAX_SURFACES) {
520 if (steal == -1)
521 return -ENOMEM;
522 /* find someone with a surface reg and nuke their BO */
523 reg = &rdev->surface_regs[steal];
524 old_object = reg->robj;
525 /* blow away the mapping */
526 DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object);
527 ttm_bo_unmap_virtual(&old_object->tobj);
528 old_object->surface_reg = -1;
529 i = steal;
530 }
531
532 robj->surface_reg = i;
533 reg->robj = robj;
534
535out:
536 radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch,
537 robj->tobj.mem.mm_node->start << PAGE_SHIFT,
538 robj->tobj.num_pages << PAGE_SHIFT);
539 return 0;
540}
541
542void radeon_object_clear_surface_reg(struct radeon_object *robj)
543{
544 struct radeon_device *rdev = robj->rdev;
545 struct radeon_surface_reg *reg;
546
547 if (robj->surface_reg == -1)
548 return;
549
550 reg = &rdev->surface_regs[robj->surface_reg];
551 radeon_clear_surface_reg(rdev, robj->surface_reg);
552
553 reg->robj = NULL;
554 robj->surface_reg = -1;
555}
556
557void radeon_object_set_tiling_flags(struct radeon_object *robj,
558 uint32_t tiling_flags, uint32_t pitch)
559{
560 robj->tiling_flags = tiling_flags;
561 robj->pitch = pitch;
562}
563
564void radeon_object_get_tiling_flags(struct radeon_object *robj,
565 uint32_t *tiling_flags,
566 uint32_t *pitch)
567{
568 if (tiling_flags)
569 *tiling_flags = robj->tiling_flags;
570 if (pitch)
571 *pitch = robj->pitch;
572}
573
574int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
575 bool force_drop)
576{
577 if (!(robj->tiling_flags & RADEON_TILING_SURFACE))
578 return 0;
579
580 if (force_drop) {
581 radeon_object_clear_surface_reg(robj);
582 return 0;
583 }
584
585 if (robj->tobj.mem.mem_type != TTM_PL_VRAM) {
586 if (!has_moved)
587 return 0;
588
589 if (robj->surface_reg >= 0)
590 radeon_object_clear_surface_reg(robj);
591 return 0;
592 }
593
594 if ((robj->surface_reg >= 0) && !has_moved)
595 return 0;
596
597 return radeon_object_get_surface_reg(robj);
598}
599
600void radeon_bo_move_notify(struct ttm_buffer_object *bo,
601 struct ttm_mem_reg *mem)
602{
603 struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
604 radeon_object_check_tiling(robj, 0, 1);
605}
606
607void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
608{
609 struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
610 radeon_object_check_tiling(robj, 0, 0);
611}