Skip to content

Releases: petronijus/nexusQ-reloaded

v1.6.3 — companion app + LAN control bridge

Choose a tag to compare

@petronijus petronijus released this 30 Jun 23:11

Highlights

📱 A companion app + an on-device control bridge — a phone/desktop remote for the
Q (volume, LED theme + brightness, now-playing), replacing the dead 2012 Google
companion app.

nexusq-control — a new LAN control bridge (pure-Python, TCP 45015, mDNS
_nexusq._tcp, line-delimited JSON). It fans out to: the ALSA softvol
(volume/mute), nexusqd over its Unix socket (LED theme + brightness), and a
librespot --onevent hook (now-playing). Protocol: companion/PROTOCOL.md.

Software master volume — a nexusq_soft softvol control (NexusQ) layered on
the v1.6.2 audio tee, shared by librespot (--mixer alsa --alsa-mixer-control NexusQ)
and the companion, so Spotify-Connect volume and companion volume are one knob
and the LED visualizer still tracks the (post-volume) output.

nexusqd brightness <0-255> — a software ring-brightness scalar (no firmware change).

Companion app (companion/app) — a cross-platform Flutter remote (sphere UI,
animated LED ring, mDNS auto-discovery; volume + LED theme/brightness + now-playing).
Built and installed separately on the phone — not part of the device image.

Verified live on a clean flash: the bridge auto-starts (active), answers every
protocol method, volume works, the LED visualizer still reacts to playback, and mDNS
advertises "Nexus Q". (Getting the bridge to auto-start was a saga — see
docs/2026-07-01-companion-bridge-boot-enablement.md: a systemd-preset to survive
preset-all, and dropping an After= that formed a boot ordering cycle.)

The kernel is unchanged from v1.6.1/v1.6.2nexusq-boot-v1.6.3.img is
byte-identical to v1.6.2's. Only the rootfs changed, so if v1.6.2's boot is
already on the device you only need to flash userdata.

Known issues

  • Transport (play/pause/next) is unavailable in v1 — librespot is a
    Spotify-Connect receiver with no local transport API; transport happens from the
    Spotify app. The protocol reserves the slot for a future backend.

Install

zstd -d nexusq-rootfs-v1.6.3-sparse.img.zst
fastboot flash boot nexusq-boot-v1.6.3.img            # optional if v1.6.2 boot is already flashed
fastboot -S 100M flash userdata nexusq-rootfs-v1.6.3-sparse.img

WiFi is per-device (a flash wipes it). Once on WiFi, the companion app auto-discovers
the device via mDNS; the Spotify "Nexus Q" target appears on the same network.

Assets

  • nexusq-boot-v1.6.3.img (5.0 MiB) — kernel + appended SMP DTB; identical to v1.6.2
  • nexusq-rootfs-v1.6.3-sparse.img.zst (447 MiB; ~2.08 GiB raw) — zstd all-RAW sparse
  • nexusq-v1.6.3.sha256 — checksums

v1.6.2 — LED music visualizer reacts to playback

Choose a tag to compare

@petronijus petronijus released this 30 Jun 20:14

Highlights

