Architecture

Register Map

The Apollo communicates with the host via memory-mapped I/O (MMIO) registers at PCI BAR0. All register access from userspace goes through the kernel driver's ioctl interface.


BAR0 layout overview

The BAR0 address space is divided into several functional regions:

RegionOffset rangePurpose
Global / ID0x00000x0034Firmware version, serial number, hardware UID
DSP ring banks0x20000x23FFPer-DSP command and response ring buffers (DSP 0–3)
Interrupt / DMA0x22000x22FFInterrupt controller, DMA control, transport
Audio extension0x22400x2284Audio transport, channel counts, clock
Mixer settings0x38000x3A5CDSP mixer parameter registers (52 setting slots; first 38 used)
Mixer readback0x38100x3914Hardware readback status and data
DSP ring banks (high)0x5E000x61FFPer-DSP ring buffers (DSP 4–7)
DMA scatter-gather0x80000xBFFFPlayback and capture DMA descriptor tables
Notification / SRAM0xC0000xC4FFConfig, notification status, IO descriptors, CLI

Global and identification registers

OffsetNameAccessDescription
0x0000FW_VERSIONRFirmware version / identification word
0x0020SERIAL_BASER16-byte ASCII serial string (4 registers)
0x0030HW_UID_LORHardware unique ID, low 32 bits
0x0034HW_UID_HIRHardware unique ID, high 32 bits
0x2218FPGA_REVRFPGA revision (v1 devices: bits[31:28] = device type + 1)
0x2234EXT_CAPSRExtended capabilities (v2 FW). Bits[25:20] = device type, bits[15:8] = DSP count
0x2238SERIALRSerial number / device info

The serial prefix (first 4 ASCII digits) identifies the device model. For example, prefix 2005 maps to Apollo x4 (device_type 0x1F).


Interrupt and DMA control

OffsetNameAccessDescription
0x2200DMA_CTRLR/WDMA engine control. Enable bits[8:1], reset strobes bits[16:9]
0x2204IRQ_ENABLER/WInterrupt mask register, low 32 vectors
0x2208IRQ_STATUSR/WInterrupt status register. Write-back to acknowledge
0x220CWALLCLOCKRWallclock / interrupt pending
0x221CDSP_RESETR/WDSP reset control
0x2220TRANSPORTR/WTransport control (0 = stop)
0x2264EXT_IRQ_STATUSR/WInterrupt status, high 32 vectors (v2 firmware)
0x2268EXT_IRQ_ENABLER/WInterrupt mask, high 32 vectors (v2 firmware)

DMA control bitmask (v2 firmware)

  • Bits [8:1] — DMA engine enables (16 engines total with v2 mask 0x1FFFE)
  • Bits [16:9] — Reset strobes. Write 1 to reset, then clear

A DMA reset pulse (set strobes then clear) while engines are enabled kicks the ring buffer DMA engine into an active state. Without this pulse, the FPGA ignores ring buffer doorbells.


Audio extension transport registers

These registers control DMA audio streaming, not the DSP mixer.

OffsetNameAccessDescription
0x2240AX_BUF_SIZER/WBuffer frame size minus 1
0x2244AX_SAMPLE_POSRCurrent sample position
0x2248AX_CONTROLR/WMain transport control
0x224CAX_P2P_ROUTER/WPeer-to-peer routing
0x2250AX_PLAY_CHR/WTotal playback channel count
0x2254AX_FRAME_CTRRFrame counter
0x2258AX_FRAME_CFGR/WFrame counter config
0x225CAX_REC_CHR/WTotal record channel count
0x2260AX_CONNECTWConnection doorbell
0x226CAX_DMA_BLKSZR/WDMA block size
0x2270AX_TIMER_CFGR/WPeriodic timer interval
0x22C0AX_STATUSRTransport status (read fence)

AX_CONTROL bits

BitNameDescription
0DMA_ENDMA enable
1PLAY_ENPlayback enable
2REC_ENRecord enable
3IRQ_ENInterrupt enable
9EXT_MODEExtended mode (firmware >= 10)

Start all: write 0x20F (DMA + play + rec + IRQ + extended mode).

AX_CONNECT doorbell values

ValueAction
0x01Initiate connection
0x04Trigger clock change notification
0x10Initiate disconnection

Clock registers

OffsetNameAccessDescription
0x2280CLOCK_SRC0R/WClock source register 0
0x2284CLOCK_SRC1R/WClock source register 1

Mixer settings window (0x3800)

The DSP mixer engine uses a shared memory window at BAR0 + 0x3800 for parameter exchange between host and DSP.

OffsetNameAccessDescription
0x3808MIXER_SEQ_WRR/WSequence counter, host to DSP
0x380CMIXER_SEQ_RDRSequence counter, DSP readback
0x38B40x3A5CMIXER_SETTING[0..51]R/W52 setting slots, 8 bytes each (2 x u32). Only the first 38 (settings 0–37) are written during the batch update protocol. Settings 38–51 are reserved.

