From caaef210e85f91314de646708c8c798b70c2fb26 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Mon, 2 Nov 2026 00:37:38 -0500 Subject: [PATCH] drm/apple: use the 14.7 swap_start layout in the classic template On a J613's external processor, swap_start's reply is eight bytes, the swap ID and a status, as the native 14.7 path and the 26.x template read it. The classic template's 14.7 instance still expected 24, with the status at the end. That didn't matter until "drm: apple: retain displaced framebuffers until confirmed completion" began checking the status and filling replies with 0xff first. The firmware doesn't write that far, so the template read 0xffffffff and refused every swap: the mode set succeeds, and the display stays dark. A dump of the reply, with the fill changed, shows the swap ID, a status of 0, then the bytes it left alone. Use the 0x10-byte request and 8-byte reply for this template instance, as those paths do. Any other DCP on 14.7.0 firmware also uses this instance: we have no way to test one. Fixes: 98d767ecf92 ("drm/apple, media: apple: avd: T6030 internal panel, external display and AVD fixes") Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Scott Jones --- drivers/gpu/drm/apple/iomfb_template.h | 31 +++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/apple/iomfb_template.h b/drivers/gpu/drm/apple/iomfb_template.h index b987ddfbd8ce74..68021cff617618 100644 --- a/drivers/gpu/drm/apple/iomfb_template.h +++ b/drivers/gpu/drm/apple/iomfb_template.h @@ -162,12 +162,10 @@ struct DCP_FW_NAME(dcp_swap_submit_resp) { } __packed; /* - * A406 swap_start / A473 set_power_state. H17P shrank both requests: the - * 0x10-byte struct dcp_iouserclient became a bare u64 handle and the - * swap_start response no longer echoes it. swap_start is 0x10 in / 0x8 out, - * set_power_state 0x10 in. + * A406 swap_start. From 14.7 the 0x10-byte struct dcp_iouserclient is a bare + * u64 handle, and the response no longer echoes it: 0x10 in, 8 out. */ -#if DCP_FW_VER >= DCP_FW_VERSION(26, 0, 0) +#if DCP_FW_VER >= DCP_FW_VERSION(26, 0, 0) || DCP_FW_LAYOUT_14_7(DCP_FW_VER) struct DCP_FW_NAME(dcp_swap_start_req) { u32 swap_id; u64 client; /* IOUserClient kernel VA */ @@ -180,16 +178,8 @@ struct DCP_FW_NAME(dcp_swap_start_resp) { u32 ret; } __packed; -struct DCP_FW_NAME(dcp_set_power_state_req) { - u64 unklong; - u32 unkint; /* widened from u8 on H17P */ - u8 unkint_null; - u8 padding[3]; -} __packed; - static_assert(sizeof(struct DCP_FW_NAME(dcp_swap_start_req)) == 0x10); static_assert(sizeof(struct DCP_FW_NAME(dcp_swap_start_resp)) == 0x8); -static_assert(sizeof(struct DCP_FW_NAME(dcp_set_power_state_req)) == 0x10); #else struct DCP_FW_NAME(dcp_swap_start_req) { u32 swap_id; @@ -204,7 +194,22 @@ struct DCP_FW_NAME(dcp_swap_start_resp) { struct dcp_iouserclient client; u32 ret; } __packed; +#endif + +/* + * A473 set_power_state. H17P shrank the request: the iouserclient became a + * bare u64 handle, 0x10 in. + */ +#if DCP_FW_VER >= DCP_FW_VERSION(26, 0, 0) +struct DCP_FW_NAME(dcp_set_power_state_req) { + u64 unklong; + u32 unkint; /* widened from u8 on H17P */ + u8 unkint_null; + u8 padding[3]; +} __packed; +static_assert(sizeof(struct DCP_FW_NAME(dcp_set_power_state_req)) == 0x10); +#else struct DCP_FW_NAME(dcp_set_power_state_req) { u64 unklong; u8 unkbool;