Commit graph fp6-img/aports
Author SHA1 Message Date
Jorijn van der Graaf
6ecc1dc87b fp6-vendor-blobs: ship a systemd preset so the unit stays enabled
The package installs a multi-user.target.wants symlink, but that alone does
not survive image build: pmbootstrap runs systemctl preset-all, which removes
manually-installed .wants links for any unit whose preset does not enable it.
The 2026-08-24 image therefore shipped the service as
'disabled; preset: disabled' and it never ran, so aw88261_acf.bin was never
extracted from the stock vendor partition and a fresh install came up with no
sound card at all.

Reproduced and verified on the dev phone: with no preset file installed,
systemctl preset leaves the unit disabled; with it, the unit comes back enabled
and stays enabled across a full preset-all.

Investigation and evidence: fp6 repo journal/blobs/, 2026-08-28.

Assisted-by: Claude:claude-fable-5
2026-08-28 00:57:56 +02:00
1e673ca1c4 aports: extract aw88261_acf.bin on-device instead of shipping it
All checks were successful
image / image (push) Successful in 2h24m43s
New package fp6-vendor-blobs: a manifest-driven systemd oneshot that
copies proprietary blobs out of the stock Android partitions on first
boot. pmOS installs flash only boot+userdata, so every installed unit
still carries the stock vendor/dsp partitions - the device duplicates a
file it already contains, for its own operation, and nothing proprietary
is distributed by us. Partitions are mounted read-only (ext4 additionally
with noload - not even a journal replay touches the stock data), every
copy is sha256-pinned and a miss fails loudly, and the consuming devices
are unbound and re-probed afterwards so the feature works the same boot.

The rebind is unconditional by design: aw88261 binds on a bare i2c
chip-id probe and requests the ACF only at ASoC card init (~21 s, after
SoundWire enumeration), so a bound device can still be one that lost the
firmware race - and that failed request is never retried.

soc-fairphone-fp6-audio (pkgver 4) stops shipping the blob, installs the
manifest fragment instead, and re-runs the extractor from
post-install/post-upgrade so upgrades restore the file immediately (the
old package version removed it on upgrade). License drops back to plain
BSD-3-Clause - nothing proprietary left in the package.

Verified on the dev phone (fp6 repo journal/blobs/captures/
2026-08-24-first-boot-extractor-verification.txt): first-boot extraction
+ same-boot audio, mid-session post-upgrade recovery, and the everyday
fast-path no-op; committed files byte-identical to the tested deployment.

Assisted-by: Claude:claude-fable-5
2026-08-24 21:00:34 +02:00
970a44f93d aports/fp6-device-tweaks: stop the modem-gnss 30 s restart loop
Some checks failed
image / image (push) Has been cancelled
pmOS's modem-gnss.service runs two qmicli calls, and the second --
--loc-set-nmea-types=all -- can never succeed on this modem: the LOC
engine answers QMI error 94 'NotSupported' to both get and set. That is
a permanent capability gap, not the boot race Restart=on-failure exists
for, so the unit failed and restarted every 30 s for the whole uptime
(restart counter 25 after 13 minutes; 165 over one evening). Its
StartLimit does not stop it either: 10 restarts at RestartSec=30 span
~303 s, just past StartLimitInterval=300.

Ship a drop-in that tolerates that one command's failure. The boot-race
retry stays armed -- a LOC service that is genuinely not up still fails
the first ExecStart. Nothing is lost: ModemManager issues its own
set-NMEA-types and takes the same 94 regardless, and location comes from
the Position Report path our modemmanager patches add.

Byte-identical to the drop-in verified on the dev phone (sha256
b0b5f71b0f25c3c5a8fc9e926f187412a6711da95f773234065f37ddcc1d3c6d):
across a reboot the unit runs once, Result=success, 0 restarts.

