Subject: [PATCH 23/24] drm: detach cursor planes in grouped tiled DPMS disable

From: Justin Youens <[email-masked]>
Date: Tue, 18 Aug 2026 11:40:29 -0500

Hardware cursor planes stayed assigned to the UltraFine CRTCs, so the
kernel rejected the all-member disable even after the classifier accepted
enabled=false. Clear each member primary and cursor before dropping
ACTIVE and CRTC_ID.
---
 src/backend/drm/TiledRuntimeAuthority.cpp | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/backend/drm/TiledRuntimeAuthority.cpp b/src/backend/drm/TiledRuntimeAuthority.cpp
index 632346955024bc9922dddf4918718109c49727ec..e1c0342665a9ed954ed926a8b7720a0edb315471 100644
--- a/src/backend/drm/TiledRuntimeAuthority.cpp
+++ b/src/backend/drm/TiledRuntimeAuthority.cpp
@@ -8,6 +8,7 @@
 #include <functional>
 #include <limits>
 #include <ranges>
+#include <set>
 #include <utility>
 
 #include <drm_fourcc.h>
@@ -1308,18 +1309,22 @@ CGroupedRuntimeAuthority::SGroupedDisableResult CGroupedRuntimeAuthority::submit
                                              const auto add = [&](uint32_t objectId, uint32_t propertyId, uint64_t value) {
                                                  return propertyId == 0 || operations->addProperty(request, objectId, propertyId, value) >= 0;
                                              };
-                                             bool ok = true;
+                                             const auto disablePlane = [&](const CSharedPointer<SDRMPlane>& plane, std::set<uint32_t>& seen) {
+                                                 if (!plane || plane->id == 0 || !seen.insert(plane->id).second)
+                                                     return true;
+                                                 return add(plane->id, plane->props.values.fb_id, 0) && add(plane->id, plane->props.values.crtc_id, 0);
+                                             };
+                                             bool               ok = true;
+                                             std::set<uint32_t> seenPlanes;
                                              for (const auto& MEMBER : members) {
                                                  ok = ok && add(MEMBER->id, MEMBER->props.values.crtc_id, 0);
                                                  ok = ok && add(MEMBER->id, MEMBER->props.values.dpms, DRM_MODE_DPMS_OFF);
                                                  if (!MEMBER->crtc)
                                                      continue;
+                                                 ok = ok && disablePlane(MEMBER->crtc->primary, seenPlanes);
+                                                 ok = ok && disablePlane(MEMBER->crtc->cursor, seenPlanes);
                                                  ok = ok && add(MEMBER->crtc->id, MEMBER->crtc->props.values.mode_id, 0);
                                                  ok = ok && add(MEMBER->crtc->id, MEMBER->crtc->props.values.active, 0);
-                                                 if (!MEMBER->crtc->primary)
-                                                     continue;
-                                                 ok = ok && add(MEMBER->crtc->primary->id, MEMBER->crtc->primary->props.values.fb_id, 0);
-                                                 ok = ok && add(MEMBER->crtc->primary->id, MEMBER->crtc->primary->props.values.crtc_id, 0);
                                              }
                                              return ok;
                                          });