Commit 50c26c30 authored by René Rebe's avatar René Rebe Committed by Thomas Zimmermann
Browse files

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: default avatarRené Rebe <rene@exactco.de>
Link: https://lore.kernel.org/dri-devel/20251202.170626.2134482663677806825.rene@exactco.de/

 # [1]
Reviewed-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Link: https://patch.msgid.link/20251212.210504.1355099120650239629.rene@exactco.de
parent c83e4299
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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;
+9 −2
Original line number Diff line number Diff line
@@ -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);