aboutsummaryrefslogtreecommitdiffci
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
authorGravatar Saya Andy <saya.andy@posteo.com> 2026-09-07 04:46:01 +0700
committerGravatar Saya Andy <saya.andy@posteo.com> 2026-09-07 04:46:01 +0700
commitfbbe093a4d07ee6b6370101f5161c0eef2865e50 (patch)
treec3aa25070126e7de61af062dd4af91b07f2f14ea
parent551cf11d2d3475996ef499358644486ccfec8e0a (diff)
downloadkernel-surface-fbbe093a4d07ee6b6370101f5161c0eef2865e50.tar.gz
kernel-surface-fbbe093a4d07ee6b6370101f5161c0eef2865e50.zip
feat: add local patches for fixing libcamera color pattern issue + irisfedora-45-kernel-7.2.3-patchset-2
decoder sign misfit
-rw-r--r--README.md20
-rw-r--r--kernel-surface.spec18
-rwxr-xr-xmake-sources.sh24
-rw-r--r--patch-order.txt9
-rw-r--r--patches/camera/0027-media-i2c-ov13858-fix-bayer-order-when-mirrored.patch115
-rw-r--r--patches/surface/0016-arm64-dts-qcom-purwa-Microsoft-Surface-Pro-12in-iris-firmware-name.patch32
6 files changed, 210 insertions, 8 deletions
diff --git a/README.md b/README.md
index 38cc10e..0058df3 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,26 @@ 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
diff --git a/kernel-surface.spec b/kernel-surface.spec
index 5acf949..e238be7 100644
--- a/kernel-surface.spec
+++ b/kernel-surface.spec
@@ -17,7 +17,7 @@
# Bumped whenever the patch tarball changes without the upstream version moving.
%if %{undefined patchset_ver}
-%global patchset_ver 1
+%global patchset_ver 2
%endif
# rpm gives - to the version-release separator, so it cannot appear in Version
@@ -143,6 +143,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
@@ -234,5 +246,9 @@ fi
%ghost %attr(0644,root,root) /boot/vmlinuz-%{kverrel}
%changelog
+* 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..7271bf8 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}"
diff --git a/patch-order.txt b/patch-order.txt
index 5a4b0c8..d47080f 100644
--- a/patch-order.txt
+++ b/patch-order.txt
@@ -1,5 +1,8 @@
-# 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), plus phy -- which that ebuild leaves out even though it
@@ -18,5 +21,7 @@ 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..06b8495
--- /dev/null
+++ b/patches/camera/0027-media-i2c-ov13858-fix-bayer-order-when-mirrored.patch
@@ -0,0 +1,115 @@
+media: i2c: ov13858: report the right bayer order when mirrored
+
+The driver always advertises MEDIA_BUS_FMT_SGRBG10_1X10, but the horizontal
+mirror moves the Bayer phase by one column, so the sensor actually delivers
+RGGB while HFLIP is set. The Surface Pro 12in has the rear ov13858 mounted
+upside down (rotation = <180> in DT), so both flips end up enabled and every
+frame is debayered with the wrong pattern: the two greens land in the red and
+blue output channels and the picture comes out desaturated, close to
+monochrome.
+
+Measured on a Surface Pro 12in by capturing raw frames off the CAMSS RDI node
+and comparing the mean absolute difference of the two diagonal pairs of each
+2x2 quad (the two green samples correlate far better than red against blue):
+
+ hflip=0 vflip=0 diagonal 4.29 antidiagonal 6.84 -> greens diagonal
+ hflip=1 vflip=0 diagonal 7.03 antidiagonal 4.31 -> greens antidiagonal
+ hflip=0 vflip=1 diagonal 4.35 antidiagonal 6.84 -> greens diagonal
+ hflip=1 vflip=1 diagonal 6.93 antidiagonal 4.34 -> greens antidiagonal
+
+So only the horizontal mirror moves the phase; the ISP Y window offset written
+for VFLIP compensates the vertical one. 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.
+
+--- 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 GRBG order
++ * becomes RGGB. 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_SRGGB10_1X10
++ : MEDIA_BUS_FMT_SGRBG10_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";
+ };
+