Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 89e3e142 authored by Tvrtko Ursulin's avatar Tvrtko Ursulin Committed by Daniel Vetter
Browse files

drm/i915: Support NV12 in rotated GGTT mapping



Just adding the rotated UV plane at the end of the rotated Y plane.

v2: Rebase.

Signed-off-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 804beb4b
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -3282,10 +3282,13 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
{
	struct intel_rotation_info *rot_info = &ggtt_view->rotation_info;
	unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
	unsigned int size_pages_uv;
	struct sg_page_iter sg_iter;
	unsigned long i;
	dma_addr_t *page_addr_list;
	struct sg_table *st;
	unsigned int uv_start_page;
	struct scatterlist *sg;
	int ret = -ENOMEM;

	/* Allocate a temporary list of source pages for random access. */
@@ -3294,12 +3297,18 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
	if (!page_addr_list)
		return ERR_PTR(ret);

	/* Account for UV plane with NV12. */
	if (rot_info->pixel_format == DRM_FORMAT_NV12)
		size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
	else
		size_pages_uv = 0;

	/* Allocate target SG list. */
	st = kmalloc(sizeof(*st), GFP_KERNEL);
	if (!st)
		goto err_st_alloc;

	ret = sg_alloc_table(st, size_pages, GFP_KERNEL);
	ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL);
	if (ret)
		goto err_sg_alloc;

@@ -3311,15 +3320,30 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
	}

	/* Rotate the pages. */
	rotate_pages(page_addr_list, 0,
	sg = rotate_pages(page_addr_list, 0,
		     rot_info->width_pages, rot_info->height_pages,
		     st, NULL);

	/* Append the UV plane if NV12. */
	if (rot_info->pixel_format == DRM_FORMAT_NV12) {
		uv_start_page = size_pages;

		/* Check for tile-row un-alignment. */
		if (offset_in_page(rot_info->uv_offset))
			uv_start_page--;

		rotate_pages(page_addr_list, uv_start_page,
			     rot_info->width_pages_uv,
			     rot_info->height_pages_uv,
			     st, sg);
	}

	DRM_DEBUG_KMS(
		      "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages).\n",
		      "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n",
		      obj->base.size, rot_info->pitch, rot_info->height,
		      rot_info->pixel_format, rot_info->width_pages,
		      rot_info->height_pages, size_pages);
		      rot_info->height_pages, size_pages + size_pages_uv,
		      size_pages);

	drm_free_large(page_addr_list);

@@ -3331,10 +3355,11 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
	drm_free_large(page_addr_list);

	DRM_DEBUG_KMS(
		      "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages)\n",
		      "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n",
		      obj->base.size, ret, rot_info->pitch, rot_info->height,
		      rot_info->pixel_format, rot_info->width_pages,
		      rot_info->height_pages, size_pages);
		      rot_info->height_pages, size_pages + size_pages_uv,
		      size_pages);
	return ERR_PTR(ret);
}

+3 −0
Original line number Diff line number Diff line
@@ -138,10 +138,13 @@ enum i915_ggtt_view_type {
struct intel_rotation_info {
	unsigned int height;
	unsigned int pitch;
	unsigned int uv_offset;
	uint32_t pixel_format;
	uint64_t fb_modifier;
	unsigned int width_pages, height_pages;
	uint64_t size;
	unsigned int width_pages_uv, height_pages_uv;
	uint64_t size_uv;
};

struct i915_ggtt_view {
+12 −0
Original line number Diff line number Diff line
@@ -2263,6 +2263,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
	info->height = fb->height;
	info->pixel_format = fb->pixel_format;
	info->pitch = fb->pitches[0];
	info->uv_offset = fb->offsets[1];
	info->fb_modifier = fb->modifier[0];

	tile_height = intel_tile_height(fb->dev, fb->pixel_format,
@@ -2272,6 +2273,17 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
	info->size = info->width_pages * info->height_pages * PAGE_SIZE;

	if (info->pixel_format == DRM_FORMAT_NV12) {
		tile_height = intel_tile_height(fb->dev, fb->pixel_format,
						fb->modifier[0], 1);
		tile_pitch = PAGE_SIZE / tile_height;
		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2,
						     tile_height);
		info->size_uv = info->width_pages_uv * info->height_pages_uv *
				PAGE_SIZE;
	}

	return 0;
}