Add GC2395/CAMSS rear camera driver and fix audio, earpiece, micbias, and modem routing

This commit is contained in:
Luxferre
2026-10-19 23:34:06 +03:00
parent a6e3fa184f
commit a14a7aa543
20 changed files with 1623 additions and 49 deletions
+74 -5
View File
@@ -31,16 +31,21 @@ This manual covers flashing, operating, and customizing **Bananarchy Linux** (`v
- Includes instant case toggling during preedit, full 32-character ASCII punctuation/symbol entry, terminal control sequences (`^A`–`^Z`, `Esc`, `Tab`, `F1`–`F12`), and a `450ms` long-press `*` `Ctrl+` modifier latch.
3. **Bantam AI agent (`prebuilt/bantam/bantam`)**:
- Fetched from the latest `master` branch of `https://code.luxferre.top/luxferre/bantam-cpp`, cross-compiled for `armv7`, and installed to `/usr/bin/bantam` and `/usr/local/bin/bantam` (with no default `.bantam.cfg` pre-created).
4. **Mainline 6.12.1-msm8916 QDSP6 audio, voice call & LTE modem stack**:
4. **Mainline 6.12.1-msm8916 QDSP6 audio (loudspeaker, earpiece, MEMS & headset mics), voice call & LTE modem stack**:
- Patched `q6core`, `q6afe`, `q6afe-dai`, `q6voice-dai`, `q6mvm`, and device trees (`VoiceMMode1` DAI + PM8909 WCD codec).
- WirePlumber `50-s16le.lua` (`S16LE` sample format enforcement), ALSA UCM2 profiles (`HiFi.conf` and `VoiceCall.conf`), `q6voiced`, `rmtfs`, `msm-modem-uim-selection`, `msm8909-modem-wwan-port`, and `ModemManager`.
5. **Memory & swap tuning for 512 MB RAM**:
- Automatic PM8909 WCD analog codec register initialization at boot (`CDC_A_MICB_1_VAL` `0xf141 = 0x60` for 2.8V internal MEMS microphone bias, and `CDC_A_RX_EAR_CTL` `0xf1c0 |= 0x20` for +6 dB earpiece PA gain).
- WirePlumber `50-s16le.lua` (`S16LE` sample format enforcement), ALSA UCM2 profiles (`qdsp6.conf`, `HiFi.conf`, and `VoiceCall.conf`), `q6voiced` (`card=0, device=2`), `sxmo_audio.sh` / `sxmo_modemaudio.sh` PipeWire UCM profile switching, `sxmo_ob.sh` (`WOB_DISABLE_PLEDGE=1`), `rmtfs`, `msm-modem-uim-selection`, `msm8909-modem-wwan-port`, and `ModemManager` (`mmcli`).
5. **Rear 2MP camera (`src/msm8905-cam/`) & SY7807 torch LED (`src/leds-msm8905-torch/`)**:
- `msm8905-cam.ko`: powers PM8909 LDOs (`L2` 1.2V, `L6` 1.8V, `L17` 2.85V) and `CAMSS_MCLK0` (24 MHz on GPIO 26), configures the GalaxyCore `GC2395` MIPI CSI-2 sensor (`blsp_i2c3` `0x37`) and MSM8909 `CAMSS` (`CSIPHY0 -> CSID0 -> ISPIF -> VFE0 RDI0 -> VBIF -> CMA`), and exposes `/dev/video0` (`800x600` 24-bit `RGB3` V4L2 capture device).
- `leds-msm8905-torch.ko`: exposes `/sys/class/leds/white:torch` (`GPIO 31`), configures WCD micbias/earpiece registers at boot, and hooks PM8909 `PON` clean shutdown.
6. **Memory & swap tuning for 512 MB RAM**:
- `384 MiB` ZSTD-compressed `zram0` swap (priority `100`) + `512 MiB` `/swapfile` (priority `10`), with `vm.swappiness=100` and `vm.page-cluster=0`.
6. **Preinstalled on-device development & scripting stack**:
7. **Preinstalled on-device development & scripting stack**:
- **C / C++ toolchain & build tools**: `gcc`, `g++`, `musl-dev`, `make`, `git`, `nano`
- **Janet**: `janet`, `janet-dev`, `jpm` (Janet package manager)
- **Perl**: `perl`, `perl-io-socket-ssl` (`IO::Socket::SSL`)
- **Tcl & SQLite**: `tcl`, `tcl-lib` (`tcllib`), `tcl-tls`, `sqlite` (`sqlite3`), `sqlite-tcl` (`tcl-sqlite`)
- **Hardware & media utilities**: `v4l-utils` (`v4l2-ctl`), `i2c-tools`, `ffmpeg`, `mpv`, `imv`
---
@@ -218,10 +223,74 @@ You can switch between **vertical (`splitv`, one under another)**, **horizontal
## 4. Default credentials, USB SSH & Bantam AI agent
- **Username**: `user`
- **Password**: `147147` (`doas` and `sudo` enabled)
- **Password**: `147147` (`doas` and `sudo` enabled, with passwordless `doas` configured for `wheel` in `/etc/doas.d/50-sxmo.conf`)
- **USB networking SSH**:
```bash
ssh user@172.16.42.1
```
- **Bantam AI agent**:
Run `bantam` in the terminal (`Foot`) or over SSH. Configure your endpoint/API key via environment variables or `~/.bantam.cfg` when needed.
---
## 5. Camera, audio, flashlight & cellular modem reference
### 5.1 Taking photos with the rear camera (`/dev/video0`)
The `msm8905-cam` kernel module drives the rear 2MP GalaxyCore `GC2395` sensor through MSM8909 `CAMSS` (`CSIPHY0 -> CSID0 -> ISPIF -> VFE0 -> VBIF`) and registers `/dev/video0` (`800x600` 24-bit `RGB3`).
To capture a photo to `~/photo.jpg` (or `.png`), stream a frame with `v4l2-ctl` and encode it with `ffmpeg -f rawvideo`:
```bash
v4l2-ctl -d /dev/video0 \
--set-fmt-video=width=800,height=600,pixelformat=RGB3 \
--stream-mmap --stream-count=1 --stream-to=/tmp/frame.rgb && \
ffmpeg -hide_banner -loglevel error \
-f rawvideo -pixel_format rgb24 -video_size 800x600 \
-i /tmp/frame.rgb -frames:v 1 -y ~/photo.jpg && \
rm -f /tmp/frame.rgb
```
- **Viewing photos on the phone**: run `imv ~/photo.jpg` or `mpv ~/photo.jpg`.
- **Why `v4l2-ctl` + `ffmpeg -f rawvideo` is used**: Alpine's `libavdevice` links against `libv4l2.so.0`, whose `v4l2_mmap` wrapper on 32-bit ARM (`musl` 64-bit `off_t`) misaligns variadic `syscall(SYS_mmap2, ...)` arguments. Capturing via `v4l2-ctl` and encoding via `ffmpeg -f rawvideo` bypasses `libv4l2` completely.
### 5.2 Switching speakers (loudspeaker vs. earpiece) & recording microphone audio
Both the rear loudspeaker (`Speaker` / `SPK_OUT`) and the front earpiece speaker (`Earpiece` / `EAR`, boosted by +6 dB in `CDC_A_RX_EAR_CTL`), as well as the internal MEMS microphone (`Mic1` / `AMIC3`, biased at 2.8V in `CDC_A_MICB_1_VAL`) and 3.5mm headset microphone (`Mic2` / `AMIC2`), are managed through PipeWire/WirePlumber and `sxmo_audio.sh`:
- **List available audio outputs (`Speaker`, `Earpiece`, `Headphones`)**:
```bash
sxmo_audio.sh out list
```
- **Switch active output to the rear loudspeaker**:
```bash
sxmo_audio.sh out set "Speaker"
```
- **Switch active output to the front earpiece speaker**:
```bash
sxmo_audio.sh out set "Earpiece"
```
- **Record from the internal MEMS microphone (`Mic1`)**:
```bash
pw-record --rate=48000 --channels=1 --format=s16 ~/recording.wav
```
### 5.3 Flashlight (`white:torch`) & keypad backlight (`white:kbd_backlight`)
- **Turn rear flashlight on / off**:
```bash
brightnessctl -d white:torch set 1
brightnessctl -d white:torch set 0
```
- **Set keypad backlight brightness (`0`–`255`)**:
```bash
brightnessctl -d white:kbd_backlight set 255
```
### 5.4 GSM / WCDMA / LTE modem & voice calls (`ModemManager` & `q6voiced`)
- **Inspect modem registration, operator, and signal quality**:
```bash
mmcli -m any
```
- **Place or manage voice calls and SMS**:
Use the Sxmo **Phone** / **Texts** menu (`Left softkey`) or `mmcli -m any --voice-list-calls` / `mmcli -m any --messaging-list-sms`. In-call audio is automatically routed between the modem (`VoiceMMode1`) and the PM8909 WCD codec by the `q6voiced` service and `sxmo_modemaudio.sh`.
+8 -7
View File
@@ -6,7 +6,7 @@
See [The Bananarchy Manifesto](./MANIFESTO.md) for the rationale behind this entire project.
Bananarchy targets the **Sxmo (`sxmo-de-sway`)** environment exclusively, tuned for 1:1 native `240x320` resolution, enlarged high-contrast typography, sub-115 MB idle RAM footprint on 512 MB devices, full Qualcomm QDSP6/Q6Voice audio and LTE modem routing, pre-integrated **Bantam** AI agent (`https://code.luxferre.top/luxferre/bantam-cpp`), a complete on-device development & scripting stack (`git`, `gcc`/`g++`, `make`, `nano`, `janet` + `jpm`, `perl` + `IO::Socket::SSL`, `tcl` + `tcllib`/`tcl-tls`/`sqlite-tcl`, `sqlite`), and a custom **6-mode `fcitx5-t9` input engine** supporting lowercase, one-shot Shift, Caps Lock, all 32 ASCII punctuation symbols, terminal control codes (`^A`-`^Z`, `Esc`, `Tab`, `F1`-`F12`), and direct numeric entry.
Bananarchy targets the **Sxmo (`sxmo-de-sway`)** environment exclusively, tuned for 1:1 native `240x320` resolution, enlarged high-contrast typography, sub-115 MB idle RAM footprint on 512 MB devices, full Qualcomm QDSP6/Q6Voice audio (loudspeaker, earpiece speaker, and internal/headset microphones with PM8909 WCD analog codec 2.8V micbias and +6 dB EAR PA gain), GSM/WCDMA/LTE modem routing (`ModemManager` + `q6voiced`), rear 2MP camera support (`msm8905-cam` V4L2 driver for GalaxyCore `GC2395` + MSM8909 `CAMSS` on `/dev/video0`), pre-integrated **Bantam** AI agent (`https://code.luxferre.top/luxferre/bantam-cpp`), a complete on-device development & scripting stack (`git`, `gcc`/`g++`, `make`, `nano`, `janet` + `jpm`, `perl` + `IO::Socket::SSL`, `tcl` + `tcllib`/`tcl-tls`/`sqlite-tcl`, `sqlite`, `i2c-tools`, `v4l-utils`), and a custom **6-mode `fcitx5-t9` input engine** supporting lowercase, one-shot Shift, Caps Lock, all 32 ASCII punctuation symbols, terminal control codes (`^A`-`^Z`, `Esc`, `Tab`, `F1`-`F12`), and direct numeric entry.
The current Bananarchy version is `v0.0.1`.
@@ -30,7 +30,7 @@ The current Bananarchy version is `v0.0.1`.
bananarchy/
├── README.md # Project architecture, build system, and quickstart guide
├── MANIFESTO.md # The Bananarchy Manifesto
├── MANUAL.md # Complete flashing, keypad, T9, Bantam, and modem manual
├── MANUAL.md # Complete flashing, keypad, T9, camera, audio, Bantam, and modem manual
├── flash-edl.sh # Automated USB EDL flasher wrapper (sudo + ModemManager handling)
├── flash-edl.py # Multi-device Qualcomm Sahara/Firehose EDL flasher
├── rebuild-image.sh # Builds boot.img, MBR raw .img, and Android .sparse.img
@@ -69,17 +69,18 @@ bananarchy/
│ └── 0001-bananarchy-multimode-t9-and-fcitx5-5.1.19.patch
├── src/
│ ├── fcitx5-t9/ # C++20 source of Bananarchy's 6-mode fcitx5-t9 input method
│ └── leds-msm8905-torch/ # Kernel driver for SY7807 rear torch LED & PM8909 PON shutdown
│ ├── leds-msm8905-torch/ # Kernel driver for SY7807 rear torch LED, WCD codec init & PM8909 PON shutdown
│ └── msm8905-cam/ # Kernel V4L2 driver for GC2395 2MP rear camera & MSM8909 CAMSS (/dev/video0)
├── overlay/
│ └── rootfs/ # Complete Bananarchy rootfs overlay (OS branding, Sxmo, audio, T9)
│ └── rootfs/ # Complete Bananarchy rootfs overlay (OS branding, Sxmo, audio, camera, T9)
├── prebuilt/
│ ├── kernel-6.12.1-msm8916/ # Prebuilt QDSP6/Q6Voice .ko modules, torch .ko, and 5 device DTBs
│ ├── kernel-6.12.1-msm8916/ # Prebuilt QDSP6/Q6Voice .ko, torch .ko, camera .ko, and 5 device DTBs
│ ├── fcitx5-t9/ # Prebuilt armv7 libt9.so and fcitx5 addon/inputmethod configs
│ └── bantam/ # Prebuilt armv7 bantam AI agent binary
└── scripts/
├── generate-artwork.py # Generates all wallpapers, icons, and splashes from icon-large.png
├── mipi-dbi-cmd.py # Compiles MIPI-DBI panel .txt init sequences into .bin firmware
├── build-kernel-audio.sh # Cross-compiles Linux 6.12.1-msm8916 QDSP6/torch modules & DTBs
├── build-kernel-audio.sh # Cross-compiles Linux 6.12.1-msm8916 QDSP6/torch/camera modules & DTBs
├── build-fcitx5-t9.sh # Cross-compiles src/fcitx5-t9 for armv7
├── build-bantam.sh # Fetches master from https://code.luxferre.top/luxferre/bantam-cpp & cross-compiles for armv7
├── apply-bananarchy-overlay.sh # Applies overlay, prebuilts, artwork, and device DTB to rootfs
@@ -105,7 +106,7 @@ All components are pre-compiled in `prebuilt/` and `overlay/rootfs/`, and can be
# Fetch latest master from https://code.luxferre.top/luxferre/bantam-cpp and cross-compile Bantam AI agent
./scripts/build-bantam.sh
# Rebuild Linux 6.12.1-msm8916 QDSP6/Q6Voice audio modules & DTBs
# Rebuild Linux 6.12.1-msm8916 QDSP6/Q6Voice audio modules, torch LED module, camera module & DTBs
./scripts/build-kernel-audio.sh
```
-6
View File
@@ -2,13 +2,7 @@ permit persist :wheel
permit nopass :wheel as root cmd busybox args poweroff
permit nopass :wheel as root cmd busybox args reboot
permit nopass :wheel as root cmd poweroff
permit nopass :wheel as root cmd /sbin/poweroff
permit nopass :wheel as root cmd reboot
permit nopass :wheel as root cmd /sbin/reboot
permit nopass :wheel as root cmd halt
permit nopass :wheel as root cmd /sbin/halt
permit nopass :wheel as root cmd openrc-shutdown
permit nopass :wheel as root cmd /sbin/openrc-shutdown
permit nopass :wheel as root cmd sxmo_wifitoggle.sh
permit nopass setenv { SXMO_OS } :wheel as root cmd sxmo_bluetoothtoggle.sh
permit nopass :wheel as root cmd rc-service args bluetooth restart
+1
View File
@@ -2,3 +2,4 @@ af_packet
ipv6
panel_mipi_dbi
leds_msm8905_torch
msm8905-cam
+317
View File
@@ -0,0 +1,317 @@
#!/bin/sh
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2022 Sxmo Contributors
# shellcheck source=configs/default_hooks/sxmo_hook_icons.sh
. sxmo_hook_icons.sh
. sxmo_common.sh
set -e
notifyvol() {
vol="$1"
if [ "-" = "$vol" ]; then
vol="$(cat)"
fi
if [ "muted" = "$vol" ]; then
vol=0
fi
if [ -z "$SXMO_WOB_DISABLE" ]; then
printf "%s\n" "$vol" > "$XDG_RUNTIME_DIR"/sxmo.obsock
else
notify-send -r 999 "$icon_audio Volume $vol"
fi
}
# adjust *output* vol/mute
volup() {
pactl set-sink-volume @DEFAULT_SINK@ +"${1:-5}%"
}
voldown() {
pactl set-sink-volume @DEFAULT_SINK@ -"${1:-5}%"
}
voltogglemute() {
pactl set-sink-mute @DEFAULT_SINK@ toggle
}
volismuted() {
pactl get-sink-mute @DEFAULT_SINK@ | grep -q "Mute: yes"
}
volget() {
if volismuted; then
printf "muted"
else
pactl get-sink-volume @DEFAULT_SINK@ | head -n1 | cut -d'/' -f2 | sed 's/ //g' | sed 's/\%//'
fi
}
volset() {
pactl set-sink-volume @DEFAULT_SINK@ "$1"%
}
# adjust *input* vol/mute
micvolup() {
pactl set-source-volume @DEFAULT_SOURCE@ +"${1:-5}%"
}
micvoldown() {
pactl set-source-volume @DEFAULT_SOURCE@ -"${1:-5}%"
}
mictogglemute() {
pactl set-source-mute @DEFAULT_SOURCE@ toggle
}
micismuted() {
pactl get-source-mute @DEFAULT_SOURCE@ | grep -q "Mute: yes"
}
micvolget() {
if micismuted; then
printf "muted"
else
pactl get-source-volume @DEFAULT_SOURCE@ | head -n1 | cut -d'/' -f2 | sed 's/ //g' | sed 's/\%//'
fi
}
micvolset() {
pactl set-source-volume @DEFAULT_SOURCE@ "$1"%
}
# set the *active port* for output
deviceset() {
if pactl --format=json list sinks | jq -e ".[] | select(.name == \"$(pactl get-default-sink)\") | .ports[] | select(.name == \"[Out] $1\")" >/dev/null 2>&1; then
pactl set-sink-port @DEFAULT_SINK@ "[Out] $1"
else
prof="$(pactl --format=json list cards | jq -r ".[] | . as \$c | .ports[\"[Out] $1\"]? | select(. != null and .availability != \"not available\") | .profiles[] | select(\$c.profiles[.].available == true) | \"\(\$c.name) \(.)\"" | head -n1)"
if [ -n "$prof" ]; then
card="$(printf "%s" "$prof" | cut -f1)"
profile="$(printf "%s" "$prof" | cut -f2)"
pactl set-card-profile "$card" "$profile"
fi
fi
}
# set the *active port* for input
devicesetinput() {
pactl set-source-port @DEFAULT_SOURCE@ "[In] $1"
}
# get the *active port* for input
devicegetinput() {
[ -z "$1" ] && default_source="$(pactl get-default-source)" || default_source="$1"
pactl --format=json list sources | jq -r ".[] | select(.name == \"$default_source\") | .active_port" | sed 's/\[In] //'
}
# get the *active port* for output
deviceget() {
[ -z "$1" ] && default_sink="$(pactl get-default-sink)" || default_sink="$1"
pactl --format=json list sinks | jq -r ".[] | select(.name == \"$default_sink\") | .active_port" | sed 's/\[Out] //'
}
# get the default sink
devicegetdefaultsink() {
pactl get-default-sink
}
# get the default source
devicegetdefaultsource() {
pactl get-default-source
}
sourceset() {
pactl set-default-source "$1"
}
sinkset() {
pactl set-default-sink "$1"
}
profileset() {
pactl set-card-profile "$1" "$2"
}
# get a list of sinks
_sinkssubmenu() {
[ -z "$1" ] && default_sink="$(pactl get-default-sink)" || default_sink="$1"
pactl --format=json list sinks | jq -r '.[] | .name, .description' | while read -r line; do
name="$line"
read -r description
if [ "$default_sink" = "$name" ]; then
printf "%s %s %s ^ sinkset %s\n" "$icon_chk" "$icon_spk" "$description" "$name"
else
printf " %s %s ^ sinkset %s\n" "$icon_spk" "$description" "$name"
fi
done
}
# get a list of output ports
_outportssubmenu() {
[ -z "$1" ] && default_sink="$(pactl get-default-sink)" || default_sink="$1"
active_out_port="$(deviceget "$default_sink")"
pactl --format=json list cards | jq -r ".[] | .ports | to_entries[] | select((.key | startswith(\"[Out] \")) and .value.availability != \"not available\") | .key" | sed 's/\[Out] //' | while read -r line; do
[ "$active_out_port" = "$line" ] && icon="$icon_ton" || icon="$icon_tof"
printf " %s %s ^ deviceset %s
" "$icon" "$line" "$line"
done
}
# get a list of input sources
_sourcessubmenu() {
[ -z "$1" ] && default_source="$(pactl get-default-source)" || default_source="$1"
pactl --format=json list sources | jq -r '.[] | select (.monitor_source == "") | .name, .description' | while read -r line; do
name="$line"
read -r description
if [ "$default_source" = "$name" ]; then
printf "%s %s %s ^ sourceset %s\n" "$icon_chk" "$icon_mic" "$description" "$name"
else
printf " %s %s ^ sourceset %s\n" "$icon_mic" "$description" "$name"
fi
done
}
_cardssubmenu() {
cards="$(pactl -f json list cards)"
printf "%s\n" "$cards" | jq -r '.[] | [.name, .active_profile] | @tsv' | \
while IFS=" " read -r card active_profile; do
printf "%s %s\n" "$icon_nte" "$card"
printf "%s\n" "$cards" | jq -r ".[] | select(.name == \"$card\") | .profiles | to_entries[] | select(.value.available) | [.key, .value.description] | @tsv" | \
while IFS=" " read -r profile desc; do
if [ "$profile" = "$active_profile" ]; then
printf "%s %s ^ true\n" "$icon_chk" "$desc"
else
printf " %s ^ profileset %s \"%s\"\n" "$desc" "$card" "$profile"
fi
done
done
}
# get a list of input ports
_inportssubmenu() {
# if the Headset is NOT plugged in, then do not display Headset
# as a option, as clicking on it causes pulse to unset the source!!
[ -z "$1" ] && default_source="$(pactl get-default-source)" || default_source="$1"
active_in_port="$(devicegetinput "$default_source")"
pactl --format=json list sources | jq -r ".[] | select(.name == \"$default_source\" ) | .ports[] | select(.availability != \"not available\" ) | .name" | sed 's/\[In] //' | while read -r line; do
[ "$active_in_port" = "$line" ] && icon="$icon_ton" || icon="$icon_tof"
printf " %s %s ^ devicesetinput %s\n" "$icon" "$line" "$line"
done
}
_ringmodesubmenu() {
if [ -f "$XDG_CONFIG_HOME"/sxmo/.noring ]; then
printf " %s Ring ^ rm -f \"$XDG_CONFIG_HOME\"/sxmo/.noring\n" "$icon_tof"
else
printf " %s Ring ^ touch \"$XDG_CONFIG_HOME\"/sxmo/.noring\n" "$icon_ton"
fi
if [ -f "$XDG_CONFIG_HOME"/sxmo/.novibrate ]; then
printf " %s Vibrate ^ rm -f \"$XDG_CONFIG_HOME\"/sxmo/.novibrate\n" "$icon_tof"
else
printf " %s Vibrate ^ touch \"$XDG_CONFIG_HOME\"/sxmo/.novibrate\n" "$icon_ton"
fi
if [ -f "$XDG_CONFIG_HOME"/sxmo/.busy ]; then
end="$(cat "$XDG_CONFIG_HOME"/sxmo/.busy)"
if [ -n "$end" ] && [ "$(date +%s)" -gt "$end" ]; then
rm "$XDG_CONFIG_HOME"/sxmo/.busy
fi
fi
if [ -f "$XDG_CONFIG_HOME"/sxmo/.busy ]; then
printf " %s Busy ^ rm -f \"$XDG_CONFIG_HOME\"/sxmo/.busy\n" "$icon_ton"
else
printf " %s Busy ^ touch \"$XDG_CONFIG_HOME\"/sxmo/.busy\n" "$icon_tof"
printf " %s Busy for 15 min ^ date '+%%s+15*60' | bc > \"$XDG_CONFIG_HOME\"/sxmo/.busy\n" "$icon_tmr"
printf " %s Busy for 30 min ^ date '+%%s+30*60' | bc > \"$XDG_CONFIG_HOME\"/sxmo/.busy\n" "$icon_tmr"
printf " %s Busy for 1 hour ^ date '+%%s+60*60' | bc > \"$XDG_CONFIG_HOME\"/sxmo/.busy\n" "$icon_tmr"
printf " %s Busy for 2 hour ^ date '+%%s+2*60*60' | bc > \"$XDG_CONFIG_HOME\"/sxmo/.busy\n" "$icon_tmr"
printf " %s Busy for 3 hour ^ date '+%%s+3*60*60' | bc > \"$XDG_CONFIG_HOME\"/sxmo/.busy\n" "$icon_tmr"
fi
}
menuchoices() {
cur_vol="$(volget)"
cur_mic_vol="$(micvolget)"
default_sink_name="$(devicegetdefaultsink)"
default_source_name="$(devicegetdefaultsource)"
grep . <<EOF
$icon_cls Close Menu ^ exit
Output:
$(_sinkssubmenu "$default_sink_name")
$(
if [ "$cur_vol" != "muted" ]; then
printf " %s Volume (%s%%) ^ volup\n" "$icon_aru" "$cur_vol"
printf " %s Volume (%s%%) ^ voldown\n" "$icon_ard" "$cur_vol"
printf " %s Output Mute ^ voltogglemute\n" "$icon_tof"
else
printf " %s Output Mute ^ voltogglemute\n" "$icon_ton"
fi
)
$(_outportssubmenu "$default_sink_name")
Input:
$(_sourcessubmenu "$default_source_name")
$(
if [ "$cur_mic_vol" != "muted" ]; then
printf " %s Volume (%s%%) ^ micvolup\n" "$icon_aru" "$cur_mic_vol"
printf " %s Volume (%s%%) ^ micvoldown\n" "$icon_ard" "$cur_mic_vol"
printf " %s Input Mute ^ mictogglemute\n" "$icon_tof"
else
printf " %s Input Mute ^ mictogglemute\n" "$icon_ton"
fi
)
$(_inportssubmenu "$default_source_name")
Cards:
$(_cardssubmenu)
$(_ringmodesubmenu)
EOF
}
if [ -n "$SXMO_NO_AUDIO" ]; then
sxmo_log "Audio is disabled."
exit
fi
if [ -z "$*" ]; then
set -- menu
fi
cmd="$1"
shift
case "$cmd" in
menu)
while : ; do
CHOICES="$(menuchoices)"
PICKED="$(
printf "%s\n" "$CHOICES" |
cut -d'^' -f1 |
sxmo_dmenu.sh -i -p "Audio"
)"
CMD="$(printf "%s\n" "$CHOICES" | grep -m1 -F "$PICKED" | cut -d '^' -f2)"
eval "$CMD"
done
;;
vol)
verb="$1"
shift
vol"$verb" "$@"
;;
mic)
verb="$1"
shift
mic"$verb" "$@"
;;
device)
verb="$1"
shift
device"$verb" "$1"
;;
notify)
notifyvol "$(volget)"
;;
micnotify)
notifyvol "$(micvolget)"
;;
esac
+63
View File
@@ -0,0 +1,63 @@
#!/bin/sh
# shellcheck source=scripts/core/sxmo_common.sh
. sxmo_common.sh
ca_dbus_get_prop() {
dbus-send --session --print-reply --dest=org.mobian_project.CallAudio \
--reply-timeout=2500 /org/mobian_project/CallAudio org.freedesktop.DBus.Properties.Get \
string:org.mobian_project.CallAudio string:"$1"
}
ca_dbus_set_prop() {
dbus-send --session --print-reply --type=method_call \
--reply-timeout=2500 --dest=org.mobian_project.CallAudio \
/org/mobian_project/CallAudio org.mobian_project.CallAudio."$1" "$2" |\
grep -q "boolean true" && return 0 || return 1
}
enable_call_audio_mode() {
if pactl -f json info 2>/dev/null | jq -r .server_name | grep -q PipeWire; then
sxmo_audio.sh device set Earpiece
sxmo_log "Successfully enabled call audio mode (Earpiece)."
sxmo_hook_statusbar.sh volume
return 0
fi
if ca_dbus_set_prop SelectMode uint32:1; then
sxmo_log "Successfully enabled call audio mode."
sxmo_hook_statusbar.sh volume
else
sxmo_notify_user.sh "Failed to enable call audio mode."
return 1
fi
}
disable_call_audio_mode() {
if pactl -f json info 2>/dev/null | jq -r .server_name | grep -q PipeWire; then
sxmo_audio.sh device set Speaker
sxmo_log "Successfully disabled call audio mode (Speaker)."
sxmo_hook_statusbar.sh volume
return 0
fi
if ca_dbus_set_prop SelectMode uint32:0; then
sxmo_log "Successfully disabled call audio mode."
sxmo_hook_statusbar.sh volume
else
sxmo_notify_user.sh "Failed to disable call audio mode."
return 1
fi
}
setup_audio() {
if ! enable_call_audio_mode; then
return 1
fi
}
reset_audio() {
if ! disable_call_audio_mode; then
return 1
fi
}
"$@"
+29
View File
@@ -0,0 +1,29 @@
#!/bin/sh
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2022 Sxmo Contributors
# This script is responsible for starting wob, or xob, and making sure it exits cleanly
# include common definitions
# shellcheck source=scripts/core/sxmo_common.sh
. sxmo_common.sh
export WOB_DISABLE_PLEDGE=1
ob_sock="$XDG_RUNTIME_DIR"/sxmo.obsock
rm -f "$ob_sock"
mkfifo "$ob_sock"
# By opening the socket as read-write it isn't closed after the first write
# see https://unix.stackexchange.com/questions/392697
"${1:-wob}" <> "$ob_sock" &
OBPID=$!
finish() {
# Only finish once
trap - TERM INT EXIT
kill "$OBPID"
rm -f "$ob_sock"
}
trap 'finish' TERM INT EXIT
wait "$OBPID"
@@ -1,9 +1,6 @@
# Use case configuration for common MSM8916 devices.
# All analog outputs/inputs connected to internal PM8916 codec.
Define {
WcdPlaybackPCM "hw:${CardId},0"
WcdCapturePCM "hw:${CardId},1"
WcdPlaybackPCM "hw:${CardId},0"
WcdCapturePCM "hw:${CardId},1"
}
<platforms/msm8916/qdsp6-components.conf>
@@ -12,5 +9,4 @@ Define {
<codecs/msm8916-wcd/Headphones.conf>
<codecs/msm8916-wcd/PrimaryMic.conf>
<codecs/msm8916-wcd/SecondaryMic.conf>
<codecs/msm8916-wcd/HeadsetMic.conf>
@@ -0,0 +1,15 @@
SectionVerb {
EnableSequence [
cset "name='${var:MultiMedia1Port} Audio Mixer MultiMedia1' 1"
cset "name='MultiMedia2 Mixer ${var:MultiMedia2Port}' 1"
cset "name='${var:VoiceRXPort} Voice Mixer VoiceMMode1' 1"
cset "name='VoiceMMode1 Capture Mixer ${var:VoiceTXPort}' 1"
]
DisableSequence [
cset "name='${var:MultiMedia1Port} Audio Mixer MultiMedia1' 0"
cset "name='MultiMedia2 Mixer ${var:MultiMedia2Port}' 0"
cset "name='${var:VoiceRXPort} Voice Mixer VoiceMMode1' 0"
cset "name='VoiceMMode1 Capture Mixer ${var:VoiceTXPort}' 0"
]
}
@@ -0,0 +1,2 @@
q6voice_card=0
q6voice_device=4
Binary file not shown.
+8 -2
View File
@@ -43,9 +43,9 @@ echo "[1/4] Installing Bananarchy rootfs overlay (artwork, branding, Sxmo 240x32
rm -f "$TARGET_ROOTFS/usr/bin/bantam" "$TARGET_ROOTFS/usr/local/bin/bantam" "$TARGET_ROOTFS/etc/doas.d/wheel.conf"
cp -af "$BASE_DIR/overlay/rootfs/." "$TARGET_ROOTFS/"
chown 0:0 "$TARGET_ROOTFS/etc/doas.d/50-sxmo.conf" 2>/dev/null || true
chmod 600 "$TARGET_ROOTFS/etc/doas.d/50-sxmo.conf" 2>/dev/null || true
chmod 640 "$TARGET_ROOTFS/etc/doas.d/50-sxmo.conf" 2>/dev/null || true
echo "[2/4] Installing prebuilt QDSP6/Q6Voice kernel modules, torch LED module, and DTBs..."
echo "[2/4] Installing prebuilt QDSP6/Q6Voice kernel modules, torch LED module, camera module, and DTBs..."
if [ -d "$TARGET_ROOTFS/lib/modules/6.12.1-msm8916/kernel/sound/soc/qcom/qdsp6" ]; then
cp -af "$BASE_DIR/prebuilt/kernel-6.12.1-msm8916/qdsp6/"*.ko* \
"$TARGET_ROOTFS/lib/modules/6.12.1-msm8916/kernel/sound/soc/qcom/qdsp6/"
@@ -55,6 +55,12 @@ if [ -d "$BASE_DIR/prebuilt/kernel-6.12.1-msm8916/leds" ] && \
cp -af "$BASE_DIR/prebuilt/kernel-6.12.1-msm8916/leds/"*.ko* \
"$TARGET_ROOTFS/lib/modules/6.12.1-msm8916/kernel/drivers/leds/"
fi
if [ -d "$BASE_DIR/prebuilt/kernel-6.12.1-msm8916/camera" ] && \
[ -d "$TARGET_ROOTFS/lib/modules/6.12.1-msm8916/kernel/drivers" ]; then
mkdir -p "$TARGET_ROOTFS/lib/modules/6.12.1-msm8916/kernel/drivers/media/platform/qcom/camss"
cp -af "$BASE_DIR/prebuilt/kernel-6.12.1-msm8916/camera/"*.ko* \
"$TARGET_ROOTFS/lib/modules/6.12.1-msm8916/kernel/drivers/media/platform/qcom/camss/"
fi
mkdir -p "$TARGET_ROOTFS/boot/dtbs"
cp -af "$BASE_DIR/prebuilt/kernel-6.12.1-msm8916/dtbs/"*.dtb "$TARGET_ROOTFS/boot/dtbs/"
cp -af "$BASE_DIR/prebuilt/kernel-6.12.1-msm8916/dtbs/$DTB_FILE" "$TARGET_ROOTFS/boot/$DTB_FILE"
+31 -7
View File
@@ -41,14 +41,22 @@ EOF
curl \
tar \
xz \
zstd \
gcc-armv7 \
g++-armv7 \
binutils-armv7
mkdir -p /tmp/kbuild
mkdir -p /tmp/kbuild /bananarchy/prebuilt/kernel-6.12.1-msm8916
CACHE_TAR="/bananarchy/prebuilt/kernel-6.12.1-msm8916/linux-${KERNEL_TAG#v}.tar.gz"
cd /tmp/kbuild
echo "[1/5] Downloading Linux ${KERNEL_TAG}..."
curl -sSL "$KERNEL_URL" -o linux.tar.gz
if [ -f "$CACHE_TAR" ]; then
echo "[1/5] Using cached Linux ${KERNEL_TAG} tarball..."
cp "$CACHE_TAR" linux.tar.gz
else
echo "[1/5] Downloading Linux ${KERNEL_TAG}..."
curl -sSL "$KERNEL_URL" -o linux.tar.gz
cp linux.tar.gz "$CACHE_TAR" || true
fi
tar -xzf linux.tar.gz
cd "linux-${KERNEL_TAG#v}"
@@ -60,11 +68,13 @@ EOF
make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- olddefconfig
make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- modules_prepare
echo "[4/5] Building QDSP6/Q6Voice sound modules, torch LED module, and Nokia MSM8905/MSM8909 DTBs..."
echo "[4/5] Building QDSP6/Q6Voice sound modules, torch LED module, camera module, and Nokia MSM8905/MSM8909 DTBs..."
make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- -j"$(nproc)" \
KBUILD_MODPOST_WARN=1 M=sound/soc/qcom/qdsp6 modules
make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- -j"$(nproc)" \
KBUILD_MODPOST_WARN=1 M=/bananarchy/src/leds-msm8905-torch modules
make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- -j"$(nproc)" \
KBUILD_MODPOST_WARN=1 M=/bananarchy/src/msm8905-cam modules
make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- -j"$(nproc)" \
qcom/qcom-msm8905-nokia-argon.dtb \
qcom/qcom-msm8909-nokia-sparkler.dtb \
@@ -73,15 +83,27 @@ EOF
echo "[5/5] Exporting built modules and DTBs to prebuilt/kernel-6.12.1-msm8916..."
mkdir -p /bananarchy/prebuilt/kernel-6.12.1-msm8916/qdsp6 \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/leds \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/camera \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/dtbs
cp -a sound/soc/qcom/qdsp6/*.ko /bananarchy/prebuilt/kernel-6.12.1-msm8916/qdsp6/
cp -a /bananarchy/src/leds-msm8905-torch/leds-msm8905-torch.ko \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/leds/
cp -a /bananarchy/src/msm8905-cam/msm8905-cam.ko \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/camera/
armv7-alpine-linux-musleabihf-strip --strip-unneeded \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/qdsp6/*.ko \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/leds/*.ko
/bananarchy/prebuilt/kernel-6.12.1-msm8916/leds/*.ko \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/camera/*.ko
for ko in \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/qdsp6/*.ko \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/leds/*.ko \
/bananarchy/prebuilt/kernel-6.12.1-msm8916/camera/*.ko; do
zstd -f -q -k "$ko" -o "${ko}.zst"
done
make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- \
M=/bananarchy/src/leds-msm8905-torch clean
make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- \
M=/bananarchy/src/msm8905-cam clean
cp -a arch/arm/boot/dts/qcom/qcom-msm8905-nokia-argon.dtb \
arch/arm/boot/dts/qcom/qcom-msm8909-nokia-sparkler.dtb \
arch/arm/boot/dts/qcom/qcom-msm8909-nokia-leo.dtb \
@@ -92,6 +114,8 @@ EOF
dtc -I dts -O dtb -o /bananarchy/prebuilt/kernel-6.12.1-msm8916/dtbs/qcom-msm8905-nokia-coconut.dtb \
/bananarchy/devices/nokia-tough/qcom-msm8905-nokia-coconut.dts 2>/dev/null
chown -R "$HOST_UID:$HOST_GID" /bananarchy/prebuilt/kernel-6.12.1-msm8916 /bananarchy/src/leds-msm8905-torch
echo "Kernel audio modules, torch LED module, and DTBs built successfully."
chown -R "$HOST_UID:$HOST_GID" /bananarchy/prebuilt/kernel-6.12.1-msm8916 \
/bananarchy/src/leds-msm8905-torch \
/bananarchy/src/msm8905-cam
echo "Kernel audio modules, torch LED module, camera module, and DTBs built successfully."
'
+20 -5
View File
@@ -73,7 +73,14 @@ configure_common_rootfs() {
tcl-lib \
tcl-tls \
sqlite \
sqlite-tcl
sqlite-tcl \
modemmanager \
modemmanager-udev \
mobile-broadband-provider-info \
postmarketos-base-ui-modemmanager \
postmarketos-base-ui-modemmanager-openrc \
i2c-tools \
v4l-utils
echo " -> Installing busybox and busybox-extras symlinks..."
for applet in $(/bin/busybox --list-full); do
@@ -218,9 +225,11 @@ EOF
sed -i 's|^#ttyS0::respawn:/sbin/getty.*|ttyMSM0::respawn:/sbin/getty -L 115200 ttyMSM0 vt100|' "$ROOTFS/etc/inittab"
fi
if ! grep -qx "panel_mipi_dbi" "$ROOTFS/etc/modules" 2>/dev/null; then
echo "panel_mipi_dbi" >> "$ROOTFS/etc/modules"
fi
for mod in panel_mipi_dbi leds_msm8905_torch msm8905-cam; do
if ! grep -qx "$mod" "$ROOTFS/etc/modules" 2>/dev/null; then
echo "$mod" >> "$ROOTFS/etc/modules"
fi
done
mkdir -p "$ROOTFS/etc/udev/rules.d"
cat > "$ROOTFS/etc/udev/rules.d/90-nokia-argon-leds.rules" <<EOF
@@ -236,11 +245,16 @@ vm.vfs_cache_pressure = 150
vm.min_free_kbytes = 16384
EOF
echo " -> Installing patched audio DTB, 20 QDSP6 kernel modules, UCM, and WirePlumber S16LE rules..."
echo " -> Installing patched audio DTB, QDSP6/torch/camera kernel modules, UCM, and WirePlumber S16LE rules..."
cp "$BANANARCHY_DIR/prebuilt/kernel-6.12.1-msm8916/dtbs/qcom-msm8905-nokia-argon.dtb" \
"$ROOTFS/boot/dtbs/qcom-msm8905-nokia-argon.dtb"
cp "$BANANARCHY_DIR/prebuilt/kernel-6.12.1-msm8916/qdsp6/"*.ko* \
"$ROOTFS/lib/modules/6.12.1-msm8916/kernel/sound/soc/qcom/qdsp6/"
mkdir -p "$ROOTFS/lib/modules/6.12.1-msm8916/extra"
cp "$BANANARCHY_DIR/prebuilt/kernel-6.12.1-msm8916/leds/"*.ko* \
"$ROOTFS/lib/modules/6.12.1-msm8916/extra/" 2>/dev/null || true
cp "$BANANARCHY_DIR/prebuilt/kernel-6.12.1-msm8916/camera/"*.ko* \
"$ROOTFS/lib/modules/6.12.1-msm8916/extra/" 2>/dev/null || true
depmod -b "$ROOTFS" 6.12.1-msm8916
sed -i 's/"CS-Voice"/"VoiceMMode1"/g' \
@@ -676,6 +690,7 @@ EOF
if [ -x /bananarchy/scripts/apply-bananarchy-overlay.sh ]; then
/bananarchy/scripts/apply-bananarchy-overlay.sh "$ROOTFS" nokia-argon
depmod -b "$ROOTFS" 6.12.1-msm8916
fi
chown -R 10000:10000 "$ROOTFS/home/user"
+30 -11
View File
@@ -188,20 +188,39 @@ static void msm8905_pon_lookup_regmap(void)
{
struct device_node *np;
struct platform_device *pon_pdev;
struct platform_device *codec_pdev;
struct regmap *codec_regmap = NULL;
np = of_find_compatible_node(NULL, NULL, "qcom,pm8916-pon");
if (!np)
return;
if (np) {
pon_pdev = of_find_device_by_node(np);
of_node_put(np);
if (pon_pdev) {
if (pon_pdev->dev.parent)
pon_regmap = dev_get_regmap(pon_pdev->dev.parent, NULL);
put_device(&pon_pdev->dev);
}
}
pon_pdev = of_find_device_by_node(np);
of_node_put(np);
if (!pon_pdev)
return;
if (pon_pdev->dev.parent)
pon_regmap = dev_get_regmap(pon_pdev->dev.parent, NULL);
put_device(&pon_pdev->dev);
/*
* Configure PM8909 WCD analog codec (USID 1):
* - CDC_A_MICB_1_VAL (0xf141) = 0x60 (2.8V micbias for internal MEMS mic)
* - CDC_A_RX_EAR_CTL (0xf1c0) |= 0x20 (+6 dB EAR PA gain for earpiece)
*/
np = of_find_compatible_node(NULL, NULL, "qcom,pm8916-wcd-analog-codec");
if (np) {
codec_pdev = of_find_device_by_node(np);
of_node_put(np);
if (codec_pdev) {
if (codec_pdev->dev.parent)
codec_regmap = dev_get_regmap(codec_pdev->dev.parent, NULL);
put_device(&codec_pdev->dev);
}
}
if (codec_regmap) {
regmap_write(codec_regmap, 0xf141U, 0x60U);
regmap_update_bits(codec_regmap, 0xf1c0U, 0x20U, 0x20U);
}
}
static int __init msm8905_torch_init(void)
+10
View File
@@ -0,0 +1,10 @@
obj-m += msm8905-cam.o
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
File diff suppressed because it is too large Load Diff