From d974d7d732973f31a85a0b8909d30f54c6c7d6df Mon Sep 17 00:00:00 2001 From: widgetii <6576495+widgetii@users.noreply.github.com> Date: Thu, 28 May 2026 15:36:03 +0300 Subject: [PATCH] kernel/mipi_rx/hi3516cv500: remove openipc_frame_ts vsync IRQ block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #155 (May 22, "Add openipc_frame_ts") added a MIPI vsync IRQ dispatch block to `kernel/mipi_rx/hi3516cv500/mipi_rx_hal.c`'s `mipi_rx_interrupt_route()`. PR-time validation was 21 fps on an av300 lab cam at 100 monotonic events — but under sustained 4K30fps load (IMX415 sensor on a hi3516av300_lite production board) the block destabilises the MIPI pipeline: * Periodic `Timeout from venc channel 0` errors in majestic (11/4 min on the freshly-flashed `nightly-20260527-3ec25c3`), * Persistent magenta colour cast in the output image (sensor bayer rows misaligned → RGGB decode picks up the wrong colour channel per row, AWB then computes weird gain ratios trying to compensate), * Visible "flicker" — frames dropping and recovering against the magenta-tinted baseline. Identical pattern to the V4 regression `OpenIPC/openhisilicon#195` fixed by gating the same vsync block off in the generic `kernel/mipi_rx/mipi_rx_hal.c`. The cv500 copy of that block (introduced in #155 as a parallel hook) carries the same hazard: unmasking `MIPI_CTRL_INT.vsync` (bit 4) and `LVDS_CTRL_INT.lvds_vsync` (bit 28) raises IRQ at the line-rate the vsync indicator pulses, and the W1C clear inside the ISR top half collides with the MIPI controller's internal frame-state machine on cv500-class silicon, just like it did on V4. Drop the block + revert the mask widening to pre-#155 values. cv500 keeps the `ISP_FEND` event source (added in #178, sits in `kernel/isp/arch/hi3516cv500/mkp/src/isp.c`, fires from the ISP IRQ — unchanged). Consumers that want a frame-edge timestamp on cv500 still get one per frame via ISP_FEND; they just lose the MIPI_FS edge until a non-IRQ-disrupting hook lands. Verified on the dlab `openipc-hi3516av300.dlab.torturelabs.com` cam (IMX415 4K30fps, hi3516av300_lite): pre-fix (master + opensdk 073e6e8 — this repo's main): Timeout from venc: 11 / 4 min rt_mutex_trylock WARN: 0 Image: magenta cast (AWB R/G≈1.4, B/G≈3.0 despite scene neutral) RTSP 20 s luma stdev: n/a — stream drops too often post-fix (this commit): Timeout from venc: 0 / 90 s rt_mutex_trylock WARN: 0 Image: correct colours RTSP 20 s luma stdev: 0.22 (0.18 % variance) R/G=1.21 B/G=0.91 — both within scene-correct range for warm-orange scene; no magenta cast Refs: openhisilicon#155 #178 #195 (V4 sibling fix) --- kernel/mipi_rx/hi3516cv500/mipi_rx_hal.c | 39 ------------------------ kernel/mipi_rx/hi3516cv500/mipi_rx_hal.h | 8 ++--- 2 files changed, 2 insertions(+), 45 deletions(-) diff --git a/kernel/mipi_rx/hi3516cv500/mipi_rx_hal.c b/kernel/mipi_rx/hi3516cv500/mipi_rx_hal.c index 8303fa6e..6b970375 100644 --- a/kernel/mipi_rx/hi3516cv500/mipi_rx_hal.c +++ b/kernel/mipi_rx/hi3516cv500/mipi_rx_hal.c @@ -2326,51 +2326,12 @@ static int mipi_rx_interrupt_route(int irq, void *dev_id) { volatile mipi_rx_sys_regs_t *mipi_rx_sys_regs = get_mipi_rx_sys_regs(); volatile lvds_ctrl_regs_t *lvds_ctrl_regs = NULL; - volatile mipi_ctrl_regs_t *mipi_ctrl_regs; int i = 0; for (i = 0; i < MIPI_RX_MAX_PHY_NUM; i++) { mipi_rx_phy_cil_int_statis(i); } - /* - * Frame-start dispatch (openipc_frame_ts). Runs outside the - * CHN_INT_RAW gate below because vsync IRQs alone don't set it. - * MIPI CSI-2 and LVDS vsync bits are W1C'd independently in case - * both are wired up, but openipc_frame_ts_push fires at most once - * per device per IRQ so consumers get one event per physical frame. - */ - /* - * Edge-detect on the raw vsync bits per device — see the - * matching comment in kernel/mipi_rx/mipi_rx_hal.c for the - * level-held-bit reasoning. cv500 also has the ~30–80 µs - * double-vsync quirk that the 1 ms openipc_frame_ts dedupe - * absorbs as a second line of defence. - */ - for (i = 0; i < MIPI_RX_MAX_DEV_NUM; i++) { - static bool s_vsync_was_set[MIPI_RX_MAX_DEV_NUM]; - unsigned int mipi_int, lvds_int; - bool vsync_now = false; - - mipi_ctrl_regs = get_mipi_ctrl_regs(i); - lvds_ctrl_regs = get_lvds_ctrl_regs(i); - - mipi_int = mipi_ctrl_regs->MIPI_CTRL_INT.u32; - lvds_int = lvds_ctrl_regs->LVDS_CTRL_INT.u32; - - if (mipi_int & MIPI_INT_VSYNC) { - vsync_now = true; - mipi_ctrl_regs->MIPI_CTRL_INT_RAW.u32 = MIPI_INT_VSYNC; - } - if (lvds_int & LVDS_INT_VSYNC) { - vsync_now = true; - lvds_ctrl_regs->LVDS_CTRL_INT_RAW.u32 = LVDS_INT_VSYNC; - } - if (vsync_now && !s_vsync_was_set[i]) - openipc_frame_ts_push(i, OPENIPC_FT_EVT_MIPI_FS); - s_vsync_was_set[i] = vsync_now; - } - for (i = 0; i < MIPI_RX_MAX_DEV_NUM; i++) { lvds_ctrl_regs = get_lvds_ctrl_regs(i); if (lvds_ctrl_regs->CHN_INT_RAW.u32) { diff --git a/kernel/mipi_rx/hi3516cv500/mipi_rx_hal.h b/kernel/mipi_rx/hi3516cv500/mipi_rx_hal.h index 7812b396..c5b18ac4 100644 --- a/kernel/mipi_rx/hi3516cv500/mipi_rx_hal.h +++ b/kernel/mipi_rx/hi3516cv500/mipi_rx_hal.h @@ -15,12 +15,8 @@ #define MIPI_RX_MIN_EXT_DATA_TYPE_BIT_WIDTH 8 #define MIPI_CIL_INT_MASK 0x00003f3f -/* Vsync bits unmasked so frame-start propagates to mipi_rx_interrupt_route, - * where openipc_frame_ts dispatches it. Error-stat bits unchanged. */ -#define MIPI_INT_VSYNC (1u << 4) /* MIPI_CTRL_INT.int_vsync */ -#define LVDS_INT_VSYNC (1u << 28) /* LVDS_CTRL_INT.lvds_vsync */ -#define MIPI_CTRL_INT_MASK 0x00030013 -#define LVDS_CTRL_INT_MASK 0x1f110000 +#define MIPI_CTRL_INT_MASK 0x00030003 +#define LVDS_CTRL_INT_MASK 0x0f110000 /* lvds_vsync_msk and lane0~3_sync_err_msk ignore, not err int */ #define MIPI_FRAME_INT_MASK 0x000f0000 #define MIPI_PKT_INT1_MASK 0x0001000f #define MIPI_PKT_INT2_MASK 0x000f000f