Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
33 changes: 33 additions & 0 deletions .github/workflows/new_version.yaml
Comment thread
RadxaYuntian marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Create release
on:
workflow_dispatch:

permissions:
contents: write

jobs:
build:
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
token: ${{secrets.GIT_PUSH_TOKEN}}
- name: Create release commit
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y git-buildpackage
export DEBEMAIL="dev@radxa.com"
export DEBFULLNAME='"Radxa Computer Co., Ltd"'
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Test
run: |
sudo apt-get install --no-install-recommends -y devscripts
sudo apt build-dep -y .
make deb
- name: Push
run: |
git push
88 changes: 88 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Build & Release
on:
workflow_dispatch:
pull_request:
push:
merge_group:

jobs:
build:
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y git-buildpackage devscripts
export DEBEMAIL="dev@radxa.com"
export DEBFULLNAME='"Radxa Computer Co., Ltd"'
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
sudo apt build-dep -y .
export DEB_BUILD_OPTIONS=nocheck
make deb
- name: Workaround actions/upload-artifact#176
run: |
echo "artifacts_path=$(realpath ..)" >> $GITHUB_ENV
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ github.event.repository.name }}
path: |
${{ env.artifacts_path }}/*.deb
release:
runs-on: ubuntu-24.04-arm
needs: build
if: github.event_name != 'pull_request' && github.event_name != 'merge_group' && github.ref_name == 'main'
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/download-artifact@v5
with:
name: ${{ github.event.repository.name }}
- name: Check if the latest version is releasable
run: |
version="$(dpkg-parsechangelog -S Version)"
echo "version=$version" >> $GITHUB_ENV
echo "changes<<EOF" >> $GITHUB_ENV
echo '```' >> $GITHUB_ENV
echo "$(dpkg-parsechangelog -S Changes)" >> $GITHUB_ENV
echo '```' >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
if [[ -n "$(git tag -l "$version")" ]]
then
echo "distro=UNRELEASED" >> $GITHUB_ENV
else
echo "distro=$(dpkg-parsechangelog -S Distribution)" >> $GITHUB_ENV
fi
echo "$version" > VERSION
- name: Release
if: env.distro != 'UNRELEASED'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.version }}
body_path: README.md
token: ${{ secrets.GITHUB_TOKEN }}
target_commitish: main
draft: false
fail_on_unmatched_files: false
files: |
*.deb
pkg.conf
VERSION
- name: Append changelog
if: env.distro != 'UNRELEASED'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.version }}
body: |
## Changelog for ${{ env.version }}
${{ env.changes }}
append_body: true
- name: Update Test repos
if: env.distro != 'UNRELEASED'
uses: radxa-repo/update-repo-action@main
with:
test-repo: true
token: ${{ secrets.RADXA_APT_TEST_REPO_TOKEN }}
45 changes: 45 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
PROJECT ?= mutter
DEBIAN_RULES := debian/rules

.PHONY: all
all:

# Clean
#
.PHONY: distclean
distclean: clean

.PHONY: clean
clean: clean-deb

.PHONY: clean-deb
clean-deb:
rm -rf debian/.debhelper debian/${PROJECT} debian/debhelper-build-stamp debian/files debian/*.debhelper.log debian/*.postrm.debhelper debian/*.substvars

#
# Release
#
.PHONY: deb
deb: debian pre_debuild debuild post_debuild

.PHONY: pre_debuild
pre_debuild:
# dh default use Makefile, set meson.build explicitly
@echo "Checking if debian/rules needs --buildsystem=meson..."
@if ! grep -q -- '--buildsystem=meson' $(DEBIAN_RULES); then \
echo "Patching debian/rules to use meson..."; \
if grep -q 'dh $$@' $(DEBIAN_RULES); then \
sed -i 's/dh $$@/dh $$@ --buildsystem=meson/' $(DEBIAN_RULES); \
fi ;\
fi

.PHONY: debuild
debuild:
debuild --no-sign -b

.PHONY: post_debuild
post_debuild:

.PHONY: release
release:
gh workflow run .github/workflows/new_version.yaml --ref $(shell git branch --show-current)
7 changes: 7 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
mutter (46.2-1ubuntu0.24.04.15-radxa-1) noble; urgency=medium

* d/p/radxa/kms-plane-Avoid-assigning-plane-active-on-other-CRTC.patch:
Fix plane switching CRTC on Qualcomm platforms causing EINVAL.

-- "Radxa Computer Co., Ltd" <dev@radxa.com> Mon, 25 May 2026 20:30:00 +0800

mutter (46.2-1ubuntu0.24.04.15) noble; urgency=medium

[ Simon Poirier ]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
From: Alessandro Astone <alessandro.astone@canonical.com>
Date: Fri, 12 Dec 2025 11:12:12 +0100
Subject: kms/plane: Avoid assigning a plane that is active on another CRTC

The DRM atomic API does not allow switching a plane from one CRTC to
another in a single commit. On Qualcomm platforms (SC8280XP), the
kernel's `plane_switching_crtc()` check rejects atomic commits that
reassign a plane to a different CRTC without first disabling it.

Add a `current_crtc_id` field to `MetaKmsPlane` (read from the DRM
plane at init time) and use it in `find_unassigned_plane()` to skip
planes that are currently active on a different CRTC. Also skip planes
that are already assigned to another CRTC in mutter's internal state.

This fixes "drmModeAtomicCommit: Invalid argument" errors when toggling
mirror/extend mode with multiple displays connected.

Origin: upstream, https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4850
Bug: https://gitlab.gnome.org/GNOME/mutter/-/issues/4399
Bug-Radxa: HDMI/DP multi-display mode switching EINVAL on Q8B (SC8280XP)
Forwarded: not-needed
Last-Update: 2025-05-25
---
src/backends/native/meta-crtc-kms.c | 53 ++++++++++++++++++++++++++++
src/backends/native/meta-kms-plane-private.h | 2 +
src/backends/native/meta-kms-plane.c | 8 ++++
3 files changed, 63 insertions(+)

diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
index 3498f922a..9a4051c7b 100644
--- a/src/backends/native/meta-crtc-kms.c
+++ b/src/backends/native/meta-crtc-kms.c
@@ -30,6 +30,7 @@
#include "backends/native/meta-kms-device.h"
#include "backends/native/meta-kms-mode.h"
#include "backends/native/meta-kms-plane.h"
+#include "backends/native/meta-kms-plane-private.h"
#include "backends/native/meta-kms-update.h"
#include "backends/native/meta-kms.h"
#include "backends/native/meta-monitor-manager-native.h"
@@ -247,6 +248,44 @@ is_plane_assigned (MetaKmsPlane *plane,
return FALSE;
}

+static gboolean
+is_plane_active_on_other_crtc (MetaKmsDevice *kms_device,
+ MetaKmsPlane *kms_plane,
+ MetaKmsCrtc *target_kms_crtc,
+ MetaKmsPlaneType kms_plane_type)
+{
+ GList *l;
+
+ for (l = meta_kms_device_get_crtcs (kms_device); l; l = l->next)
+ {
+ MetaKmsCrtc *kms_crtc = l->data;
+ MetaCrtcKms *crtc_kms;
+ MetaKmsPlane *assigned = NULL;
+
+ if (kms_crtc == target_kms_crtc)
+ continue;
+
+ crtc_kms = meta_crtc_kms_from_kms_crtc (kms_crtc);
+
+ switch (kms_plane_type)
+ {
+ case META_KMS_PLANE_TYPE_PRIMARY:
+ assigned = meta_crtc_kms_get_assigned_primary_plane (crtc_kms);
+ break;
+ case META_KMS_PLANE_TYPE_CURSOR:
+ assigned = meta_crtc_kms_get_assigned_cursor_plane (crtc_kms);
+ break;
+ default:
+ break;
+ }
+
+ if (assigned == kms_plane)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static MetaKmsPlane *
find_unassigned_plane (MetaCrtcKms *crtc_kms,
MetaKmsPlaneType kms_plane_type,
@@ -254,6 +293,7 @@ find_unassigned_plane (MetaCrtcKms *crtc_kms,
{
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
+ uint32_t target_crtc_id = meta_kms_crtc_get_id (kms_crtc);
GList *l;

for (l = meta_kms_device_get_planes (kms_device); l; l = l->next)
@@ -266,6 +306,19 @@ find_unassigned_plane (MetaCrtcKms *crtc_kms,
if (!meta_kms_plane_is_usable_with (kms_plane, kms_crtc))
continue;

+ /*
+ * The DRM atomic API does not allow switching a plane from one CRTC
+ * to another in a single commit. Skip planes that are currently
+ * active on a different CRTC to avoid EINVAL from the kernel.
+ */
+ if (meta_kms_plane_get_current_crtc_id (kms_plane) != 0 &&
+ meta_kms_plane_get_current_crtc_id (kms_plane) != target_crtc_id)
+ continue;
+
+ if (is_plane_active_on_other_crtc (kms_device, kms_plane,
+ kms_crtc, kms_plane_type))
+ continue;
+
if (is_plane_assigned (kms_plane, kms_plane_type,
crtc_assignments))
continue;
diff --git a/src/backends/native/meta-kms-plane-private.h b/src/backends/native/meta-kms-plane-private.h
index 8d3c5f88c..c06d403c3 100644
--- a/src/backends/native/meta-kms-plane-private.h
+++ b/src/backends/native/meta-kms-plane-private.h
@@ -87,3 +87,5 @@ uint64_t meta_kms_plane_get_prop_drm_value (MetaKmsPlane *plane,

MetaKmsPropType meta_kms_plane_get_prop_internal_type (MetaKmsPlane *plane,
MetaKmsPlaneProp prop);
+
+uint32_t meta_kms_plane_get_current_crtc_id (MetaKmsPlane *plane);
diff --git a/src/backends/native/meta-kms-plane.c b/src/backends/native/meta-kms-plane.c
index 69a0b12d3..63da9c4b4 100644
--- a/src/backends/native/meta-kms-plane.c
+++ b/src/backends/native/meta-kms-plane.c
@@ -44,6 +44,7 @@ struct _MetaKmsPlane
gboolean is_fake;

uint32_t id;
+ uint32_t current_crtc_id;

uint32_t possible_crtcs;

@@ -83,6 +84,12 @@ meta_kms_plane_get_plane_type (MetaKmsPlane *plane)
return plane->type;
}

+uint32_t
+meta_kms_plane_get_current_crtc_id (MetaKmsPlane *plane)
+{
+ return plane->current_crtc_id;
+}
+
uint32_t
meta_kms_plane_get_prop_id (MetaKmsPlane *plane,
MetaKmsPlaneProp prop)
@@ -581,6 +588,7 @@ meta_kms_plane_new (MetaKmsPlaneType type,
plane = g_object_new (META_TYPE_KMS_PLANE, NULL);
plane->type = type;
plane->id = drm_plane->plane_id;
+ plane->current_crtc_id = drm_plane->crtc_id;
plane->possible_crtcs = drm_plane->possible_crtcs;
plane->device = meta_kms_impl_device_get_device (impl_device);
1 change: 1 addition & 0 deletions debian/patches/series
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ window-drag-Handle-pointer-emulated-touch-events.patch
backends-output-Allow-checking-whether-an-output-already-.patch
compositor-Handle-skipped-transition-in-visual-bell.patch
Backport-mutter-merge-request-3184-for-fixing-glxgears-fp.patch
radxa/kms-plane-Avoid-assigning-plane-active-on-other-CRTC.patch
Loading