Skip to content

Add SoI JXK06 sensor driver for T23 SoC - #1

Open
tensorcrush wants to merge 15 commits into
thingino:mainfrom
tensorcrush:main
Open

Add SoI JXK06 sensor driver for T23 SoC#1
tensorcrush wants to merge 15 commits into
thingino:mainfrom
tensorcrush:main

Conversation

@tensorcrush

Copy link
Copy Markdown

Adds `3.10.14/sensor-src/t23/jxk06.c` — port of the existing T31 JXK06 driver adapted to the T23 sensor SDK conventions.

Context

The SoI JXK06 is a 3MP (2560×1440 native) rolling-shutter CMOS sensor, I²C addr 0x40, sold widely in Chinese Ingenic-T23 IP cameras (e.g. Aobocam A12 / Hopeway rebrand). The T31 and T41 driver trees already carry it; the T23 tree previously did not, so those boards had no upstream option.

What's done

  • New file: `3.10.14/sensor-src/t23/jxk06.c` (1028 lines).
  • Derived from `3.10.14/sensor-src/t31/jxk06.c` with the standard t31→t23 delta pattern (removed `SENSOR_CHIP_ID` combined define, inlined `.chip_id = 0x0852` in `sensor_attr`, dropped `SENSOR_MAX_WIDTH`/`SENSOR_MAX_HEIGHT` defines). Same delta as `t31/jxk05.c` → `t23/jxk05.c`.
  • Chip ID matches physical silicon (verified via i²c reads on Aobocam A12: regs 0x0a/0x0b = 0x08/0x52 = JXK06 per SoI `sensor_info`).

Testing

Compiled cleanly against the T23 kernel 3.10.14 build (module `sensor_jxk06_t23.ko`).

Full end-to-end runtime test with a companion defconfig is pending — my local build environment (WSL1 buildroot) produces images that don't boot WiFi even with an unmodified upstream defconfig, so I can't validate the sensor pipeline locally. Ready for CI validation.

Companion PR

Values decoded from the vendor sensor_jxk06_t23.ko (jxk06_attr,
jxk06_again_lut, jxk06_init_regs_*) rather than carried over from t31:

  - mipi.clk 800 -> 400
  - mipi.settle_time_apative_en 0 -> 1
  - max_again 259142 -> 324678, again_lut extended to 0x4f (80 entries)
  - total_width 2432 -> 3000, one_line_expr_in_us 22 -> 17

total_width = HTS(0x21:0x20) * 2 and total_height = VTS(0x23:0x22).
All three vendor modes then land on 86.4 MHz, matching
SENSOR_SUPPORT_SCLK_4M, and the vendor default mode 1440x1440@15fps
(HTS=1920 VTS=1500) reproduces its static attr exactly (3840 / 1500).

Also fix the TX_SENSOR_MAX_FPS_15 path in sensor_set_fps, which left
sclk unshifted and so computed half the correct VTS, and drop the
unused SENSOR_MAX_WIDTH/HEIGHT defines.

