Files
b0hemia e0bc4785e9 diskOS installer: initial public beta
Flashes the diskOS custom UI onto the FiiO Snowsky Disc over Ingenic mask-ROM USB,
building the image from your own stock firmware. Runs from source via install.sh.
2026-08-26 15:26:14 +10:00

15 KiB
Raw Permalink Blame History

Snowsky Disc - Hardware Capability Map

Live-probed from the device root shell (serial /dev/ttyACM0) on 2026-06-25, while running stock firmware (V2.09 family, kernel built 2026-06-03). This documents what the hardware can do, independent of what stock software chooses to use - to scope diskOS enhancements and the "write our own mq_player/mq_ui" question.

Probing was read-only (/proc, /sys, aplay --dump-hw-params, i2cdetect-equivalent via sysfs names, dmesg). Nothing was written to the device during this survey.


1. SoC & Compute

Item Value Source
SoC Ingenic X2000 (xburst2), board ingenic,x2000_halley5_module_base /proc/cpuinfo
Cores 2× XBurst II V2, SMP /proc/cpuinfo (processor 0,1)
Clock ~1.2 GHz (BogoMIPS ≈ 2390) /proc/cpuinfo
FPU Yes (per-core) /proc/cpuinfo
SIMD MSA (MIPS SIMD Architecture, 128-bit) - ASEs implemented: msa /proc/cpuinfo
ISA mips1 / mips2 / mips32r2 + MSA /proc/cpuinfo
TLB 288 entries; 1 HW watchpoint; 6 kscratch regs /proc/cpuinfo
DVFS None exposed - no cpufreq/scaling_available_frequencies /sys/.../cpufreq
Thermal No thermal zones - /sys/class/thermal empty sysfs
GPU None (X2000 has no GPU) /dev has no gpu node
VPU / video decode None - no vpu/video/mem2mem dev nodes /dev
Hardware JPEG None as a dev node (stock jpg_to_png.c is software) /dev, RE

Implication: all audio DSP and all UI rendering are CPU-bound. The single biggest untapped compute lever is MSA SIMD - diskOS's LVGL is almost certainly built without -mmsa, so blends/scales/rotations run scalar. Rebuilding LVGL (and any DSP/resampler) with MSA is the highest-leverage perf win available.


2. Memory

Item Value
RAM total 120 MB (MemTotal: 120308 kB)
Free / available (stock running) ~19 MB free / ~64 MB available

Tight but workable. diskOS already runs in this budget. Big in-RAM buffers (e.g. a full-res rotating album-art layer) must be sized carefully.


3. Storage

NAND (MTD) with A/B dual-boot for OTA, plus the user microSD:

