From 2ccebf561e4a9024c8477459acf9b6176c4b40c7 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 2 Jul 2020 13:50:16 +0200 Subject: drm/ast: Move cursor functions to ast_cursor.c The cursor manipulation functions are unrelated to modesetting. Move them into their own file. Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-2-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 218 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 drivers/gpu/drm/ast/ast_cursor.c (limited to 'drivers/gpu/drm/ast/ast_cursor.c') diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c new file mode 100644 index 000000000000..53bb6eebc7cd --- /dev/null +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -0,0 +1,218 @@ +/* + * Copyright 2012 Red Hat Inc. + * Parts based on xf86-video-ast + * Copyright (c) 2005 ASPEED Technology Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ +/* + * Authors: Dave Airlie + */ + +#include + +#include "ast_drv.h" + +/* + * Allocate cursor BOs and pins them at the end of VRAM. + */ +int ast_cursor_init(struct drm_device *dev) +{ + struct ast_private *ast = to_ast_private(dev); + size_t size, i; + struct drm_gem_vram_object *gbo; + int ret; + + size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); + + for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { + gbo = drm_gem_vram_create(dev, size, 0); + 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; + } + + ast->cursor.gbo[i] = gbo; + } + + return 0; + +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; +} + +void ast_cursor_fini(struct drm_device *dev) +{ + struct ast_private *ast = to_ast_private(dev); + 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); + } +} + +static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height) +{ + union { + u32 ul; + u8 b[4]; + } srcdata32[2], data32; + union { + u16 us; + u8 b[2]; + } data16; + u32 csum = 0; + s32 alpha_dst_delta, last_alpha_dst_delta; + u8 *srcxor, *dstxor; + int i, j; + u32 per_pixel_copy, two_pixel_copy; + + alpha_dst_delta = AST_MAX_HWC_WIDTH << 1; + last_alpha_dst_delta = alpha_dst_delta - (width << 1); + + srcxor = src; + dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta; + per_pixel_copy = width & 1; + two_pixel_copy = width >> 1; + + for (j = 0; j < height; j++) { + for (i = 0; i < two_pixel_copy; i++) { + srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; + srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0; + data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); + data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); + data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4); + data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4); + + writel(data32.ul, dstxor); + csum += data32.ul; + + dstxor += 4; + srcxor += 8; + + } + + for (i = 0; i < per_pixel_copy; i++) { + srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; + data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); + data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); + writew(data16.us, dstxor); + csum += (u32)data16.us; + + dstxor += 2; + srcxor += 4; + } + dstxor += last_alpha_dst_delta; + } + return csum; +} + +int ast_cursor_update(void *dst, void *src, unsigned int width, + unsigned int height) +{ + u32 csum; + + /* do data transfer to cursor cache */ + csum = copy_cursor_image(src, dst, width, height); + + /* write checksum + signature */ + dst += AST_HWC_SIZE; + writel(csum, dst); + writel(width, dst + AST_HWC_SIGNATURE_SizeX); + writel(height, dst + AST_HWC_SIGNATURE_SizeY); + writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX); + writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); + + return 0; +} + +void ast_cursor_set_base(struct ast_private *ast, u64 address) +{ + u8 addr0 = (address >> 3) & 0xff; + u8 addr1 = (address >> 11) & 0xff; + u8 addr2 = (address >> 19) & 0xff; + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc8, addr0); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc9, addr1); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2); +} + +int ast_cursor_move(struct drm_crtc *crtc, int x, int y) +{ + struct ast_crtc *ast_crtc = to_ast_crtc(crtc); + struct ast_private *ast = to_ast_private(crtc->dev); + struct drm_gem_vram_object *gbo; + int x_offset, y_offset; + u8 *dst, *sig; + u8 jreg; + + 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); + + x_offset = ast_crtc->offset_x; + y_offset = ast_crtc->offset_y; + if (x < 0) { + x_offset = (-x) + ast_crtc->offset_x; + x = 0; + } + + if (y < 0) { + y_offset = (-y) + ast_crtc->offset_y; + y = 0; + } + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, (x & 0xff)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, ((x >> 8) & 0x0f)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, (y & 0xff)); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07)); + + /* dummy write to fire HWC */ + jreg = 0x02 | + 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; +} -- cgit From beb2355eecbf67d2fce79af73215c875173d9990 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 2 Jul 2020 13:50:17 +0200 Subject: drm/ast: Pass struct ast_private instance to cursor init/fini functions Removes some typecasting. v2: * use to_ast_private() instead of struct drm_device.dev_private Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-3-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_cursor.c') diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 53bb6eebc7cd..1d4f51a7fe22 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -34,9 +34,9 @@ /* * Allocate cursor BOs and pins them at the end of VRAM. */ -int ast_cursor_init(struct drm_device *dev) +int ast_cursor_init(struct ast_private *ast) { - struct ast_private *ast = to_ast_private(dev); + struct drm_device *dev = ast->dev; size_t size, i; struct drm_gem_vram_object *gbo; int ret; @@ -72,9 +72,8 @@ err_drm_gem_vram_put: return ret; } -void ast_cursor_fini(struct drm_device *dev) +void ast_cursor_fini(struct ast_private *ast) { - struct ast_private *ast = to_ast_private(dev); size_t i; struct drm_gem_vram_object *gbo; -- cgit From dd004b9a5505f9810f66a9ddfbdf02978703f1f6 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 2 Jul 2020 13:50:18 +0200 Subject: drm/ast: Move cursor fb pinning and mapping into helper The new helper ast_cursor_blit() updates a cursor's backbuffer HW BO from a framebuffer structure. The cursor plane's prepare_fb() function now uses the new interface. Pinning and mapping of BOs is done automatically by the helper. This includes the source BO, which was not pinned by the original code in prepare_fb(). Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-4-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 57 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_cursor.c') diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 1d4f51a7fe22..8f94d4712f66 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -140,8 +140,8 @@ static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height) return csum; } -int ast_cursor_update(void *dst, void *src, unsigned int width, - unsigned int height) +static int ast_cursor_update(void *dst, void *src, unsigned int width, + unsigned int height) { u32 csum; @@ -159,6 +159,59 @@ int ast_cursor_update(void *dst, void *src, unsigned int width, return 0; } +int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) +{ + struct drm_device *dev = ast->dev; + struct drm_gem_vram_object *gbo; + int ret; + void *src; + void *dst; + + if (drm_WARN_ON_ONCE(dev, fb->width > AST_MAX_HWC_WIDTH) || + drm_WARN_ON_ONCE(dev, fb->height > AST_MAX_HWC_HEIGHT)) + return -EINVAL; + + gbo = drm_gem_vram_of_gem(fb->obj[0]); + + ret = drm_gem_vram_pin(gbo, 0); + if (ret) + return ret; + src = drm_gem_vram_vmap(gbo); + if (IS_ERR(src)) { + ret = PTR_ERR(src); + goto err_drm_gem_vram_unpin; + } + + dst = drm_gem_vram_vmap(ast->cursor.gbo[ast->cursor.next_index]); + if (IS_ERR(dst)) { + ret = PTR_ERR(dst); + goto err_drm_gem_vram_vunmap_src; + } + + ret = ast_cursor_update(dst, src, fb->width, fb->height); + if (ret) + goto err_drm_gem_vram_vunmap_dst; + + /* + * Always unmap buffers here. Destination buffers are + * perma-pinned while the driver is active. We're only + * changing ref-counters here. + */ + drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst); + drm_gem_vram_vunmap(gbo, src); + drm_gem_vram_unpin(gbo); + + return 0; + +err_drm_gem_vram_vunmap_dst: + drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst); +err_drm_gem_vram_vunmap_src: + drm_gem_vram_vunmap(gbo, src); +err_drm_gem_vram_unpin: + drm_gem_vram_unpin(gbo); + return ret; +} + void ast_cursor_set_base(struct ast_private *ast, u64 address) { u8 addr0 = (address >> 3) & 0xff; -- cgit From 932a62aa3bfd96ec44799fec3523756e531988dc Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 2 Jul 2020 13:50:19 +0200 Subject: drm/ast: Update cursor image and checksum from same function Cursor image and checksum go hand in hand. Update both in the same place. The helper cannot fail, so remove the return type. Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-5-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_cursor.c') diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 8f94d4712f66..7474baddf048 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -84,7 +84,7 @@ void ast_cursor_fini(struct ast_private *ast) } } -static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height) +static void update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height) { union { u32 ul; @@ -96,7 +96,8 @@ static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height) } data16; u32 csum = 0; s32 alpha_dst_delta, last_alpha_dst_delta; - u8 *srcxor, *dstxor; + u8 __iomem *dstxor; + const u8 *srcxor; int i, j; u32 per_pixel_copy, two_pixel_copy; @@ -137,16 +138,6 @@ static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height) } dstxor += last_alpha_dst_delta; } - return csum; -} - -static int ast_cursor_update(void *dst, void *src, unsigned int width, - unsigned int height) -{ - u32 csum; - - /* do data transfer to cursor cache */ - csum = copy_cursor_image(src, dst, width, height); /* write checksum + signature */ dst += AST_HWC_SIZE; @@ -155,8 +146,6 @@ static int ast_cursor_update(void *dst, void *src, unsigned int width, writel(height, dst + AST_HWC_SIGNATURE_SizeY); writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX); writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); - - return 0; } int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) @@ -188,9 +177,8 @@ int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) goto err_drm_gem_vram_vunmap_src; } - ret = ast_cursor_update(dst, src, fb->width, fb->height); - if (ret) - goto err_drm_gem_vram_vunmap_dst; + /* do data transfer to cursor BO */ + update_cursor_image(dst, src, fb->width, fb->height); /* * Always unmap buffers here. Destination buffers are @@ -203,8 +191,6 @@ int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) return 0; -err_drm_gem_vram_vunmap_dst: - drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst); err_drm_gem_vram_vunmap_src: drm_gem_vram_vunmap(gbo, src); err_drm_gem_vram_unpin: -- cgit From 75d9d8e66db834551e81e74e522c2900fe93ef5c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 2 Jul 2020 13:50:20 +0200 Subject: drm/ast: Move cursor pageflip into helper The new helper ast_cursor_page_flip() switches the cursor's front and back BOs. This simplifies the cursor plane's update helper. Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-6-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/ast/ast_cursor.c') diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 7474baddf048..815d95b2f392 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -198,7 +198,7 @@ err_drm_gem_vram_unpin: return ret; } -void ast_cursor_set_base(struct ast_private *ast, u64 address) +static void ast_cursor_set_base(struct ast_private *ast, u64 address) { u8 addr0 = (address >> 3) & 0xff; u8 addr1 = (address >> 11) & 0xff; @@ -209,6 +209,24 @@ void ast_cursor_set_base(struct ast_private *ast, u64 address) ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2); } +void ast_cursor_page_flip(struct ast_private *ast) +{ + struct drm_device *dev = ast->dev; + struct drm_gem_vram_object *gbo; + s64 off; + + gbo = ast->cursor.gbo[ast->cursor.next_index]; + + off = drm_gem_vram_offset(gbo); + if (drm_WARN_ON_ONCE(dev, off < 0)) + return; /* Bug: we didn't pin the cursor HW BO to VRAM. */ + + ast_cursor_set_base(ast, off); + + ++ast->cursor.next_index; + ast->cursor.next_index %= ARRAY_SIZE(ast->cursor.gbo); +} + int ast_cursor_move(struct drm_crtc *crtc, int x, int y) { struct ast_crtc *ast_crtc = to_ast_crtc(crtc); -- cgit From 81039adc92cd7a1eb99a6c53f33376e972d96971 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 2 Jul 2020 13:50:21 +0200 Subject: drm/ast: Replace ast_cursor_move() with ast_cursor_show() Having a cursor move function is misleading, as it actually enables the cursor's image for displaying. So rename it to ast_cursor_show(). It's semantics is to show a cursor at the specified location on the screen. The displayed cursor is always the image in the cursor front BO. This change also simplifies struct ast_crtc to being a mere wrapper around around struct drm_crtc. It will be removed by a later patch. Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-7-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 42 ++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_cursor.c') diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 815d95b2f392..8f8fdc831830 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -227,12 +227,27 @@ void ast_cursor_page_flip(struct ast_private *ast) ast->cursor.next_index %= ARRAY_SIZE(ast->cursor.gbo); } -int ast_cursor_move(struct drm_crtc *crtc, int x, int y) +static void ast_cursor_set_location(struct ast_private *ast, u16 x, u16 y, + u8 x_offset, u8 y_offset) +{ + u8 x0 = (x & 0x00ff); + u8 x1 = (x & 0x0f00) >> 8; + u8 y0 = (y & 0x00ff); + u8 y1 = (y & 0x0700) >> 8; + + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, x0); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, x1); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, y0); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1); +} + +int ast_cursor_show(struct ast_private *ast, int x, int y, + unsigned int offset_x, unsigned int offset_y) { - struct ast_crtc *ast_crtc = to_ast_crtc(crtc); - struct ast_private *ast = to_ast_private(crtc->dev); struct drm_gem_vram_object *gbo; - int x_offset, y_offset; + u8 x_offset, y_offset; u8 *dst, *sig; u8 jreg; @@ -245,23 +260,20 @@ int ast_cursor_move(struct drm_crtc *crtc, int x, int y) writel(x, sig + AST_HWC_SIGNATURE_X); writel(y, sig + AST_HWC_SIGNATURE_Y); - x_offset = ast_crtc->offset_x; - y_offset = ast_crtc->offset_y; if (x < 0) { - x_offset = (-x) + ast_crtc->offset_x; + x_offset = (-x) + offset_x; x = 0; + } else { + x_offset = offset_x; } - if (y < 0) { - y_offset = (-y) + ast_crtc->offset_y; + y_offset = (-y) + offset_y; y = 0; + } else { + y_offset = offset_y; } - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, (x & 0xff)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, ((x >> 8) & 0x0f)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, (y & 0xff)); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07)); + + ast_cursor_set_location(ast, x, y, x_offset, y_offset); /* dummy write to fire HWC */ jreg = 0x02 | -- cgit From c91eadd110463f4455483ab7bc5c5e7cea28a906 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 2 Jul 2020 13:50:23 +0200 Subject: drm/ast: Add helper to hide cursor As the inverse to ast_cursor_show(), ast_cursor_hide() disables the HW cursor. Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-9-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/ast/ast_cursor.c') diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 8f8fdc831830..5421241015d6 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -284,3 +284,8 @@ int ast_cursor_show(struct ast_private *ast, int x, int y, return 0; } + +void ast_cursor_hide(struct ast_private *ast) +{ + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00); +} -- cgit From 0d384eec10ea723f39df9736a04966e047850cfb Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 2 Jul 2020 13:50:24 +0200 Subject: drm/ast: Keep cursor HW BOs mapped Updating the image in a cursor's HW BO requires a mapping of the BO's buffer in the kernel's address space. Cursor image updates can happen frequently and create CPU overhead. As cursor HW BOs are small and never move, they are now map exactly once during the initialization and the mapping is used throughout the driver's lifetime. This change also removes a possible source of failures from ast_cursor_show(). As the helper does not establish mappings, it cannot fail. As a result, the cursor plane's atomic-update helper does not call any failable interfaces. All failures are detected before trying to update the cursor plane. Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-10-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 44 ++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_cursor.c') diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 5421241015d6..35680402e410 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -39,6 +39,7 @@ int ast_cursor_init(struct ast_private *ast) struct drm_device *dev = ast->dev; size_t size, i; struct drm_gem_vram_object *gbo; + void __iomem *vaddr; int ret; size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); @@ -55,8 +56,16 @@ int ast_cursor_init(struct ast_private *ast) drm_gem_vram_put(gbo); goto err_drm_gem_vram_put; } + vaddr = drm_gem_vram_vmap(gbo); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + drm_gem_vram_unpin(gbo); + drm_gem_vram_put(gbo); + goto err_drm_gem_vram_put; + } ast->cursor.gbo[i] = gbo; + ast->cursor.vaddr[i] = vaddr; } return 0; @@ -65,9 +74,11 @@ err_drm_gem_vram_put: while (i) { --i; gbo = ast->cursor.gbo[i]; + drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]); drm_gem_vram_unpin(gbo); drm_gem_vram_put(gbo); ast->cursor.gbo[i] = NULL; + ast->cursor.vaddr[i] = NULL; } return ret; } @@ -79,6 +90,7 @@ void ast_cursor_fini(struct ast_private *ast) for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) { gbo = ast->cursor.gbo[i]; + drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]); drm_gem_vram_unpin(gbo); drm_gem_vram_put(gbo); } @@ -154,7 +166,7 @@ int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) struct drm_gem_vram_object *gbo; int ret; void *src; - void *dst; + void __iomem *dst; if (drm_WARN_ON_ONCE(dev, fb->width > AST_MAX_HWC_WIDTH) || drm_WARN_ON_ONCE(dev, fb->height > AST_MAX_HWC_HEIGHT)) @@ -171,28 +183,16 @@ int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) goto err_drm_gem_vram_unpin; } - dst = drm_gem_vram_vmap(ast->cursor.gbo[ast->cursor.next_index]); - if (IS_ERR(dst)) { - ret = PTR_ERR(dst); - goto err_drm_gem_vram_vunmap_src; - } + dst = ast->cursor.vaddr[ast->cursor.next_index]; /* do data transfer to cursor BO */ update_cursor_image(dst, src, fb->width, fb->height); - /* - * Always unmap buffers here. Destination buffers are - * perma-pinned while the driver is active. We're only - * changing ref-counters here. - */ - drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst); drm_gem_vram_vunmap(gbo, src); drm_gem_vram_unpin(gbo); return 0; -err_drm_gem_vram_vunmap_src: - drm_gem_vram_vunmap(gbo, src); err_drm_gem_vram_unpin: drm_gem_vram_unpin(gbo); return ret; @@ -243,18 +243,14 @@ static void ast_cursor_set_location(struct ast_private *ast, u16 x, u16 y, ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1); } -int ast_cursor_show(struct ast_private *ast, int x, int y, - unsigned int offset_x, unsigned int offset_y) +void ast_cursor_show(struct ast_private *ast, int x, int y, + unsigned int offset_x, unsigned int offset_y) { - struct drm_gem_vram_object *gbo; u8 x_offset, y_offset; - u8 *dst, *sig; + u8 __iomem *dst, __iomem *sig; u8 jreg; - gbo = ast->cursor.gbo[ast->cursor.next_index]; - dst = drm_gem_vram_vmap(gbo); - if (IS_ERR(dst)) - return PTR_ERR(dst); + dst = ast->cursor.vaddr[ast->cursor.next_index]; sig = dst + AST_HWC_SIZE; writel(x, sig + AST_HWC_SIGNATURE_X); @@ -279,10 +275,6 @@ int ast_cursor_show(struct ast_private *ast, int x, int y, jreg = 0x02 | 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; } void ast_cursor_hide(struct ast_private *ast) -- cgit From 3e9d787371eaa842682bf4fc86ae9475548d9cee Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 2 Jul 2020 13:50:25 +0200 Subject: drm/ast: Managed cursor release Register a release function to finalize cursors. The _fini() function gets un-exported from the source file. The function ast_mode_fini() is now empty and will be removed by a later patch. Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200702115029.5281-11-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/ast/ast_cursor.c') diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 35680402e410..acf0d23514e8 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -28,9 +28,30 @@ */ #include +#include #include "ast_drv.h" +static void ast_cursor_fini(struct ast_private *ast) +{ + 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_vunmap(gbo, ast->cursor.vaddr[i]); + drm_gem_vram_unpin(gbo); + drm_gem_vram_put(gbo); + } +} + +static void ast_cursor_release(struct drm_device *dev, void *ptr) +{ + struct ast_private *ast = dev->dev_private; + + ast_cursor_fini(ast); +} + /* * Allocate cursor BOs and pins them at the end of VRAM. */ @@ -68,7 +89,7 @@ int ast_cursor_init(struct ast_private *ast) ast->cursor.vaddr[i] = vaddr; } - return 0; + return drmm_add_action_or_reset(dev, ast_cursor_release, NULL); err_drm_gem_vram_put: while (i) { @@ -77,25 +98,10 @@ err_drm_gem_vram_put: drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]); drm_gem_vram_unpin(gbo); drm_gem_vram_put(gbo); - ast->cursor.gbo[i] = NULL; - ast->cursor.vaddr[i] = NULL; } return ret; } -void ast_cursor_fini(struct ast_private *ast) -{ - 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_vunmap(gbo, ast->cursor.vaddr[i]); - drm_gem_vram_unpin(gbo); - drm_gem_vram_put(gbo); - } -} - static void update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height) { union { -- cgit