summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
diff options
context:
space:
mode:
authorjames qian wang (Arm Technology China)2019-05-23 11:56:54 +0200
committerLiviu Dudau2019-06-19 12:42:16 +0200
commit65ad2392dd6d1691db93e82b08d3311298b9d64a (patch)
tree5121cdc03675131265b661d958cff79c26d121b7 /drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
parentdrm/komeda: Add writeback support (diff)
downloadkernel-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.c75
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;