Assisted-by: Claude:claude-opus-5
2026-08-24 19:44:18 +02:00
eb13c18ea8 aports: add fp6-charging-mode (offline charging, charger-boot detection)
Charger-insertion boots (androidboot.mode=charger, ABL-appended) divert to
a minimal charging.target instead of the full UI, ending the dead-battery
bootloop: ADSP charging/USB-PD runs, splash+panel killed ~6-10s in via an
initramfs hook, modem+cdsp stopped, radios/sensors suppressed, CPU capped.
Power key reboots to a normal boot, volume-up shows battery status,
volume-down enables USB ssh, unplug powers off. Measured >= breakeven on a
100mA-classified SDP port, strongly net-positive on real chargers.

Suspend duty-cycling (~13mA floor) exists behind an off-by-default flag:
resume from deep suspend intermittently kills the UFS link (hibern8 exit
failed ret=5) - do not enable until that kernel bug is fixed.

Byte-identical to the deployment verified on the dev phone 2026-08-24
(journal/power: r5 armed tests, crash autopsies, measurements).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 04:03:06 +02:00
d91963975a temp/libcamera: r9 - zone-gated AWB for the simple IPA (patch 0016)
Some checks failed
image / image (push) Failing after 3h4m27s
Divide the softISP statistics window into 16x12 zones and, when a white
point locus is tuned, vote only with zones whose implied gains lie within
zoneGateMargin of the locus - a large coloured light source can no longer
drag the white balance. Validated on-phone 2026-08-24: keyboard-scene A/B
shows a ~1700 K estimate shift caused solely by the gate (desk renders
neutral instead of blue); torch-toggle stability equal or better than r8
(settle 1.35-1.79 s, ON-edge repeatability +-0.011, CCM churn 21 vs 30
switches); AF regression clean. Evidence:
journal/camera/captures/2026-08-24-awb-zonegate-validation.md

Assisted-by: Claude:claude-fable-5
2026-08-24 01:05:14 +02:00
a4851dbd0e device/soc-fairphone-fp6-audio: correct the license field
The package declared BSD-3-Clause while shipping aw88261_acf.bin, a
verbatim proprietary Awinic blob extracted from the stock vendor
partition - an affirmative false claim about the file. Mark the license
compound (BSD-3-Clause AND proprietary) and document per-file provenance;
the durable fix (FairBlobs adoption or install-time on-device extraction)
is tracked in the audio journal.

Assisted-by: Claude:claude-fable-5
2026-08-24 00:23:47 +02:00
6491afde53 kernel: move to the 7.2 base (v7.2.0-milos + rebased carries)
All checks were successful
image / image (push) Successful in 2h23m53s
pkgver 7.1.2 -> 7.2.0; config regenerated from the pmOS 7.2.0-r0 config
plus the FP6 bring-up fragment (same enables as before), olddefconfig'd
against the rebased combined-stable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 03:50:53 +02:00
738148b51a camera: enable the FP6 main camera stack (kernel config)
All checks were successful
image / image (push) Successful in 2h13m32s
milos-linux combined-stable now carries the camera-main merge
(af49850e65bd): camss C-PHY support, the IMX896 main sensor, the DW9784
AF controller and the board DTS for all three (the VL53L3 ToF node is
DTS-only for now, its driver is future work). Kernel config gains
CONFIG_VIDEO_IMX896=m + CONFIG_VIDEO_DW9784=m - the camss core, CAMCC
and CCI are on since the ultra-wide commit, and the libcamera side
(IMX896 tuning, contrast AF, AWB stabilization) already ships since
aport r8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 10:45:54 +02:00
0c6c4cde25 build: generate the fd.o source tarballs locally instead of fetching archives
Some checks failed
image / image (push) Has been cancelled
gitlab.freedesktop.org's on-demand archive endpoint 503/504s for hours
at a stretch: runs #25, #27, #30 and #31 all died in 'abuild checksum'
fetching the pinned libqmi tarball, outlasting the 3x30s in-run retry.
git clone is served from a different code path and holds up (verified
against all three repos while the archive endpoint was flaky), so clone
libqmi/ModemManager/libcamera (retried) and git-archive the pinned refs
into the aports, the same way the kernel and imsd tarballs are already
produced. The pins stay single-sourced in the APKBUILDs.

