summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRené Rebe <rene@exactco.de>2025-12-12 23:05:04 +0300
committerThomas Zimmermann <tzimmermann@suse.de>2025-12-21 23:44:35 +0300
commit50c26c301c5176cc8b431044390e10ec862b9b77 (patch)
tree058b22bef0f761bbd6cebfda845be09162789c4f
parentc83e42990303c05e60001d636212502ed5a2d48a (diff)
downloadlinux-50c26c301c5176cc8b431044390e10ec862b9b77.tar.xz
drm/ast: Swap framebuffer writes on big-endian machines
Swap the pixel data when writing to framebuffer memory on big-endian machines. Fixes incorrect output. Aspeed graphics does not appear to support big-endian framebuffers after AST2400, although the feature has been documented. There's a lengthy discussion at [1]. v5: - avoid restricted cast from __be16 (kernel test robot) Signed-off-by: René Rebe <rene@exactco.de> Link: https://lore.kernel.org/dri-devel/20251202.170626.2134482663677806825.rene@exactco.de/ # [1] Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patch.msgid.link/20251212.210504.1355099120650239629.rene@exactco.de
-rw-r--r--drivers/gpu/drm/ast/ast_cursor.c11
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c11
2 files changed, 17 insertions, 5 deletions
diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c
index 30b62d3f0151..3fa8e75db9c0 100644
--- a/drivers/gpu/drm/ast/ast_cursor.c
+++ b/drivers/gpu/drm/ast/ast_cursor.c
@@ -93,12 +93,17 @@ static void ast_set_cursor_image(struct ast_device *ast, const u8 *src,
unsigned int width, unsigned int height)
{
u8 __iomem *dst = ast_plane_vaddr(&ast->cursor_plane.base);
- u32 csum;
-
- csum = ast_cursor_calculate_checksum(src, width, height);
+ u32 csum = ast_cursor_calculate_checksum(src, width, height);
/* write pixel data */
+#if defined(__BIG_ENDIAN)
+ unsigned int i;
+
+ for (i = 0; i < AST_HWC_SIZE; i += 2)
+ writew(swab16(*(const __u16 *)&src[i]), &dst[i]);
+#else
memcpy_toio(dst, src, AST_HWC_SIZE);
+#endif
/* write checksum + signature */
dst += AST_HWC_SIZE;
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index cd08990a10f9..57c6fbc3232b 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -526,12 +526,18 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
static void ast_handle_damage(struct ast_plane *ast_plane, struct iosys_map *src,
struct drm_framebuffer *fb,
- const struct drm_rect *clip)
+ const struct drm_rect *clip,
+ struct drm_format_conv_state *fmtcnv_state)
{
struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(ast_plane_vaddr(ast_plane));
iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
+
+#if defined(__BIG_ENDIAN)
+ drm_fb_swab(&dst, fb->pitches, src, fb, clip, !src[0].is_iomem, fmtcnv_state);
+#else
drm_fb_memcpy(&dst, fb->pitches, src, fb, clip);
+#endif
}
static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
@@ -561,7 +567,8 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE) == 0) {
drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
drm_atomic_for_each_plane_damage(&iter, &damage) {
- ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage);
+ ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage,
+ &shadow_plane_state->fmtcnv_state);
}
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);