diff options
author | Thomas Zimmermann <tzimmermann@suse.de> | 2019-09-27 11:03:09 +0200 |
---|---|---|
committer | Thomas Zimmermann <tzimmermann@suse.de> | 2019-10-04 10:00:21 +0200 |
commit | 0090ef3ecbd4ff176cb793f26d99cd29772cea57 (patch) | |
tree | 61f4071b1a074a3a37e510b550a942a0490886f7 /drivers/gpu/drm/ast/ast_mode.c | |
parent | 659d1a49c63d7e12f876404368c6830d0605ffd4 (diff) |
drm/ast: Allocate cursor BOs at high end of video memory
By putting cursor BOs at the high end of the video memory, we can avoid
memory fragmentation. Starting at the low end, contiguous video memory is
available for framebuffers.
The patch also simplifies the buffer swapping by splitting
struct ast_private.cursor_cache BO into two separate boffer objects. Cursor
images alternate between these buffers instead of offsets within cursor_cache.
v3:
* fixes space-before-tab error near AST_HWC_SIGNATURE_CHECKSUM
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190927090309.10254-6-tzimmermann@suse.de
Diffstat (limited to 'drivers/gpu/drm/ast/ast_mode.c')
-rw-r--r-- | drivers/gpu/drm/ast/ast_mode.c | 91 |
1 files changed, 49 insertions, 42 deletions
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 6a517ffb1c5c..b13eaa2619ab 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -883,50 +883,53 @@ static int ast_connector_init(struct drm_device *dev) static int ast_cursor_init(struct drm_device *dev) { struct ast_private *ast = dev->dev_private; - int size; - int ret; - struct drm_gem_object *obj; + size_t size, i; struct drm_gem_vram_object *gbo; - s64 gpu_addr; - void *base; + int ret; - size = (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE) * AST_DEFAULT_HWC_NUM; + size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); - ret = ast_gem_create(dev, size, true, &obj); - if (ret) - return ret; - gbo = drm_gem_vram_of_gem(obj); - ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); - if (ret) - goto fail; - gpu_addr = drm_gem_vram_offset(gbo); - if (gpu_addr < 0) { - drm_gem_vram_unpin(gbo); - ret = (int)gpu_addr; - goto fail; - } + for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { + gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, + size, 0, false); + if (IS_ERR(gbo)) { + ret = PTR_ERR(gbo); + goto err_drm_gem_vram_put; + } + ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM | + DRM_GEM_VRAM_PL_FLAG_TOPDOWN); + if (ret) { + drm_gem_vram_put(gbo); + goto err_drm_gem_vram_put; + } - /* kmap the object */ - base = drm_gem_vram_kmap(gbo, true, NULL); - if (IS_ERR(base)) { - ret = PTR_ERR(base); - goto fail; + ast->cursor.gbo[i] = gbo; } - ast->cursor_cache = obj; return 0; -fail: + +err_drm_gem_vram_put: + while (i) { + --i; + gbo = ast->cursor.gbo[i]; + drm_gem_vram_unpin(gbo); + drm_gem_vram_put(gbo); + ast->cursor.gbo[i] = NULL; + } return ret; } static void ast_cursor_fini(struct drm_device *dev) { struct ast_private *ast = dev->dev_private; - struct drm_gem_vram_object *gbo = - drm_gem_vram_of_gem(ast->cursor_cache); - drm_gem_vram_kunmap(gbo); - drm_gem_vram_unpin(gbo); - drm_gem_object_put_unlocked(ast->cursor_cache); + size_t i; + struct drm_gem_vram_object *gbo; + + for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { + gbo = ast->cursor.gbo[i]; + drm_gem_vram_unpin(gbo); + drm_gem_vram_put(gbo); + } } int ast_mode_init(struct drm_device *dev) @@ -1156,12 +1159,12 @@ static int ast_show_cursor(struct drm_crtc *crtc, void *src, struct ast_private *ast = crtc->dev->dev_private; struct ast_crtc *ast_crtc = to_ast_crtc(crtc); struct drm_gem_vram_object *gbo; - u8 *dst, *dst_next; + void *dst; s64 off; int ret; u8 jreg; - gbo = drm_gem_vram_of_gem(ast->cursor_cache); + gbo = ast->cursor.gbo[ast->cursor.next_index]; dst = drm_gem_vram_vmap(gbo); if (IS_ERR(dst)) return PTR_ERR(dst); @@ -1171,10 +1174,7 @@ static int ast_show_cursor(struct drm_crtc *crtc, void *src, goto err_drm_gem_vram_vunmap; } - dst_next = dst + (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE) * - ast->next_cursor; - - ret = ast_cursor_update(dst_next, src, width, height); + ret = ast_cursor_update(dst, src, width, height); if (ret) goto err_drm_gem_vram_vunmap; ast_cursor_set_base(ast, off); @@ -1187,7 +1187,8 @@ static int ast_show_cursor(struct drm_crtc *crtc, void *src, jreg |= 1; ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg); - ast->next_cursor = (ast->next_cursor + 1) % AST_DEFAULT_HWC_NUM; + ++ast->cursor.next_index; + ast->cursor.next_index %= ARRAY_SIZE(ast->cursor.gbo); drm_gem_vram_vunmap(gbo, dst); @@ -1257,13 +1258,17 @@ static int ast_cursor_move(struct drm_crtc *crtc, { struct ast_crtc *ast_crtc = to_ast_crtc(crtc); struct ast_private *ast = crtc->dev->dev_private; + struct drm_gem_vram_object *gbo; int x_offset, y_offset; - u8 *sig; + u8 *dst, *sig; u8 jreg; - sig = drm_gem_vram_kmap(drm_gem_vram_of_gem(ast->cursor_cache), - false, NULL); - sig += (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE; + gbo = ast->cursor.gbo[ast->cursor.next_index]; + dst = drm_gem_vram_vmap(gbo); + if (IS_ERR(dst)) + return PTR_ERR(dst); + + sig = dst + AST_HWC_SIZE; writel(x, sig + AST_HWC_SIGNATURE_X); writel(y, sig + AST_HWC_SIGNATURE_Y); @@ -1290,5 +1295,7 @@ static int ast_cursor_move(struct drm_crtc *crtc, 0x01; /* enable ARGB4444 cursor */ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg); + drm_gem_vram_vunmap(gbo, dst); + return 0; } |