sensor: fix IMX415 latching into an IMX335 misdetection via 0x316A - #179
Conversation
0x316A is INCKSEL4, not an identifier. A pristine IMX415 reads 0x00 there,
but libsns_imx335.so writes 0x316A=0x7E in both its linear and WDR init
tables -- the same value a real IMX335 reads. Streamers ask ipctool which
sensor is present and then load that vendor lib, so a single misdetection
stamps 0x7E into an IMX415 and every later probe agrees with itself. The
loop survives streamer restarts and soft reboots; only removing power
clears it. The existing IMX415 test (0x3B00) sat below the 0x316A test and
was unreachable once latched.
Rule IMX415 out before concluding IMX335, using 3B00h ("set to 2Eh",
default after reset 28h, IMX415 datasheet p.46) together with 300Bh, which
neither vendor init table writes and which therefore survives the latch
(IMX415: 0xA0, IMX335: 0x00). Only reject IMX335 when IMX415 is positively
identified, mirroring the IMX347 disambiguation added in #167, so no sensor
loses detection if a register drifts.
Measured 0x316A: IMX415 pristine 0x00, IMX415 after the IMX335 driver ran
0x7E, real IMX335 0x7E. Measured 0x300B: IMX415 0xA0 both latched and
pristine, IMX335 0x00. The dropped HINT claiming 0x30C0 == 0x20 on IMX415
is wrong -- it measures 0x2A.
Verified on Hi3516AV300 + IMX415 (imx335_i2c -> imx415_i2c while still
latched, then 3840x2160 @ 20fps on libsns_imx415.so after a cold boot) and
on Hi3516EV300 + IMX335 (unchanged; its 0x3057 reads 0x06, so it exercises
the #167 fall-through).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR Summary by Qodosensor: prevent IMX415 misdetecting as IMX335 by avoiding 0x316A latch
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
Code Review by Qodo
1.
|
READ() returns -1 on I2C failure, and the code treated that as a plain "not equal", so a failed 0x300B read made is_imx415 false. A latched IMX415 would then slip into the IMX335 branch and re-arm the very loop this series removes -- and re-arming it costs a physical power cycle. Guard only the IMX335 decision: the checks further down re-test 0x3B00 themselves, so no other sensor's path changes behaviour. Reported by Qodo on #179. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Valid, and worth fixing — addressed in 46b775c. Confirmed the sentinel is real rather than theoretical: I scoped it more narrowly than the suggested fix: if (r316A > 0 && ((r316A & 0xFC) == 0x7C) && !is_imx415) {
if (r3B00 == -1 || r300B == -1)
return false;
...
}The guard sits inside the IMX335 branch rather than before it, because only that decision is at risk. Hoisting it would make a failed Re-verified on hardware after the change: Hi3516AV300 + IMX415 → |
Problem
A Sony IMX415 on Hi3516AV300 is reported as
imx335_i2c. The streamer trusts that answer and brings the sensor up with the IMX335 register table — a 4K sensor forced into a 5MP IMX335 mode.This is not a regression from #167. That PR only touches the
READ(0x3057) == 0x06 → IMX347branch, and IMX415 reads0x3057 == 0x00, so the branch is never entered. #167 is verified still working (see below).Root cause
0x316Ais INCKSEL4 (input-clock select), not an identifier, and the check(r316A & 0xFC) == 0x7Ccannot discriminate. Measured on real silicon:0x316A0x00libsns_imx335.soran0x7E0x7EIt self-latches.
libsns_imx335.sowrites0x316A = 0x7Ein both its linear and WDR init tables (sony_imx335/imx335_sensor_ctl.c:238and:435, commentedINCKSEL4 = 37.125). Streamers ask ipctool which sensor is present, then dlopen that vendor lib. So a single misdetection — from any cause — stamps0x7Einto an IMX415, and from then on ipctool keeps agreeing with itself. The loop survives streamer restarts and soft reboots; only removing power clears it. That is why an affected camera works for months and then "suddenly" breaks and stays broken.Compounding this, the correct IMX415 test (
0x3B00) sat below the0x316Atest, so it was unreachable once latched.Fix
Rule IMX415 out before concluding IMX335.
0x300Bis the right discriminator: neither vendor init table writes it, so it is a true reset default on both parts, and it measured0xA0on the IMX415 in both the latched and pristine states.Only reject IMX335 when IMX415 is positively identified — the same idiom #167 established for IMX347 — so no sensor loses detection if a register drifts. The looser
0x3B00-only test is kept below as a fallback.Evidence
Full
0x3000–0x40FFdumps (4352 registers) from a real IMX415 and a real IMX335, cross-referenced against the register-address sets each vendor init table writes:0x316A0x7E¹0x7E0x7E)0x3B000x28²0x000x2E)0x300B0xA00x000x30C00x2A0x000x341C0x470xFF0x3072/0x30740x00/0x190x28/0xB0¹ latched; pristine
0x00²0x2Eonce the IMX415 driver has run — the code accepts both, which is necessary.The dropped HINT claiming
0x30C0 == 0x20on IMX415 is wrong; it measures0x2A.Verification on hardware
imx335_i2c→imx415_i2c. The fix works without a power cycle, which is the point.imx335_i2c, unchanged. Its0x3057reads0x06, so it genuinely exercises the sensor: fix IMX335 misdetected as IMX347 after WDR cycle (#157) #167 fall-through rather than skipping it.imx415_i2c→imx415_i2c.ini+libsns_imx415.so→IMX415 4K2K_10BIT_30FPS init succuss!, VI pipe 3840x2160 (was 2592x1944 under the wrong driver), IntCnt +80 over 4s = 20 fps, LostFrame 0, VbFail 0.Note for future sensor work
Any Sony fingerprint register that appears in a vendor init table is a latch hazard, not an identifier — a wrong answer makes the streamer write that table and cement the error. Screening candidates against the init-table address lists leaves 915 registers that separate IMX415 from IMX335 and are written by neither, so there is no shortage of safe choices.
🤖 Generated with Claude Code