[Intel-gfx] [PATCH 6/8] drm/i915: Support NV12 in rotated GGTT mapping
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Fri May 8 05:02:41 PDT 2015
From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Just adding the rotated UV plane at the end of the rotated Y plane.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
---
drivers/gpu/drm/i915/i915_gem_gtt.c | 47 ++++++++++++++++++++++++++++++------
drivers/gpu/drm/i915/i915_gem_gtt.h | 1 +
drivers/gpu/drm/i915/intel_display.c | 1 +
3 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index d7f2e5d..bf3ee44 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2693,12 +2693,18 @@ intel_calc_tiled_geometry(struct drm_device *dev,
unsigned int plane)
{
unsigned int tile_height, tile_pitch;
+ unsigned int height;
+
+ if (rot_info->pixel_format == DRM_FORMAT_NV12 && plane == 1)
+ height = rot_info->height / 2;
+ else
+ height = rot_info->height;
tile_height = intel_tile_height(dev, rot_info->pixel_format,
rot_info->fb_modifier, plane);
tile_pitch = PAGE_SIZE / tile_height;
*width_pages = DIV_ROUND_UP(rot_info->pitch, tile_pitch);
- *height_pages = DIV_ROUND_UP(rot_info->height, tile_height);
+ *height_pages = DIV_ROUND_UP(height, tile_height);
return (*width_pages) * (*height_pages);
}
@@ -2709,12 +2715,15 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
{
struct drm_device *dev = obj->base.dev;
struct intel_rotation_info *rot_info = &ggtt_view->rotation_info;
- unsigned long pages, rot_pages;
+ unsigned long pages, rot_pages, rot_pages_uv = 0;
struct sg_page_iter sg_iter;
unsigned long i;
dma_addr_t *page_addr_list;
struct sg_table *st;
unsigned int width_pages, height_pages;
+ unsigned int width_pages_uv, height_pages_uv;
+ unsigned int uv_start_page;
+ struct scatterlist *sg;
int ret = -ENOMEM;
pages = obj->base.size / PAGE_SIZE;
@@ -2723,6 +2732,13 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
rot_pages = intel_calc_tiled_geometry(dev, rot_info,
&width_pages, &height_pages, 0);
+ /* Account for UV plane with NV12. */
+ if (rot_info->pixel_format == DRM_FORMAT_NV12) {
+ rot_pages_uv = intel_calc_tiled_geometry(dev, rot_info,
+ &width_pages_uv,
+ &height_pages_uv, 1);
+ }
+
/* Allocate a temporary list of source pages for random access. */
page_addr_list = drm_malloc_ab(pages, sizeof(dma_addr_t));
if (!page_addr_list)
@@ -2733,7 +2749,7 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
if (!st)
goto err_st_alloc;
- ret = sg_alloc_table(st, rot_pages, GFP_KERNEL);
+ ret = sg_alloc_table(st, rot_pages + rot_pages_uv, GFP_KERNEL);
if (ret)
goto err_sg_alloc;
@@ -2745,13 +2761,28 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
}
/* Rotate the pages. */
- rotate_pages(page_addr_list, 0, width_pages, height_pages, st, NULL);
+ sg = rotate_pages(page_addr_list, 0,
+ width_pages, height_pages,
+ st, NULL);
+
+ /* Append the UV plane if NV12. */
+ if (rot_info->pixel_format == DRM_FORMAT_NV12) {
+ uv_start_page = rot_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,
+ width_pages_uv, height_pages_uv,
+ st, sg);
+ }
DRM_DEBUG_KMS(
- "Created rotated page mapping for object size %lu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages).\n",
+ "Created rotated page mapping for object size %lu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages (%lu plane 0)).\n",
obj->base.size, rot_info->pitch, rot_info->height,
rot_info->pixel_format, width_pages, height_pages,
- rot_pages);
+ rot_pages + rot_pages_uv, rot_pages);
drm_free_large(page_addr_list);
@@ -2763,10 +2794,10 @@ err_st_alloc:
drm_free_large(page_addr_list);
DRM_DEBUG_KMS(
- "Failed to create rotated mapping for object size %lu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages)\n",
+ "Failed to create rotated mapping for object size %lu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages (%lu plane 0))\n",
obj->base.size, ret, rot_info->pitch, rot_info->height,
rot_info->pixel_format, width_pages, height_pages,
- rot_pages);
+ rot_pages + rot_pages_uv, rot_pages);
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 4e6cac5..5118da1 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -123,6 +123,7 @@ 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;
};
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a87faca..b4bf998 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2346,6 +2346,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
info->pixel_format = fb->pixel_format;
info->pitch = fb->pitches[0];
info->fb_modifier = fb->modifier[0];
+ info->uv_offset = fb->offsets[1];
return 0;
}
--
2.4.0
More information about the Intel-gfx
mailing list