Skip to content

sigmastar: infinity6c: add SmartSens SC430AI driver (TP-Link Tapo C120) - #7

Merged
openipc-ai merged 3 commits into
OpenIPC:masterfrom
nzzane:sc430ai
Sep 19, 2026
Merged

openipc-ai merged 3 commits into
OpenIPC:masterfrom
nzzane:sc430ai

Conversation

@nzzane

@nzzane nzzane commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

Adds sigmastar/infinity6c/sensor_sc430ai_mipi.c for the SmartSens SC430AI (4 MP, 4-lane MIPI, I2C 0x60, ID 0xCE39).

Why: OpenIPC boots on the TP-Link Tapo C120 (SSC377) but had no SC430AI driver, and the stock sc430ai_MIPI.ko oopses inside OpenIPC's mi.ko (sensor-handle layout differs between SDK builds) — see OpenIPC/firmware#1654 and OpenIPC/firmware#1766.

What: the sc450ai driver as the skeleton, with the SC430AI register tables, gain steps (analog step table + coarse/fine digital gain) and exposure limits taken from the sensor's stock SigmaStar SDK driver. Modes: 2688x1520@30 (default), 2560x1440@30 (crop), 2688x1520@60. DOL/HDR entries keep the template structure and are untested.

Tested on a Tapo C120 with the current OpenIPC infinity6c kernel (5.10.61) and majestic: Sensor index 0: 2688x1520@30fps, 3A on with the vendor IQ file, RTSP/JPEG fine, IR-cut day/night switching fine. Builds with this repo's Makefile without warnings.

Follow-up in OpenIPC/firmware#2445: sc430ai in load_sigmastar (auto-detection via ipcinfo -s already works, srcfg 0 1 0 0 0 0 is fine on this board) and the IQ file sc430ai.bin.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add SmartSens SC430AI driver for SigmaStar Infinity6C

✨ Enhancement 🕐 40+ Minutes

Grey Divider

AI Description

• Adds native SC430AI support for Infinity6C and TP-Link Tapo C120.
• Supports 4 MP 30/60 fps output and cropped 1440p capture.
• Implements identification, initialization, orientation, frame timing, exposure, and gain control.
Diagram

sequenceDiagram
    participant Stack as Camera Stack
    participant Driver as SC430AI Driver
    participant Bus as I2C Bus
    participant Sensor as SC430AI Sensor
    participant CSI as MIPI CSI
    participant ISP as SigmaStar ISP
    Stack->>Driver: Select capture mode
    Driver->>Bus: Write register table
    Bus->>Sensor: Configure sensor
    Stack->>Driver: Update AE and orientation
    Driver->>Bus: Commit frame registers
    Bus->>Sensor: Apply controls
    Sensor-->>CSI: Stream RAW10 frames
    CSI-->>ISP: Deliver image data
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Reuse the stock kernel module
  • ➕ Retains the vendor-provided implementation and its original register behavior.
  • ➕ Avoids maintaining a large sensor-specific source driver.
  • ➖ The stock module crashes with OpenIPC because its sensor-handle ABI differs.
  • ➖ It remains coupled to the original SigmaStar SDK build and cannot integrate safely.
2. Add an SDK ABI compatibility shim
  • ➕ Could permit reuse of other vendor sensor modules with similar layout mismatches.
  • ➕ Centralizes compatibility logic instead of duplicating sensor implementations.
  • ➖ Requires reverse-engineering undocumented handle layouts across SDK versions.
  • ➖ Introduces broad kernel risk and remains dependent on proprietary binary modules.

Recommendation: Keep the source-level driver based on the repository's SC450AI skeleton. It matches the active Infinity6C sensor API, avoids the known binary ABI crash, and allows SC430AI-specific modes and AE behavior to be maintained directly. The untested DOL/HDR callbacks should remain explicitly experimental until hardware validation is available.

Files changed (1) +2003 / -0

Enhancement (1) +2003 / -0
sensor_sc430ai_mipi.cImplement the Infinity6C SC430AI MIPI sensor driver +2003/-0

Implement the Infinity6C SC430AI MIPI sensor driver

• Adds SC430AI identification, power sequencing, four-lane MIPI configuration, and register tables for 2688x1520 at 30/60 fps plus a cropped 2560x1440 mode. Implements frame-rate, shutter, analog/digital gain, orientation, and frame-synchronized register updates through the SigmaStar sensor API. DOL/HDR entry points and tables preserve the template structure but remain untested.