mtd size name notes
mtd0 2 MB uboot bootloader
mtd1 8 MB kernel slot A
mtd2 128 MB rootfs slot A - squashfs, read-only (why fiio_init.sh can't be edited in place)
mtd3 8 MB kernel2 slot B
mtd4 25 MB rootfs2 slot B (smaller - recovery/fallback)
mtd5 1 MB ota OTA state
mtd6 1 MB mac MAC/calibration
mtd7 83 MB userdata writable - mounted as /usr/data, where diskOS lives
mmcblk0 ~238 GB microSD single partition mmcblk0p1 - the music card

Implication: the boot hook is a small edit patched into the read-only rootfs's usr/project/fiio_init.sh (which is why enabling it requires rewriting the rootfs partition - the flash). The payload it launches - the mq_ui binary and diskOS's runtime state - lives in the writable /usr/data (mtd7), the safe persistent target. So: the hook is baked into the RO rootfs; only the UI/state are on /usr/data.


4. Audio - the headline subsystem

4.1 DACs - quad CS43131, fully balanced

Four Cirrus CS43131 chips on I²C bus 3:

I²C addr sysfs name /dev node (major)
3-0030 cs43131 /dev/cs43131 (248)
3-0031 cs43131b /dev/cs43131b (247)
3-0032 cs43131c /dev/cs43131c (246)
3-0033 cs43131d /dev/cs43131d (245)

dmesg tags include cs43131_left_negetive and cs43131b_open → the four DACs are wired as L+/L−/R+/R− (fully differential / balanced), two CS43131 per channel. This is an unusually serious analog design for the form factor. (Whether the physical jack exposes balanced (4.4 mm) or sums to single-ended (3.5 mm) is a board question - confirm against the unit's connectors.)

Each CS43131 is a stereo DAC + integrated headphone amp; the family supports PCM to 384 kHz and DSD64/128/256. Control is via a custom FiiO cs43131 kernel driver exposing the four char devices above; stock mq_player drives them with ioctl (not ALSA controls). Raw /dev/i2c-3 is also present as a fallback.

4.2 SoC I²S/DMA path - the streaming ceiling

The Ingenic audio controller (ALSA card 0 x2000) exposes 5 playback + 5 capture DMA channels (hw:0,0-hw:0,4 playback). aplay --dump-hw-params on an idle channel:

FORMAT:  ALL
SAMPLE_BITS: [3 64]
CHANNELS:    [1 8]
RATE:        [8000 768000]

So the kernel/I²S link can stream up to 768 kHz / 64-bit / 8-channel - far beyond the current track (S32_LE / 48 kHz / 2ch on DMA3). The real output ceiling is set by the CS43131 (~384 kHz PCM, DSD256), not the SoC.

4.3 ALSA mixer surface

amixer controls shows only the SoC internal codec (ICODEC HPOUTL/MIC GAIN, MICBIAS), digital mic (DMIC ...), line-out muxes (LO0_MUX…LO11_MUX), and the five audio-interface formatters (baic0_fmt…baic4_fmt). There is no CS43131 control, no DSD switch, and no digital-filter control in ALSA - all of that is the kernel driver + mq_player ioctl path. BAIC: baic start/stop in dmesg marks I²S on/off per track.

4.4 Decode & format support (from mq_player RE)

  • Decoder backend: libavcodec.so.58 (ffmpeg) - string decoder_ffmpeg.
  • DSD: DSD_MODE_NONE / DSD_MODE_NATIVE / DSD_MODE_DOP - native DSD and DoP.
  • MQA: is_mqa flag (detection/passthrough).
  • Containers: FLAC, APE, DSF/DFF, SACD ISO, CUE sheets; ffmpeg covers ALAC/OPUS/ WavPack/etc.
  • Param validation: check_sample_param, reset hw params, AudioCodecOpen dsd, no support sample! dsd_mode/out_dev/... - the player gates rate/format per DAC mode.

Tools present: aplay, amixer, tinyplay, tinymix - raw PCM playback is possible today (the DAC just has to already be configured for the rate).


5. Display

Item Value
Driver ingenicfb
Visible 360×360, 32 bpp (XRGB8888/BGRA, panel mounted 180°-rotated)
Framebuffer virtual 360×1080 = triple-buffered 360×360
Overlay layers fb0-fb3 = 4 hardware LCDC planes (/dev/fb0..fb3)
Backlight standard backlight class, 41 levels (0-40)

Layer control interface (confirmed via sysfs): ingenicfb exposes layer0-layer3 under /sys/class/graphics/fb0/device/, each with enable, src_fmt, src_size, target_pos, and target_size. target_size ≠ src_size ⇒ the LCDC has a per-layer hardware scaler (notable, since there's otherwise no GPU/VPU). layer0 is the active UI plane (enable: 1, src 360×360). Layers position + scale in hardware but do not rotate.

Implication: static scaled art/backdrops could be HW-composited on fb1-3 (e.g. a scaled cover or a dim backdrop under the LVGL UI) with no CPU blend. BUT:

  • A spinning cover still needs software rotation (layers don't rotate) - LVGL already does this fine, so the overlay is an optimization, not a requirement.
  • Alpha/blend mode is NOT in sysfs (no alpha/zorder/colorkey node) - likely an FBIO ioctl in the ingenicfb driver; blending behavior is unverified.
  • Visual confirmation needs a camera: fbshot reads fb0's memory, but overlays composite at scanout, so an fb1 test pattern won't appear in an fb0 capture. Defer the live overlay test until we're ready to pursue HW-layer art and can eyeball the panel.

6. Input

Device node notes
Touch /dev/input/event1 - cst816t single-finger panel, but speaks MT type-B protocol (slot/tracking-id/ABS_MT_POSITION_X/Y/TOUCH_MAJOR/PRESSURE; no plain ABS_X/Y). Caps EV=0xb, ABS=0x6618000 (high word).
Keys /dev/input/event0 - x2000_key physical buttons (GPIO keys)

We can synthesize input by writing the 32-bit-ABI input_event (16-byte) MT-B sequence to /dev/input/event1 - verified working (used to drive stock's UI pages over serial during RE). diskOS can also read the hardware keys via event0.


7. Power

IC I²C role
SGM41513 2-001a battery charger (Li-ion, ~3A class)
CW221X (Cellwise) 2-0064 battery fuel gauge → /sys/class/power_supply/cw221X-bat
AW35615 2-0022 USB-C PD / CC controller (Type-C orientation + power delivery)

Live read: capacity 100%, 4.32 V, source "Mains". The fuel gauge gives real %/voltage; /dev/usbcc_ioctl (from RE) is the PD/CC control path. PD negotiation hardware exists, so faster charging / power-role awareness is at least theoretically addressable.


8. Connectivity (wireless)

Item Value Source
Module AP6212 = Broadcom BCM43438 / 4343A1 dmesg: chip:0xa9a6, fw_bcm43438a1.bin, nvram_ap6212a.txt
WiFi 2.4 GHz only, 802.11 b/g/n (single-band) BCM43438 spec
WiFi attach SDIO ([dhd] driver v101.10.591.91.40, 512 KB dongle RAM) dmesg
Bluetooth Broadcom BT over UART /dev/ttyS0 @3Mbaud (hci0, BD address (device-specific, redacted)) hciconfig
BT firmware BCM4343A1_001.002.009.1026.1055.hcd (the BCM4345C5/C0 .hcd files are leftovers for other FiiO models) /lib/firmware/bt_bcm
BT bring-up hci0 is NOT attached at boot - bcmdhd.ko only loads the driver/GPIOs. The HCI iface is created on-demand by brcm_patchram_plus --enable_lpm --enable_hci --baudrate 3000000 --patchram <.hcd> /dev/ttyS0, then /usr/project/bluetoothd (a2dp,avrcp,source) + bluealsa --device=hci0 (SBC/LDAC). Stock = bluez; bsa_server/bt_enable_bsa*.sh = dead code for the wrong chip. Decoded from mq_player strings. mq_player RE

Corrects prior note: earlier memory said "BCM4345C5". The actual silicon is BCM43438 (AP6212) - single-band 2.4 GHz + BT 4.x.

Implication: no 5 GHz → WiFi music transfer / streaming is capped at 2.4 GHz real throughput (tens of Mbps, congestion-sensitive). BT codec quality (LDAC/aptX) is a userspace-stack question, not a chip blocker for A2DP.


9. USB

Item Value
Controller DWC2 OTG (13500000.otg_new) - dual-role (host or device)
Current mode device; gadget serial_demo exposing ACM only (VID 0x0525 / PID 0xa4a7) → this is our serial shell
USB-DAC mode stock "UAC" work-mode reconfigures the gadget to USB Audio Class (device-as-DAC for a host PC)

Untapped: DWC2 is OTG, so USB host mode is physically possible - mounting USB storage, or driving an external USB DAC (device as a pure transport). Stock only ships device-mode (serial + UAC). Host-mode would need role switch + the right gadget/host config and likely a USB-C OTG adapter.


10. Misc

  • RTC: rtc0 present and correct - real hardware clock.
  • ADC: SoC SAR ADC, 6 aux channels (/dev/jz_adc_aux_0..5) - analog reads (e.g. jack/line detect, if wired).
  • Watchdog: hardware /dev/jz_watchdog.
  • LED: none. /sys/class/leds is empty and there is no physical LED on the unit (confirmed visually). The RGB_LEVEL/RGB_STATUS fields in mq_player's config blob are vestigial, inherited from the halley5 reference design / other FiiO products. → diskOS should plan no LED features.
  • Motion sensors: none on I²C (no accel/gyro) - no tilt/gesture input despite the round watch-like shape.

11. Stock-uses vs hardware-can-do (gap list)

Capability HW supports Stock uses diskOS opportunity
MSA SIMD Yes (128-bit) UI not built for it (unknown) Rebuild LVGL/DSP -mmsa → faster render/effects
LCDC overlay planes 4 (fb0-3) fb0 only HW-composited art/video layer (spinning cover, backdrops)
I²S rate 768k/64b/8ch ≤384k/DSD256 (DAC-limited) none beyond DAC; already maxes the DAC
DSD native + DoP Yes Yes parity - reuse driver ioctls
Quad balanced DACs Yes Yes direct ioctl control for bit-perfect / HW volume
USB host (OTG) Yes No (device-only) USB storage / external USB-DAC transport
UAC2 gadget Yes Yes (UAC mode) expose/control USB-DAC from diskOS
USB-C PD Yes (AW35615) basic charge PD-aware fast charge / power-role UI
Physical keys Yes (x2000_key) Yes map HW buttons in diskOS
WiFi 5 GHz No - hard ceiling: 2.4 GHz only
GPU / VPU / HW JPEG No - hard ceiling: video is CPU-only (MSA-assisted at best)
Thermal / DVFS Not exposed - no power/thermal tuning via standard sysfs
LED None vestigial config none - drop from plans

12. "Write our own mq_player / mq_ui?" - assessment

mq_ui: already done. diskOS is our own UI; it reuses stock mq_player purely as an audio engine over mqueue IPC. No reason to change that split for UI work.

mq_player: a full rewrite is high-effort but the local-playback core is feasible. What a from-scratch local player needs, and how hard each piece is:

Piece Feasibility Notes
Decode Easy reuse on-device libavcodec.so.58 (same as stock)
PCM out Easy tinyalsa/libasound to card 0; up to 768k/64b
DAC control (rate/DSD/filter/volume/mute) Medium open /dev/cs43131* and replay the kernel-driver ioctls - must RE the ioctl numbers + sequences from mq_player.asm (bounded but real work). This is the critical enabler.
Native DSD / DoP Medium once DAC ioctls are known, feed the right format
MCU glue (keys/charge/USB-detect/power) Medium stock player talks to the FiiO MCU; our player must too (MCU command surface mapped during RE)
Streaming receivers (AirPlay/DLNA/Roon/QPlay/BT-sink) Hard large independent stacks - do not rewrite; keep stock or graft open-source (e.g. shairport-sync)

Recommendation (hybrid, incremental):

  1. Keep stock mq_player as the engine for now - it already handles DAC/DSD/streaming/ MCU and diskOS drives it fine over IPC.
  2. RE the cs43131 ioctl interface regardless - it's the key that lets diskOS (or a future thin player) control bit-perfect output, hardware volume, DSD, and filters directly. Highest-value RE next step.
  3. Only build our own local player if we need something stock won't expose - e.g. software parametric EQ, ReplayGain, custom gapless/crossfade, or a DSP chain - using ffmpeg + tinyalsa + the RE'd DAC ioctls. Leave streaming to stock.

The streaming receivers and MCU dependency are what make a complete replacement expensive; the audiophile local-playback path is the tractable, high-value slice.


Appendix: probe commands (reproducible)

  • SoC/mem: cat /proc/cpuinfo /proc/meminfo, uname -a
  • Audio: cat /proc/asound/{cards,pcm}, aplay -l, aplay -D hw:0,0 --dump-hw-params /dev/zero, amixer -c0 controls
  • I²C map: for d in /sys/bus/i2c/devices/*/name; do echo "$d: $(cat $d)"; done
  • Power: cat /sys/class/power_supply/*/{type,capacity,voltage_now,status}
  • Storage: cat /proc/partitions /proc/mtd
  • USB: ls /sys/class/udc, cat /sys/class/udc/*/state, ls /sys/kernel/config/usb_gadget/*
  • Wireless: dmesg | grep -iE 'dhd|bcm|chip', hciconfig -a, ls /lib/firmware/{wifi_bcm,bt_bcm}
  • Display/input: cat /sys/class/graphics/fb0/{name,virtual_size,bits_per_pixel}, ls /dev/fb*, cat /proc/bus/input/devices
  • Engines: ls /dev | grep -iE 'ipu|vpu|jpeg|adc|watchdog'