Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/tasks/46-camera-imx363.md
Fimeg 11668f097f task-46: rear IMX363 NACKs at 0x10, moved to 0x1a
And the lesson that cost the front camera: camss creates all sensor->csiphy
links in the async notifier's .complete, which needs every declared subdev to
bind. One non-probing sensor leaves the working front pair registered with zero
links. Never leave a failing sensor node enabled; a rear-disabled DTB is parked
on the device for one-cp recovery.
2026-08-01 13:57:05 -04:00

7.1 KiB
Raw Blame History

TASK 46 — Camera

Status: rear sensor written and building 2026-07-28; the front pair was already wired. Repo: Pixel3Arch (kernel DT).

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 IMX363 DT work (c7784b716, branch mic-race-fix) is still worth finishing, but it is no longer the blocker for "does this phone have a camera". Next real steps are exposure/gain controls (v4l2-ctl --list-ctrls on the sensor subdev), then libcamera so something other than a shell script can open it, 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.

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).