struct tx_isp_sensor_attribute sensor_attr={
.name = SENSOR_NAME,
.chip_id = 0x0852,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be set via SENSOR_CHIP_ID

static __init int init_sensor(void)
{
int ret = 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sensor_common_init(&sensor_info);
is missing

static __exit void exit_sensor(void)
{
private_i2c_del_driver(&sensor_driver);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sensor_common_exit();
is missing

static int shvflip = 1;
module_param(shvflip, int, S_IRUGO);
MODULE_PARM_DESC(shvflip, "Sensor HV Flip Enable interface");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static struct sensor_info sensor_info = {
        .name = SENSOR_NAME,
        .chip_id = SENSOR_CHIP_ID,
        .version = SENSOR_VERSION,
        .min_fps = SENSOR_OUTPUT_MIN_FPS,
        .max_fps = SENSOR_OUTPUT_MAX_FPS,
        .actual_fps = 0,
        .chip_i2c_addr = SENSOR_I2C_ADDRESS,
        .width = SENSOR_MAX_WIDTH,
        .height = SENSOR_MAX_HEIGHT,
};

is missing

t23 had no jxk06 IQ file, so INSTALL_SENSOR_BIN silently installed
nothing and the resulting image shipped an empty /usr/share/sensor.

This is the tuning blob from the stock firmware of the Aobocam A12
(HW_ZY_T2G2_1MK1_V5), which runs the JXK06 on a T23DL. It is 176288
bytes, the same size as every other t23 IQ file in this directory.
The VIC reported "hor err" on every channel and libimp died right
after the pipeline configured 2304x1296: the link could not deliver a
full line before the horizontal timer expired.

Required lane rate is active_pixels * bpp / lanes / line_period. At
2304x1296 that is 2304 * 10 / 2 / 17us = 678 Mbps, but mipi.clk was
400. The 400 came from the vendor blob's static attr, which describes
its 1440x1440@15fps default mode, where 1440 px over a 22us line only
needs 327 Mbps. Use 800, matching what the t31 driver runs for its own
large mode.
On real hardware 2304x1296 floods the VIC with "hor err" on every line
and no frame ever reaches the ISP, while the same board switched to
win_sizes[0] stops erroring after six lines. Raising the lane rate to
800 Mbps did not help, so the fault is not link bandwidth.

Fall back to the configuration the vendor blob itself boots in, which
is the only one whose attr is known byte for byte:

  win_sizes[0] 1440x1440@15fps, image_t 1440x1440, mipi.clk 400,
  total 3840x1500, one_line_expr_in_us 22, integration limit 1496

2304x1296 stays in win_sizes and its register table is unchanged, so
it can be revisited once the VIC timing for that mode is understood.
With the VIC finally quiet, rvd still died with

  sensor_set_vflip() enable: 0x0, val: 0x20.
  do_page_fault() thingino#2: sending SIGSEGV to rvd for invalid read access
  from 00000b38, epc/ra in libimp.so

after building both encoders, so the fault is inside libimp rather than
the pipeline description. probe forced attr->expo_fs = 1, which is a
t31 habit: the t23 ports of jxk04 and jxk05 drop the field entirely and
the vendor blob ships it as 0. The small fault address looks like a
null base plus member offset, consistent with libimp following an
exposure-frame-sync path this SoC does not implement.
The static attr describes win_sizes[0] (1440x1440@15fps), so selecting
win_sizes[1] left the ISP configured for a 1440-wide frame while the
sensor sent 2304, and the VIC raised "hor err" on every line. Fill in
the 2304x1296 geometry when that mode is picked:

  image_t 2304x1296, total 3000x1440, one_line_expr_in_us 17,
  integration limit 1436

total_width is HTS * 2 and a line lasts HTS / 86.4 MHz, the same rule
the vendor's own 1440x1440 values follow.

Default to the native 2304x1296 mode; sensor_max_fps=15 still selects
1440x1440, so both are reachable at load time without a rebuild.
On hardware the bottom fifth of every frame is garbage: the break is
sharp, sits at the same place on both the main and the sub stream, and
does not follow a vertical flip, so the ISP is being told the sensor
sends more lines than it really does.

Finding the true figure needs trying several values, and a rebuild per
attempt is impractical on a camera that can only be reflashed by hand.
Expose the geometry as parameters instead:

  ovr_win, ovr_twidth, ovr_theight, ovr_total_width,
  ovr_total_height, ovr_line_us, ovr_clk

Each defaults to -1, which keeps whatever the selected win_size
implies, so behaviour is unchanged unless a value is passed. probe logs
the resulting geometry so what the ISP was told is visible in dmesg.
Dumping the vendor blob's jxk06_attr and ours side by side leaves only
two differing words in the whole mipi region:

  mipi_sc.mipi_vcomp_en    vendor 1     ours 0
  mipi_sc.data_type_value  vendor 0x2b  ours 0

0x2b is the CSI-2 data type for RAW10. Without vertical compensation
the bottom fifth of every frame came back as noise, and without the
data type the VIC rejected every line of the 1920x1080 and 2304x1296
modes.
probe in the vendor blob memcpy()s a 124 byte Jxk06_mipi template over
the whole mipi field, so the template wins over whatever the static
jxk06_attr holds. Comparing against the template instead:

  settle_time_apative_en   0, not 1
  mipi_sc.mipi_vcomp_en    0
  mipi_sc.data_type_value  0

and the disassembly of its per-mode branches gives mipi.clk 216 for
both 2304x1296 and 1920x1080, against 400 for 1440x1440. The rest of
the per-mode geometry it writes matches what was already here.

Also expose settle/vcomp/data_type as parameters so the remaining
horizontal errors on the wide modes can be probed without a rebuild.
With settle_time_apative_en back to the template's 0 the VIC finally
accepts 2304x1296, but both modes still turn to noise partway down the
frame: at row ~1115 of 1296, and ~1123 of 1440. Register 0x2f:0x2e in
the vendor tables reads 1116 and 1134 for those modes, so the sensor
appears to stop there and the ISP keeps writing rows that never arrive.

Add ovr_win_w / ovr_win_h to trim the selected win_size, so the real
height can be confirmed on hardware before it is written down.
Sweeping the window height on hardware puts the end of usable data at
row 1120: at 1116 the framesource refuses to start, at 1128 a corner of
noise is left, and at 1152 a visible strip. 1120 gives a clean frame in
both modes, and matches register 0x2f:0x2e, which reads 1116 for
2304x1296 and 1134 for 1440x1440.

So the modes are 2304x1120 and 1440x1120 rather than the advertised
1296 and 1440 lines. Everything below that row was noise before.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants