aboutsummaryrefslogtreecommitdiffci
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
-rw-r--r--Jenkinsfile54
-rw-r--r--README.md45
-rw-r--r--config/base-aarch64.config23
-rw-r--r--config/foreign-socs.config68
-rw-r--r--kernel-sp12in.repo2
-rw-r--r--kernel-surface.spec45
-rwxr-xr-xmake-sources.sh28
m---------overlay0
-rw-r--r--patch-order.txt15
-rw-r--r--patches/camera/0027-media-i2c-ov13858-fix-bayer-order-when-mirrored.patch142
-rw-r--r--patches/surface/0016-arm64-dts-qcom-purwa-Microsoft-Surface-Pro-12in-iris-firmware-name.patch32
11 files changed, 392 insertions, 62 deletions
diff --git a/Jenkinsfile b/Jenkinsfile
index 74f942c..1ab3e47 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -71,7 +71,7 @@ spec:
memory: 5Gi
ephemeral-storage: 40Gi
limits:
- memory: 7Gi
+ memory: 5Gi
ephemeral-storage: 100Gi
"""
}
@@ -118,22 +118,31 @@ spec:
rpmdev-setuptree
- # The published file name is whatever the spec
+ # The published file names are whatever the spec
# resolves to under the tag's versions, so the two
- # cannot drift. A kernel build is expensive; if this
- # exact NEVRA is already in the bucket, skip
- # straight to the metadata.
- rpm_file=$(rpmspec -q \\
+ # cannot drift. Note the plural: kernel-surface-dtb
+ # is a separate package because the main one is
+ # installonly and cannot own a path that carries no
+ # kernel version. Publishing only the first would
+ # leave the kernel unresolvable.
+ prefix="s3://${RPM_BUCKET}/fedora/${fedora_version}/aarch64"
+ rpm_files=$(rpmspec -q \\
--define "upstream_ver ${UPSTREAM_VER}" \\
--define "patchset_ver ${PATCHSET_VER}" \\
--queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm\\n' \\
- kernel-surface.spec | head -n1)
- dest="s3://${RPM_BUCKET}/fedora/${fedora_version}/aarch64/${rpm_file}"
+ kernel-surface.spec)
- skip_build=false
- if aws s3 ls --endpoint-url "${B2_ENDPOINT}" "${dest}"; then
- echo "${rpm_file} already published, skipping build"
- skip_build=true
+ # A kernel build is expensive; skip it only when
+ # every one of those is already in the bucket.
+ skip_build=true
+ for rpm_name in ${rpm_files}; do
+ if ! aws s3 ls --endpoint-url "${B2_ENDPOINT}" \\
+ "${prefix}/${rpm_name}"; then
+ skip_build=false
+ fi
+ done
+ if [ "${skip_build}" = true ]; then
+ echo "${TAG_NAME} is already published in full, skipping build"
fi
if [ "${skip_build}" = false ]; then
@@ -146,29 +155,34 @@ spec:
--define '_smp_mflags -j4' \\
kernel-surface.spec
- built="${HOME}/rpmbuild/RPMS/aarch64/${rpm_file}"
- test -f "${built}"
+ # kernel-surface-dtb is noarch, so it lands
+ # in RPMS/noarch rather than RPMS/aarch64; ask
+ # where each one actually is.
+ for rpm_name in ${rpm_files}; do
+ built=$(find "${HOME}/rpmbuild/RPMS" -type f \\
+ -name "${rpm_name}" -print -quit)
+ test -n "${built}"
- aws s3 cp --endpoint-url "${B2_ENDPOINT}" \\
- "${built}" "${dest}"
+ aws s3 cp --endpoint-url "${B2_ENDPOINT}" \\
+ "${built}" "${prefix}/${rpm_name}"
+ done
fi
- repo_url="s3://${RPM_BUCKET}/fedora/${fedora_version}/aarch64"
repo="${WORKSPACE}/repo"
mkdir -p "${repo}"
aws s3 sync --endpoint-url "${B2_ENDPOINT}" \\
--exclude '*' --include '*.rpm' \\
- "${repo_url}/" "${repo}/"
+ "${prefix}/" "${repo}/"
createrepo_c --update "${repo}"
aws s3 sync --endpoint-url "${B2_ENDPOINT}" \\
--exclude 'repomd.xml*' \\
- "${repo}/repodata/" "${repo_url}/repodata/"
+ "${repo}/repodata/" "${prefix}/repodata/"
aws s3 cp --endpoint-url "${B2_ENDPOINT}" \\
"${repo}/repodata/repomd.xml" \\
- "${repo_url}/repodata/repomd.xml"
+ "${prefix}/repodata/repomd.xml"
# Served next to the repository so that consumers
# can `dnf config-manager --add-repo` the URL.
diff --git a/README.md b/README.md
index 8f2c9f0..bb8fcbd 100644
--- a/README.md
+++ b/README.md
@@ -13,25 +13,45 @@ Used in [Fedora KIWI descriptions, modified by me for Surface Pro 12"](https://s
`vanilla-kernel-*.ebuild` applies them, minus `gpu` (does not exist) and
`rockchip` (irrelevant).
+An entry prefixed with `local:` is not the overlay's, it is `patches/<name>/`
+in this repository. Those carry fixes the overlay has not picked up, and they
+live outside the submodule so that `git submodule update` cannot silently drop
+them. They are listed right after the overlay directory they extend, so the
+same numbering that orders the overlay's series orders these too.
+
+- `patches/camera/0027-media-i2c-ov13858-fix-bayer-order-when-mirrored.patch`
+ the rear camera advertises GRBG while the horizontal mirror, which
+ `rotation = <180>` turns on, makes it deliver RGGB. Debayering with the wrong
+ pattern puts both greens into the red and blue channels, so the picture comes
+ out close to monochrome.
+- `patches/surface/0016-arm64-dts-qcom-purwa-Microsoft-Surface-Pro-12in-iris-firmware-name.patch`
+ the video codec firmware in linux-firmware is signed with Qualcomm's SecTools
+ test key, which this device's TrustZone rejects with `error -22 initializing
+ firmware`. Points the iris node at the production-signed build shipped in the
+ Windows driver package instead.
+
+Send them upstream to the overlay when they are ready; drop the `local:` entry
+and the directory once the overlay carries them.
+
## Configuration
The starting point is `config/base-aarch64.config`: Fedora's own aarch64
-kernel config, taken verbatim from the `config` file inside
-`kernel-core-7.2.0-61.fc45.aarch64.rpm`. It is vendored rather than downloaded,
-so the build depends on no third-party host and a refresh shows up as a
-reviewable diff. To refresh it for a newer Fedora, replace everything below the
-comment header with:
+kernel config, taken verbatim from the `config` file. It is vendored rather
+than downloaded, so the build depends on no third-party host and a refresh
+shows up as a reviewable diff. To refresh it for a newer Fedora, replace
+everything below the comment header with:
```bash
dnf download kernel-core --arch aarch64
-rpm2cpio kernel-core-*.aarch64.rpm | cpio -idm './usr/lib/modules/*/config'
+rpm2archive -n - < kernel-core-*.aarch64.rpm |
+ tar -xO --wildcards '*/modules/*/config' |
+ wl-copy
```
-The overlay's ebuild seeds itself from the same Fedora config by way of a
-Gentoo-side fork, `projg2/fedora-kernel-config-for-gentoo`. That repository no
-longer exists, which is why the base config lives here instead.
+If the extraction comes up empty, `rpm -qlp kernel-core-*.aarch64.rpm | grep
+config` says whether the package still carries the file at all.
-Three fragments are merged on top with `scripts/kconfig/merge_config.sh`:
+Four fragments are merged on top with `scripts/kconfig/merge_config.sh`:
* `config/surface.config` – the drivers the patch set enables (SAM stack and
its new RTC, CAMSS and the CSI-2 D-PHY, fastrpc, ath12k, AudioReach).
@@ -39,6 +59,9 @@ Three fragments are merged on top with `scripts/kconfig/merge_config.sh`:
and dm-snapshot/overlayfs built in for `dracut`'s `dmsquash-live`, the EFI
stub because GRUB's aarch64 `linux` command loads the kernel as an EFI
application, and xz module compression.
+* `config/foreign-socs.config` – the ARM64 platforms this machine is not.
+ Fedora's config enables every platform it supports because a distribution
+ kernel has to boot on all of them; this one boots on `qcom,x1p42100` alone.
* `config/no-debug-info.config` – DWARF and BTF off. The package produces no
`-debuginfo` subpackage (`%global debug_package %{nil}`) and strips modules
at install time, so the DWARF was compiled only to be discarded, and it is
@@ -62,7 +85,7 @@ matches the ISO (the project README notes Secure Boot is not available for it).
```bash
dnf config-manager addrepo --from-repofile=\
- https://f003.backblazeb2.com/file/dist-sayagit-fedora-rpm/fedora/45/kernel-sp12in.repo
+ https://rpm.sayag.it/kernel-sp12in/fedora/45/kernel-sp12in.repo
```
## Building
diff --git a/config/base-aarch64.config b/config/base-aarch64.config
index 8ccb3a9..ed863d0 100644
--- a/config/base-aarch64.config
+++ b/config/base-aarch64.config
@@ -1,10 +1,11 @@
# Fedora's own aarch64 kernel configuration, used as the starting point for
# this package. Taken verbatim from the config shipped inside
-# kernel-core-7.2.0-61.fc45.aarch64.rpm:
+# kernel-core-7.2.4-300.fc45.aarch64.rpm:
#
# dnf download kernel-core --arch aarch64
-# rpm2cpio kernel-core-*.aarch64.rpm |
-# cpio -idm './usr/lib/modules/*/config'
+# rpm2archive -n - < kernel-core-*.aarch64.rpm |
+# tar -xO --wildcards '*/modules/*/config' |
+# wl-copy
#
# It is vendored rather than downloaded so the build has no dependency on a
# third-party host, and so the base config is reviewable in a diff when it is
@@ -12,11 +13,11 @@
# top of it in %prep; do not edit this file by hand.
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 7.2.0-61.fc45.aarch64 Kernel Configuration
+# Linux/arm64 7.2.4-300.fc45.aarch64 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="gcc (GCC) 16.1.1 20260703 (Red Hat 16.1.1-4)"
+CONFIG_CC_VERSION_TEXT="gcc (GCC) 16.2.1 20260819 (Red Hat 16.2.1-2)"
CONFIG_CC_IS_GCC=y
-CONFIG_GCC_VERSION=160101
+CONFIG_GCC_VERSION=160201
CONFIG_CLANG_VERSION=0
CONFIG_AS_IS_GNU=y
CONFIG_AS_VERSION=20285426
@@ -56,7 +57,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_UAPI_HEADER_TEST=y
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_BUILD_SALT="7.2.0-61.fc45.aarch64"
+CONFIG_BUILD_SALT="7.2.4-300.fc45.aarch64"
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_ZSTD=y
# CONFIG_KERNEL_GZIP is not set
@@ -13229,11 +13230,9 @@ CONFIG_CRYPTO_DEV_SUN4I_SS=m
CONFIG_CRYPTO_DEV_SUN8I_CE=m
# CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG is not set
CONFIG_CRYPTO_DEV_SUN8I_CE_HASH=y
-CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG=y
CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG=y
CONFIG_CRYPTO_DEV_SUN8I_SS=m
# CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG is not set
-CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG=y
CONFIG_CRYPTO_DEV_SUN8I_SS_HASH=y
CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON=m
CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC=m
@@ -14083,9 +14082,3 @@ CONFIG_RUST_OVERFLOW_CHECKS=y
CONFIG_IO_URING_ZCRX=y
CONFIG_IO_URING_BPF=y
CONFIG_IO_URING_BPF_OPS=y
-
-#
-# Red Hat options
-#
-# CONFIG_RHEL_DIFFERENCES is not set
-# end of Red Hat options
diff --git a/config/foreign-socs.config b/config/foreign-socs.config
new file mode 100644
index 0000000..5926d06
--- /dev/null
+++ b/config/foreign-socs.config
@@ -0,0 +1,68 @@
+# Config fragment turning off the ARM64 platforms this machine is not.
+#
+# Two platforms are deliberately kept:
+#
+# ARCH_QCOM what this machine is.
+# ARCH_VEXPRESS cheap, and it is the ARM reference/model platform that pulls
+# in the AMBA PrimeCell parts a QEMU `virt` guest expects,
+# which is how an image built from this kernel can be smoke
+# tested without the hardware in hand.
+
+# Allwinner
+# CONFIG_ARCH_SUNXI is not set
+
+# Apple M-series
+# CONFIG_ARCH_APPLE is not set
+
+# Broadcom, including Raspberry Pi
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BCM2835 is not set
+
+# Black Sesame
+# CONFIG_ARCH_BST is not set
+
+# CIX
+# CONFIG_ARCH_CIX is not set
+
+# Texas Instruments K3
+# CONFIG_ARCH_K3 is not set
+
+# HiSilicon
+# CONFIG_ARCH_HISI is not set
+
+# Amlogic
+# CONFIG_ARCH_MESON is not set
+
+# Marvell EBU
+# CONFIG_ARCH_MVEBU is not set
+
+# NXP: i.MX, Layerscape and S32
+# CONFIG_ARCH_NXP is not set
+# CONFIG_ARCH_LAYERSCAPE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_S32 is not set
+
+# Renesas
+# CONFIG_ARCH_RENESAS is not set
+
+# Rockchip
+# CONFIG_ARCH_ROCKCHIP is not set
+
+# AMD Seattle
+# CONFIG_ARCH_SEATTLE is not set
+
+# Socionext SynQuacer
+# CONFIG_ARCH_SYNQUACER is not set
+
+# NVIDIA Tegra
+# CONFIG_ARCH_TEGRA is not set
+
+# Cavium ThunderX and ThunderX2 servers
+# CONFIG_ARCH_THUNDER is not set
+# CONFIG_ARCH_THUNDER2 is not set
+
+# AppliedMicro X-Gene
+# CONFIG_ARCH_XGENE is not set
+
+# Xilinx ZynqMP
+# CONFIG_ARCH_ZYNQMP is not set
diff --git a/kernel-sp12in.repo b/kernel-sp12in.repo
index 226108c..fa257a2 100644
--- a/kernel-sp12in.repo
+++ b/kernel-sp12in.repo
@@ -1,5 +1,5 @@
[kernel-sp12in]
name=kernel-sp12in for Fedora $releasever - $basearch
-baseurl=https://f003.backblazeb2.com/file/dist-sayagit-fedora-rpm/fedora/$releasever/$basearch/
+baseurl=https://rpm.sayag.it/kernel-sp12in/fedora/$releasever/$basearch/
enabled=1
gpgcheck=0
diff --git a/kernel-surface.spec b/kernel-surface.spec
index dc29ae3..ee6e132 100644
--- a/kernel-surface.spec
+++ b/kernel-surface.spec
@@ -12,7 +12,7 @@
# passes them in with --define, which takes precedence -- so keep the plain
# `%%global <name> <value>` shape, which make-sources.sh reads with awk.
%if %{undefined upstream_ver}
-%global upstream_ver 7.2.3
+%global upstream_ver 7.2.4
%endif
# Bumped whenever the patch tarball changes without the upstream version moving.
@@ -56,6 +56,7 @@ Source2: base-aarch64.config
Source3: surface.config
Source4: live-image.config
Source5: no-debug-info.config
+Source6: foreign-socs.config
BuildRequires: bc
BuildRequires: binutils
@@ -71,6 +72,7 @@ BuildRequires: gzip
BuildRequires: hostname
BuildRequires: kmod
BuildRequires: make
+BuildRequires: openssl
BuildRequires: openssl-devel
BuildRequires: patch
BuildRequires: perl-interpreter
@@ -142,6 +144,18 @@ for patchdir in patches/*/; do
done
rm -rf patches
+# The camera series calls devm_phy_get_by_of_node(), which only the phy series
+# adds -- and the overlay's own 7.2.3 ebuild left phy out of its loop while
+# shipping the camera patch that needs it. Applying one without the other
+# compiles for twenty-odd minutes before failing in camss-csiphy.c, so assert
+# the declaration is here while it is still cheap to say so.
+grep -q 'devm_phy_get_by_of_node' include/linux/phy/phy.h || {
+ echo "ERROR: include/linux/phy/phy.h does not declare devm_phy_get_by_of_node."
+ echo "The camera patches need the phy ones; check phy is in patch-order.txt"
+ echo "and that it exists at the pinned overlay commit."
+ exit 1
+}
+
# Fold the -rcN suffix into the package release instead of carrying it in
# uname -r, so the module directory is named the way Fedora names it.
sed -i 's/^EXTRAVERSION[[:space:]]*=.*/EXTRAVERSION =/' Makefile
@@ -157,7 +171,7 @@ CONFIG_BUILD_SALT="%{kverrel}"
EOF
ARCH=arm64 scripts/kconfig/merge_config.sh -m -O . \
- .config .release.config %{SOURCE3} %{SOURCE4} %{SOURCE5}
+ .config .release.config %{SOURCE3} %{SOURCE4} %{SOURCE5} %{SOURCE6}
make ARCH=arm64 olddefconfig
# merge_config.sh is only advisory about symbols it could not set, so check the
@@ -179,6 +193,7 @@ test "${kernelrelease}" = "%{kverrel}" || {
}
%build
+export KCFLAGS="-mcpu=oryon-1+nopauth"
%make_build ARCH=arm64 Image modules dtbs
%install
@@ -204,7 +219,7 @@ install -Dm644 System.map \
install -Dm644 .config \
%{buildroot}/usr/lib/modules/%{kverrel}/config
install -Dm644 arch/arm64/boot/dts/qcom/x1p42100-microsoft-sp12in.dtb \
- %{buildroot}/usr/lib/surface-dtb/x1p42100-microsoft-sp12in.dtb
+ %{buildroot}/usr/lib/surface-dtb/%{kverrel}/x1p42100-microsoft-sp12in.dtb
%post
/usr/sbin/depmod -a %{kverrel} || :
@@ -226,12 +241,34 @@ fi
%files
%license COPYING
/usr/lib/modules/%{kverrel}/
-/usr/lib/surface-dtb/x1p42100-microsoft-sp12in.dtb
+/usr/lib/surface-dtb/%{kverrel}/
%ghost %attr(0644,root,root) /boot/config-%{kverrel}
%ghost %attr(0644,root,root) /boot/initramfs-%{kverrel}.img
%ghost %attr(0600,root,root) /boot/System.map-%{kverrel}
%ghost %attr(0644,root,root) /boot/vmlinuz-%{kverrel}
%changelog
+* Wed Sep 09 2026 Saya Andy 7.2.4-2
+- Compile kernel specifically for Oryon v1 instruction set (Snapdragon X1 cpu)
+
+* Tue Sep 08 2026 Saya Andy 7.2.4-1
+- Update Linux kernel from 7.2.3 to 7.2.4
+
+* Mon Sep 07 2026 Saya Andy 7.2.3-4
+- Turn off all the ARM64 platform kernel modules besides qcom and vexpress
+ (used in qemu)
+- Fix Bayer order in rear camera resulting in color space shift
+
+* Mon Sep 07 2026 Saya Andy 7.2.3-3
+- Key the /usr/lib/surface-dtb copy of the device tree by kernel version. This
+ package is installonly, so an unqualified path there conflicts between two
+ installed releases as soon as the device tree they build differs.
+
+* Sun Sep 06 2026 Saya Andy 7.2.3-2
+- Local camera patch: report the right bayer order when mirrored (fixes the
+ black-green monochrome output issue)
+- Local surface patch: point iris at the OEM video firmware (fixes error -22
+ for video encoding/decoding)
+
* Sun Sep 06 2026 Saya Andy 7.2.3-1
- Initial package: vanilla 7.2.3 with the overlay's Surface Pro 12" patch set
diff --git a/make-sources.sh b/make-sources.sh
index b4abb4b..5c11ee2 100755
--- a/make-sources.sh
+++ b/make-sources.sh
@@ -3,8 +3,9 @@
# Assemble the rpmbuild sources for kernel-surface.spec:
#
# * kernel-surface-patches-<upstream_ver>-<patchset_ver>.tar.gz, built from the
-# overlay submodule's sys-kernel/vanilla-kernel/files directories listed in
-# patch-order.txt
+# directories listed in patch-order.txt: bare names come from the overlay
+# submodule's sys-kernel/vanilla-kernel/files, "local:" ones from this
+# repository's patches/
# * the upstream kernel tarball
# * the base kernel config and the fragments from config/
#
@@ -32,6 +33,7 @@ spec="${script_dir}/kernel-surface.spec"
order_file="${script_dir}/patch-order.txt"
overlay_dir=${OVERLAY_DIR:-${script_dir}/overlay}
patch_root="${overlay_dir}/sys-kernel/vanilla-kernel/files"
+local_patch_root="${script_dir}/patches"
output_dir=""
skip_download=false
@@ -95,7 +97,19 @@ while read -r dir; do
dir=${dir//[[:space:]]/}
[[ -n ${dir} ]] || continue
- src="${patch_root}/${dir}"
+ # "local:foo" is patches/foo in this repository, "foo" is the overlay's
+ # files/foo. The staging name keeps the prefix so the tarball, and the
+ # spec's "Applying ..." log, say where each patch came from.
+ if [[ ${dir} == local:* ]]; then
+ name=${dir#local:}
+ src="${local_patch_root}/${name}"
+ label="local-${name}"
+ else
+ name=${dir}
+ src="${patch_root}/${name}"
+ label=${name}
+ fi
+
if [[ ! -d ${src} ]]; then
echo "ERROR: ${src} does not exist (listed in patch-order.txt)" >&2
exit 1
@@ -107,11 +121,11 @@ while read -r dir; do
exit 1
fi
- dest=$(printf '%s/patches/%02d-%s' "${staging}" "${index}" "${dir}")
+ dest=$(printf '%s/patches/%02d-%s' "${staging}" "${index}" "${label}")
mkdir -p "${dest}"
cp "${src}"/*.patch "${dest}/"
- printf ' %02d %-12s %2d patches\n' "${index}" "${dir}" "${count}"
+ printf ' %02d %-18s %2d patches\n' "${index}" "${label}" "${count}"
index=$((index + 1))
total=$((total + count))
done < "${order_file}"
@@ -125,10 +139,10 @@ echo "${tarball} (${index} directories, ${total} patches)"
#--------------------------------------
# Base config and fragments
#--------------------------------------
-for cfg in base-aarch64 surface live-image no-debug-info; do
+for cfg in base-aarch64 surface live-image no-debug-info foreign-socs; do
cp "${script_dir}/config/${cfg}.config" "${output_dir}/${cfg}.config"
done
-echo "${output_dir}/{base-aarch64,surface,live-image,no-debug-info}.config"
+echo "${output_dir}/{base-aarch64,surface,live-image,no-debug-info,foreign-socs}.config"
if [[ ${skip_download} == true ]]; then
exit 0
diff --git a/overlay b/overlay
-Subproject b8ef9b54f09965d7e30ce03b3a70f5a36f4591b
+Subproject f44f42db1e93545205bdba04567de9ecb634584
diff --git a/patch-order.txt b/patch-order.txt
index 334f847..d47080f 100644
--- a/patch-order.txt
+++ b/patch-order.txt
@@ -1,9 +1,13 @@
-# Patch directories under the Gentoo overlay's sys-kernel/vanilla-kernel/files,
-# in application order.
+# Patch directories in application order.
+#
+# A bare name is a directory under the Gentoo overlay's
+# sys-kernel/vanilla-kernel/files. A "local:" prefix means patches/<name> in
+# this repository, for fixes the overlay does not carry yet.
#
# This mirrors the loop in vanilla-kernel-7.2.3.ebuild's src_prepare(), minus
-# rockchip (irrelevant). There is no phy directory at this overlay commit; the
-# CSI-2 D-PHY driver is part of the camera series here.
+# rockchip (irrelevant), plus phy -- which that ebuild leaves out even though it
+# ships the camera patch that calls devm_phy_get_by_of_node(). Without phy the
+# build dies in camss-csiphy.c; only the 7.3_rc1 ebuild wired phy into its loop.
other
audio
clk
@@ -15,6 +19,9 @@ video
wifi
input
el2
+phy
camera
+local:camera
irq
surface
+local:surface
diff --git a/patches/camera/0027-media-i2c-ov13858-fix-bayer-order-when-mirrored.patch b/patches/camera/0027-media-i2c-ov13858-fix-bayer-order-when-mirrored.patch
new file mode 100644
index 0000000..d465f8d
--- /dev/null
+++ b/patches/camera/0027-media-i2c-ov13858-fix-bayer-order-when-mirrored.patch
@@ -0,0 +1,142 @@
+media: i2c: ov13858: report the right bayer order
+
+The driver advertises MEDIA_BUS_FMT_SGRBG10_1X10 unconditionally, but that is
+not what the sensor delivers in any flip state on the Surface Pro 12in. The
+horizontal mirror moves the Bayer phase by one column, and the native order is
+GBRG rather than GRBG, so the two correct codes are GBRG unmirrored and BGGR
+mirrored.
+
+The rear ov13858 is mounted upside down (rotation = <180> in DT), so userspace
+enables both flips to compensate and every frame is then debayered as RGGB
+while the sensor emits BGGR. Red and blue are exchanged: an orange object comes
+out cyan, warm wood comes out blue, while neutrals are unaffected, which is
+what makes it easy to mistake for a white balance problem.
+
+Two measurements on a Surface Pro 12in, from raw frames captured off the CAMSS
+RDI video node. The first locates the green pair by comparing the mean absolute
+difference of the diagonal against the antidiagonal samples of each 2x2 quad,
+the two greens correlating far better than red against blue:
+
+ hflip=0 vflip=0 diagonal 8.65 antidiagonal 56.82 -> greens diagonal
+ hflip=1 vflip=0 diagonal 56.25 antidiagonal 8.34 -> greens antidiagonal
+ hflip=0 vflip=1 diagonal 13.21 antidiagonal 55.94 -> greens diagonal
+ hflip=1 vflip=1 diagonal 56.04 antidiagonal 13.16 -> greens antidiagonal
+
+So only the horizontal mirror moves the phase; the ISP Y window offset written
+for VFLIP compensates the vertical one.
+
+That test cannot tell red from blue, because GBRG and GRBG share a green
+diagonal just as BGGR and RGGB share a green antidiagonal. Resolving the
+remaining ambiguity needs colour: a scene of objects with known colour was
+captured in all four states, and the red channel identified as the one whose
+ratio to blue matches the scene. The rejected assignment is the reciprocal, so
+the margin is large:
+
+ hflip=0 vflip=0 R/B 1.651 (reciprocal 0.606) -> GBRG
+ hflip=0 vflip=1 R/B 1.622 (reciprocal 0.616) -> GBRG
+ hflip=1 vflip=0 R/B 1.651 (reciprocal 0.606) -> BGGR
+ hflip=1 vflip=1 R/B 1.625 (reciprocal 0.615) -> BGGR
+
+Derive the media bus code from HFLIP and tag the control with
+V4L2_CTRL_FLAG_MODIFY_LAYOUT so userspace knows to renegotiate the format after
+toggling it.
+
+The native order disagreeing with upstream is suspicious in itself. The removal
+of the per-mode {0x3811, 0x04} and {0x3813, 0x05} ISP window offsets in
+"media: i2c: ov13858: add rotate control support", which now writes 1 or 2 into
+those registers from the flip handlers, changes the X parity, and that patch
+also sets BIT(3) of ROTATE_CONTROL when HFLIP is clear while VFLIP sets BIT(4)
+when set. Whether the phase should instead be corrected there is left alone
+here: this patch only reports what the sensor is measured to emit.
+
+--- a/drivers/media/i2c/ov13858.c
++++ b/drivers/media/i2c/ov13858.c
+@@ -1032,6 +1032,7 @@
+ struct v4l2_ctrl *vblank;
+ struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *exposure;
++ struct v4l2_ctrl *hflip;
+
+ struct clk *img_clk;
+ struct gpio_desc *reset_gpio;
+@@ -1222,8 +1223,10 @@
+ OV13858_DGTL_GAIN_MIN, OV13858_DGTL_GAIN_MAX,
+ OV13858_DGTL_GAIN_STEP, OV13858_DGTL_GAIN_DEFAULT);
+
+- v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_HFLIP,
+- 0, 1, 1, 0);
++ ov13858->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops,
++ V4L2_CID_HFLIP, 0, 1, 1, 0);
++ if (ov13858->hflip)
++ ov13858->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+
+ v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_VFLIP,
+ 0, 1, 1, 0);
+@@ -1258,12 +1261,24 @@
+ return ret;
+ }
+
+-static void ov13858_update_pad_format(const struct ov13858_mode *mode,
++/*
++ * Mirroring shifts the Bayer phase by one column, so the native GBRG order
++ * becomes BGGR. The vertical flip is compensated by the ISP Y window offset
++ * and leaves the order alone.
++ */
++static u32 ov13858_get_format_code(struct ov13858 *ov13858)
++{
++ return ov13858->hflip->val ? MEDIA_BUS_FMT_SBGGR10_1X10
++ : MEDIA_BUS_FMT_SGBRG10_1X10;
++}
++
++static void ov13858_update_pad_format(struct ov13858 *ov13858,
++ const struct ov13858_mode *mode,
+ struct v4l2_mbus_framefmt *fmt)
+ {
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+- fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
++ fmt->code = ov13858_get_format_code(ov13858);
+ fmt->field = V4L2_FIELD_NONE;
+ }
+
+@@ -1418,7 +1433,7 @@
+ ARRAY_SIZE(supported_modes),
+ width, height,
+ fmt->format.width, fmt->format.height);
+- ov13858_update_pad_format(mode, &fmt->format);
++ ov13858_update_pad_format(ov13858, mode, &fmt->format);
+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+@@ -1453,11 +1468,11 @@
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+ {
+- /* Only one bayer order(GRBG) is supported */
++ /* Only one bayer order is supported, which one depends on the mirror */
+ if (code->index > 0)
+ return -EINVAL;
+
+- code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
++ code->code = ov13858_get_format_code(to_ov13858(sd));
+
+ return 0;
+ }
+@@ -1469,7 +1484,7 @@
+ if (fse->index >= ARRAY_SIZE(supported_modes))
+ return -EINVAL;
+
+- if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
++ if (fse->code != ov13858_get_format_code(to_ov13858(sd)))
+ return -EINVAL;
+
+ fse->min_width = supported_modes[fse->index].width;
+@@ -1520,7 +1535,7 @@
+ {
+ struct ov13858 *ov13858 = to_ov13858(sd);
+
+- ov13858_update_pad_format(ov13858->cur_mode,
++ ov13858_update_pad_format(ov13858, ov13858->cur_mode,
+ v4l2_subdev_state_get_format(sd_state, 0));
+
+ return 0;
diff --git a/patches/surface/0016-arm64-dts-qcom-purwa-Microsoft-Surface-Pro-12in-iris-firmware-name.patch b/patches/surface/0016-arm64-dts-qcom-purwa-Microsoft-Surface-Pro-12in-iris-firmware-name.patch
new file mode 100644
index 0000000..b182b0b
--- /dev/null
+++ b/patches/surface/0016-arm64-dts-qcom-purwa-Microsoft-Surface-Pro-12in-iris-firmware-name.patch
@@ -0,0 +1,32 @@
+arm64: dts: qcom: purwa: Microsoft Surface Pro 12in: point iris at the OEM video firmware
+
+The generic qcom/vpu/vpu30_p1_s7.mbn shipped by linux-firmware is signed with
+the Qualcomm SecTools test key chain ("SECTOOLS SECP384R1 CURVE TEST ROOT" /
+"General Use Test Key (for testing only)"), which the TrustZone on a retail
+Surface Pro 12in refuses:
+
+ qcom-iris aa00000.video-codec: error -22 initializing firmware qcom/vpu/vpu30_p1_s7.mbn
+ qcom-iris aa00000.video-codec: firmware download failed
+ qcom-iris aa00000.video-codec: core init failed
+
+The -22 comes straight out of qcom_scm_pas_init_image() in
+__qcom_mdt_pas_init(), i.e. the image metadata is rejected before anything is
+loaded.
+
+The Windows driver package for this machine carries the same firmware signed
+with the production chain ("QMC Attestation Root CA 6"), in two builds:
+qcvss8380.mbn and qcvss8380_pa.mbn. The _pa one is what loads here. It has an
+identical 7 MiB load span, so it fits the existing video_mem reservation
+unchanged. Point the iris node at it, the same way the board already does for
+the aDSP, cDSP and GPU firmware.
+
+--- a/arch/arm64/boot/dts/qcom/x1p42100-microsoft-sp12in.dts
++++ b/arch/arm64/boot/dts/qcom/x1p42100-microsoft-sp12in.dts
+@@ -1098,6 +1098,7 @@
+ };
+
+ &iris {
++ firmware-name = "qcom/x1p42100/Microsoft/Surface12/qcvss8380_pa.mbn";
+ status = "okay";
+ };
+