Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/tasks/46-camera-imx363.md
Fimeg 5224fcb013 tasks: camera and fingerprint rows match what shipped
rear imx363 is at 0x1a on blueline, shipped in r162 on edge with the
rotation fix; blueline-camera 1-1 owns the userspace half. fingerprint
row catches up to its own task doc: wall down, protocol recovered.
2026-08-20 23:15:38 -04:00

165 lines
8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# TASK 46 — Camera
**Status:** front pair proven on glass 2026-07-29. Rear IMX363 wired
(`c7784b716`), answers at **0x1a** (`8fc7623a3`), rotation corrected
(`457a667bd`) — all three on `blueline`, shipped as
`linux-blueline-7.1.1.r162.g457a667bd3eb-1` on edge. Userspace half shipped as
`blueline-camera` 1-1. Left: exposure/gain controls and a fresh acceptance pass
on glass. **Repos:** `Fimeg/linux-blueline` (canonical kernel), `Pixel3Arch`
(DT, packages).
## THE FRONT CAMERA WORKS — first frame captured 2026-07-29
No reboot, no new kernel, no DT change. On the **running** kernel
(`7.1.1-sdm845-g2bb09876e66a`) the whole front path was already live and
nobody had tried it: `qcom_camss` and `imx355` loaded, `/dev/media0` +
`/dev/video0..13`, and **both** front sensors bound and linked
`ENABLED,IMMUTABLE``imx355 17-001a` -> `msm_csiphy1`, `imx355 17-0010` ->
`msm_csiphy2`. The sensor advertises exactly one format,
`SRGGB10_1X10/3280x2464`.
Captured a real 10,131,968-byte frame off `/dev/video0` and debayered it: a
ceiling, a curtain rail with the curtains drawn, a doorframe, a smoke
detector. Correct geometry, correct colour, sane noise. **This device has now
produced a camera image.**
### The exact recipe (RDI raw path, no ISP)
```sh
M=/dev/media0
media-ctl -d $M -l '"msm_csiphy1":1 -> "msm_csid0":0 [1]'
media-ctl -d $M -l '"msm_csid0":1 -> "msm_vfe0_rdi0":0 [1]'
F='[fmt:SRGGB10_1X10/3280x2464]'
for p in '"imx355 17-001a":0' '"msm_csiphy1":0' '"msm_csiphy1":1' \
'"msm_csid0":0' '"msm_csid0":1' '"msm_vfe0_rdi0":0' '"msm_vfe0_rdi0":1'; do
media-ctl -d $M -V "$p $F"
done
v4l2-ctl -d /dev/video0 --set-fmt-video=width=3280,height=2464,pixelformat=pRAA
v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=1 --stream-to=/tmp/frame.raw
```
Gotchas that cost time, so they are written down:
- The node is **Video Capture Multiplanar**. `RG10` is rejected; the format
that matches SRGGB10 is **`pRAA`** (10-bit Bayer RGRG/GBGB *Packed*).
- **The row stride is 4112, not 4100.** 3280 px x 10 bits = 4100 bytes of
payload; the driver pads each row to 4112. Reshaping by 4100 shears the
image diagonally and looks like a broken sensor.
- MIPI RAW10 packing: 4 pixels per 5 bytes — bytes 0-3 are the high 8 bits,
byte 4 packs the four low bit-pairs, pixel `i` taking `(b4 >> 2i) & 3`.
- Black level is ~64 in 10-bit (the `0x10` floor visible in a raw hexdump).
Subtract it before scaling or everything is a flat grey field.
- **`cam` / `qcam` (libcamera) are NOT installed.** `media-ctl` and `v4l2-ctl`
are. There is no auto-exposure running, so the frame is whatever the sensor's
power-on defaults give — dark indoors, and that is expected, not a fault.
### What this changes
The rear path is finished and shipped (see status). The userspace half is done
too: `blueline-camera` 1-1 — libcamera's simple-pipeline soft-ISP exported
through PipeWire, so a portal consumer sees a real camera — built by Pixel3Arch
CI and published into the shared multi-producer edge archive. Recipe:
`Pixel3Arch/pkgs/blueline-camera`. Remaining: exposure/gain controls
(`v4l2-ctl --list-ctrls` on the sensor subdev), a fresh acceptance pass on
glass for the rear path, then TASK-12's face-auth question.
## What was actually missing
A first pass at this said blueline's DT declared no camera at all. Wrong — that
grep only looked at `sdm845-google-blueline.dts`, and the camera lives in the
`sdm845-google-common.dtsi` it includes. The real state:
| Piece | State |
|---|---|
| CAMSS driver (Titan 170 ISP) | present, `CONFIG_VIDEO_QCOM_CAMSS=m` |
| `imx363.c` / `imx355.c` | present, both `=m` |
| Front IMX355 ×2 (CCI1, CSIPHY1+2, ports 1/2) | **already declared**, with regulators, reset pins and shared MCLK2 |
| **Rear IMX363 (CCI0, CSIPHY0, port 0)** | **was absent** — added `c7784b716` |
So the front half had been done and the rear was never finished. CSIPHY0 and
CCI master 0 sat unused with the driver built and enabled.
## What was added (kernel `c7784b716`, branch `mic-race-fix`)
Read off the downstream DTBO's `cam-sensor@0` (`~/pixel3-work/dtbo_9.dts`),
which is the same source the front pair's numbers came from — every front value
in the tree matches its downstream node exactly, which is what made the rear
ones trustworthy:
- MCLK0 gpio13, RESET0 gpio80, VANA0 gpio16 (a GPIO switch off BOB, same shape
as both front avdd regulators)
- `vdig``vreg_s3a_1p35`, `vif``vreg_lvs1_1p8`, `vana` → new
`camera_rear_avdd`
- 24 MHz MCLK and a 636 MHz link frequency — what the driver's 24 MHz table
expects; the front pair runs 19.2 MHz because the imx355 driver wants that
- `camss` port@0`csiphy0`, 4 lanes
Verified by compiling the DTB: 117,471 bytes, no new warnings, every phandle
and lane value correct in the decompiled output.
## The one guess in it — ANSWERED 2026-08-01, and it cost the front camera
**The slave address.** 0x10 was Xiaomi beryllium's for the same IMX363, and the
address is in neither the downstream DTBO nor the eeprom node `cam-sensor@0`
points at (`qcom,eeprom@1`, phandle 0x25, `cci-master = <0x00>` — confirms CCI0,
carries no `slave-addr`). On glass, `0x10` NACKs:
```
imx363: 4 lanes
imx363 16-0010: Error reading reg 0x0016: -6
imx363 16-0010: failed to read chip id 363
```
`-ENXIO`, and `imx363_probe()` calls `imx363_power_on()` *before*
`imx363_identify_module()`, so the rail, reset and MCLK were all exercised and
nothing answered. Moved to **0x1a** (`8fc7623a3`), the remaining candidate —
landed on `blueline`, which also carries the rotation fix. Trap with a date:
on 2026-08-20 both local kernel clones read that commit as missing, because
their `origin` points at the sibling checkout and neither had ever fetched the
forge branches. Fetch from `Fimeg/linux-blueline` before declaring a commit
lost. `mic-race-fix` still sits at the 0x10 state and is superseded by
`blueline`; fold or delete it.
**The expensive lesson is what a failed sensor probe does to the others.**
`camss_subdev_notifier_complete()` creates every sensor→csiphy link, and
`.complete` only fires once *all* declared async subdevs have bound. The rear
sensor never bound, so the notifier never completed, so **no** sensor links were
created — the front pair stayed registered (`entity 235/237`) with **0 links**
each, and the working front camera stopped working. Adding a broken sensor is
not a contained failure on this driver.
Practical consequence: never leave a non-probing sensor node enabled. A DTB with
the rear `status = "disabled"` is kept on the device as
`/boot/dtbs/sdm845-google-blueline.dtb.rear-off` for exactly this — it restores
the front camera in one `cp` and a reboot.
The DTB is loaded separately by extlinux (`fdt /boot/dtbs/...`), so testing an
address costs a DTB build and a reboot, not a kernel rebuild.
## Acceptance
- `media-ctl -p` enumerates a pipeline and the rear sensor probes.
- `v4l2-ctl` streams a frame off it.
- A still lands on disk. **Colour and tuning are not acceptance** — libcamera
needs a tuning file and there is none for this unit.
## The driver is a WIP snapshot, and that is the next lever
`imx363.c` in our tree carries commented-out register writes, a commented-out
19.2 MHz link-frequency table, and a literal `// NOT SURE HOW TO FIND THIS
VALUE` against the 636 MHz entry. Two modes only (4032×3024, 1920×1080), no
lens/actuator support — so no autofocus, though the downstream node has an
actuator and an eeprom on the same bus.
Casey has a Matrix conversation with Dylan Van Assche pointing at a newer
commit with "all the possible fixes, focus and more". It is **not in mainline
or linux-next** (both checked directly, 404), not in linux-media patchwork, and
not on the branches of his GitLab fork or the sdm845-mainline group repo. Get
the link from that conversation rather than re-searching — it is the difference
between two modes and a working camera.
## Connects to
TASK-12 (face auth wants the front sensors, already wired), TASK-40 (a camera
stream is the sharpest inference-tiering case on the device), TASK-20 (where
captured media would land).