sigmastar/infinity6c/sensor_sc430ai_mipi.c

4 MP, 4-lane MIPI, 2688x1520@30 (also 2560x1440 crop and 2688x1520@60).
Ported from the sc450ai driver; register tables, gain steps and AE limits
come from the sensor's stock SigmaStar SDK driver (TP-Link Tapo C120).
Linear mode is tested on the Tapo C120 (SSC377) with majestic; the DOL/HDR
paths keep the template structure and are untested.
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. HDR reports twice the configured rate ✓ Resolved 🐞 Bug ≡ Correctness
Description
pCus_GetFPS_HDR derives the frame rate from the linear tVts_reg array instead of tVts_reg_HDR.
The initial arrays contain 1650 and 3300 lines respectively, so a 30-fps HDR stream reports 60 fps
and later HDR frame-rate changes remain invisible to the getter.
Code

sigmastar/infinity6c/sensor_sc430ai_mipi.c[1180]

+    u32 tVts = (params->tVts_reg[0].data << 8) | (params->tVts_reg[1].data << 0);
Evidence
The HDR getter reads the 1650-line linear cache, while the HDR setter writes the separate 3300-line
HDR cache; the sibling SC830AI implementation reads its HDR array.

sigmastar/infinity6c/sensor_sc430ai_mipi.c[1176-1211]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[753-761]
sigmastar/infinity6c/sensor_sc830ai_mipi.c[1180-1182]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The HDR frame-rate getter reads the linear VTS cache, causing a configured 30-fps HDR stream to report 60 fps and ignoring HDR VTS updates.
## Fix Focus Areas
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1176-1187]
## Recommended Fix
Build `tVts` from `params->tVts_reg_HDR` in `pCus_GetFPS_HDR`, matching the array updated by `pCus_SetFPS_HDR`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Long HDR exposure reads back as zero ✓ Resolved 🐞 Bug ≡ Correctness
Description
The HDR long-frame handle installs pCus_GetAEUSecs, whose conversion uses the linear-only
Preview_line_period global. HDR initialization does not assign that global, so exposure queries
return zero on a fresh HDR setup or use stale timing after a previous linear mode.
Code

sigmastar/infinity6c/sensor_sc430ai_mipi.c[R1970-1972]

+    handle->pCus_sensor_AEStatusNotify = pCus_AEStatusNotify_HDR_LEF;
+    handle->pCus_sensor_GetAEUSecs = pCus_GetAEUSecs;
+    handle->pCus_sensor_SetAEUSecs = pCus_SetAEUSecs_HDR_LEF;
Evidence
The registered getter uses Preview_line_period, which is assigned only by the linear resolution
setter, whereas the HDR setter and the corresponding sibling implementation use
Preview_line_period_HDR.

sigmastar/infinity6c/sensor_sc430ai_mipi.c[1373-1385]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[1023-1047]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[1290-1315]
sigmastar/infinity6c/sensor_sc830ai_mipi.c[1323-1335]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The HDR long-frame callback uses the linear exposure getter and therefore converts exposure with an uninitialized or stale linear line period.
## Fix Focus Areas
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1373-1385]
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1970-1972]
## Recommended Fix
Implement a dedicated HDR LEF getter that decodes `tExpo_reg` but uses `Preview_line_period_HDR`, then register that function on the HDR LEF handle.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Short HDR exposure reads 32 times high ✓ Resolved 🐞 Bug ≡ Correctness
Description
pCus_GetAEUSecs_HDR_SEF treats the two cached register bytes as whole lines even though
pCus_SetAEUSecs_HDR_SEF stores a half-line count shifted left by four bits. Every short-exposure
readback is therefore inflated by a factor of 32 apart from integer rounding, disrupting any HDR
control logic that consumes the getter.
Code

sigmastar/infinity6c/sensor_sc430ai_mipi.c[R1330-1333]

+    lines |= (u32)(params->tExpo_reg_HDR_SEF[0].data & 0xff) << 8;
+    lines |= (u32)(params->tExpo_reg_HDR_SEF[1].data & 0xff) << 0;
+
+    *us = (lines * Preview_line_period_HDR) / 1000;
Evidence
The setter computes a half-line count and shifts it left four before splitting it into registers,
while the getter neither reverses that shift nor divides half-lines by two; the linear getter
demonstrates both required operations.

