diff --git a/MANUAL.md b/MANUAL.md index 254022e..ce7e295 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -35,8 +35,9 @@ This manual covers flashing, operating, and customizing **Bananarchy Linux** (`v - Patched `q6core`, `q6afe`, `q6afe-dai`, `q6voice-dai`, `q6mvm`, and device trees (`VoiceMMode1` DAI + PM8909 WCD codec). - 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/`)**: +5. **Rear 2MP camera (`src/msm8905-cam/` & `bananarchy-photo`) & 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). + - `bananarchy-photo`: CLI and Sxmo menu camera utility (`Camera` in the Sxmo System and Apps menus) supporting instant JPEG/PNG photo capture, optional flash (`-f`), and `imv` photo viewing (`-v`). - `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`. @@ -45,7 +46,7 @@ This manual covers flashing, operating, and customizing **Bananarchy Linux** (`v - **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` + - **Hardware & media utilities**: `bananarchy-photo`, `v4l-utils` (`v4l2-ctl`), `i2c-tools`, `ffmpeg`, `mpv`, `imv` --- @@ -235,22 +236,37 @@ You can switch between **vertical (`splitv`, one under another)**, **horizontal ## 5. Camera, audio, flashlight & cellular modem reference -### 5.1 Taking photos with the rear camera (`/dev/video0`) +### 5.1 Taking photos with the rear camera (`bananarchy-photo` & `/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. +- **From the Sxmo keypad UI**: + Open the **System menu** (`Left softkey`) or **Apps menu** (`Left softkey` -> `Apps`) and select **Camera** (`bananarchy-photo --menu`). From the Camera menu you can: + - **Take photo**: capture a photo to `~/Pictures/photo-YYYYMMDD-HHMMSS.jpg` and immediately open it in `imv`. + - **Take photo (flash)**: turn on the rear flashlight (`white:torch`), capture a photo, restore the flashlight state, and open the photo in `imv`. + - **View photos**: browse all saved photos in `~/Pictures` using `imv` (press `Right softkey` inside `imv` to navigate, zoom, rotate, or quit). +- **From the CLI (`bananarchy-photo`)**: + ```bash + # Capture to ~/Pictures/photo-YYYYMMDD-HHMMSS.jpg and print path + bananarchy-photo + + # Capture with rear LED flash enabled and open in imv + bananarchy-photo -f -v + + # Capture to a custom JPEG or PNG file path + bananarchy-photo ~/my-shot.png + ``` +- **Direct low-level capture (`v4l2-ctl` + `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 + ``` +- **Why `v4l2-ctl` + `ffmpeg -f rawvideo` is used under the hood**: 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 diff --git a/README.md b/README.md index d00183c..a174988 100644 --- a/README.md +++ b/README.md @@ -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 (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. +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` and `bananarchy-photo` CLI/Sxmo app), 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`. diff --git a/overlay/rootfs/usr/bin/bananarchy-photo b/overlay/rootfs/usr/bin/bananarchy-photo new file mode 100755 index 0000000..898581f --- /dev/null +++ b/overlay/rootfs/usr/bin/bananarchy-photo @@ -0,0 +1,187 @@ +#!/bin/sh +# Bananarchy rear camera photo capture utility and Sxmo menu wrapper +# Captures 800x600 24-bit RGB frames from /dev/video0 (msm8905-cam / GC2395) +# via v4l2-ctl and encodes JPEG/PNG images via ffmpeg -f rawvideo. + +set -eu + +DEV="/dev/video0" +USE_FLASH=0 +VIEW_AFTER=0 +MENU_MODE=0 +OUT_FILE="" + +usage() { + cat <<'EOF' +Usage: bananarchy-photo [options] [output_file] + +Options: + -d, --device V4L2 video device (default: /dev/video0) + -f, --flash Enable rear flashlight (white:torch) during capture + -v, --view Open captured photo in imv after saving + -m, --menu Open interactive Sxmo camera menu + -h, --help Show this help message + +If output_file is omitted, saves to ~/Pictures/photo-YYYYMMDD-HHMMSS.jpg. +EOF +} + +while [ $# -gt 0 ]; do + case "$1" in + -d|--device) + DEV="$2" + shift 2 + ;; + -f|--flash) + USE_FLASH=1 + shift + ;; + -v|--view) + VIEW_AFTER=1 + shift + ;; + -m|--menu) + MENU_MODE=1 + shift + ;; + -h|--help) + usage + exit 0 + ;; + --) + shift + break + ;; + -*) + echo "bananarchy-photo: unknown option: $1" >&2 + usage >&2 + exit 1 + ;; + *) + OUT_FILE="$1" + shift + ;; + esac +done + +if [ $# -gt 0 ] && [ -z "$OUT_FILE" ]; then + OUT_FILE="$1" +fi + +get_pictures_dir() { + pic_dir="${XDG_PICTURES_DIR:-$HOME/Pictures}" + mkdir -p "$pic_dir" + printf "%s\n" "$pic_dir" +} + +notify_msg() { + if command -v sxmo_notify_user.sh >/dev/null 2>&1 && [ -n "${WAYLAND_DISPLAY:-}" ]; then + sxmo_notify_user.sh -t 2000 "$1" >/dev/null 2>&1 || true + fi +} + +take_photo() { + flash_flag="$1" + target_path="$2" + + if [ -z "$target_path" ]; then + pic_dir="$(get_pictures_dir)" + target_path="$pic_dir/photo-$(date +%Y%m%d-%H%M%S).jpg" + else + mkdir -p "$(dirname "$target_path")" + fi + + if [ ! -e "$DEV" ]; then + echo "bananarchy-photo: camera device $DEV not found" >&2 + notify_msg "Camera $DEV not found" + return 1 + fi + + prev_torch="" + if [ "$flash_flag" -eq 1 ] && [ -w /sys/class/leds/white:torch/brightness ]; then + prev_torch="$(cat /sys/class/leds/white:torch/brightness 2>/dev/null || echo 0)" + echo 1 > /sys/class/leds/white:torch/brightness 2>/dev/null || true + sleep 0.15 + fi + + frame_tmp="/tmp/bananarchy-frame-$$.rgb" + rc=0 + + v4l2-ctl -d "$DEV" \ + --set-fmt-video=width=800,height=600,pixelformat=RGB3 \ + --stream-mmap --stream-count=1 --stream-to="$frame_tmp" >/dev/null 2>&1 || rc=$? + + if [ "$flash_flag" -eq 1 ] && [ -n "$prev_torch" ] && [ -w /sys/class/leds/white:torch/brightness ]; then + echo "$prev_torch" > /sys/class/leds/white:torch/brightness 2>/dev/null || true + fi + + if [ "$rc" -ne 0 ] || [ ! -s "$frame_tmp" ]; then + rm -f "$frame_tmp" + echo "bananarchy-photo: failed to capture frame from $DEV" >&2 + notify_msg "Photo capture failed" + return 1 + fi + + if ! ffmpeg -hide_banner -loglevel error \ + -f rawvideo -pixel_format rgb24 -video_size 800x600 \ + -i "$frame_tmp" -frames:v 1 -y "$target_path"; then + rm -f "$frame_tmp" + echo "bananarchy-photo: ffmpeg failed to encode $target_path" >&2 + notify_msg "Photo encoding failed" + return 1 + fi + + rm -f "$frame_tmp" + printf "%s\n" "$target_path" + notify_msg "Saved $(basename "$target_path")" + + if [ "$VIEW_AFTER" -eq 1 ] && [ -n "${WAYLAND_DISPLAY:-}" ] && command -v imv >/dev/null 2>&1; then + imv "$target_path" >/dev/null 2>&1 & + fi + return 0 +} + +run_menu() { + if [ -f /usr/share/sxmo/default_hooks/sxmo_hook_icons.sh ]; then + # shellcheck disable=SC1091 + . /usr/share/sxmo/default_hooks/sxmo_hook_icons.sh + fi + ic_cam="${icon_cam:-*}" + ic_fll="${icon_fll:-*}" + ic_img="${icon_img:-*}" + ic_cls="${icon_cls:-x}" + + choice="$(printf "%s\n" \ + "$ic_cam Take photo" \ + "$ic_fll Take photo (flash)" \ + "$ic_img View photos" \ + "$ic_cls Close" | sxmo_dmenu.sh -p "Camera" || true)" + + case "$choice" in + *"Take photo (flash)"*) + VIEW_AFTER=1 + take_photo 1 "" + ;; + *"Take photo"*) + VIEW_AFTER=1 + take_photo 0 "" + ;; + *"View photos"*) + pic_dir="$(get_pictures_dir)" + if ls "$pic_dir"/*.jpg "$pic_dir"/*.png >/dev/null 2>&1; then + imv "$pic_dir" >/dev/null 2>&1 & + else + notify_msg "No photos in $pic_dir" + fi + ;; + *) + exit 0 + ;; + esac +} + +if [ "$MENU_MODE" -eq 1 ]; then + run_menu +else + take_photo "$USE_FLASH" "$OUT_FILE" +fi diff --git a/overlay/rootfs/usr/share/applications/bananarchy-photo.desktop b/overlay/rootfs/usr/share/applications/bananarchy-photo.desktop new file mode 100644 index 0000000..b43765e --- /dev/null +++ b/overlay/rootfs/usr/share/applications/bananarchy-photo.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Camera +Comment=Bananarchy rear camera photo capture +Exec=bananarchy-photo --menu +Icon=camera-photo +Terminal=false +Type=Application +Categories=Graphics;Photography; diff --git a/overlay/rootfs/usr/share/sxmo/default_hooks/sxmo_hook_apps.sh b/overlay/rootfs/usr/share/sxmo/default_hooks/sxmo_hook_apps.sh index 5e1e257..2ff9555 100755 --- a/overlay/rootfs/usr/share/sxmo/default_hooks/sxmo_hook_apps.sh +++ b/overlay/rootfs/usr/share/sxmo/default_hooks/sxmo_hook_apps.sh @@ -38,6 +38,7 @@ write_line_app badwolf "$icon_glb Badwolf" "badwolf" write_line_app baobab "$icon_pie Baobab" "baobab" write_line_app bluetuith "$icon_bth Bluetuith" "sxmo_terminal.sh bluetuith" write_line_app calcurse "$icon_clk Calcurse" "sxmo_terminal.sh calcurse" +write_line_app bananarchy-photo "$icon_cam Camera" "bananarchy-photo --menu" write_line_app celluloid "$icon_mvi Celluloid" "celluloid" write_line_app chatty "$icon_msg Chatty" "chatty" ([ -z "$WAYLAND_DISPLAY" ] && command -v clipmenu >/dev/null) && \ diff --git a/overlay/rootfs/usr/share/sxmo/default_hooks/sxmo_hook_contextmenu.sh b/overlay/rootfs/usr/share/sxmo/default_hooks/sxmo_hook_contextmenu.sh index 1d3bfa8..cc2a635 100755 --- a/overlay/rootfs/usr/share/sxmo/default_hooks/sxmo_hook_contextmenu.sh +++ b/overlay/rootfs/usr/share/sxmo/default_hooks/sxmo_hook_contextmenu.sh @@ -180,13 +180,14 @@ case "$WMCLASS" in *imv*) # imv CHOICES=" - $icon_arr Next ^ 1 ^ sxmo_type -k Right - $icon_arl Previous ^ 1 ^ sxmo_type -k Left - $icon_zmi Zoom in ^ 1 ^ sxmo_type -k i - $icon_zmo Zoom out ^ 1 ^ sxmo_type -k minus - $icon_exp Zoom to fit ^ 1 ^ sxmo_type -k r - $icon_ror Rotate ^ 1 ^ sxmo_type -M ctrl r - $icon_inf Toggle filename ^ 1 ^ sxmo_type -k d + $icon_arr Next ^ 1 ^ sxmo_type.sh -k Right + $icon_arl Previous ^ 1 ^ sxmo_type.sh -k Left + $icon_zmi Zoom in ^ 1 ^ sxmo_type.sh -k i + $icon_zmo Zoom out ^ 1 ^ sxmo_type.sh -k minus + $icon_exp Zoom to fit ^ 1 ^ sxmo_type.sh -k r + $icon_ror Rotate ^ 1 ^ sxmo_type.sh -M ctrl r + $icon_inf Toggle filename ^ 1 ^ sxmo_type.sh -k d + $icon_cls Quit ^ 0 ^ sxmo_type.sh -k q " WINNAME=Imv ;; @@ -818,7 +819,13 @@ case "$WMCLASS" in rfkill list bluetooth -no ID,SOFT,HARD | grep -vq " blocked" && printf %b "$icon_bth Bluetooth ^ 1 ^ sxmo_bluetoothmenu.sh" ) - $(command -v megapixels >/dev/null && echo "$icon_cam Camera ^ 0 ^ GDK_SCALE=2 megapixels") + $( + if command -v bananarchy-photo >/dev/null; then + echo "$icon_cam Camera ^ 0 ^ bananarchy-photo --menu" + elif command -v megapixels >/dev/null; then + echo "$icon_cam Camera ^ 0 ^ GDK_SCALE=2 megapixels" + fi + ) $( if brightness="$(brightnessctl -l -m | grep -e "white:torch" -e "white:flash" | cut -d ',' -f 3)" && [ -n "$brightness" ]; then printf "%s Flashlight " "$icon_fll" diff --git a/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko b/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko index ecc2879..64afdf5 100644 Binary files a/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko and b/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko differ diff --git a/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko.zst b/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko.zst index 677b22b..9d4df1c 100644 Binary files a/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko.zst and b/prebuilt/kernel-6.12.1-msm8916/camera/msm8905-cam.ko.zst differ diff --git a/scripts/build-kernel-audio.sh b/scripts/build-kernel-audio.sh index b2ca409..c3a0c0d 100755 --- a/scripts/build-kernel-audio.sh +++ b/scripts/build-kernel-audio.sh @@ -10,6 +10,13 @@ fi KERNEL_TAG="v6.12.1-msm8916" KERNEL_URL="https://github.com/msm8916-mainline/linux/archive/refs/tags/${KERNEL_TAG}.tar.gz" +KERNEL_CACHE_DIR="${KERNEL_CACHE_DIR:-/tmp/linux-msm8916}" +DOCKER_CACHE_ARGS="" +if [ -d "$KERNEL_CACHE_DIR" ]; then + DOCKER_CACHE_ARGS="-v $KERNEL_CACHE_DIR:/kcache" +fi + +# shellcheck disable=SC2086 exec docker run --rm --network=host \ -e HOST_UID="$(id -u)" \ -e HOST_GID="$(id -g)" \ @@ -17,6 +24,7 @@ exec docker run --rm --network=host \ -e KERNEL_URL="$KERNEL_URL" \ -v "$BASE_DIR:/bananarchy" \ -v "$ROOTFS_DIR:/target-rootfs:ro" \ + $DOCKER_CACHE_ARGS \ alpine:3.24 sh -eu -c ' cat > /etc/apk/repositories </dev/null; then + echo "[2/5] Applying Bananarchy QDSP6/Q6Voice and MSM8905/MSM8909 DTS patches..." + patch -p1 < /bananarchy/patches/kernel/0001-msm8909-qdsp6-voice-sound-nokia-argon-6.12.patch + fi + if [ ! -f include/config/auto.conf ]; then + echo "[3/5] Preparing kernel configuration..." + cp /bananarchy/patches/kernel/config-bananarchy-msm8909.armv7 .config + make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- olddefconfig + make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- modules_prepare + fi else - echo "[1/5] Downloading Linux ${KERNEL_TAG}..." - curl -sSL "$KERNEL_URL" -o linux.tar.gz - cp linux.tar.gz "$CACHE_TAR" || true + mkdir -p /tmp/kbuild + CACHE_TAR="/bananarchy/prebuilt/kernel-6.12.1-msm8916/linux-${KERNEL_TAG#v}.tar.gz" + cd /tmp/kbuild + if [ -f "$CACHE_TAR" ] && [ "$(wc -c < "$CACHE_TAR")" -gt 1000000 ]; 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 -f -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}" + + echo "[2/5] Applying Bananarchy QDSP6/Q6Voice and MSM8905/MSM8909 DTS patches..." + patch -p1 < /bananarchy/patches/kernel/0001-msm8909-qdsp6-voice-sound-nokia-argon-6.12.patch + + echo "[3/5] Preparing kernel configuration and Module.symvers..." + cp /bananarchy/patches/kernel/config-bananarchy-msm8909.armv7 .config + make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- olddefconfig + make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- modules_prepare fi - tar -xzf linux.tar.gz - cd "linux-${KERNEL_TAG#v}" - - echo "[2/5] Applying Bananarchy QDSP6/Q6Voice and MSM8905/MSM8909 DTS patches..." - patch -p1 < /bananarchy/patches/kernel/0001-msm8909-qdsp6-voice-sound-nokia-argon-6.12.patch - - echo "[3/5] Preparing kernel configuration and Module.symvers..." - cp /bananarchy/patches/kernel/config-bananarchy-msm8909.armv7 .config - 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, camera module, and Nokia MSM8905/MSM8909 DTBs..." make ARCH=arm CROSS_COMPILE=armv7-alpine-linux-musleabihf- -j"$(nproc)" \ diff --git a/src/msm8905-cam/msm8905-cam.c b/src/msm8905-cam/msm8905-cam.c index 980d1b8..b68b259 100644 --- a/src/msm8905-cam/msm8905-cam.c +++ b/src/msm8905-cam/msm8905-cam.c @@ -320,6 +320,9 @@ static int msm8905_cam_hw_init(struct msm8905_cam_dev *cam) u16 chip_id; u32 r; + if (cam->hw_initialized) + return 0; + /* 1. Ensure PM8909 LDO6 (1.8V) and LDO17 (2.85V) are enabled */ if (cam->usid1_regmap) { regmap_update_bits(cam->usid1_regmap, PM8909_LDO6_EN_CTL, @@ -497,6 +500,29 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb) return ret; } + /* Ensure GC2395 stream and VFE0 WM0/RDI0 are idle before resetting ISPIF */ + gc2395_write_reg(cam, 0xfeU, 0x00U); + gc2395_write_reg(cam, 0xedU, 0x00U); + cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U); + cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U); + wmb(); + + /* Reset ISPIF cleanly for this frame */ + cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00001ff9U); + usleep_range(1000, 1500); + cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00000000U); + usleep_range(1000, 1500); + cam_w32(cam->camss_base, ISPIF_BASE + 0x200U, 0x00000040U); + cam_w32(cam->camss_base, ISPIF_BASE + 0x230U, 0xffffffffU); + cam_w32(cam->camss_base, ISPIF_BASE + 0x234U, 0xffffffffU); + cam_w32(cam->camss_base, ISPIF_BASE + 0x238U, 0xffffffffU); + cam_w32(cam->camss_base, ISPIF_BASE + 0x01cU, 0x00000001U); + cam_w32(cam->camss_base, ISPIF_BASE + 0x208U, 0xffffffffU); + cam_w32(cam->camss_base, ISPIF_BASE + 0x20cU, 0xffffffffU); + cam_w32(cam->camss_base, ISPIF_BASE + 0x210U, 0xffffffffU); + cam_w32(cam->camss_base, ISPIF_BASE + 0x244U, 0x00000000U); + cam_w32(cam->camss_base, ISPIF_BASE + 0x264U, 0x00000001U); + /* Program WM0 PING & PONG to raw_dma_phys and arm single frame */ cam_w32(cam->camss_base, VFE0_BASE + 0x050U, (u32)cam->raw_dma_phys); cam_w32(cam->camss_base, VFE0_BASE + 0x054U, (u32)cam->raw_dma_phys); @@ -529,21 +555,21 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb) usleep_range(2000, 3000); } - /* Immediately stop WM0, ISPIF RDI0, and GC2395 stream to prevent overflow */ - cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xaaaaaaaaU); + /* Stop GC2395 stream, WM0, and RDI0 cleanly */ + gc2395_write_reg(cam, 0xfeU, 0x00U); + gc2395_write_reg(cam, 0xedU, 0x00U); cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U); + cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U); cam_w32(cam->camss_base, VFE0_BASE + 0x024U, 0xffffffffU); cam_w32(cam->camss_base, VFE0_BASE + 0x028U, 0xffffffffU); cam_w32(cam->camss_base, VFE0_BASE + 0x018U, 0x00000001U); + cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00001ff9U); + usleep_range(500, 1000); + cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00000000U); wmb(); - gc2395_write_reg(cam, 0xfeU, 0x00U); - gc2395_write_reg(cam, 0xedU, 0x00U); - - if (!(irq0 & 0x00000040U)) { - cam->hw_initialized = false; + if (!(irq0 & 0x00000040U)) return -ETIMEDOUT; - } msm8905_cam_demosaic(cam->raw_dma_buf, dst_rgb); cam->sequence++; @@ -751,8 +777,9 @@ static int msm8905_cam_dqbuf(struct file *file, void *priv, b->field = V4L2_FIELD_NONE; b->sequence = cam->sequence; b->memory = V4L2_MEMORY_MMAP; + b->m.offset = idx * PAGE_ALIGN(CAM_OUT_FRAME_BYTES); b->length = CAM_OUT_FRAME_BYTES; - ktime_get_ts64((struct timespec64 *)&b->timestamp); + v4l2_buffer_set_timestamp(b, ktime_get_ns()); return 0; }