From 7ff02d92deef4bd12824c8af2bb45f508b55396b Mon Sep 17 00:00:00 2001 From: James Calligeros Date: Mon, 2 Mar 2026 21:15:07 +1000 Subject: [PATCH 1/2] drm: apple: Force colour management changes on CRTC enable Signed-off-by: James Calligeros --- drivers/gpu/drm/apple/apple_drv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/apple/apple_drv.c b/drivers/gpu/drm/apple/apple_drv.c index ab9fd49467dcfc..3c2ede2ee81bf7 100644 --- a/drivers/gpu/drm/apple/apple_drv.c +++ b/drivers/gpu/drm/apple/apple_drv.c @@ -111,8 +111,11 @@ static void apple_crtc_atomic_enable(struct drm_crtc *crtc, dcp_poweron(apple_crtc->dcp); } - if (crtc_state->active) + if (crtc_state->active) { + /* Force the CTM to be set on first swap */ + crtc_state->color_mgmt_changed = true; dcp_crtc_atomic_modeset(crtc, state); + } } static void apple_crtc_atomic_disable(struct drm_crtc *crtc, From 6d4a11790163a0b467093d3f8eec4f8038e99a05 Mon Sep 17 00:00:00 2001 From: James Calligeros Date: Mon, 2 Mar 2026 21:15:49 +1000 Subject: [PATCH 2/2] drm: apple: Explicitly set the identity matrix when no CTM blob exists Some clients will clear/free the CTM property blob rather than set it explicitly to the identity matrix. Since we were checking for a valid CTM blob, this was resulting in a misconfigured colour management pipeline. This was most noticeable when using kwin's Night Light feature, specifically when waking the display after the morning transition was supposed to happen. Despite triggering a colour management change on CRTC enable, kwin clearing the CTM blob meant that there was nothing for us to passs in to IOMFB to set DCP's internal CTM. Explicitly pass the identity matrix to IOMFB if we have a pending colour management change and no CTM blob. Signed-off-by: James Calligeros --- drivers/gpu/drm/apple/iomfb_template.c | 41 +++++++++++++++++++------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/apple/iomfb_template.c b/drivers/gpu/drm/apple/iomfb_template.c index c016e75bc2d480..d14e30ca34dc5e 100644 --- a/drivers/gpu/drm/apple/iomfb_template.c +++ b/drivers/gpu/drm/apple/iomfb_template.c @@ -1406,20 +1406,39 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru dcp->brightness.update = false; } - if (crtc_state->color_mgmt_changed && crtc_state->ctm) { + if (crtc_state->color_mgmt_changed) { struct iomfb_set_matrix_req mat; - struct drm_color_ctm *ctm = (struct drm_color_ctm *)crtc_state->ctm->data; mat.unk_u32 = 9; - mat.r[0] = ctm->matrix[0]; - mat.r[1] = ctm->matrix[1]; - mat.r[2] = ctm->matrix[2]; - mat.g[0] = ctm->matrix[3]; - mat.g[1] = ctm->matrix[4]; - mat.g[2] = ctm->matrix[5]; - mat.b[0] = ctm->matrix[6]; - mat.b[1] = ctm->matrix[7]; - mat.b[2] = ctm->matrix[8]; + + if (crtc_state->ctm) { + struct drm_color_ctm *ctm = (struct drm_color_ctm *)crtc_state->ctm->data; + + mat.r[0] = ctm->matrix[0]; + mat.r[1] = ctm->matrix[1]; + mat.r[2] = ctm->matrix[2]; + mat.g[0] = ctm->matrix[3]; + mat.g[1] = ctm->matrix[4]; + mat.g[2] = ctm->matrix[5]; + mat.b[0] = ctm->matrix[6]; + mat.b[1] = ctm->matrix[7]; + mat.b[2] = ctm->matrix[8]; + } else { + /* + * Some clients will clear/free the CTM blob rather than + * reset or ramp it back to the identity. Deal with these + * here. + */ + mat.r[0] = 1; + mat.r[1] = 0; + mat.r[2] = 0; + mat.g[0] = 0; + mat.g[1] = 1; + mat.g[2] = 0; + mat.b[0] = 0; + mat.b[1] = 0; + mat.b[2] = 1; + } iomfb_set_matrix(dcp, false, &mat, do_swap, NULL); } else