sigmastar/infinity6c/sensor_sc430ai_mipi.c[1325-1363]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[1373-1383]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The HDR short-exposure getter omits both the four-bit register decoding shift and the half-line conversion, producing values approximately 32 times too large.
## Fix Focus Areas
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1325-1337]
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1340-1363]
## Recommended Fix
After reconstructing the register value, shift it right by four to recover the half-line count and convert it with `Preview_line_period_HDR / 1000 / 2`, matching the setter's units.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. One camera changes another's timing ✓ Resolved 🐞 Bug ≡ Correctness
Description
pCus_SetVideoRes stores each handle's base VTS and line period in the file-scope vts_30fps and
Preview_line_period variables. When the module is mapped to multiple camera IDs, selecting 30 or
60 fps on one camera changes exposure, shutter, and frame-rate calculations performed for every
other handle.
Code

sigmastar/infinity6c/sensor_sc430ai_mipi.c[R74-75]

+u32 Preview_line_period;
+u32 vts_30fps;
Evidence
The registration macro allocates distinct private data for every selected camera ID, but this driver
mutates shared globals in its per-handle resolution callback and reads them from per-handle AE
callbacks.

sigmastar/infinity6c/include/drv_sensor_common.h[225-250]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[74-76]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[1023-1047]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[1388-1413]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Mutable timing values are shared by all camera handles, allowing a resolution change on one mapped camera to alter another camera's calculations.
## Fix Focus Areas
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[74-76]
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1023-1047]
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1133-1173]
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1373-1413]
## Recommended Fix
Move the mutable base VTS and line-period values into `sc430ai_params`, initialize them for each handle and selected resolution, and use the per-handle values in FPS, exposure, and shutter calculations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Gain queries return no value ✓ Resolved 🐞 Bug ≡ Correctness
Description
pCus_GetAEGain returns success without assigning the caller's gain output, even though
pCus_SetAEGain changes the cached gain registers. Linear and HDR handles both expose this getter,
so any consumer querying the current gain receives its previous or uninitialized buffer contents.
Code

sigmastar/infinity6c/sensor_sc430ai_mipi.c[R1425-1429]

