[PATCH v3 8/8] drm/rockchip: vop2: Fix the AFBC offsets of a source that starts inside a superblock

From: Arun Iyengar via B4 Relay

Date: Fri Nov 13 2026 - 15:52:27 EST


From: Arun Iyengar <aiyengar1990@xxxxxxxxx>

For an AFBC source that starts inside a superblock, AFBC_TILE_NUM misses
the first, partial superblock column, and the transform offset is the
whole x position (truncated to 8 bits) instead of the offset inside the
superblock.

Count the columns from the first one the source touches and take the x
offset modulo the superblock width, as the vendor kernel does.

Fixes: 604be85547ce ("drm/rockchip: Add VOP2 driver")
Signed-off-by: Arun Iyengar <aiyengar1990@xxxxxxxxx>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 0c300279399a..fc36edfe79d8 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -431,7 +431,7 @@ static bool vop2_half_block_enable(struct drm_plane_state *pstate)
}

static u32 vop2_afbc_transform_offset(struct drm_plane_state *pstate,
- bool afbc_half_block_en)
+ bool afbc_half_block_en, u32 block_w)
{
struct drm_rect *src = &pstate->src;
struct drm_framebuffer *fb = pstate->fb;
@@ -479,7 +479,7 @@ static u32 vop2_afbc_transform_offset(struct drm_plane_state *pstate,
ty = act_yoffset;
break;
case DRM_MODE_REFLECT_Y:
- tx = act_xoffset;
+ tx = act_xoffset % block_w;
ty = bottom_crop_line_num - act_yoffset;
break;
case DRM_MODE_ROTATE_90:
@@ -491,7 +491,7 @@ static u32 vop2_afbc_transform_offset(struct drm_plane_state *pstate,
ty = vir_width - width - act_xoffset;
break;
case 0:
- tx = act_xoffset;
+ tx = act_xoffset % block_w;
ty = act_yoffset;
break;
}
@@ -1433,7 +1433,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
if (fb->modifier & AFBC_FORMAT_MOD_YTR)
afbc_format |= (1 << 4);

- afbc_tile_num = ALIGN(src_w, block_w) / block_w;
+ afbc_tile_num = ALIGN(src_w + (src->x1 >> 16) % block_w, block_w) / block_w;

/*
* AFBC pic_vir_width is count by pixel, this is different
@@ -1484,7 +1484,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
vop2_win_write(win, VOP2_WIN_AFBC_PLD_OFFSET, yrgb_mst);
}

- transform_offset = vop2_afbc_transform_offset(pstate, half_block_en);
+ transform_offset = vop2_afbc_transform_offset(pstate, half_block_en, block_w);
vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst);
vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info);
vop2_win_write(win, VOP2_WIN_TRANSFORM_OFFSET, transform_offset);

--
2.55.0