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

8 KiB
Raw Blame History

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,IMMUTABLEimx355 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)

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)
  • vdigvreg_s3a_1p35, vifvreg_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).