🔴🎵 The LED ring now reacts to the music. v1.6.1 routed librespot straight to
the speaker, so nexusqd's audio analyzer (the snd-aloop loopback) got nothing and
the ring stayed idle during playback. The nexusq ALSA PCM is now a tee
(type multi + type route) that duplicates the 48 kHz stereo to BOTH the TAS5713
speaker AND the snd-aloop loopback (hw:Loopback,0); nexusqd's existing arecord
tap on hw:Loopback,1 drives the FFT/beat visualizer while the speaker plays. The
speaker is the timing master; the loopback slave is plughw, so it adapts to
whatever rate the cable is at (nexusqd's arecord may have set it) and never blocks
playback. New /etc/modules-load.d/snd-aloop.conf auto-loads the loopback
(CONFIG_SND_ALOOP=m). device-google-steelhead pkgrel 12.

Verified live: the ring pulses/animates to Spotify; no ALSA/xrun errors,
nexusqd/librespot NRestarts=0; the tee opens regardless of which side grabs the
loopback first.

The kernel is unchanged from v1.6.1 (same TAS5713 2× audio fix) —
nexusq-boot-v1.6.2.img is byte-identical to v1.6.1's. Only the rootfs
changed, so if v1.6.1's boot is already on the device you only need to flash
userdata.

Install

zstd -d nexusq-rootfs-v1.6.2-sparse.img.zst
fastboot flash boot nexusq-boot-v1.6.2.img            # optional if v1.6.1 boot is already flashed
fastboot -S 100M flash userdata nexusq-rootfs-v1.6.2-sparse.img

WiFi is configured per-device (a flash wipes it); the Spotify "Nexus Q" target
appears on a phone on the same WiFi.

Known issues

  • The Spotify Connect session can briefly go "inactive" on the first play and
    reconnect (librespot "context is not available" — a single-track-vs-playlist
    quirk; no ALSA error). Playback is stable afterwards.

Assets

  • nexusq-boot-v1.6.2.img (5.0 MiB) — kernel + appended SMP DTB; identical to v1.6.1
  • nexusq-rootfs-v1.6.2-sparse.img.zst (448 MiB; ~2.08 GiB raw) — zstd all-RAW sparse
  • nexusq-v1.6.2.sha256 — checksums

v1.6.1 — TAS5713 audio fixed (2× speed bug) + Spotify Connect baked in

Choose a tag to compare

@petronijus petronijus released this 30 Jun 06:17

Highlights

🔊 TAS5713 speaker audio fixed — it played exactly 2× too fast. Root cause:
simple-audio-card drove the McBSP2→TAS5713 I2S link as bit/frame master but never
set the McBSP bit-clock divider, so omap-mcbsp left CLKGDV = 0 (the undivided
24.576 MHz functional clock as BCLK) and sized the frame as in_freq/rate = 256
BCLK → FSYNC = 96 kHz for a 48 kHz stream = 2× too fast. Kernel patch 0022
derives CLKGDV from the real func-clock rate and uses a minimal wlen*channels
I2S frame → CLKGDV 15, BCLK 1.536 MHz, FSYNC 48 kHz, bit-identical to the factory
kernel. Verified on hardware: 60 s of audio now plays in 60.00 s (was ~30 s).
This 2× is also why librespot auto-skipped tracks ~40 s in. (The "B7 MCLK 16 vs
12.288 MHz" theory was a red herring — mainline tas571x has no .set_sysclk.)

🎵 Spotify Connect (librespot) baked into the build. The image now ships
librespot — advertising as "Nexus Q" — with an enabled systemd unit, an ALSA
nexusq PCM that resamples to the device's clean 48 kHz and addresses the speaker
by name (hw:CARD=NexusQSpeaker,0 — card numbers race TAS5713/HDMI across
boots), and an nftables drop-in opening mDNS + the zeroconf port. Discovery + auth

  • streaming verified over 5 GHz WiFi, audio at correct pitch.

🛠 Build fixes (docker-build.sh): the fakeroot-as-root patch re-targeted for
pmbootstrap 3.10.1 (env-dict format changed → patch was silently skipped → fakeroot
hang); firmware-google-steelhead now built explicitly so cold builds don't fail
at install.

Verified end-to-end from a clean flash: uname #26-postmarketOS, python3 -S
rc 0, audio 60.00 s, librespot advertising, WiFi, dual-core SMP @ 1.2 GHz.

Install

See INSTALL.md. Decompress the rootfs first, then flash:

zstd -d nexusq-rootfs-v1.6.1-sparse.img.zst
fastboot flash boot nexusq-boot-v1.6.1.img
fastboot -S 100M flash userdata nexusq-rootfs-v1.6.1-sparse.img

After first boot the Spotify "Nexus Q" target appears on your phone (same WiFi);
WiFi is configured per-device (a flash wipes it).

Assets

  • nexusq-boot-v1.6.1.img (5.0 MiB) — kernel + appended SMP DTB, ramdisk-less
  • nexusq-rootfs-v1.6.1-sparse.img.zst (447 MiB; ~2.08 GiB raw) — zstd-compressed
    all-RAW Android-sparse rootfs (byte-exact on the non-erased eMMC)
  • nexusq-v1.6.1.sha256 — checksums

v1.6.0 — working python3 on the device

Choose a tag to compare

@petronijus petronijus released this 28 Jun 22:27

First release with a working python3 on the device, hardware-verified from a
clean flash. Over 1.5.0: a working armv7 python3 — the actual fix was the
raw2simg.py byte-exact (all-RAW) flash; the on-device SIGSEGV was a flash bug, not
a build bug (a local python3 rebuild supersedes Alpine's broken -r2, with a
build-integrity gate + ship gate kept as a safety net) — plus zram compressed swap,
user namespaces, on-device gdb/python3-dbg, and a live re-confirmation of
dual-core SMP + cpufreq-to-1.2 GHz power/thermal.

Added

  • zram compressed swap. Kernel CONFIG_ZRAM=m plus
    deviceinfo_zram_swap_algo="lzo-rle" brings up postmarketos-zram-swap. The
    mainline ZRAM module here only carries the lzo/lzo-rle backend, so the service's
    default zstd failed (zramctl: failed to set algorithm: Invalid argument)
    and swap never came up; lzo-rle is also the CPU-cheap pick for this Cortex-A9.
    Verified live: /dev/zram0 lzo-rle, 1.4 G, active [SWAP]. (linux APKBUILD
    pkgrel 23→24.)
  • User namespacesCONFIG_USER_NS=y. Verified live:
    max_user_namespaces=7716, unshare --user works.
  • Dual-core SMP re-confirmed on the full-rootfs imagenproc=2,
    cpu/online=0-1, both Cortex-A9 in /proc/cpuinfo. (SMP shipped in 1.2.0; this
    corrects any stale "CPU1 not brought up / SMP is groundwork" framing — it is done
    and working on the current image.)
  • CPU power/thermal health confirmed live — scales 350/700/920/1200 MHz,
    reaches 1.2 GHz under load, VDD_MPU tracks the OPP exactly (1200→1380, 920→1317,
    350→1025 mV; abb_mpu FBB@Nitro 1375 mV). Idle ~70 °C, peak 95 °C under sustained
    2-core load (no throttle; 100 °C passive trip not reached).

Changed

  • Build infra: local python3 override aport + gated Phase 7d.
    docker-build.sh stages pmos/python3/main/python3 (Phase 6) and builds it
    (pmbootstrap --no-cross build python3 --arch armv7, Phase 7d) so a higher pkgrel
    (now r5) supersedes Alpine's broken python3-3.14.5-r2 in the rootfs. The override
    drops --with-lto + --enable-optimizations and the !gettext-dev makedepends
    token (pmbootstrap's apk wrapper rejects ! entries), keeps stock -O2 and the
    default linker (bfd). Phase 7d gates every built libpython with
    scripts/verify-libpython-clean.py and rebuilds on residual corruption (pkgrel-exact
    apk selection, no stale-apk glob); Phase 10 re-gates the installed rootfs libpython
    before emitting an image — a build-integrity safety net (the on-device crash was a
    flash bug, see Fixed; this only guarantees the build feeding the flash is clean).
  • device-google-steelhead no longer masks sleep-inhibitor.service; adds
    on-device debug tools.
    The /dev/null mask was removed in favour of fixing the
    root cause (the python crash, now fixed below); the image also ships gdb (16.3) +
    python3-dbg (used to coredump-debug the crash on hardware; gdb links libpython,
    so it works once python links a clean libpython). (device APKBUILD pkgrel 6→10.)

Fixed

  • Flash: the rootfs sparse image is now byte-exact (all-RAW, no DONT_CARE).
    raw2simg.py (raw ext4 → Android sparse for the 2012 U-Boot fastboot, which lacks
    FILL-chunk support) used to emit every all-zero 4 KiB block as a DONT_CARE chunk to
    shrink the image — but fastboot skips DONT_CARE blocks, which is only correct
    on a pre-erased partition. The Nexus Q's U-Boot does not erase userdata, so
    each skipped block kept STALE data from the previous flash, re-corrupting on-device
    file zero-regions — specifically libpython's .PyRuntime / .data.rel.ro (PROGBITS,
    read during Py_Initialize) — which was the actual and only root cause of the
    on-device armv7 python SIGSEGV (rc 139)
    , even though the flashed (and built) image
    was provably clean. Forensic signature distinguishing flash- from build-corruption:
    the on-device libpython differed from the (gate-CLEAN) flashed image in exactly 47
    4 KiB blocks, all "image-zero → device-garbage", 0 other
    (.PyRuntime longest_run 30652); the image gated CLEAN, the device gated CORRUPT, and
    scp-ing the clean image libpython over the device's → python3 -S -c '' rc 0
    instantly — proof it was the flash, not the build. Fix: raw2simg.py now encodes
    every block as RAW (no DONT_CARE), so the flash is byte-exact regardless of prior
    eMMC content (sparse ≈ raw size; correctness over compression). Verified by a de-sparse
    round-trip (md5 of de-sparsed == raw image) and on hardware: a fresh flash (no
    live-patch) of a default-linker (bfd) build gives /usr/lib/libpython3.14.so.1.0 md5
    79a0d4ace1358bb2d94c8a4d72479da9, SYSPY_OK 3.14.5 … [GCC 15.2.0], SYS_PY_RC=0.
    Lesson: integrity-verify what the device runs, not just the built artifact. See
    docs/2026-06-28-session-findings.md.
  • armv7 python3 works on the device — the on-device SIGSEGV was the FLASH bug
    above, not a build bug.
    Alpine's python3-3.14.5-r2 SIGSEGVed deterministically on
    the Cortex-A9 (python3 -S -c '' → rc 139 during Py_Initialize), taking down
    onboard, blueman-applet, sleep-inhibitor.service and gdb (it links
    libpython). The single root cause was the raw2simg.py DONT_CARE flash bug
    (above): a re-flash over non-erased eMMC left stale garbage in libpython's
    should-be-zero .PyRuntime / .data.rel.ro, landing on
    interp->types.builtins.num_initialized (read back as 0xf0012b00) → wild
    type-index deref → SIGSEGV. v1.6.0 ships a local pmos/python3/ override (same 3.14.5
    at a higher pkgrel, r5, default linker / bfd) so it supersedes Alpine's -r2;
    the override drops --with-lto + --enable-optimizations and the !gettext-dev
    makedepends token, keeps stock -O2. A qemu-user "linker mmap zero-fill corrupts
    the build" theory and a gold-linker workaround (-fuse-ld=gold -Wl,--no-mmap-output-file, binutils-gold makedep) were investigated and DROPPED as
    unnecessary
    — the build was never reproducibly corrupt: 6 independent default-linker
    builds were all integrity-gate-clean, and a bfd build (gold-note absent, libpython md5
    79a0d4ace1358bb2d94c8a4d72479da9), flashed via the corrected all-RAW raw2simg, ran
    python3 -S -c '' rc 0 on the real device (6/6 clean would be ~1.6 % if a real 50 %
    build coin-flip existed). Retained — not as a "gold fix" but as a cheap
    build-integrity safety net that catches zero-region corruption from any source:
    scripts/verify-libpython-clean.py (flags long non-zero runs in those zero-regions;
    clean ≤52 B, corrupt ≥22000 B, threshold 256), run in a Phase-7d gate+retry loop and
    again as a Phase-10 ship gate, with pkgrel-exact apk selection. Other early suspects
    also disproven: LTO/PGO, LDREXD alignment, gnu2/TLSDESC, optimization level. The
    all-RAW flash fix above is what actually fixed the device; the gate only guarantees the
    build feeding it is clean. See docs/2026-06-28-session-findings.md.
  • Build-pipeline: rootfs python ≠ the verified apk — fixed. Phase 7d's old bare
    python3-3.14.5-r*.apk glob could match a stale apk in the persistent work-volume
    repo rather than the one just built, so the rootfs could install a different build than
    the one gated. Fixed by selecting the exact pkgver-pkgrel apk, gating that file,
    and re-gating the installed rootfs libpython at ship time (the version-only check
    that green-lit a mismatch is gone). (The apparent "two r4 builds, one crashes / one
    runs" that first surfaced this was almost certainly a post-flash device pull — the
    flash bug above — misread as build corruption, not a real build coin-flip.)

Known issues / in progress

  • On-board LAN9500A Ethernet still down — the v1.4.0 cpufreq boot-timing
    regression is unchanged: smsc95xx registers but the device never enumerates, no
    eth0. Use WiFi / the USB gadget. (Fix tracked for 1.4.1.)

Full Changelog: v1.5.0...v1.6.0

v1.5.0

Choose a tag to compare

@petronijus petronijus released this 26 Jun 23:01

[1.5.0] - 2026-06-26

Added

  • NFC: the PN544 stack is built into the kernel (NFC / HCI / PN544 / PN544_I2C
    =y) with stock-faithful tweaks — a 20 ms VEN settle and a level-triggered IRQ.
    The chip is proven alive (it ACKs i2c when powered); full NFC functionality is a
    follow-up.
  • Nexus Q diagnostics suite. nq-healthd continuously watches the things that
    silently fail in the field (LED-ring / nexusqd hangs, VDD_MPU-vs-OPP drift,
    thermal throttle, kernel errors) and logs to /var/log/nq-health;
    nq-diag-snapshot captures a full one-shot device snapshot. Both ship enabled in
    the device image, with host-side helpers (scripts/diag/) and a nexusq-diag
    skill to collect and analyse it over the best available link.
  • nexusqd now signals systemd readiness + watchdog via sd_notify
    (self-contained, no libsystemd dependency), so the LED-ring daemon runs as a
    proper Type=notify unit.

Changed

  • DTS regulators now point at the real board rails — DSS vdda_video→vcxio,
    tmp101 vs→v1v8, the Bluetooth vbat/vddio, and the TAS5713 amp AVDD/DVDD→a
    3V3 rail replace placeholder dummies. The spurious "supplying voltage" warnings
    drop from 10 to 5.
  • Default cpufreq governor → conservative — idle now settles at 350 MHz (vs
    ondemand's 920 MHz), ~66 °C, instead of holding a high clock.
  • Ethernet (LAN9500A) is reliable again — it came up on every boot tested in
    v1.5.0 (the v1.4.0 cpufreq-build bring-up intermittency was not reproducible),
    sustaining full ~100 Mbit/s line-rate throughput.
  • Device image UI: added nm-tray (network applet), blueman (Bluetooth
    manager) and breeze-icons to the LXQt-Wayland session.

Fixed

  • WiFi: the BCM4330 radio no longer sleeps when idle. brcmfmac forced the
    firmware mpc (Minimum Power Consumption) iovar on, powering the radio down
    between packets — ~30 % packet loss and 270–530 ms latency. A new brcmfmac mpc
    module parameter plus a device modprobe.d conf (mpc=0) keep it awake (the
    Nexus Q is mains-powered): loss 30 %→0 %, latency 270–530 ms→4–59 ms. Stock-proven
    to be a driver gap — the same firmware + nvram works under the vendor bcmdhd.
  • WiFi: disabled brcmfmac P2P on the BCM4330 — the firmware advertises P2P but
    cannot create the P2P_DEVICE interface, which spammed the log with failed p2p-dev
    creations and orphaned "event handler failed (72)" errors.
  • boot: silenced the benign ti-sysc active-timer -EBUSY probe error for
    GPTIMER1 (an always-on system clockevent owned by the timer core).

Known issues

  • WiFi 2.4 GHz bulk throughput is limited by Bluetooth coexistence (the BCM4330
    combo shares one 2.4 GHz antenna) on a g-only AP — use 5 GHz for full speed
    (~26–30 Mbit/s, 802.11n). See
    docs/2026-06-26-wifi-mpc-fix-and-bulk-bufferbloat.md.

v1.4.0 — MPU cpufreq DVFS to 1.2 GHz (3.4×)

Choose a tag to compare

@petronijus petronijus released this 26 Jun 11:04

[1.4.0] - 2026-06-26

Added

  • MPU CPU frequency scaling — on-demand up to 1.2 GHz (3.4× the old floor). 🚀
    The OMAP4460 was pinned at its 350 MHz boot OPP; it now scales across
    350 / 700 / 920 / 1200 MHz under the ondemand governor. Built up in small,
    hardware-validated stages, each cross-checked against this unit's
    reverse-engineered stock kernel:
    • VDD_MPU is handed from the TWL6030 VCORE1 SMPS to the external TPS62361
      regulator over the PRM Voltage-Controller SR-i2c — the same hand-over stock does.
    • A thin "VC-bridge" cpu-supply regulator lets cpufreq-dt scale the rail
      through the OMAP voltage layer (VP force-update), at the stock-measured nominal
      voltages (1025 / 1203 / 1317 / 1380 mV).
    • At the 1.2 GHz OPP, Forward Body Bias is engaged on VDD_MPU via the on-chip
      ABB LDO — required for stable 1.2 GHz operation.
    • Thermal throttling: at the 100 °C trip the CPU cooling drops the frequency
      and ramps it back as it cools, so sustained full load stays safe.
  • USB serial debug console. The USB gadget is now an ACM serial console
    (/dev/ttyACM0 on the host, with a steelhead login: prompt) that survives
    reboots and leaves fastboot untouched.

Changed

  • The USB gadget no longer exposes a host-side network interface — it was swapped
    from the RNDIS network gadget to the serial console above. Use the on-board
    ethernet / WiFi for networking.

Known issues

  • On-board LAN9500A USB-Ethernet is down — a regression from 1.3.0. 🌐 The
    Ethernet that 1.3.0 fixed no longer enumerates on these cpufreq builds: the
    LAN9500A fails to connect (the EHCI port's PORTSC connect-status stays 0). It
    is a boot-timing side-effect of the voltage/cpufreq changes, which tipped the
    formerly-marginal connect timing into consistent failure. WiFi works in the
    meantime; a fix (a settle delay in the ethernet bring-up, or reordering the
    voltage init) is tracked for 1.4.1.

Full Changelog: v1.3.0...v1.4.0

v1.3.0 — Ethernet works 🌐

Choose a tag to compare

@petronijus petronijus released this 24 Jun 21:32

[1.3.0] - 2026-06-24

Fixed

  • On-board LAN9500A USB-Ethernet now works on mainline 6.12 🌐 — the
    long-standing "intermittent / never enumerates" problem is resolved. The
    chip enumerates on every boot (0424:9e00smsc95xx … eth0), the link comes
    up at 100 Mbps/Full and passes traffic cleanly. Verified on hardware: 5/5
    reboots all enumerate, 600 sustained pings at 0 % loss, 410 MB moved with
    zero rx/tx/CRC/drop errors. Root cause was two combined bugs, both found by
    stock-parity auditing against the factory Android kernel:
    • Patch 0012 (mfd: omap-usb-host): mainline only enables the per-port
      UTMI functional clock (usb_host_hs_utmi_pN_clk — the L3INIT CLKCTRL
      OPTFCLKEN gate) for TLL/HSIC port modes. An external-PHY (ehci-phy)
      port falls through to default: and never gets its clock, so the port-1 UTMI
      link block ran unclocked (clk_summary showed it disabled) and the
      controller never latched the downstream connect (PORTSC CCS stuck 0). Added
      OMAP_EHCI_PORT_MODE_PHY to the clock enable/disable paths.
    • Patch 0006 (usb: ehci-omap): stock's omap_ehci_soft_phy_reset (the
      UHH softreset / gpio pulse / clock re-park / ULPI register burst) is not
      the EHCI .reset hook — it is a runtime ehci_hub_control recovery
      handler that only fires when a port reset/resume times out, after a
      device has connected. We were running that whole sequence at bring-up, which
      blocked the very first connect. The .reset hook is now a plain
      ehci_setup() bring-up (the USB3320's reset defaults already put it in host
      mode); the ULPI/UHH recovery helpers are retained for a future hub_control
      hook.

Changed

  • All kernel patch headers now carry petronijus@bastla.com (was a work email /
    placeholder).

Artifacts

  • nexusq-boot-v1.3.0.img — kernel-only change (the ethernet fix); flash to the
    boot partition. The rootfs is unchanged from v1.2.0 — reuse
    nexusq-rootfs-v1.2.0-sparse.img from the v1.2.0 release.

Full Changelog: v1.2.0...v1.3.0

v1.1.0 — Ethernet (LAN9500A) works 🎉

Choose a tag to compare

@petronijus petronijus released this 22 Jun 15:47

[1.1.0] - 2026-06-22

Added

  • Ethernet (LAN9500A) now works 🎉 — the soldered on-board SMSC LAN9500A
    USB-ethernet enumerates and carries traffic. Two kernel changes did it:

    • 0006-usb-ehci-omap-steelhead-keep-ethernet-port-alive-ulp — steelhead
      host-init in ehci-omap: INSNREG01 burst thresholds, a ULPI Function-Control
      soft reset of the USB3320 PHY before usb_add_hcd(), and
      usb_disable_autosuspend() on the root hub so the idle port is not
      clock-gated away.
    • 0008-mfd-omap-usb-host-steelhead-UHH-HOSTCONFIG-connect — program
      UHH_HOSTCONFIG to the vendor's 0x11c (set P1_CONNECT_STATUS, leave
      APP_START_CLK clear) so the EHCI latches the port-1 connect. Measured
      mainline default was 0x1c; the stock Android 3.0 kernel uses 0x11c.

    The long-standing "ethernet is dead hardware" verdict was wrong — the stock
    kernel enumerates the same chip on this unit, proving the HW is fine and the bug
    was ours. Verified on hardware (#8 kernel): eth0 (0424:9e00smsc95xx)
    links at 100 Mbps/Full and passes bidirectional traffic — 0% packet loss over a
    direct cable, zero rx/tx/CRC/frame errors after ~660 MB moved. Throughput
    ~30–60 Mbps (USB2 / single-core OMAP4 bound, not a link fault). Reach the device
    over ethernet with the persistent eth-direct NetworkManager profile
    (static 10.42.0.2/24).

  • Kernel patch 0007-clk-ti-composite-implement-divider-round-set-rate — OMAP4
    ti,composite-clock nodes (gate + divider) had stub round_rate/set_rate
    returning -EINVAL, so any clk_set_rate() on them failed. Delegated both to
    ti_clk_divider_ops (as recalc_rate already did). Fixes the TAS5713
    amplifier MCLK: dpll_per_m3x2_ck now sets to 61.44 MHz →
    auxclk1_ck = 12.288 MHz (256 × 48 kHz). Verified on hardware (#4 kernel):
    clock rates correct, ALSA card 0 NexusQ-Speaker registers cleanly, no
    couldn't set dpll_per_m3x2_ck error.

  • CONFIG_SRAM=y in the defconfig (OMAP4 on-chip SRAM driver).

  • Tooling: scripts/regen-dts-patch.sh (regenerate patch 0003 from the working
    DTS) and scripts/extract-and-repack.sh (pull kernel+DTB from the build
    chroot pkgdir and repack a partition-sized boot image — a fast path that skips
    the rootfs build).

  • Build fix: the recurring abuild create_apks "Permission denied" on
    /home/pmos/packages//pmos/armv7/...apk is fixed. On a reused nexusq-workdir
    volume $WORK/packages was owned by the container pmos (uid 1000) while
    abuild inside the chroot runs as uid 12345, so it could not write its .apk.
    docker-build.sh Phase 7a now chowns $WORK/packages to 12345 before the
    build, so linux-google-steelhead-*.apk is created cleanly and pmbootstrap install runs. extract-and-repack.sh is kept as a fast path, no longer a
    required workaround.

  • Build fix: clearing the armv7 ccache out-of-band leaves its directory owned
    by uid 1000, so abuild inside the chroot (uid 12345) then hits ccache: error: Permission denied at make olddefconfig. docker-build.sh Phase 7a now also
    chowns $WORK/cache_ccache_armv7 to 12345 (alongside $WORK/packages).

Changed

  • DTS: delete the upstream cpu@1 node to match the single-core build
    (CONFIG_SMP=n). Clears the early-DT nodes greater than max cores 1 warning
    and the resulting kernel taint (was 512, now 0). Re-add together with the
    deferred OMAP4460 SMP / CPU1 bring-up. Patch 0003 regenerated accordingly.
  • Device root password is now read at runtime from a gitignored .nexus_pw
    (no hard-coded credential in the SSH/flash helpers).

Known limitations

  • Rootfs image build (pmbootstrap install, Phase 9) currently fails on a
    device-google-steelhead post-install step (exit 127); the kernel .apk and
    boot image build fine, so kernel/DTB iteration is unaffected. Reflash boot only.

Install: flash nexusq-boot-v1.1.0.img to the 8 MB boot partition
(dd … of=/dev/mmcblk0p9 conv=fsync from a running system, or fastboot flash boot). The root filesystem is unchanged since v0.1.0 — reuse
nexusq-rootfs-v0.1.0-sparse.img. The boot image is kernel #8; it prints the
UHH_HOSTCONFIG values once at boot (diagnostic) and is functionally identical to
the cleaned 0008 source patch in this tag. sha256 in sha256sums.txt.

Note: the rootfs image build (pmbootstrap install, Phase 9) currently fails on
a device post-install step; the kernel/boot image build is unaffected.

Full Changelog: v0.1.0...v1.1.0

v0.1.0 — First working system

Choose a tag to compare

@petronijus petronijus released this 10 Jun 14:33

First release where the Nexus Q boots into a usable OS. From a bricked-looking black screen to postmarketOS with WiFi, Bluetooth, SSH and a desktop.

Highlights

  • postmarketOS (systemd) boots from the userdata partition
  • WiFi via BCM4330 with the device's original factory calibration (recovered from the intact 2012 Android system partition)
  • Bluetooth with original "Proxima" firmware config
  • XFCE4 desktop on HDMI, SSH over USB gadget and WiFi
  • TAS5713 25 W amplifier audio path wired and software-verified
  • 4 kernel patches on mainline 6.12.12 (TAS5713 support, steelhead DTS, TWL6030 32k clock cell)

Install

See INSTALL.md. Short version:

fastboot flash boot nexusq-boot-v0.1.0.img
fastboot -S 100M flash userdata nexusq-rootfs-v0.1.0-sparse.img

Default login user/147147 — change it. SSH host keys generate on first boot.

Known issues

  • ~1 in 3 boots hangs (old U-Boot flakiness) — power-cycle again
  • Single-core only (U-Boot leaves CPU1 in a bad state)
  • On the reference unit, ethernet and the TWL6040 codec are dead hardware; your unit may differ

v1.0.0 - First Successful Build

Choose a tag to compare

@petronijus petronijus released this 26 Feb 13:31

nexusQ Reloaded - First Build

Initial successful build for Google Nexus Q.

Included artifacts

  • boot.img — Boot image
  • google-steelhead.img — Full system image for Google Nexus Q