feat(camera): add bananarchy-photo CLI, Sxmo menu integration, and multi-capture ISPIF/VFE0 reset

This commit is contained in:
Luxferre
2026-10-19 23:51:09 +03:00
parent a14a7aa543
commit ad012360c3
10 changed files with 322 additions and 52 deletions
+36 -9
View File
@@ -320,6 +320,9 @@ static int msm8905_cam_hw_init(struct msm8905_cam_dev *cam)
u16 chip_id;
u32 r;
if (cam->hw_initialized)
return 0;
/* 1. Ensure PM8909 LDO6 (1.8V) and LDO17 (2.85V) are enabled */
if (cam->usid1_regmap) {
regmap_update_bits(cam->usid1_regmap, PM8909_LDO6_EN_CTL,
@@ -497,6 +500,29 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb)
return ret;
}
/* Ensure GC2395 stream and VFE0 WM0/RDI0 are idle before resetting ISPIF */
gc2395_write_reg(cam, 0xfeU, 0x00U);
gc2395_write_reg(cam, 0xedU, 0x00U);
cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U);
cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U);
wmb();
/* Reset ISPIF cleanly for this frame */
cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00001ff9U);
usleep_range(1000, 1500);
cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00000000U);
usleep_range(1000, 1500);
cam_w32(cam->camss_base, ISPIF_BASE + 0x200U, 0x00000040U);
cam_w32(cam->camss_base, ISPIF_BASE + 0x230U, 0xffffffffU);
cam_w32(cam->camss_base, ISPIF_BASE + 0x234U, 0xffffffffU);
cam_w32(cam->camss_base, ISPIF_BASE + 0x238U, 0xffffffffU);
cam_w32(cam->camss_base, ISPIF_BASE + 0x01cU, 0x00000001U);
cam_w32(cam->camss_base, ISPIF_BASE + 0x208U, 0xffffffffU);
cam_w32(cam->camss_base, ISPIF_BASE + 0x20cU, 0xffffffffU);
cam_w32(cam->camss_base, ISPIF_BASE + 0x210U, 0xffffffffU);
cam_w32(cam->camss_base, ISPIF_BASE + 0x244U, 0x00000000U);
cam_w32(cam->camss_base, ISPIF_BASE + 0x264U, 0x00000001U);
/* Program WM0 PING & PONG to raw_dma_phys and arm single frame */
cam_w32(cam->camss_base, VFE0_BASE + 0x050U, (u32)cam->raw_dma_phys);
cam_w32(cam->camss_base, VFE0_BASE + 0x054U, (u32)cam->raw_dma_phys);
@@ -529,21 +555,21 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb)
usleep_range(2000, 3000);
}
/* Immediately stop WM0, ISPIF RDI0, and GC2395 stream to prevent overflow */
cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xaaaaaaaaU);
/* Stop GC2395 stream, WM0, and RDI0 cleanly */
gc2395_write_reg(cam, 0xfeU, 0x00U);
gc2395_write_reg(cam, 0xedU, 0x00U);
cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U);
cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U);
cam_w32(cam->camss_base, VFE0_BASE + 0x024U, 0xffffffffU);
cam_w32(cam->camss_base, VFE0_BASE + 0x028U, 0xffffffffU);
cam_w32(cam->camss_base, VFE0_BASE + 0x018U, 0x00000001U);
cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00001ff9U);
usleep_range(500, 1000);
cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00000000U);
wmb();
gc2395_write_reg(cam, 0xfeU, 0x00U);
gc2395_write_reg(cam, 0xedU, 0x00U);
if (!(irq0 & 0x00000040U)) {
cam->hw_initialized = false;
if (!(irq0 & 0x00000040U))
return -ETIMEDOUT;
}
msm8905_cam_demosaic(cam->raw_dma_buf, dst_rgb);
cam->sequence++;
@@ -751,8 +777,9 @@ static int msm8905_cam_dqbuf(struct file *file, void *priv,
b->field = V4L2_FIELD_NONE;
b->sequence = cam->sequence;
b->memory = V4L2_MEMORY_MMAP;
b->m.offset = idx * PAGE_ALIGN(CAM_OUT_FRAME_BYTES);
b->length = CAM_OUT_FRAME_BYTES;
ktime_get_ts64((struct timespec64 *)&b->timestamp);
v4l2_buffer_set_timestamp(b, ktime_get_ns());
return 0;
}