#!/bin/bash
# GeniePod — Jetson audio bring-up at boot.
#
# Configures the Tegra APE AHUB route for external I2S2 capture so the
# external audio frontend (e.g. ESP32-LyraT V4.3 over the 40-pin header)
# appears as `hw:APE,0` / `plughw:APE,0`.
#
# Invoked by genie-audio.service after sound.target. Safe to run manually
# at any time. Idempotent — re-running has no negative effect.
#
# Prerequisites (not handled here):
#   - Jetson-IO has applied the 40-pin I2S2 overlay (sudo jetson-io.py).
#   - The external master is wired: SCLK→12, LRCK→35, DIN→38, GND→6.
#
# See doc/lyrat-jetson-audio.md for the full external bring-up.

set -uo pipefail

CARD="APE"
LOG_TAG="genie-audio-init"

log() { echo "[${LOG_TAG}] $*"; }
warn() { echo "[${LOG_TAG}] WARN: $*" >&2; }

# Wait for the APE card to appear in /proc/asound/cards. This is a plain
# file read so it works regardless of amixer permissions or quirks in
# `amixer controls` output (which has been observed to return an empty
# list in some non-systemd contexts even when controls are reachable via
# `amixer cget`). The card normally appears during sound.target.
for _ in $(seq 1 30); do
    if grep -qE '^[[:space:]]*[0-9]+[[:space:]]+\[APE' /proc/asound/cards 2>/dev/null; then
        break
    fi
    sleep 1
done

if ! grep -qE '^[[:space:]]*[0-9]+[[:space:]]+\[APE' /proc/asound/cards 2>/dev/null; then
    warn "card $CARD not enumerated in /proc/asound/cards — skipping route setup."
    exit 0
fi

# Configure the AHUB route and I2S2 framing for external-master capture
# at 48 kHz / 16-bit / stereo (ALSA plughw layer will downmix / resample
# to whatever the consumer asks for, including 16 kHz mono for Whisper).
set_ctrl() {
    local name="$1"
    local value="$2"
    if amixer -c "$CARD" cset name="$name" "$value" >/dev/null 2>&1; then
        log "  $name = $value"
    else
        warn "  failed to set $name = $value (control may be absent on this kernel)"
    fi
}

log "configuring ${CARD} I2S2 → ADMAIF1 capture route"
set_ctrl "ADMAIF1 Mux"                       "I2S2"
set_ctrl "I2S2 codec master mode"            "cbm-cfm"   # external master drives BCLK + LRCK
set_ctrl "I2S2 codec frame mode"             "i2s"       # Philips I2S framing
# I2S2 Sample Rate must match the LyraT wire LRCK frequency. The LyraT
# firmware (examples/recorder/lyrat_jp4_passthrough/) configures the ESP32
# I2S for 48 kHz, but ESP-IDF's I2S driver on this board+rate combo emits
# 24 kHz LRCK on the wire (confirmed empirically: setting Jetson side to
# 48 kHz produces 2x-speed chipmunk playback; setting to 24 kHz produces
# natural pitch). 24 kHz keeps Nyquist at 12 kHz which is still well
# above the speech band; whisper-server resamples to 16 kHz internally.
# Investigating the ESP-IDF clock divider behavior is tracked as future
# alpha.6 work — see doc/lyrat-jetson-audio.md.
set_ctrl "I2S2 Sample Rate"                  "24000"
set_ctrl "I2S2 Capture Audio Channels"       "2"
set_ctrl "I2S2 Capture Audio Bit Format"     "16"
set_ctrl "I2S2 Client Channels"              "2"
set_ctrl "I2S2 Client Bit Format"            "16"
set_ctrl "ADMAIF1 Capture Audio Channels"    "2"
set_ctrl "ADMAIF1 Capture Client Channels"   "2"

log "done"
