Skip to content

Commit 1bead33

Browse files
authored
sensor: fix IMX415 latching into an IMX335 misdetection via 0x316A (#179)
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. A failed read (-1) is not taken as "not IMX415", which would otherwise let a latched part re-arm the loop. 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).
1 parent 9f57d6e commit 1bead33

1 file changed

Lines changed: 22 additions & 7 deletions

File tree

src/sensors.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,9 @@ static int detect_sony_sensor(sensor_ctx_t *ctx, int fd,
158158
if (i2c_change_addr(fd, i2c_addr) < 0)
159159
return false;
160160

161-
// 0x3057 is Y_OUT_SIZE MSB (host-writable), not a chip ID — Sony
162-
// sensors have no dedicated chip ID register. IMX335 can read 0x06
161+
// 0x3057 is Y_OUT_SIZE MSB and is host-writable: IMX335 reads 0x06
163162
// here after a WDR-cropping cycle (#157). Disambiguate via OB
164-
// cropping defaults that survive majestic init:
163+
// cropping defaults that survive sensor re-initialisation:
165164
// IMX335: 0x3072=0x28, 0x3074=0xB0
166165
// IMX347: 0x3072=0x14, 0x3074=0x3C
167166
int chip_id = READ(0x57);
@@ -189,8 +188,24 @@ static int detect_sony_sensor(sensor_ctx_t *ctx, int fd,
189188
if (r316A == -1)
190189
return false;
191190

192-
// HINT: possible check 0x316A == 0x7C && 0x3078 == 0x1
193-
if (r316A > 0 && ((r316A & 0xFC) == 0x7C)) {
191+
// 0x316A is INCKSEL4: IMX415 reads 0x7E here just like IMX335, and
192+
// libsns_imx335.so *writes* 0x316A=0x7E in both its linear and WDR init
193+
// tables. Once an IMX415 has been brought up with the IMX335 driver the
194+
// misdetection latches until the sensor loses power. Rule IMX415 out
195+
// first: 3B00h is "set to 2Eh, reset default 28h" (IMX415 datasheet p.46)
196+
// and 300Bh is a reset default that neither vendor init table touches
197+
// (IMX415: 0xA0, IMX335: 0x00).
198+
int r3B00 = READ(0xB00);
199+
int r300B = READ(0xB);
200+
int is_imx415 = (r3B00 == 0x2E || r3B00 == 0x28) && r300B == 0xA0;
201+
202+
if (r316A > 0 && ((r316A & 0xFC) == 0x7C) && !is_imx415) {
203+
// A failed read (-1) must not pass for "not IMX415": a latched
204+
// IMX415 would slip back into IMX335 here and re-arm the loop.
205+
// Only this decision needs the guard — the checks below re-test
206+
// 0x3B00 on their own.
207+
if (r3B00 == -1 || r300B == -1)
208+
return false;
194209
sprintf(ctx->sensor_id, "IMX335");
195210
return true;
196211
}
@@ -208,8 +223,8 @@ static int detect_sony_sensor(sensor_ctx_t *ctx, int fd,
208223

209224
// from IMX415 datasheet, p.46
210225
// 3B00h, Set to "2Eh", default value after reset is 28h
211-
// HINT: possible check 0x300B == 0xA0 && 0x30C0 == 0x20
212-
int r3B00 = READ(0xB00);
226+
// Looser than the is_imx415 test above on purpose: catches an IMX415
227+
// whose 0x300B differs, once 0x316A has ruled IMX335 out.
213228
if (r3B00 == 0x2E || r3B00 == 0x28) {
214229
sprintf(ctx->sensor_id, "IMX415");
215230
return true;

0 commit comments

Comments
 (0)