[PATCH 0/7] media: qcom: camss: icp: Add HFI/ICP v4l m2m driver for x1e80100 BPS/IPE
From: Bryan O'Donoghue
Date: Fri Jul 03 2026 - 11:53:07 EST
This series is a very loose RFC for a block of code I've been developing to
enable the firmware based camera path available on most recent Qualcomm
platforms.
The Image Control Processor (ICP) provides a Host Firmware Interface (HFI)
which implements a session based system providing all of the most advanced
Camera algorithms on the Qualcomm stack.
Since it is firmware based with a session the ICP can achieve things like
IPE:
- Motion Compensated Temporal Filtering - MCTF/temporal denoise
- Image Correction Adjustment - ICA warp/geometric correction
- Advanced noise reduction - ANR - multi-pass noise reduction in a single
frame
- Electronic Image Stablisation - EIS
- Upscaling
Not present in the inline hardware
- Local Tone Mapping / LTM - done on current frame using current stats
BPS:
- Multi Frame Noise Reduction / MFNR
- Bracketed HDR frames
All of the same functionality as with Inline Image Front End (IFE) is
available in the ICP version with the key differences that inline processes
sensor data directly whereas the offline processes frames submitted to it
via HFI.
One thing I'd like to reason about is if the offline engine would be a
better fit in driver/accel. This RFC solve the engineering problem of
actually getting the ICP to boot and exchanging some data with it.
A putative structure of bot the BPS and IPE appearing as /dev/videoX nodes
in user-space is sketched out and the stastics and parameters the ICP/HFI
expects are included in the drop for reference.
As is obvious YAML is missing, uAPI documentation is missing.
Speaking/listening to several people at the media summit in Nice this year
got me to thinking v4l2 m2m might be a another solution for an offline
engine like this one, with the inline engines fitting into v4l with the
media-graph and the ability to route different sensor/PHY combinations to
different CSI decoders.
This version of the code uses simple-mfd to probe the bus but that is _not_
my intention for a v1 and beyond. There is already code in-flight for
CSIPHY to effectively make sub-nodes probe themselves so please ignore that
part.
Link: https://git.kernel.org/pub/scm/linux/kernel/git/bod/linux.git/log/?h=qcom-laptops-v6.18-rc4-camss-icp-bps-ipe-icp-boots%2Bstats-b4
Here's an example of the ICP log right now on my reference machine:
camss -e csi
[ 0.000000] OF: reserved mem: initialized node camera_icp_mem, compatible id shared-dma-pool
[ 0.000000] OF: reserved mem: 0x0000000bef000000..0x0000000bffffffff (278528 KiB) map reusable camera_icp_mem
[ 0.000000] OF: reserved mem: 0x0000000081f20000..0x0000000081f2ffff (64 KiB) nomap non-reusable usb-ucsi-shared@81f20000
[ 1.443825] platform ac01000.icp: Adding to iommu group 5
[ 6.665683] camss-icp ac01000.icp: assigned reserved memory node camera_icp_mem
[ 6.673517] camss-icp ac01000.icp: clk=ahb
[ 6.687251] camss-icp ac01000.icp: clk=core
[ 6.704545] camss-icp ac01000.icp: clk=debug_xo
[ 6.716389] camss-icp ac01000.icp: clk=gcc_hf_axi
[ 6.727918] camss-icp ac01000.icp: clk=gcc_sf_axi
[ 6.727919] camss-icp ac01000.icp: clk=cpas_ahb
[ 6.727920] camss-icp ac01000.icp: clk=core_ahb
[ 6.727921] camss-icp ac01000.icp: clk=cpas_fast_ahb
[ 6.742587] camss-icp ac01000.icp: clk=camnoc_axi_rt
[ 6.742588] camss-icp ac01000.icp: clk=camnoc_axi_nrt
[ 6.742589] camss-icp ac01000.icp: clk=bps_ahb
[ 6.742591] camss-icp ac01000.icp: clk=bps_fast_ahb
[ 6.754909] camss-icp ac01000.icp: clk=bps
[ 6.754911] camss-icp ac01000.icp: clk=cpas_bps
[ 6.754912] camss-icp ac01000.icp: clk=ipe_ahb
[ 6.754913] camss-icp ac01000.icp: clk=ipe_nps_fast_ahb
[ 6.767222] camss-icp ac01000.icp: clk=ipe_pps_fast_ahb
[ 6.781681] camss-icp ac01000.icp: clk=ipe_nps
[ 6.803558] camss-icp ac01000.icp: clk=ipe_pps
[ 6.813041] camss-icp ac01000.icp: clk=cpas_ipe
[ 6.827852] camss-icp ac01000.icp: Voting for BW now ahb
[ 6.837128] camss-icp ac01000.icp: Voting for BW now hf_0
[ 6.871958] camss-icp ac01000.icp: Voting for BW now sf_0
[ 6.983317] camss-icp ac01000.icp: Voting for BW now sf_icp
[ 6.989219] camss-icp ac01000.icp: HW version: 0x20000000
[ 6.994830] camss-icp ac01000.icp: FW memory: phys=0x0x000000008e100000 size=8388608
[ 7.012769] camss-icp ac01000.icp: Firmware loaded: qcom/x1e80100/CAMERA_ICP.mdt (7340032 bytes)
[ 7.012770] camss-icp ac01000.icp: HFI struct sizes: q_hdr=956 q_tbl_hdr=24 (expect 956, 24)
[ 7.012962] camss-icp ac01000.icp: Allocated: vaddr=ffff800085201000 dma_addr=0xfff00000 size=0x100000
[ 7.013650] camss-icp ac01000.icp: Allocated: vaddr=ffff800087801000 dma_addr=0xff800000 size=0x700000
[ 7.013803] camss-icp ac01000.icp: Allocated: vaddr=ffff800085601000 dma_addr=0xff700000 size=0x100000
[ 7.013804] camss-icp ac01000.icp: HFI memory layout:
[ 7.013805] camss-icp ac01000.icp: SHMEM: dma=0xfff00000 size=0x100000
[ 7.013806] camss-icp ac01000.icp: FwUncached: dma=0xff800000 size=0x700000
[ 7.013808] camss-icp ac01000.icp: QDSS: dma=0xff700000 size=0x100000
[ 7.013810] camss-icp ac01000.icp: QTBL initialized: ver=0xffffffff size=0xb4c
[ 7.013811] camss-icp ac01000.icp: Queue headers in QTBL:
[ 7.013813] camss-icp ac01000.icp: Q[0]: status=1 start_addr=0xffb00000 type=0 q_size=262144
[ 7.013815] camss-icp ac01000.icp: Q[1]: status=1 start_addr=0xffc00000 type=1 q_size=262144
[ 7.013817] camss-icp ac01000.icp: Q[2]: status=1 start_addr=0xffd00000 type=2 q_size=262144
[ 7.086701] camss-icp ac01000.icp: Firmware ready! version=0x01000100
[ 7.098579] camss-icp ac01000.icp: CIRQ after FW init: MASK=0x0 STATUS=0x0
[ 7.098581] camss-icp ac01000.icp: GP registers after FW init:
[ 7.232986] camss-icp ac01000.icp: GP0 (unused): 0x00000000
[ 7.239586] camss-icp ac01000.icp: GP1 (FW_VERSION): 0x01000100
[ 7.246249] camss-icp ac01000.icp: GP2 (INIT_REQ): 0x00000001
[ 7.252839] camss-icp ac01000.icp: GP3 (INIT_RESP): 0x00000001
[ 7.259434] camss-icp ac01000.icp: GP4 (SHMEM_PTR): 0xfff00000 (we wrote: 0xfff00000)
[ 7.268067] camss-icp ac01000.icp: GP5 (SHMEM_SIZE): 0x00100000 (we wrote: 0x00100000)
[ 7.276691] camss-icp ac01000.icp: GP6 (QTBL_PTR): 0xffa00000 (we wrote: 0xffa00000)
[ 7.285319] camss-icp ac01000.icp: GP7 (SECHEAP_PTR): 0xff900000 (we wrote: 0xff900000)
[ 7.293949] camss-icp ac01000.icp: GP8 (SECHEAP_SIZE): 0x00100000 (we wrote: 0x00100000)
[ 7.302710] camss-icp ac01000.icp: GP9 (STATUS): 0x023200c3
[ 7.309294] camss-icp ac01000.icp: GP10 (SFR_PTR): 0xffe00000 (we wrote: 0xffe00000)
[ 7.317920] camss-icp ac01000.icp: GP11 (QDSS_IOVA): 0xff700000 (we wrote: 0xff700000)
[ 7.326559] camss-icp ac01000.icp: GP12 (QDSS_SIZE): 0x00100000
[ 7.333141] camss-icp ac01000.icp: GP17 (FWUNCACHED): 0xff800000 (we wrote: 0xff800000)
[ 7.341778] camss-icp ac01000.icp: GP18 (FWUNC_SIZE): 0x00700000 (we wrote: 0x00700000)
[ 7.350447] camss-icp ac01000.icp: Starting HFI core init (SYS_INIT command)
[ 7.357741] camss-icp ac01000.icp: CMD_Q before: read=0 write=0
[ 7.363919] camss-icp ac01000.icp: MSG_Q before: read=0 write=0
[ 7.376337] camss-icp ac01000.icp: hdr->type 0x00010001 size 0x00000008 tx:00 00 00 00 00 00 00 00
[ 7.385590] camss-icp ac01000.icp: CMD_Q after write: read=0 write=2
[ 7.392168] camss-icp ac01000.icp: Raising HOST2ICPINT (CIRQ STATUS before: 0x0)
[ 7.399925] camss-icp ac01000.icp: CIRQ STATUS after HOST2ICPINT: 0x0
[ 7.430285] camss-icp ac01000.icp: MSG_Q has data (polled): read=0 write=14
[ 7.437487] camss-icp ac01000.icp: CMD_Q final: read=2 write=2 (FW consumed: YES)
[ 7.445226] camss-icp ac01000.icp: MSG_Q final: read=0 write=14 (FW responded: YES)
[ 7.453146] camss-icp ac01000.icp: hdr->type 0x00020001 size 0x00000038 rx:00 00 00 00 01 00 00 00 04 00 00 00 c3 00 32 02 05 09 06 00 00 03 01 01 00 00 00 20 00 00 01 20 02 00 00 20 02 00 00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 7.475216] camss-icp ac01000.icp: Parsed: size=56 type=0x20001 error=0x0 prop_num=0x1
[ 7.483406] camss-icp ac01000.icp: Props 04 00 00 00
[ 7.483409] camss-icp ac01000.icp: hdr->type 0x00020003 size 0x00000104 rx:08 00 00 00 e9 00 00 00 00 00 00 00 eb ca 70 01 43 49 43 50 5f 46 57 5f 45 20 3a 20 48 46 49 20 20 3a 51 43 5f 49 4d 41 47 45 5f 56 45 52 53 49 4f 4e 5f 53 54 52 49 4e 47 3d 43 49 43 50 2e 46
[ 7.483412] camss-icp ac01000.icp: ICP FW [24169195]: CICP_FW_E : HFI :QC_IMAGE_VERSION_STRING=CICP.FW.5.0-00020,OEM_IMAGE_VERSION_STRING=CRM,BUILD_TIME: Feb 8 2023 03:05:23,CACHE_ENABLED at icphostinterface.c:683 QC_IMAGE_VERSION_STRING=CICP.FW.5.0-00020 OEM_IMAGE_VERSION_STRING=CRM
[ 7.483414] camss-icp ac01000.icp: hdr->type 0x00020003 size 0x000000ec rx:08 00 00 00 d1 00 00 00 00 00 00 00 ba 71 71 01 43 49 43 50 5f 46 57 5f 45 20 3a 20 48 46 49 20 20 3a 45 4c 46 20 76 61 72 69 61 6e 74 3a 20 43 41 43 48 45 2d 45 4e 41 42 4c 45 44 3a 54 34 38
[ 7.483416] camss-icp ac01000.icp: ICP FW [24211898]: CICP_FW_E : HFI :ELF variant: CACHE-ENABLED:T480:API_V2:USE_CDM_1_1:T680:TCM_ENABLED: , API version: 0x23200c3 at icphostinterface.c:684 QC_IMAGE_VERSION_STRING=CICP.FW.5.0-00020 OEM_IMAGE_VERSION_STRING=CRM
[ 7.483419] camss-icp ac01000.icp: CMD_Q before: read=2 write=2
[ 7.483420] camss-icp ac01000.icp: MSG_Q before: read=14 write=14
[ 7.483421] camss-icp ac01000.icp: hdr->type 0x00010005 size 0x00000010 tx:be ba fe ca ef be ad de 00 00 00 00 00 00 00 00
[ 7.483423] camss-icp ac01000.icp: CMD_Q after write: read=2 write=6
[ 7.483425] camss-icp ac01000.icp: Raising HOST2ICPINT (CIRQ STATUS before: 0x0)
[ 7.483529] camss-icp ac01000.icp: CIRQ STATUS after HOST2ICPINT: 0x0
[ 7.650377] camss-icp ac01000.icp: MSG_Q has data (polled): read=14 write=18
[ 7.657677] camss-icp ac01000.icp: CMD_Q final: read=6 write=6 (FW consumed: YES)
[ 7.657679] camss-icp ac01000.icp: MSG_Q final: read=14 write=18 (FW responded: YES)
[ 7.657680] camss-icp ac01000.icp: hdr->type 0x00020006 size 0x00000010 rx:be ba fe ca ef be ad de 00 f5 b0 76 c9 78 e5 26
[ 7.657683] camss-icp ac01000.icp: Ping 0xdeadbeefcafebabe Pong 0xdeadbeefcafebabe
[ 7.685850] camss-bps ac2c000.bps: BPS registered as /dev/video18
[ 7.702906] camss-icp ac01000.icp: CMD_Q before: read=6 write=6
[ 7.711157] camss-icp ac01000.icp: MSG_Q before: read=18 write=18
[ 7.717472] camss-icp ac01000.icp: hdr->type 0x01010008 size 0x0000001c tx:01 00 00 00 00 80 4e 03 08 00 ff ff 00 00 00 00 00 00 00 00 00 80 ff ff 00 00 00 00
[ 7.732077] camss-icp ac01000.icp: CMD_Q after write: read=6 write=13
[ 7.738751] camss-icp ac01000.icp: Raising HOST2ICPINT (CIRQ STATUS before: 0x0)
[ 7.746535] camss-icp ac01000.icp: CIRQ STATUS after HOST2ICPINT: 0x0
[ 7.770466] camss-icp ac01000.icp: MSG_Q has data (polled): read=18 write=26
[ 7.777770] camss-icp ac01000.icp: CMD_Q final: read=13 write=13 (FW consumed: YES)
[ 7.785691] camss-icp ac01000.icp: MSG_Q final: read=18 write=26 (FW responded: YES)
[ 7.793701] camss-icp ac01000.icp: hdr->type 0x01020008 size 0x00000020 rx:00 00 00 00 98 19 29 00 00 80 4e 03 08 00 ff ff 00 00 00 00 00 00 00 00 00 d5 12 df c1 60 13 01
[ 7.809366] camss-icp ac01000.icp: fw_handle = 0x00291998
[ 7.815006] camss-icp ac01000.icp: CMD_Q before: read=13 write=13
[ 7.815008] camss-icp ac01000.icp: MSG_Q before: read=26 write=26
[ 7.815009] camss-icp ac01000.icp: hdr->type 0x0101000a size 0x00000028 tx:04 00 00 00 98 19 29 00 00 80 4e 03 08 00 ff ff 00 00 00 00 00 00 00 00 01 00 00 00 98 19 29 00 00 00 00 00 00 00 00 00
[ 7.815011] camss-icp ac01000.icp: CMD_Q after write: read=13 write=23
[ 7.815013] camss-icp ac01000.icp: Raising HOST2ICPINT (CIRQ STATUS before: 0x0)
[ 7.815116] camss-icp ac01000.icp: CIRQ STATUS after HOST2ICPINT: 0x0
[ 7.882581] camss-icp ac01000.icp: MSG_Q has data (polled): read=26 write=33
[ 7.891973] camss-icp ac01000.icp: CMD_Q final: read=23 write=23 (FW consumed: YES)
[ 7.899895] camss-icp ac01000.icp: MSG_Q final: read=26 write=33 (FW responded: YES)
[ 7.907896] camss-icp ac01000.icp: hdr->type 0x00020008 size 0x0000001c rx:ff ff ff ff 03 00 00 00 cc 00 00 00 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 7.922501] camss-icp ac01000.icp: ack.hdr.type != HFI_MSG_IPEBPS_ASYNC_DIRECT_ACK
[ 7.930419] camss-bps ac2c000.bps: failed to destory handle -71
Signed-off-by: Bryan O'Donoghue <bod@xxxxxxxxxx>
---
Bryan O'Donoghue (7):
arm64: dts: qcom: x1e80100: Add ICP/BPS/IPE nodes
media: qcom: camss: Launch ICP from CAMSS
media: qcom: camss: qcom-icp: Add minimal ICP driver with HFI infrastrucutre
media: qcom: camss: qcom-icp: bps: Add initial v4l2 m2m BPS driver
media: qcom: camss: qcom-icp: ipe: Add initial v4l2 m2m IPE driver
media: qcom: camss: Switch on ICP and BPS as make options
media: uapi: qcom-camss-stats-params
arch/arm64/boot/dts/qcom/hamoa.dtsi | 250 ++-
drivers/media/platform/qcom/camss/Kconfig | 24 +
drivers/media/platform/qcom/camss/Makefile | 8 +
drivers/media/platform/qcom/camss/camss-bps.c | 684 +++++++
drivers/media/platform/qcom/camss/camss-bps.h | 74 +
drivers/media/platform/qcom/camss/camss-icp-hfi.h | 534 ++++++
drivers/media/platform/qcom/camss/camss-icp.c | 623 ++++++
drivers/media/platform/qcom/camss/camss-icp.h | 58 +
drivers/media/platform/qcom/camss/camss-ipe.c | 558 ++++++
drivers/media/platform/qcom/camss/camss-ipe.h | 69 +
drivers/media/platform/qcom/camss/camss.c | 29 +
.../linux/media/qcom/camss/camss-stats-params.h | 2022 ++++++++++++++++++++
12 files changed, 4926 insertions(+), 7 deletions(-)
---
base-commit: ae28dda0ce21b86f8aa1c4456ede819d46eea536
change-id: 20260703-qcom-laptops-v6-18-rc4-camss-icp-bps-ipe-icp-boots-stats-b4-b252a7912d4d
Best regards,
--
Bryan O'Donoghue <bod@xxxxxxxxxx>