Platform & SDK Support¶
timps supports nine Ingenic SoC families: T10, T20, T21, T23, T30, T31,
T40, T41, C100. This page summarizes the cross-platform structure the
codebase is built around; it deliberately does not duplicate the
exhaustive per-function availability matrix already maintained in
docs/sdk-feature-gaps.md, or the rotation deep-dive in
docs/rotation.md — read those two documents directly for full depth.
What a given camera can do is reported live by GET /control (caps); for
the OpenIMP side see https://lu-fi.github.io/openimp/feature-matrix.html.
SDK headers per platform¶
The vendored Ingenic IMP headers (from the
gtxaspec/ingenic-headers
git submodule under include/) are pinned per platform in the
Makefile:
| Platform | Header path |
|---|---|
| T31 | include/T31/1.1.6/en |
| C100 | include/C100/2.1.0/en |
| T21 | include/T21/1.0.33/zh |
| T23 | include/T23/1.3.0/en (must be ≥1.1.2 — earlier headers are missing a struct member that, combined with a newer libimp, makes the framesource silently deliver no frames; fs_create() has a compile-time tripwire against this mismatch) |
| T30 | include/T30/1.0.5/zh |
| T40 | include/T40/1.3.1/en (matches the libimp 1.3.1 thingino ships; the older 1.2.0 header lacks IMPEncoderStream.isVI, so IMP_Encoder_GetStream would overrun a struct one word too short — video_thread() has a compile-time tripwire against this) |
| T41 | include/T41/1.2.6/en (matches the libimp 1.2.6 thingino ships) |
| T20, T10 | include/T20/3.12.0/zh (T10 has no distinct header set and builds against T20's) |
Two encoder-API generations¶
src/hal/hal_ingenic.c branches its encoder setup between two SDK
generations:
- New generation —
IMP_Encoder_SetDefaultParam-based configuration: T31, C100, T40, T41. - Old generation — manual
IMPEncoderChnAttr/profile/rate-control struct assembly: T10, T20, T21, T23, T30.
Every encoder-facing feature decision in the codebase (and in
docs/sdk-feature-gaps.md's roadmap of unused SDK capabilities) has to
account for this split.
ISP tuning API split¶
Separately, the ISP tuning call signatures diverge on just two
platforms: ISP_NEW_TUNING_API (src/isp_caps.h) is defined only for
T40/T41, which use a reworked API taking an IMPVI_NUM + pointer
argument form for many tuning calls, and route flips through
SetHVFLIP instead of separate SetISPHflip/SetISPVflip calls. Every
other platform (including the old-generation-encoder ones) uses the
classic tuning API.
ISP tuning capability matrix (image.*)¶
src/isp_caps.h is the single source of truth both hal_ingenic.c
(which calls guard which SDK function) and /control's caps.image list
consult — see Configuration Reference
for the full per-key table. Summary:
| Capability | Platforms |
|---|---|
| Brightness/contrast/saturation/sharpness, anti-flicker, running-mode, sensor FPS | All SoCs |
Hue (SetBcshHue) |
T23, T31, T40, T41, C100 |
| Backlight comp / defog / DPC strength | T23, T31, C100; defog and DPC also on T30 (since v1.12.0, vendor and OpenIMP) and on T41 with OpenIMP (ISP module ratios 4/3, since v1.11.0); backlight not on T30 |
| DRC / WDR strength | T21, T23, T31, C100; T30 (since v1.12.0, vendor and OpenIMP); T41 with OpenIMP (module ratio 2, since v1.11.0) |
| T30 ISP keys (since v1.12.0, vendor and OpenIMP libimp) | sinter_strength/temper_strength/dpc_strength map 0..255 onto the T30's 50..150 % (128 = 100 %, the vendor picture), dpc_strength via SetDPStrength; drc_strength via Get/SetRawDRC (0 = off, 128 = restore the attributes read before the first change, else manual strength); defog_strength via SetAntiFogAttr (≤128 off, 129–170 weak, 171–212 medium, 213+ strong). No hue on T30 |
Colour effect (colorfx) / scene preset (scene) |
OpenIMP only: colorfx on T10, T20, T21, T23, T30 (since v1.12.0), T31; scene on T10, T20, T21, T23, T31 (not T30: the call is a no-op there) |
| Highlight depress, sinter/temper NR, max analog/digital gain, manual WB, ISP-level hflip/vflip | All except T40/T41 (ISP_NEW_TUNING_API); sinter NR (since 1.9.33) and temper NR (since v1.10.0) on T41 with OpenIMP; max analog gain on T40 since v1.12.0 (vendor and OpenIMP, AeExprInfo.AeMaxAGain) |
| AE compensation | All except T21; T40 since v1.12.0 (vendor and OpenIMP); T41 with OpenIMP (since 1.9.33) |
AE average luminance (GetAeLuma, secondary day/night metric) |
T21, T23, T31, C100 |
Real sensor-attr readback (GetSensorAttr) |
T23, T31, T32, T33, T40, T41, C100 (absent on T10/T20/T21/T30) |
A build with no PLATFORM_* macro defined at all (the host make sim
build) enables every capability, so the WebUI can be fully exercised
against timpsd-sim.
Audio capability matrix (audio.*)¶
From src/audio_caps.h: every SoC supports IMP_AI_SetVol/SetGain,
EnableHpf/DisableHpf, EnableAgc/DisableAgc, and
EnableNs/DisableNs. Analog PGA gain (IMP_AI_SetAlcGain,
audio.alc_gain) is restricted to T21, T31, C100 (T10 shares T20's
headers, which also lack it, so T10 has no ALC either). See
Audio for how this interacts with the native speaker
pipeline.
Motion detection capability (motion.*)¶
From src/motion_caps.h: whether IMP_IVS move detection exists, and
the maximum grid cell budget, come directly from whichever SDK header set
a platform's build links against (IMP_IVS_MOVE_MAX_ROI_CNT) — 52 cells
on essentially every SDK version timps builds against today, with the one
documented historical exception being the old T10/T20 3.9.0 SDK (4
cells), which the current Makefile no longer selects (it pins T20 3.12.0).
See Motion Detection.
Rotation capability tiers¶
Image rotation (videoN.rotation; always built since v1.12.1, up to
v1.12.0 the build option USE_ROTATE, off by default) has the
most platform-fragmented capability story in the codebase — full detail
lives in docs/rotation.md; the tiers are:
| Tier | Macro | Platforms | Mechanism |
|---|---|---|---|
| No rotation primitive | (none) | C100; T10, T20, T21, T23, T30 with the vendor libimp | rotation accepts only 0; any 90/180/270 request is coerced to 0 with a warning. |
| FrameSource software rotate | ROT_HAS_FS_ROTATE |
T31; T10, T20, T21, T23, T30 with OpenIMP | IMP_FrameSource_SetChnRotate — rotation happens inside libimp, not visible to the rest of timps as "software," but still not true hardware. Hardware OSD/privacy overlays work on rotated 90/270 streams (fixed 2026-07-23) but are confined to a top-band region on non-square rotated streams due to an OSD coordinate range-check quirk (vendor libimp only). On T10/T20/T21 (OpenIMP only, since v1.10.0, not yet tested on hardware): sub streams only, 16-aligned, at most 704x576, whatever the libimp reports; video0 and anything larger start unrotated. Every OpenIMP SoC needs an OpenIMP that rotates there (T1x first in commit 6b7f5ae); without OpenIMP_Cap_FsRotate timps probes SetChnRotate with a 0x0 picture at start and brings the stream up unrotated when the OpenIMP stubs (9cab219, returns success without rotating) or refuses (6857610, 0c02f45, 636b6ac) it. Since v1.12.0 T23 and T30 OpenIMP builds use the same path (OpenIMP next 17082ed3 or later); an OpenIMP exporting OpenIMP_Cap_FsRotate skips the 0x0 probe, and OpenIMP_FS_RotateLimits sets the envelope per channel (current OpenIMP: T31 4096x4096 align 2; T10/T20/T21 704x576, T23 and T30 1280x720, align 16; no fps cap). The timps-own T23 software path was removed in v1.12.0, together with its USE_SW_ROTATE knob. |
| True hardware I2D rotate | ROT_HAS_HW_I2D |
T40, T41 | The dedicated I2D hardware block. Full framerate, all resolutions. With the vendor libimp timps applies the same top-band OSD/privacy clamp on 90/270 as on T31 (video.<N>.rotate_path = band; whether this libimp needs it is not verified on hardware); OpenIMP and 180 draw over the whole frame. The only tier where rotation=180 is a real, distinct, per-channel capability (elsewhere, 180 was removed as a redundant, incorrectly-per-stream-modeled global ISP flip — use image.hflip+image.vflip instead, which is always available). |
ROT_HAS_90 (gating whether 90/270 are accepted at all) is defined
whenever either apply-path macro above is active, or on the
host sim. Rotation direction conventions are not uniform across
platforms (T40/T41: 90° = clockwise; T31 and T10/T20/T21/T23/T30: 90° = counter-clockwise,
kept that way specifically for numeric compatibility with prudynt-t's raw
rotTo90 enum values) — see docs/rotation.md for the full rationale and
on-device test history. Since v1.11.0 GET /control reports the path of a
running stream in video.<N>.rotate_path (off, band, hw; sw only from timps ≤ 1.11.1).
ROI and FrontCrop tiers¶
Since v1.10.0, encoder ROI (roi<S>.<N>.*) and ISP FrontCrop
(image.fcrop_*) carry a per-SoC tier in src/roi_caps.h, reported as
caps.roi.tier / caps.fcrop.tier: effective = device-tested,
experimental = the call exists and returns 0 but the effect is unverified
(or known absent), unsupported = refused. Both setters are bound weak, so a
libimp without the symbol reports unsupported at run time. The OpenIMP tiers
come from device tests by the OpenIMP maintainer (OpenIMP d03ca24, open-tx-isp
3cf9bdac), not from timps itself.
| SoC | ROI vendor | ROI OpenIMP | FrontCrop vendor | FrontCrop OpenIMP |
|---|---|---|---|---|
| T10 | experimental | effective | unsupported | effective, live |
| T20 | experimental | effective | unsupported | effective, live (downscaled streams only) |
| T21 | experimental (no effect seen) | effective (OPENIMP_T21_ROI=0 turns it off → experimental) |
unsupported | effective, live |
| T23 | unsupported (encoder only stores the region) | effective when the libimp exports OpenIMP_Cap_T23HelixRoi (OpenIMP v2026.10.11-rc1+, since v1.10.1), otherwise unsupported; OPENIMP_T23_ROI=0 → unsupported |
unsupported (untested) | effective, live with the driver's fcrop_upscale_pct parameter (open-tx-isp b15ef235); otherwise experimental, start-only (needs 3cf9bdac+) |
| T30 | unsupported | effective since v1.12.0 (family A IMP_Encoder_SetChnROI, OpenIMP 03dd0ce3) |
unsupported | unsupported |
| C100 | unsupported | — | unsupported | — |
| T31 | unsupported (no ROI symbol in 1.1.x) | effective (SetChnRoiAttr, needs OpenIMP d03ca24 + fec3e69; OPENIMP_T31_ROI=0 → unsupported) |
experimental, live (no zoom without open-tx-isp fcrop_upscale_pct) |
effective, live with the driver's fcrop_upscale_pct parameter (open-tx-isp 27dc8be4+); otherwise experimental, live |
| T40, T41 | unsupported (vendor T41 takes deltas only; not device-tested) | experimental since v1.11.0 when the libimp exports OpenIMP_Cap_EncRoi (QP deltas only; a T41 libimp before OpenIMP 958f7f3 ignores regions under FixQP: caps.roi.streams[N] = "fixqp") |
unsupported | experimental since v1.11.0 through IMP_ISP_Tuning_SetAutoZoom when the libimp exports OpenIMP_Cap_AutoZoom (caps.fcrop.api = autozoom, no upscaling); T41 live up to the driver envelope (t41_msca_live_max_w/h, 1920x1080 on current open-tx-isp, 768x432 before), a larger stream restarts its FrameSource (~45 ms, new keyframe); T40 live up to 4K |
T23/T31 FrontCrop with OpenIMP: timps checks at start for
/sys/module/tx_isp_t23|t31/parameters/fcrop_upscale_pct, which only drivers
with the T23 crop-hang fix (open-tx-isp 164225e5/25b1d8c7) or the T31 guard
(27dc8be4) have. Without it, T23 stays start-only (older drivers hung the
pipeline on a crop change): a POST is persisted and applied at the next
/etc/init.d/S95timps restart. A window smaller than a stream that is not
scaled down is refused with -EINVAL (one WARN, caps.fcrop.state =
rejected). Since v1.11.0 image.fcrop_upscale_pct (live) writes that
parameter, so the scaler may upscale a window down to half the stream size;
the ceiling caps.fcrop.upscale_max is 100 on both (device-tested; T31 at
150 hard-hangs until the hardware watchdog resets the camera) and -1 on every
other SoC/libimp.
Day/night colour statistics¶
The colour trigger of v1.11.0 (daynight.color_pct) reads per-zone AWB
statistics: GetAwbStatistics on T40/T41, GetAwbZone on T23/T31/C100, and
on T10/T20 with OpenIMP a tuning ioctl on libimp's /dev/video0 fd. With
OpenIMP on T23/T31 and T40/T41 only where the libimp exports
OpenIMP_Cap_AwbZone / OpenIMP_Cap_AwbStatistics. Vendor T10/T20/T21, T21
with OpenIMP and T30 have none (daynight.color_trigger = unavailable).
Device-tested on T40 vendor and T20 OpenIMP only.
ROI QP ranges: delta -25..25 everywhere (-26 gave invalid H.264 on T20); T21
and OpenIMP T23 honour only about -12..+13 (caps.roi.qp_delta_eff), positive deltas are
also capped by max_qp. An absolute QP is sent as a clamped delta when it is
more than 25 from a possible picture QP (caps.roi.abs_window). T10/T20 crop
only downscaled (sub) streams; a main stream at sensor size cannot zoom
there (caps.fcrop.zoomable).
Raising a tier after a device test is one line in src/roi_caps.h plus its
ROI_MATRIX entry in the Makefile (make test-roi).
FrameSource keepalive default¶
Since v1.12.0 the default is general.fs_keepalive = 1: every build keeps
its FrameSources running from start to stop. -1 (auto, the default
before) resolves per build, from
FS_KEEPALIVE_AUTO in src/hal/fs_ref.h:
| Build | Auto resolves to | Why |
|---|---|---|
T23 with USE_OPENIMP |
on | FrameSource disable/enable edges while streaming hung a T23 on the open stack. |
T41 with USE_OPENIMP |
on | Reproduced hang (3/3): one channel stopped and restarted within ~200 ms while the other ran. |
T40 with USE_OPENIMP (since v1.11.0) |
on | Without frames the open T40 driver runs no AE, so day/night read a frozen exposure. |
T10, T20, T21, T30, T31 with USE_OPENIMP |
off | No hang known; idle cost of a 24/7 FrameSource unmeasured on these (mostly small-RAM) SoCs. |
| Every vendor-libimp build (incl. T23, T41) | off | Same; the vendor T41 has not been tested for the fault. |
general.fs_keepalive = 1 (the default) turns it on anywhere, 0 turns it off
anywhere. An unknown word parses as auto, so a typo turns the keepalive off on
every "off" build above. See Architecture.
Where to go deeper¶
docs/sdk-feature-gaps.md— an independent, function-by-function audit of everyIMP_*SDK declaration across all nine platforms against what timps actually calls today, with a fleet-weighted prioritized list of unused capabilities (live encoder bitrate/GOP/QP reconfiguration, backchannel echo cancellation, live IVS sensitivity without a full rebuild, AE zone weighting, ROI-based encoding, ePTZ, WDR, privacy mosaic, and more) — useful reading before proposing a new feature that touches the SDK directly.docs/rotation.md— the full rotation story: exact per-SoC resolution/framerate constraints, the T31 hardware-OSD-on-rotated-stream investigation trail, direction-convention history, and how the other thingino streamers (prudynt-t, raptor, strero) compare.