diff options
author | james qian wang (Arm Technology China) | 2019-05-23 11:56:54 +0200 |
---|---|---|
committer | Liviu Dudau | 2019-06-19 12:42:16 +0200 |
commit | 65ad2392dd6d1691db93e82b08d3311298b9d64a (patch) | |
tree | 5121cdc03675131265b661d958cff79c26d121b7 /drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c | |
parent | drm/komeda: Add writeback support (diff) | |
download | kernel-qcow2-linux-65ad2392dd6d1691db93e82b08d3311298b9d64a.tar.gz kernel-qcow2-linux-65ad2392dd6d1691db93e82b08d3311298b9d64a.tar.xz kernel-qcow2-linux-65ad2392dd6d1691db93e82b08d3311298b9d64a.zip |
drm/komeda: Added AFBC support for komeda driver
For supporting AFBC:
1. Check if the user requested modifier can be supported by display HW.
2. Check the obj->size with AFBC's requirement.
3. Configure HW according to the modifier (afbc features)
This patch depends on:
- https://patchwork.freedesktop.org/series/59915/
- https://patchwork.freedesktop.org/series/59000/
v2: Rebase and addressed Ayan's comments
Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
Diffstat (limited to 'drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c')
-rw-r--r-- | drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c index 4d8160cf09c3..d0e713aedb8e 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c @@ -37,6 +37,76 @@ static const struct drm_framebuffer_funcs komeda_fb_funcs = { }; static int +komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct drm_framebuffer *fb = &kfb->base; + const struct drm_format_info *info = fb->format; + struct drm_gem_object *obj; + u32 alignment_w = 0, alignment_h = 0, alignment_header; + u32 n_blocks = 0, min_size = 0; + + obj = drm_gem_object_lookup(file, mode_cmd->handles[0]); + if (!obj) { + DRM_DEBUG_KMS("Failed to lookup GEM object\n"); + return -ENOENT; + } + + switch (fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) { + case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8: + alignment_w = 32; + alignment_h = 8; + break; + case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16: + alignment_w = 16; + alignment_h = 16; + break; + default: + WARN(1, "Invalid AFBC_FORMAT_MOD_BLOCK_SIZE: %lld.\n", + fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK); + break; + } + + /* tiled header afbc */ + if (fb->modifier & AFBC_FORMAT_MOD_TILED) { + alignment_w *= AFBC_TH_LAYOUT_ALIGNMENT; + alignment_h *= AFBC_TH_LAYOUT_ALIGNMENT; + alignment_header = AFBC_TH_BODY_START_ALIGNMENT; + } else { + alignment_header = AFBC_BODY_START_ALIGNMENT; + } + + kfb->aligned_w = ALIGN(fb->width, alignment_w); + kfb->aligned_h = ALIGN(fb->height, alignment_h); + + if (fb->offsets[0] % alignment_header) { + DRM_DEBUG_KMS("afbc offset alignment check failed.\n"); + goto check_failed; + } + + n_blocks = (kfb->aligned_w * kfb->aligned_h) / AFBC_SUPERBLK_PIXELS; + kfb->offset_payload = ALIGN(n_blocks * AFBC_HEADER_SIZE, + alignment_header); + + kfb->afbc_size = kfb->offset_payload + n_blocks * + ALIGN(info->cpp[0] * AFBC_SUPERBLK_PIXELS, + AFBC_SUPERBLK_ALIGNMENT); + min_size = kfb->afbc_size + fb->offsets[0]; + if (min_size > obj->size) { + DRM_DEBUG_KMS("afbc size check failed, obj_size: 0x%lx. min_size 0x%x.\n", + obj->size, min_size); + goto check_failed; + } + + fb->obj[0] = obj; + return 0; + +check_failed: + drm_gem_object_put_unlocked(obj); + return -EINVAL; +} + +static int komeda_fb_none_afbc_size_check(struct komeda_dev *mdev, struct komeda_fb *kfb, struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd) @@ -118,7 +188,10 @@ komeda_fb_create(struct drm_device *dev, struct drm_file *file, drm_helper_mode_fill_fb_struct(dev, &kfb->base, mode_cmd); - ret = komeda_fb_none_afbc_size_check(mdev, kfb, file, mode_cmd); + if (kfb->base.modifier) + ret = komeda_fb_afbc_size_check(kfb, file, mode_cmd); + else + ret = komeda_fb_none_afbc_size_check(mdev, kfb, file, mode_cmd); if (ret < 0) goto err_cleanup; |