libcamera gains a checksum step: its committed sums were for the
fd.o-served tarball, and git-archive output is not byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 10:36:05 +02:00
48cedac3c3 libcamera: stabilize AWB with a white point locus clamp + damping (r8)
The softISP AWB is pure gray world, so panning swings ColourGains with
the frame average (white wall renders green when the frame is
warm-dominated, dark desk renders red when cool-dominated) and the CCM,
interpolated over a CT estimated from those gains, amplifies and
quantizes the swings.

Patch 0015 (ours, original work) adds optional per-sensor Awb tuning to
the simple IPA: a piecewise-linear locus of calibrated illuminant white
points in gain space that the gray-world estimate is clamped to
(clampMargin), a per-stats-frame EMA on the applied gains (damping)
with a fast-converge path for persistent illuminant changes, and CT
interpolated from the applied gains' position along the locus - on the
same scale as the tuning file's ccms table - instead of the generic
estimateCCT(). Tuning files without whitePoints keep the previous
behaviour exactly, so every other sensor is unaffected.

imx896.yaml gains the locus from the stock tuning blob's 10-point
per-illuminant AWB calibration (white points and their exactly
reciprocal gain triplets, cross-validated): the 7 on-locus points as
nodes, the 3 fluorescent points admitted via clampMargin 0.35. The
5000 K label is the blob's own proven anchor; 2856 K (A) is locked by
the fluorescent trio projecting onto the 2856-5000 chord at ~3960 K
(TL84); the rest are geometry-derived approximations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 03:24:56 +02:00
a5e3d1626c libcamera: set the measured IMX896 black level (r7)
Some checks failed
image / image (push) Failing after 3m59s
Raw-RDI dark frames (phone face-down, minimum analogue gain) put the
pedestal at exactly 64 in 10-bit (mean 63.98, median 64, p1/p99 63/65)
= 4096 on the 16-bit scale. The softISP's dynamic estimate ran at 48;
the 16-code residual was amplified by the CCM into colour casts in
dark image regions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 03:07:52 +02:00
b48702225b libcamera: ship the IMX896 colour tuning (r6)
Some checks failed
image / image (push) Failing after 4m4s
Adds imx896.yaml (CCMs for 2800/4000/5750 K) so the main camera gets
real colour instead of the uncalibrated fallback. The matrices are
numeric calibration data read out of the stock Android tuning blob -
measured spectral response of this sensor, not authored expression -
and are shipped by the project owner's decision, consistent with the
vendor-derived data this image already carries. Durable replacement is
to measure our own from a colour chart.

Note the file lists Adjust/Agc/Af as well as BlackLevel/Awb/Ccm: a
sensor-specific tuning file REPLACES the fallback's algorithm list, so
omitting them silently disables auto-exposure and autofocus.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 02:58:31 +02:00
236015ef36 libcamera: af: re-baseline the scene reference after a sweep (r5)
Some checks failed
image / image (push) Has been cancelled
Hardware finding from the first r4 run on the phone: the focus-loss
detector compared the settled scene against the maximum sharpness
recorded during the sweep, which was measured under a different AGC
state. On the FP6 that maximum read 4848088 and the same position two
stats frames later read 1995445, so the detector fired immediately and
the lens swept forever. Patch 0014 takes the reference after the lens
settles and requires four consecutive out-of-band frames.

Verified on the phone: r4 re-swept without end, r5 completes one sweep
and stays put.
2026-08-17 02:35:59 +02:00
40ccdfeed6 libcamera: backport contrast autofocus for the main camera (r4)
Some checks failed
image / image (push) Has been cancelled
The DW9784 VCM works and libcamera discovers it through the sensor's
ancillary link, but nothing in the software ISP ever moves it. Backport
the out-of-tree autofocus work onto v0.7.2:

- 0007-0009 are Vasiliy Doylov's focus control, contrast autofocus and
  focus-loss detection from the softisp-playground branch;
- 0010 is Pavel Machek's Librem5-tested robustness work (centre-window,
  brightness-normalised sharpness, two-phase sweep, settle skip),
  squashed and adapted;