Each setting occupies two 32-bit words with paired value/mask encoding:

wordA = (changed_mask[15:0]  << 16) | value[15:0]
wordB = (changed_mask[31:16] << 16) | value[31:16]

The upper 16 bits of each word are the changed-bits mask. If the mask is zero for a word, the DSP ignores that half. See DSP Protocol for the sequence counter handshake.


Hardware readback registers

OffsetNameAccessDescription
0x3810MIXER_RB_STATUSR/W1 = data ready. Write 0 to re-arm
0x3814+MIXER_RB_DATAR40 consecutive u32 words of readback data

Readback data fields

rb_data[0] — Preamp flags (4 channels, 6-bit stride):

BitsField
ch*6 + 0Mic/Line (1=Line, 0=Mic)
ch*6 + 1PAD
ch*6 + 2Link
ch*6 + 348V phantom
ch*6 + 4Low-cut filter
ch*6 + 5Phase invert
24HiZ active (hardware auto-detect)

rb_data[2] — Monitor section:

BitsField
[7:0]Monitor volume (raw 8-bit)
[15:8]HP1 volume (raw 8-bit)
16Mute
17Mono
31Dim

rb_data[3] — Preamp gain (4 channels, 8-bit stride):

BitsField
ch*8 + [7:0]Gain value per channel

rb_data[6]: bit 8 = Talkback active.

rb_data[7]: bits [7:0] = HP2 volume.

rb_data[8]–rb_data[17]: Static 0xf0000000. These are NOT audio meters — audio metering is computed in software from PCM samples.


Notification and SRAM region (0xC000)

Bank offset

Many notification registers are bank-shifted. For Apollo x4, the bank shift is 0x0A, adding an offset of 0x28 bytes:

effective_address = 0xC000 + bank_shift * 4 + register_offset

Bank-shifted registers

Effective offsetNameDescription
0xC028NOTIF_READBACKReadback buffer (up to 95 dwords)
0xC02CNOTIF_ACEFACEACEFACE handshake write target
0xC030NOTIF_STATUSNotification status (connect ack, events)
0xC074NOTIF_CLOCK_CFGSample rate / clock source write
0xC07CNOTIF_RATE_INFORate info readback
0xC080NOTIF_XPORT_INFOTransport info readback
0xC084NOTIF_CLOCK_INFOClock source info readback

Config write area (no bank shift)

OffsetNameDescription
0xC000NOTIF_CONFIG[0]Bank shift value (written after connect)
0xC004NOTIF_CONFIG[1]Readback count (0x17C = 380)
0xC0080xC024NOTIF_CONFIG[2..9]Reserved (zero)

Notification status bits (0xC030)

BitNameDescription
0OUT_IOOutput IO descriptors ready
1IN_IOInput IO descriptors ready
4TRANSPORTTransport/clock change
5EVENTGeneric event
21CONNECTConnect response (ACEFACE ack)
22SRATESample rate change

CLI register interface (0xC3F4)

The CLI (Command Line Interface) provides communication with the ARM microcontroller that controls preamps (PGA2500 SPI), phantom power relays, and the identify LED.

OffsetNameAccessDescription
0xC3F4CLI_ENABLEWWrite 1 to enable CLI
0xC3F8CLI_STATUSRCommand status / length
0xC3FCCLI_RESP_LENRResponse data length (bytes)
0xC400CLI_CMD_BUFWCommand buffer (128 bytes, 32 x u32)
0xC480CLI_RESP_BUFRResponse buffer (128 bytes, 32 x u32)

DMA scatter-gather regions

OffsetNameDescription
0x8000PLAY_DMA_BASEPlayback DMA descriptor base (1024 entries)
0xA000REC_DMA_BASERecord DMA descriptor base (1024 entries)

Each direction uses a 4 MiB DMA buffer. Descriptors point to 4 KiB pages.


Register access from userspace

All register access goes through the kernel driver's ioctl interface on /dev/ua_apollo0:

IoctlNumberStruct sizeDescription
READ_REG0x108 bytesRead BAR0 register (offset, value)
WRITE_REG0x118 bytesWrite BAR0 register (offset, value)
SET_MIXER_BUS_PARAM0x3016 bytesWrite bus coefficient via DSP ring
SET_MIXER_PARAM0x3116 bytesWrite mixer parameter (preamp, monitor)
WRITE_MIXER_SETTING0x3616 bytesAtomic mixer setting write with seq handshake
READ_MIXER_SETTING0x3716 bytesAtomic mixer setting read
CLI_COMMAND0x40264 bytesCLI command to ARM MCU
GET_HW_READBACK0x41164 bytesRead DSP readback (status + 40 data words)

Further reading

Previous
Overview