diff options
author | Tvrtko Ursulin <tvrtko.ursulin@intel.com> | 2015-03-23 07:10:36 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-03-23 10:06:31 -0400 |
commit | 50470bb011c4be278097670bea92462f4e8c8945 (patch) | |
tree | b1c92440ac31320feccbadeb2a2ea573a141e644 /drivers/gpu/drm/i915/i915_gem_gtt.c | |
parent | f64b98cd2e40052c17f67f09a081ff292bac0f77 (diff) |
drm/i915/skl: Support secondary (rotated) frame buffer mapping
90/270 rotated scanout needs a rotated GTT view of the framebuffer.
This is put in a separate VMA with a dedicated ggtt view and wired such that
it is created when a framebuffer is pinned to a 90/270 rotated plane.
Rotation is only possible with Yb/Yf buffers and error is propagated to
user space in case of a mismatch.
Special rotated page view is constructed at the VMA creation time by
borrowing the DMA addresses from obj->pages.
v2:
* Do not bother with pages for rotated sg list, just populate the DMA
addresses. (Daniel Vetter)
* Checkpatch cleanup.
v3:
* Rebased on top of new plane handling (create rotated mapping when
setting the rotation property).
* Unpin rotated VMA on unpinning from display plane.
* Simplify rotation check using bitwise AND. (Chris Wilson)
v4:
* Fix unpinning of optional rotated mapping so it is really considered
to be optional.
v5:
* Rebased for fb modifier changes.
* Rebased for atomic commit.
* Only pin needed view for display. (Ville Syrjälä, Daniel Vetter)
v6:
* Rebased after preparatory work has been extracted out. (Daniel Vetter)
v7:
* Slightly simplified tiling geometry calculation.
* Moved rotated GGTT view implementation into i915_gem_gtt.c (Daniel Vetter)
v8:
* Do not use i915_gem_obj_size to get object size since that actually
returns the size of an VMA which may not exist.
* Rebased for ggtt view changes.
v9:
* Rebased after code review changes on the preceding patches.
* Tidy function definitions. (Joonas Lahtinen)
For: VIZ-4726
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Michel Thierry <michel.thierry@intel.com> (v4)
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_gtt.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 117 |
1 files changed, 113 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 645c3636c571..fc56c112a7de 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -2500,15 +2500,119 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj, | |||
2500 | 2500 | ||
2501 | } | 2501 | } |
2502 | 2502 | ||
2503 | static void | ||
2504 | rotate_pages(dma_addr_t *in, unsigned int width, unsigned int height, | ||
2505 | struct sg_table *st) | ||
2506 | { | ||
2507 | unsigned int column, row; | ||
2508 | unsigned int src_idx; | ||
2509 | struct scatterlist *sg = st->sgl; | ||
2510 | |||
2511 | st->nents = 0; | ||
2512 | |||
2513 | for (column = 0; column < width; column++) { | ||
2514 | src_idx = width * (height - 1) + column; | ||
2515 | for (row = 0; row < height; row++) { | ||
2516 | st->nents++; | ||
2517 | /* We don't need the pages, but need to initialize | ||
2518 | * the entries so the sg list can be happily traversed. | ||
2519 | * The only thing we need are DMA addresses. | ||
2520 | */ | ||
2521 | sg_set_page(sg, NULL, PAGE_SIZE, 0); | ||
2522 | sg_dma_address(sg) = in[src_idx]; | ||
2523 | sg_dma_len(sg) = PAGE_SIZE; | ||
2524 | sg = sg_next(sg); | ||
2525 | src_idx -= width; | ||
2526 | } | ||
2527 | } | ||
2528 | } | ||
2529 | |||
2530 | static struct sg_table * | ||
2531 | intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, | ||
2532 | struct drm_i915_gem_object *obj) | ||
2533 | { | ||
2534 | struct drm_device *dev = obj->base.dev; | ||
2535 | struct intel_rotation_info *rot_info = &ggtt_view->rotation_info; | ||
2536 | unsigned long size, pages, rot_pages; | ||
2537 | struct sg_page_iter sg_iter; | ||
2538 | unsigned long i; | ||
2539 | dma_addr_t *page_addr_list; | ||
2540 | struct sg_table *st; | ||
2541 | unsigned int tile_pitch, tile_height; | ||
2542 | unsigned int width_pages, height_pages; | ||
2543 | int ret = ENOMEM; | ||
2544 | |||
2545 | pages = obj->base.size / PAGE_SIZE; | ||
2546 | |||
2547 | /* Calculate tiling geometry. */ | ||
2548 | tile_height = intel_tile_height(dev, rot_info->pixel_format, | ||
2549 | rot_info->fb_modifier); | ||
2550 | tile_pitch = PAGE_SIZE / tile_height; | ||
2551 | width_pages = DIV_ROUND_UP(rot_info->pitch, tile_pitch); | ||
2552 | height_pages = DIV_ROUND_UP(rot_info->height, tile_height); | ||
2553 | rot_pages = width_pages * height_pages; | ||
2554 | size = rot_pages * PAGE_SIZE; | ||
2555 | |||
2556 | /* Allocate a temporary list of source pages for random access. */ | ||
2557 | page_addr_list = drm_malloc_ab(pages, sizeof(dma_addr_t)); | ||
2558 | if (!page_addr_list) | ||
2559 | return ERR_PTR(ret); | ||
2560 | |||
2561 | /* Allocate target SG list. */ | ||
2562 | st = kmalloc(sizeof(*st), GFP_KERNEL); | ||
2563 | if (!st) | ||
2564 | goto err_st_alloc; | ||
2565 | |||
2566 | ret = sg_alloc_table(st, rot_pages, GFP_KERNEL); | ||
2567 | if (ret) | ||
2568 | goto err_sg_alloc; | ||
2569 | |||
2570 | /* Populate source page list from the object. */ | ||
2571 | i = 0; | ||
2572 | for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) { | ||
2573 | page_addr_list[i] = sg_page_iter_dma_address(&sg_iter); | ||
2574 | i++; | ||
2575 | } | ||
2576 | |||
2577 | /* Rotate the pages. */ | ||
2578 | rotate_pages(page_addr_list, width_pages, height_pages, st); | ||
2579 | |||
2580 | DRM_DEBUG_KMS( | ||
2581 | "Created rotated page mapping for object size %lu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages).\n", | ||
2582 | size, rot_info->pitch, rot_info->height, | ||
2583 | rot_info->pixel_format, width_pages, height_pages, | ||
2584 | rot_pages); | ||
2585 | |||
2586 | drm_free_large(page_addr_list); | ||
2587 | |||
2588 | return st; | ||
2589 | |||
2590 | err_sg_alloc: | ||
2591 | kfree(st); | ||
2592 | err_st_alloc: | ||
2593 | drm_free_large(page_addr_list); | ||
2594 | |||
2595 | DRM_DEBUG_KMS( | ||
2596 | "Failed to create rotated mapping for object size %lu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages)\n", | ||
2597 | size, ret, rot_info->pitch, rot_info->height, | ||
2598 | rot_info->pixel_format, width_pages, height_pages, | ||
2599 | rot_pages); | ||
2600 | return ERR_PTR(ret); | ||
2601 | } | ||
2503 | 2602 | ||
2504 | static inline | 2603 | static inline int |
2505 | int i915_get_ggtt_vma_pages(struct i915_vma *vma) | 2604 | i915_get_ggtt_vma_pages(struct i915_vma *vma) |
2506 | { | 2605 | { |
2606 | int ret = 0; | ||
2607 | |||
2507 | if (vma->ggtt_view.pages) | 2608 | if (vma->ggtt_view.pages) |
2508 | return 0; | 2609 | return 0; |
2509 | 2610 | ||
2510 | if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) | 2611 | if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) |
2511 | vma->ggtt_view.pages = vma->obj->pages; | 2612 | vma->ggtt_view.pages = vma->obj->pages; |
2613 | else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED) | ||
2614 | vma->ggtt_view.pages = | ||
2615 | intel_rotate_fb_obj_pages(&vma->ggtt_view, vma->obj); | ||
2512 | else | 2616 | else |
2513 | WARN_ONCE(1, "GGTT view %u not implemented!\n", | 2617 | WARN_ONCE(1, "GGTT view %u not implemented!\n", |
2514 | vma->ggtt_view.type); | 2618 | vma->ggtt_view.type); |
@@ -2516,10 +2620,15 @@ int i915_get_ggtt_vma_pages(struct i915_vma *vma) | |||
2516 | if (!vma->ggtt_view.pages) { | 2620 | if (!vma->ggtt_view.pages) { |
2517 | DRM_ERROR("Failed to get pages for GGTT view type %u!\n", | 2621 | DRM_ERROR("Failed to get pages for GGTT view type %u!\n", |
2518 | vma->ggtt_view.type); | 2622 | vma->ggtt_view.type); |
2519 | return -EINVAL; | 2623 | ret = -EINVAL; |
2624 | } else if (IS_ERR(vma->ggtt_view.pages)) { | ||
2625 | ret = PTR_ERR(vma->ggtt_view.pages); | ||
2626 | vma->ggtt_view.pages = NULL; | ||
2627 | DRM_ERROR("Failed to get pages for VMA view type %u (%d)!\n", | ||
2628 | vma->ggtt_view.type, ret); | ||
2520 | } | 2629 | } |
2521 | 2630 | ||
2522 | return 0; | 2631 | return ret; |
2523 | } | 2632 | } |
2524 | 2633 | ||
2525 | /** | 2634 | /** |