+static int pCus_GetAEGain(ms_cus_sensor* handle, u32* gain)
+{
+    int rc = 0;
+
+    return rc;
Evidence
The getter never dereferences its output parameter, while the setter updates cached sensor registers
and the function is installed as the active gain getter.

sigmastar/infinity6c/sensor_sc430ai_mipi.c[1424-1430]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[1488-1503]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[1761-1768]
sigmastar/infinity6c/sensor_sc430ai_mipi.c[1830-1835]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The gain getter reports success without populating its output parameter, leaving callers with an undefined or stale value.
## Fix Focus Areas
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1424-1430]
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1488-1503]
- sigmastar/infinity6c/sensor_sc430ai_mipi.c[1761-1768]
## Recommended Fix
Track the clamped effective gain in the handle's private `expo.final_gain` field whenever gain is set, initialize it to unity gain, and assign it to `*gain` in `pCus_GetAEGain`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can describe a rule in plain language on the Rules page and Qodo drafts it for you

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread sigmastar/infinity6c/sensor_sc430ai_mipi.c Outdated
Comment thread sigmastar/infinity6c/sensor_sc430ai_mipi.c
Comment thread sigmastar/infinity6c/sensor_sc430ai_mipi.c Outdated
Comment thread sigmastar/infinity6c/sensor_sc430ai_mipi.c Outdated
Comment thread sigmastar/infinity6c/sensor_sc430ai_mipi.c Outdated
nzzane added a commit to nzzane/firmware that referenced this pull request Sep 18, 2026
Load sensor_sc430ai_mipi.ko (OpenIPC/sensors#7) and ship its IQ file.
Detection needs nothing new: ipcinfo -s already reports sc430ai and the
default srcfg works on the Tapo C120.
- keep the base VTS and line period per handle instead of in file-scope
  globals, so one camera's mode change cannot alter another's timing
- pCus_GetAEGain returns the clamped gain last set (was left unassigned)
- pCus_GetFPS_HDR reads the HDR VTS registers, not the linear ones
- HDR long exposure gets its own getter using the HDR line period
- HDR short exposure getter undoes the setter's <<4 and half-line units

Linear mode re-tested on the Tapo C120.
nzzane added a commit to nzzane/firmware that referenced this pull request Sep 18, 2026
Load sensor_sc430ai_mipi.ko (OpenIPC/sensors#7). Detection needs nothing
new: ipcinfo -s already reports sc430ai and the default srcfg works on the
Tapo C120. The IQ file is not included (no vendor SDK release carries it);
users take /etc/sensors/sc430ai.bin from their camera's stock firmware.

@openipc-ai openipc-ai left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed this against the tree rather than the hardware — I don't have a C120 — and it holds up well.

  • The Makefile globs *$(OPENIPC_SNS_MODEL)*.c, so one file really is the whole change; no registration needed.
  • No leftovers from the sc450ai skeleton. I grepped for parent-sensor identity across all 2036 lines and the only hit is your attribution comment.
  • Chip ID 0xCE39 at 0x3107/0x3108 is distinct from every sibling here (sc401ai 0xCD2E, sc450ai 0xBD2F, sc830ai 0xC143, sc850sl 0x9D1E) and follows the family pattern; ipcinfo -s returning sc430ai is exactly the test that exercises the ID table.
  • Timing constants are self-consistent: VTS 1650 at 30 fps gives 20202 ns, at 60 fps 10101 ns, HDR VTS 3300 at 30 fps 10101 ns.

Your fix commit went further than the finding asked — moving vts_30fps and Preview_line_period out of file scope into the handle was a real multi-instance bug that nobody had flagged. Worth saying.

The untested HDR mode being advertised is not a problem with this PR: 8 of the 10 existing infinity6c drivers advertise one too, and sc450ai carries the same // Modify it template markers. You are the only one who documents the limitation.

One request, and it is the only reason this is changes-requested rather than an approval. The header names drv_ms_cus_sc430ai_MIPI_tp_ww, SigmaStar SDK build 202306132013 — a filename out of TP-Link's stock tree. That is exactly what you were asked to strip from OpenIPC/wiki#549, and it would be inconsistent of us to require it in one repo and not the other. The register tables are the substance; the stock filename and build number add nothing a reader can use. Something like "register tables and AE constants derived from the sensor's SigmaStar SDK driver" keeps the honest attribution without the disclosure.

The register tables are the substance; the vendor build's filename and
build number add nothing a reader can use, and the OpenIPC wiki page for
the same device was asked to leave them out.
nzzane added a commit to nzzane/builder that referenced this pull request Sep 19, 2026
SSC377, SmartSens SC430AI, 16 MB NOR, RTL8188FTV on USB. The generic
ssc377_lite defconfig with the 16 MB layout, the rtl8188fu driver and the
SAE-capable wpa_supplicant-openipc; the Wi-Fi module's power gate (GPIO 42)
in the wireless/usb entry; IR-cut, backlight and IR LED pins; the SC430AI
IQ file.

Depends on OpenIPC/sensors#7 (driver), OpenIPC/firmware#2445 (loader entry)
and OpenIPC/firmware#2449 (supplicant package).
@nzzane

nzzane commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

Header changed: "register tables and AE constants derived from the sensor's SigmaStar SDK driver", no filename or build number. That is the only change in the new commit.

On ordering: agreed, this goes first, then OpenIPC/firmware#2445. The builder device that ties the C120 pieces together is OpenIPC/builder#162; it was built against this branch and tested on the camera today: ipcinfo -s → sc430ai, Sensor index 0: 2688x1520@30fps, IQ file loaded by name from /etc/sensors/sc430ai.bin with no sensorConfig override.

@openipc-ai openipc-ai left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Header is clean now — no stock filename, no SDK build number, and the remaining "stock driver" mentions are generic limits with no path or identifier in them. That was the only thing outstanding.

Approving. This goes in first; OpenIPC/firmware#2445 follows, then #2449, then OpenIPC/builder#162.

Note for anyone rebuilding locally afterwards: sigmastar-osdrv-sensors tracks HEAD, and the tarball is cached by filename, so clear dl/sigmastar-osdrv-sensors or you will keep building the old sensor set.

@openipc-ai
openipc-ai merged commit 0294a00 into OpenIPC:master Sep 19, 2026
openipc-ai pushed a commit to OpenIPC/builder that referenced this pull request Sep 19, 2026
SSC377, SmartSens SC430AI, 16 MB NOR, RTL8188FTV on USB. The generic
ssc377_lite defconfig with the 16 MB layout, the rtl8188fu driver and the
SAE-capable wpa_supplicant-openipc; the Wi-Fi module's power gate (GPIO 42)
in the wireless/usb entry; IR-cut, backlight and IR LED pins; the SC430AI
IQ file.

Depends on OpenIPC/sensors#7 (driver), OpenIPC/firmware#2445 (loader entry)
and OpenIPC/firmware#2449 (supplicant package).

Co-authored-by: nzzane <12163646+nzzane@users.noreply.github.com>
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