drm/vc4: plane: Swap Cb/Cr pointers for YVU formats

hvs6 appears to have dropped support for the component order
field in 3 plane YUV formats.

Support them by swapping the Cb and Cr planes over when
reading the image pointers.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
This commit is contained in:
Dave Stevenson
2025-11-03 12:03:01 +00:00
committed by Dom Cobley
parent 719823226d
commit 8ebe56ccce

View File

@@ -37,6 +37,7 @@ static const struct hvs_format {
u32 pixel_order_hvs5; u32 pixel_order_hvs5;
bool hvs5_only; bool hvs5_only;
bool hvs6_only; bool hvs6_only;
bool hvs6_swap_chroma_pointers;
} hvs_formats[] = { } hvs_formats[] = {
{ {
.drm = DRM_FORMAT_XRGB8888, .drm = DRM_FORMAT_XRGB8888,
@@ -109,6 +110,7 @@ static const struct hvs_format {
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCRCB, .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB, .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
.hvs6_swap_chroma_pointers = true,
}, },
{ {
.drm = DRM_FORMAT_YUV444, .drm = DRM_FORMAT_YUV444,
@@ -121,6 +123,7 @@ static const struct hvs_format {
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCRCB, .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB, .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
.hvs6_swap_chroma_pointers = true,
}, },
{ {
.drm = DRM_FORMAT_YUV420, .drm = DRM_FORMAT_YUV420,
@@ -133,6 +136,7 @@ static const struct hvs_format {
.hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE, .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
.pixel_order = HVS_PIXEL_ORDER_XYCRCB, .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
.pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB, .pixel_order_hvs5 = HVS_PIXEL_ORDER_XYCRCB,
.hvs6_swap_chroma_pointers = true,
}, },
{ {
.drm = DRM_FORMAT_NV12, .drm = DRM_FORMAT_NV12,
@@ -1873,6 +1877,14 @@ static u32 vc6_plane_get_csc_mode(struct vc4_plane_state *vc4_state)
return ret; return ret;
} }
static int vc6_get_plane_idx(const struct hvs_format *format, int plane)
{
if (!plane || !format->hvs6_swap_chroma_pointers)
return plane;
return (plane == 1) ? 2 : 1;
}
static int vc6_plane_mode_set(struct drm_plane *plane, static int vc6_plane_mode_set(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
@@ -2165,8 +2177,10 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
* TODO: This only covers Raster Scan Order planes * TODO: This only covers Raster Scan Order planes
*/ */
for (i = 0; i < num_planes; i++) { for (i = 0; i < num_planes; i++) {
struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, i); int idx = vc6_get_plane_idx(format, i);
dma_addr_t paddr = bo->dma_addr + fb->offsets[i] + offsets[i]; struct drm_gem_dma_object *bo =
drm_fb_dma_get_gem_obj(fb, idx);
dma_addr_t paddr = bo->dma_addr + fb->offsets[idx] + offsets[idx];
/* Pointer Word 0 */ /* Pointer Word 0 */
vc4_state->ptr0_offset[i] = vc4_state->dlist_count; vc4_state->ptr0_offset[i] = vc4_state->dlist_count;