- 0011-0013 are ours: the lens write no longer sits inside the
  no-frame-start-emitter branch, the lensless-camera paths are guarded,
  and AfMode is advertised with a continuous default so that stock
  applications get autofocus without sending AfTrigger.

Provenance and the adaptations made to each patch are recorded in the
patch commit messages.
2026-08-17 02:02:45 +02:00
81948970e1 libcamera: add the IMX896 sensor helper and properties (r3)
Some checks failed
image / image (push) Failing after 4m17s
Teaches the software ISP's AGC the IMX896 gain law
(gain = 16384/(16384-code), inverted from the vendor driver and
round-tripped against all 3009 vendor gain-table entries, max error
0.049%) and adds the sensor properties (1.0um unit cell, test-pattern
map). Same shape as the OV13B10 pair; both verified to apply and
compile on v0.7.2 after 0001-0004.

The extracted-CCM tuning yaml is deliberately NOT packaged yet - the
color matrices come from the vendor Chromatix blob and the licensing
call is open (see the camera journal).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 21:03:10 +02:00
34cfc098d8 camera: enable the FP6 ultra-wide pipeline (kernel config + patched libcamera)
All checks were successful
image / image (push) Successful in 1h51m52s
Kernel config: CONFIG_VIDEO_OV13B10=m + CONFIG_VIDEO_DW9714=m — the camss
core, CAMCC and CCI were already enabled; the sensor and VCM drivers were
the only missing pieces. The camera carries themselves land via
milos-linux combined-stable (merge of the 'camera' topic branch,
nondescriptpointer's 5 patches, authorship preserved).

libcamera: new temp/ aport overriding pmOS 99990.7.2-r1 with -r2, adding
nondescriptpointer's OV13B10 sensor helper (gain = code/128, enables the
software-ISP AGC/AWB) and sensor properties patches on top of the pmOS
0.7.2 APKBUILD. Patch sha512s re-recorded from the actual files (his
APKBUILD diff carried stale hashes); all four patches verified to apply
against the v0.7.2 tarball.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 04:08:36 +02:00
ab506b1d80 audio fix
Some checks failed
image / image (push) Has been cancelled
2026-08-09 03:30:47 +02:00
30f2778fc4 audio: select the pipewire backend explicitly and ban the pulse one
Full-system audit findings: without an explicit provider selection the
image installed real PulseAudio (Plasma Mobile hard-path), which claims
the card and ships a wireplumber fragment disabling hardware.audio -
zero sinks forever. Mirror the dev phone's world: pipewire backend meta
+ pipewire-pulse + echo-cancel in extra_packages, pulse meta banned via
apk conflict in fp6-device-tweaks. The two hand-made /etc audio
fragments (wireplumber no-ACP rule, AEC pair for VoLTE speakerphone)
move into soc-fairphone-fp6-audio.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-09 00:32:11 +02:00
ff69f4d913 fp6-no-suspend -> fp6-device-tweaks: + the three IMU-critical /etc files
Full-system audit on the flashed phone found the IMU dead: the journal's
documented reinstall-loss trio (inv-icm42600-spi modules-load - fallback-only
SPI node never coldplugs; the accel poll udev rule for auto-rotate; the
iio-sensor-proxy libssc-crash restart drop-in). All device-critical, none
personal - now packaged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-09 00:03:09 +02:00
05cd1084b7 image completeness: fp6-no-suspend + imsd boot enablement
Two device-critical pieces previously applied only by the dev restore
script: masked sleep targets (idle-suspend resets the WCN combo firmware
and kills wifi ~40min - a device defect, not personalization) and imsd
enabled at boot, gated on /etc/imsd.env existing so unconfigured systems
don't boot a failing unit. A stranger now needs exactly: flash, wifi via
UI, write imsd.env, restart imsd.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 23:46:01 +02:00
283996b507 modemmanager: skip the test suite under qemu
3 of 38 glib tests SIGABRT under qemu-user emulation; they pass on
native builders and do not touch the patched GNSS paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 23:07:20 +02:00
4de0ffc316 libqmi: opt out of crossdirect like modemmanager
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 22:53:17 +02:00
2019e158aa modemmanager: versioned libqmi-dev makedep; kernel pkgver date stamping
pmbootstrap's build plan is not dependency-ordered: MM built first and
grabbed the cached 1.39.0 libqmi from the volume's package repo. The
versioned makedepend states the real requirement and forces our bumped
libqmi to build first. Kernel pkgver gains the source commit date so
registry-subscribed phones receive kernel updates.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 22:39:14 +02:00
851526f3fc package updates: Forgejo apk registry publishing + repo-config aport
CI publishes every locally built apk to the instance's Alpine registry
(catbot credentials via the PACKAGE_TOKEN secret; step skips until it
exists). catcrafts-fp6-repo ships the registry signing key and appends
the repo URL - NOT yet in extra_packages: the registry must have its
first content before image builds may reference it (an empty repo's
missing APKINDEX would break apk in the build chroots).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 22:33:45 +02:00
1a73502479 libqmi: bump snapshot past the !470 merge instead of patching
Our MM patches require qmi-glib >= 1.39.1 (the version bumped right after
!470 merged); Alpine's April snapshot reports 1.39.0. Upstream 30f3e998
carries both the TLV work and the version bump, so the local patch goes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 22:19:31 +02:00
8387858f37 modemmanager: opt out of crossdirect (cc1 spawn failure); build under qemu
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 22:05:21 +02:00
11dc33d843 modemmanager: drop the pinned own-subpackage from makedepends
apk cannot satisfy libmm-glib=<ver>-r100 before modemmanager r100 itself
is built; Alpine's reuse of depends_dev inside makedepends only works
when the binary repo already has the same pkgrel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 21:59:14 +02:00
45caa3ac65 aports: the two modemmanager GNSS patches were never committed
git -C <repo> format-patch -o . writes relative to the -C directory, not
the caller's cwd - the files landed in work/ModemManager and the aport
shipped an APKBUILD referencing patches that did not exist.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 21:47:57 +02:00
7578b2149c kernel config: enable NLS_ASCII - the vfat ESP mounts with iocharset=ascii
First flash boot reached systemd and died into emergency mode on
'FAT-fs (loop0p1): IO charset ascii not found': the tested phone config
never needed FAT NLS tables because the old install used an ext2 /boot;
the current device package uses a vfat ESP. Single flip, olddefconfig
roundtripped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 21:41:14 +02:00
da3d908b93 aports: GNSS via forked Alpine libqmi + modemmanager
libqmi: the upstream-merged (!470, in no release yet) LOC Register Events
client-identification TLVs, taken verbatim from upstream main (532de37e).
modemmanager: the AFW engine unlock + Position Report derivation (!1463,
still draft upstream, review-hardened and verified on device). Both as
patches on Alpine's git-snapshot aports, pkgrel=100.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 21:27:48 +02:00
4e43e6d57b image parity: imsd 0.3.0 (pinned public commit) + callaudioshim + modem-daemon override
imsd turns out to be fully public already (0.2.7 snapshot + emergency
stage 1 + the make build path) - no tag needed, same git-archive dance as
the kernel. callaudioshim was a load-bearing unpackaged home-dir script on
the phone (callaudiod replacement, working in-call mic mute); now an aport
autostarted at phase 1. kde-telephony's modem daemon autostart is hidden
via /etc/skel from the imsd package, mirroring the phone's user override.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 20:54:29 +02:00
719a10a997 aports: add soc-fairphone-fp6-audio (topology, amp config, UCM)
Files copied byte-identical from the tested dev phone; installed to the
exact deployed paths (the spaced tplg/UCM filenames come from the machine
driver's card name). Wired into the image via extra_packages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 20:48:28 +02:00
de2e819a16 scaffold: aports overlay, build script, CI workflow, README
Kernel aport forked from pmaports 7.1.2-r0, repointed at milos-linux
combined-stable with the tested FP6 config (+EFI_ZBOOT for packaging);
imsd + nftables aports from the pending pmaports submission. build.sh
carries TODO(validate) markers - not yet run end-to-end.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 15:42:45 +02:00