| -rw-r--r-- | Jenkinsfile | 52 | ||||
| -rw-r--r-- | README.md | 27 | ||||
| -rw-r--r-- | config/base-aarch64.config | 23 | ||||
| -rw-r--r-- | config/foreign-socs.config | 68 | ||||
| -rw-r--r-- | kernel-surface.spec | 44 | ||||
| -rwxr-xr-x | make-sources.sh | 28 | ||||
| -rw-r--r-- | patch-order.txt | 9 | ||||
| -rw-r--r-- | patches/camera/0027-media-i2c-ov13858-fix-bayer-order-when-mirrored.patch | 142 | ||||
| -rw-r--r-- | patches/surface/0016-arm64-dts-qcom-purwa-Microsoft-Surface-Pro-12in-iris-firmware-name.patch | 32 |
9 files changed, 376 insertions, 49 deletions
diff --git a/Jenkinsfile b/Jenkinsfile index 63e7c34..1ab3e47 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -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. @@ -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 @@ -31,7 +51,7 @@ rpm2archive -n - < kernel-core-*.aarch64.rpm | 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-surface.spec b/kernel-surface.spec index 5acf949..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 @@ -143,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 @@ -158,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 @@ -180,6 +193,7 @@ test "${kernelrelease}" = "%{kverrel}" || { } %build +export KCFLAGS="-mcpu=oryon-1+nopauth" %make_build ARCH=arm64 Image modules dtbs %install @@ -205,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} || : @@ -227,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/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..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"; + }; + |