From 50db17f86f92b0a68a58f1f28a84a216cdf73552 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 11 Nov 2026 11:18:49 -0700 Subject: [PATCH 1/3] drm/apple: answer the PMU temperature for every panel, quiet the TAOC fallback The firmware asks the AP for the PMU temperature property at boot (callback D401 "PMUS"/"Temperature") for its panel compensation's initial guess; the driver answered it only for mini-LED panels, so the OLED K116s logged "set_PMU_service: failed to read PMU temperature property!" twice. Answer with the battery temperature as the H17P and v14.7 paths do. The DCP also reads eleven SMC temperature keys itself for its 2D virtual temperature model and logs once a second that TAOC is -127.0, the SMC's no-sample value, and that it uses the 2DVT fallback. TAOC and its siblings are AOP-sourced sensors the SMC has no sample for until the AOP's sensor servers run, so route that record to the debug level; another sensor, value or verdict stays at info. This is a behaviour change for every panel that is not mini-LED, on every firmware this template drives: the firmware's PMUS "Temperature" request used to get "false" there and now gets the battery temperature, which its panel compensation then takes as the panel's initial temperature. Mini-LED panels got the temperature before and still do. Signed-off-by: Jens Axboe [thomas: describe the PMUS reply as a behaviour change] Signed-off-by: Thomas Glanzmann --- drivers/gpu/drm/apple/dcp-syslog-test.c | 9 +++++++++ drivers/gpu/drm/apple/dcp-syslog.h | 11 +++++++++++ drivers/gpu/drm/apple/iomfb_template.c | 11 +++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/apple/dcp-syslog-test.c b/drivers/gpu/drm/apple/dcp-syslog-test.c index a4442810e88a8..256343fa38ccf 100644 --- a/drivers/gpu/drm/apple/dcp-syslog-test.c +++ b/drivers/gpu/drm/apple/dcp-syslog-test.c @@ -18,6 +18,8 @@ static void dcp_syslog_transition_test(struct kunit *test) "ready_for_run_mode_change: initiating deferred run mode change: 4 -> 1" }, { "UPPipeDCP_H17P.cpp:2014", "ready_for_run_mode_change: initiating deferred run mode change: 2 -> 4" }, + { "itorContext_v4.cpp:1324", + "SMC sensor TAOC is an invalid temp -127.0, using 2DVT fallback values" }, }; char message[128]; int i; @@ -46,6 +48,13 @@ static void dcp_syslog_unknown_test(struct kunit *test) { "UPPipeDCP_H17P.cpp:2014", "ready_for_run_mode_change: timeout" }, { "UPPipeDCP_H17P.cpp:2096", "set_run_mode_safe: error -110" }, { "UPPipeDCP_H17P.cpp:2097", "set_run_mode_safe: deferring: 4 -> 1" }, + /* A different sensor, value or verdict is news. */ + { "itorContext_v4.cpp:1324", + "SMC sensor TAOJ is an invalid temp -127.0, using 2DVT fallback values" }, + { "itorContext_v4.cpp:1324", + "SMC sensor TAOC is an invalid temp -40.0, using 2DVT fallback values" }, + { "itorContext_v4.cpp:1324", + "2DVT thermal sensors valid, using computed virtual temperatures" }, }; int i; diff --git a/drivers/gpu/drm/apple/dcp-syslog.h b/drivers/gpu/drm/apple/dcp-syslog.h index c1bf4f3616ea2..d54897f453185 100644 --- a/drivers/gpu/drm/apple/dcp-syslog.h +++ b/drivers/gpu/drm/apple/dcp-syslog.h @@ -24,6 +24,17 @@ static inline bool dcp_h17p_syslog_is_debug(const char *context, const char *mes !strcmp(message, "set_run_mode_safe: deferring: 2 -> 4"); if (!strcmp(context, "UPPipeDCP_H17P.cpp:2014")) return !strcmp(message, deferred_4_1) || !strcmp(message, deferred_2_4); + /* + * The 27.x panel temperature monitor (IOMFBTemperatureMonitorContext_v4) + * reads its sensor keys from the SMC once a second and falls back to the + * default 2D virtual temperature grid while TAOC holds the SMC's -127.0 + * "no sample" sentinel (the AOP feeds TAOC/TAOJ/TAOP in macOS; nothing + * does under Linux). Match the exact record so another sensor or value + * stays visible. + */ + if (!strcmp(context, "itorContext_v4.cpp:1324")) + return !strcmp(message, "SMC sensor TAOC is an invalid temp -127.0, " + "using 2DVT fallback values"); return false; } diff --git a/drivers/gpu/drm/apple/iomfb_template.c b/drivers/gpu/drm/apple/iomfb_template.c index d070c3b5b9158..4fff1ea7b57db 100644 --- a/drivers/gpu/drm/apple/iomfb_template.c +++ b/drivers/gpu/drm/apple/iomfb_template.c @@ -1014,8 +1014,15 @@ dcpep_cb_get_uint_prop(struct apple_dcp *dcp, struct dcp_get_uint_prop_req *req) .value = 0 }; - if (dcp->panel.has_mini_led && - memcmp(req->obj, "SUMP", sizeof(req->obj)) == 0) { /* "PMUS */ + /* + * "PMUS"/"Temperature": the battery temperature in 0.1 K. Every + * firmware with a panel asks for it from TableCompensator:: + * set_PMU_service(), mini-LED or not: the OLED firmware (27.x on the + * K116s) uses it as the panel's initial temperature guess and logs + * "failed to read PMU temperature property!" when the reply is + * false. The H17P table already answers it unconditionally. + */ + if (memcmp(req->obj, "SUMP", sizeof(req->obj)) == 0) { /* "PMUS */ if (strncmp(req->key, "Temperature", sizeof(req->key)) == 0) { resp.value = dcp_pmu_temperature(dcp->dev); resp.ret = true; From 8847a289036a656b360475b334d77db3ad0b879e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 11 Nov 2026 11:51:39 -0700 Subject: [PATCH 2/3] drm/apple: apply the syslog debug filter to the internal panel's DCP too The filter that demotes known-benign firmware syslog records was only in the external H17P RTKit ops, so the TAOC fallback record still logged once a second on the internal panel. The apple-dcp host test's syslog check expects the hook on both RTKit ops now. Signed-off-by: Jens Axboe [thomas: update the apple-dcp host test to the new policy] Signed-off-by: Thomas Glanzmann --- drivers/gpu/drm/apple/dcp.c | 11 ++++++----- tools/testing/selftests/drivers/gpu/apple-dcp/boot.py | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/apple/dcp.c b/drivers/gpu/drm/apple/dcp.c index 7fb810d0320d0..4ff52115cbf47 100644 --- a/drivers/gpu/drm/apple/dcp.c +++ b/drivers/gpu/drm/apple/dcp.c @@ -1705,18 +1705,19 @@ static void dcp_rtk_shmem_destroy(void *cookie, struct apple_rtkit_shmem *bfr) dma_free_coherent(dcp->dev, bfr->size, bfr->buffer, bfr->iova); } +static bool dcp_rtk_syslog_is_debug(void *cookie, const char *context, const char *message) +{ + return dcp_h17p_syslog_is_debug(context, message); +} + static struct apple_rtkit_ops rtkit_ops = { + .syslog_is_debug = dcp_rtk_syslog_is_debug, .crashed = dcp_rtk_crashed, .recv_message = dcp_recv_msg, .shmem_setup = dcp_rtk_shmem_setup, .shmem_destroy = dcp_rtk_shmem_destroy, }; -static bool dcp_rtk_syslog_is_debug(void *cookie, const char *context, const char *message) -{ - return dcp_h17p_syslog_is_debug(context, message); -} - static const struct apple_rtkit_ops external_h17p_rtkit_ops = { .flags = APPLE_RTKIT_COPROC_PLACES_BUFFERS, .syslog_is_debug = dcp_rtk_syslog_is_debug, diff --git a/tools/testing/selftests/drivers/gpu/apple-dcp/boot.py b/tools/testing/selftests/drivers/gpu/apple-dcp/boot.py index 95c02e87ddc02..a01a8dcb5f510 100644 --- a/tools/testing/selftests/drivers/gpu/apple-dcp/boot.py +++ b/tools/testing/selftests/drivers/gpu/apple-dcp/boot.py @@ -92,9 +92,10 @@ def syslog(root): dcp = (root / 'drivers/gpu/drm/apple/dcp.c').read_text() header = (root / 'drivers/gpu/drm/apple/dcp-syslog.h').read_text() helper = header[header.index('static inline bool'):header.index('\n#endif')] - # The policy belongs only to the external H17P transport. Other RTKit - # clients, including the panel and older DCP firmware, keep info logging. - assert '.syslog_is_debug' not in block(dcp, 'static struct apple_rtkit_ops rtkit_ops =') + # The policy covers both DCP transports, the internal panel's and the + # external H17P one. It demotes only the known records it matches, so other + # records, other firmware and other RTKit clients keep info logging. + assert '.syslog_is_debug = dcp_rtk_syslog_is_debug' in block(dcp, 'static struct apple_rtkit_ops rtkit_ops =') assert '.syslog_is_debug = dcp_rtk_syslog_is_debug' in block(dcp, 'static const struct apple_rtkit_ops external_h17p_rtkit_ops =') return r''' #include From 907bb7ec5990a7662ce65087c70432252aeceadf Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 11 Nov 2026 13:29:58 -0700 Subject: [PATCH 3/3] drm/apple: take the 27.2 D590 notification as a no-op The 27.2 firmware sends a 20-byte D590 notification with no reply after swaps (the macOS handler next to swap_info is the buffer-release notification). Nothing here consumes it, so take it as a no-op instead of warning about an unknown callback. Signed-off-by: Jens Axboe --- drivers/gpu/drm/apple/iomfb_v27.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/apple/iomfb_v27.c b/drivers/gpu/drm/apple/iomfb_v27.c index 93d2fa72cc41b..57eba1fb0223a 100644 --- a/drivers/gpu/drm/apple/iomfb_v27.c +++ b/drivers/gpu/drm/apple/iomfb_v27.c @@ -474,6 +474,12 @@ static const iomfb_cb_handler cb_handlers[IOMFB_MAX_CB] = { [587] = trampoline_nop, [588] = trampoline_nop, [589] = trampoline_swap_info_h17p, + /* + * 27.2 sends this 20-byte notification with no reply after swaps (the + * macOS handler next to swap_info is the buffer-release notification); + * nothing here consumes it. + */ + [590] = trampoline_nop, [592] = trampoline_nop, [594] = trampoline_swap_complete, @@ -560,6 +566,7 @@ static const struct { [587] = { 0x0, 0x0 }, [588] = { 0x18, 0x0 }, [589] = { 0xe4, 0xe0 }, + [590] = { 0x14, 0x0 }, [592] = { 0x0, 0x0 }, [594] = { 0x730, 0x0 }, [596] = { 0x14, 0x0 },