Re: [PATCH v4 6/7] media: qcom: camss: Add CAMSS Offline Processing Engine driver
Loic Poulain <[email protected]>
| Newsgroups | org.kernel.vger.linux-hardening,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel,org.kernel.vger.linux-media |
|---|---|
| Message-ID | <CAFEp6-2nTWjU0VrMQ8D8nDzH9P-vbA1gFPimv8aX+qREWHPNow@mail.gmail.com> |
On Mon, Jul 13, 2026 at 3:05 PM Bryan O'Donoghue <[email protected]> wrote: > > On 10/07/2026 10:04, Loic Poulain wrote: > > Add an image processing driver for the Qualcomm Offline Processing Engine > > (OPE). OPE is a memory-to-memory ISP block that converts raw Bayer > > frames to YUV, performing white balance, demosaic, chroma enhancement, > > color correction and downscaling. > > > > The hardware architecture consists of Fetch Engines and Write Engines, > > connected through intermediate pipeline modules for pix processing. > > > > The driver exposes three video nodes per pipeline instance: > > - ope_input: Bayer RAW input (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) > > - ope_disp_output: YUV output (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) > > - ope_params: ISP parameters (V4L2_BUF_TYPE_META_OUTPUT) > > > > Hardware features: > > - Stripe-based processing (up to 336 pixels wide per stripe) > > - White balance (CLC_WB) > > - Demosaic / Bayer-to-RGB (CLC_DEMO) > > - RGB-to-YUV conversion (CLC_CHROMA_ENHAN) > > - Color correction matrix (CLC_CC) > > - MN downscaler for chroma and luma planes > > > > Default configuration values are based on public standards such as BT.601. > > > > Processing Model: > > OPE processes frames in stripes of up to 336 pixels. Therefore, frames must > > be split into stripes for processing. Each stripe is configured after the > > previous one has been acquired (double buffered registers). To minimize > > inter-stripe latency, stripe configurations are generated ahead of time. > > > > Signed-off-by: Loic Poulain <[email protected]> > > Co-developed-by: Hans de Goede <[email protected]> > > Signed-off-by: Hans de Goede <[email protected]> > > --- > > drivers/media/platform/qcom/camss/Kconfig | 18 + > > drivers/media/platform/qcom/camss/Makefile | 4 + > > drivers/media/platform/qcom/camss/camss-ope.c | 3245 +++++++++++++++++++++++++ > > I think this should be in a sub-directory. You mean a OPE specific directory or a kind of offline engine generic one like: drivers/media/platform/qcom/camss/offline/ope.c ? > > > 3 files changed, 3267 insertions(+) > > > > diff --git a/drivers/media/platform/qcom/camss/Kconfig b/drivers/media/platform/qcom/camss/Kconfig > > index 4eda48cb1adf049a7fb6cb59b9da3c0870fe57f4..895fc57a679655fcb6f308be1565dc6b77bbbd67 100644 > > --- a/drivers/media/platform/qcom/camss/Kconfig > > +++ b/drivers/media/platform/qcom/camss/Kconfig > > @@ -7,3 +7,21 @@ config VIDEO_QCOM_CAMSS > > select VIDEO_V4L2_SUBDEV_API > > select VIDEOBUF2_DMA_SG > > select V4L2_FWNODE > > + > > +config VIDEO_QCOM_CAMSS_OPE > > + tristate "Qualcomm Offline Processing Engine (OPE) driver" > > + depends on VIDEO_QCOM_CAMSS > > + depends on V4L_PLATFORM_DRIVERS > > + depends on VIDEO_DEV > > + depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST > > + select V4L2_ISP > > + select VIDEOBUF2_DMA_CONTIG > > + select VIDEOBUF2_VMALLOC > > + help > > + Enable support for the Qualcomm Offline Processing Engine (OPE). > > + OPE is a memory-to-memory ISP block that converts raw Bayer frames > > + to YUV, performing white balance, demosaic, chroma enhancement and > > + downscaling. Found on QCM2290 and related SoCs. > > + > > + To compile this driver as a module, choose M here: the module > > + will be called qcom-camss-ope. > > diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile > > index 5678621efb6780b67a043ec8a2e914cce02d9b98..422eebc0a86301de3f39c743fbc06c437b17ac9a 100644 > > --- a/drivers/media/platform/qcom/camss/Makefile > > +++ b/drivers/media/platform/qcom/camss/Makefile > > @@ -31,3 +31,7 @@ qcom-camss-objs += \ > > camss-params.o \ > > > > obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom-camss.o > > + > > +qcom-camss-ope-objs := camss-ope.o > > + > > +obj-$(CONFIG_VIDEO_QCOM_CAMSS_OPE) += qcom-camss-ope.o > > diff --git a/drivers/media/platform/qcom/camss/camss-ope.c b/drivers/media/platform/qcom/camss/camss-ope.c > > new file mode 100644 > > index 0000000000000000000000000000000000000000..2c0d68cf1a637c998ebe4d3afb1fa6dbdb68f029 > > --- /dev/null > > +++ b/drivers/media/platform/qcom/camss/camss-ope.c > > @@ -0,0 +1,3245 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * camss-ope.c > > + * > > + * Qualcomm MSM Camera Subsystem - Offline Processing Engine > > + * > > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. > > + */ > > + > > +/* > > + * This driver provides driver implementation for the Qualcomm Offline > > + * Processing Engine (OPE). OPE is a memory-to-memory hardware block > > + * designed for image processing on a source frame. Typically, the input > > + * frame originates from the SoC CSI capture path, though not limited to. > > + * > > + * The hardware architecture consists of Fetch Engines and Write Engines, > > + * connected through intermediate pipeline modules: > > + * [FETCH ENGINES] => [Pipeline Modules] => [WRITE ENGINES] > > + * > > + * Current Configuration: > > + * Fetch Engine: One fetch engine is used for Bayer frame input. > > + * Write Engines: Two display write engines for Y and UV planes output. > > + * > > + * Only a subset of the pipeline modules are enabled: > > + * CLC_WB: White balance for channel gain configuration > > + * CLC_DEMO: Demosaic for Bayer to RGB conversion > > + * CLC_CC: Color Correct, coefficient based RGB correction > > + * CLC_CHROMA_ENHAN: for RGB to YUV conversion > > + * CLC_DOWNSCALE*: Downscaling for UV (YUV444 -> YUV422/YUV420) and YUV planes > > + * > > + * Default configuration values are based on public standards such as BT.601. > > + * > > + * Processing Model: > > + * OPE processes frames in stripes of up to 336 pixels. Therefore, frames must > > + * be split into stripes for processing. Each stripe is configured after the > > + * previous one has been acquired (double buffered registers). To minimize > > + * inter-stripe latency, the stripe configurations are generated ahead of time. > > + */ > > + > > +#include <linux/bitfield.h> > > +#include <linux/cleanup.h> > > +#include <linux/clk.h> > > +#include <linux/completion.h> > > +#include <linux/delay.h> > > +#include <linux/dma-mapping.h> > > +#include <linux/interconnect.h> > > +#include <linux/interrupt.h> > > +#include <linux/io.h> > > +#include <linux/iopoll.h> > > +#include <linux/module.h> > > +#include <linux/of.h> > > +#include <linux/platform_device.h> > > +#include <linux/pm_clock.h> > > +#include <linux/pm_domain.h> > > +#include <linux/pm_opp.h> > > +#include <linux/pm_runtime.h> > > +#include <linux/slab.h> > > +#include <linux/units.h> > > + > > +#include <media/v4l2-device.h> > > +#include <media/media-device.h> > > +#include <media/v4l2-ctrls.h> > > +#include <media/v4l2-event.h> > > +#include <media/v4l2-fh.h> > > +#include <media/v4l2-ioctl.h> > > +#include <media/v4l2-rect.h> > > + > > +#include "camss-pipeline.h" > > + > > +#include <media/videobuf2-dma-contig.h> > > +#include <media/videobuf2-vmalloc.h> > > + > > +#include <uapi/linux/camss-config.h> > > + > > +#include "camss-params.h" > > + > > +#define OPE_NAME "qcom-camss-ope" > > + > > +/* Format descriptor */ > > +struct ope_fmt { > > + u32 fourcc; > > + unsigned int depth; > > + unsigned int align; > > + unsigned int num_planes; > > + u32 mbus_code; > > + unsigned int c_hsub; > > + unsigned int c_vsub; > > +}; > > + > > +/* Per-queue format state */ > > +struct ope_fmt_state { > > + const struct ope_fmt *fmt; > > + unsigned int width; > > + unsigned int height; > > + struct v4l2_rect crop; > > + unsigned int bytesperline; > > + unsigned int sizeimage; > > + enum v4l2_colorspace colorspace; > > + enum v4l2_xfer_func xfer_func; > > + enum v4l2_ycbcr_encoding ycbcr_enc; > > + enum v4l2_quantization quantization; > > + unsigned int sequence; > > + struct v4l2_fract timeperframe; > > +}; > > + > > +/* -------- Register layout -------- */ > > + > > +#define OPE_TOP_HW_VERSION 0x000 > > +#define OPE_TOP_HW_VERSION_STEP GENMASK(15, 0) > > +#define OPE_TOP_HW_VERSION_REV GENMASK(27, 16) > > +#define OPE_TOP_HW_VERSION_GEN GENMASK(31, 28) > > +#define OPE_TOP_RESET_CMD 0x004 > > +#define OPE_TOP_RESET_CMD_HW BIT(0) > > +#define OPE_TOP_RESET_CMD_SW BIT(1) > > +#define OPE_TOP_IRQ_STATUS 0x014 > > +#define OPE_TOP_IRQ_MASK 0x018 > > +#define OPE_TOP_IRQ_STATUS_RST_DONE BIT(0) > > +#define OPE_TOP_IRQ_STATUS_WE BIT(1) > > +#define OPE_TOP_IRQ_STATUS_FE BIT(2) > > +#define OPE_TOP_IRQ_STATUS_VIOL BIT(3) > > +#define OPE_TOP_IRQ_STATUS_IDLE BIT(4) > > +#define OPE_TOP_IRQ_CLEAR 0x01c > > +#define OPE_TOP_IRQ_CMD 0x024 > > +#define OPE_TOP_IRQ_CMD_CLEAR BIT(0) > > +#define OPE_TOP_VIOLATION_STATUS 0x028 > > + > > +/* Fetch engine */ > > +#define OPE_BUS_RD_INPUT_IF_IRQ_MASK 0x00c > > +#define OPE_BUS_RD_INPUT_IF_IRQ_CLEAR 0x010 > > +#define OPE_BUS_RD_INPUT_IF_IRQ_CMD 0x014 > > +#define OPE_BUS_RD_INPUT_IF_IRQ_CMD_CLEAR BIT(0) > > +#define OPE_BUS_RD_INPUT_IF_IRQ_STATUS 0x018 > > +#define OPE_BUS_RD_INPUT_IF_CMD 0x01c > > +#define OPE_BUS_RD_INPUT_IF_CMD_GO_CMD BIT(0) > > +#define OPE_BUS_RD_CLIENT_0_CORE_CFG 0x050 > > +#define OPE_BUS_RD_CLIENT_0_CORE_CFG_EN BIT(0) > > +#define OPE_BUS_RD_CLIENT_0_CCIF_META_DATA 0x054 > > +#define OPE_BUS_RD_CLIENT_0_CCIF_MD_PIX_PATTERN GENMASK(7, 2) > > +#define OPE_BUS_RD_CLIENT_0_ADDR_IMAGE 0x058 > > +#define OPE_BUS_RD_CLIENT_0_RD_BUFFER_SIZE 0x05c > > +#define OPE_BUS_RD_CLIENT_0_RD_STRIDE 0x060 > > +#define OPE_BUS_RD_CLIENT_0_UNPACK_CFG_0 0x064 > > + > > +/* Write engines */ > > +#define OPE_BUS_WR_INPUT_IF_IRQ_MASK_0 0x018 > > +#define OPE_BUS_WR_INPUT_IF_IRQ_MASK_1 0x01c > > +#define OPE_BUS_WR_INPUT_IF_IRQ_CLEAR_0 0x020 > > +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0 0x028 > > +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_RUP_DONE BIT(0) > > +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_BUF_DONE BIT(8) > > +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_CONS_VIOL BIT(28) > > +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_VIOL BIT(30) > > +#define OPE_BUS_WR_INPUT_IF_IRQ_STATUS_0_IMG_SZ_VIOL BIT(31) > > +#define OPE_BUS_WR_INPUT_IF_IRQ_CMD 0x030 > > +#define OPE_BUS_WR_INPUT_IF_IRQ_CMD_CLEAR BIT(0) > > +#define OPE_BUS_WR_VIOLATION_STATUS 0x064 > > +#define OPE_BUS_WR_IMAGE_SIZE_VIOLATION_STATUS 0x070 > > +#define OPE_BUS_WR_CLIENT_CFG(c) (0x200 + (c) * 0x100) > > +#define OPE_BUS_WR_CLIENT_CFG_EN BIT(0) > > +#define OPE_BUS_WR_CLIENT_CFG_AUTORECOVER BIT(4) > > +#define OPE_BUS_WR_CLIENT_ADDR_IMAGE(c) (0x204 + (c) * 0x100) > > +#define OPE_BUS_WR_CLIENT_IMAGE_CFG_0(c) (0x20c + (c) * 0x100) > > +#define OPE_BUS_WR_CLIENT_IMAGE_CFG_1(c) (0x210 + (c) * 0x100) > > +#define OPE_BUS_WR_CLIENT_IMAGE_CFG_2(c) (0x214 + (c) * 0x100) > > +#define OPE_BUS_WR_CLIENT_PACKER_CFG(c) (0x218 + (c) * 0x100) > > +#define OPE_BUS_WR_CLIENT_MAX 4 > > + > > +/* Pipeline modules */ > > +#define OPE_PP_CLC_WB_GAIN_MODULE_CFG (0x200 + 0x60) > > Can you just map the individual blocks so that we can interrogate > HW_VERSION HW_STATUS and friends ? Those regs usually come first. I can > see useful debugfs and/or dev_dbg() usages of those data. Sure, will do. > > +#define OPE_PP_CLC_WB_GAIN_MODULE_CFG_EN BIT(0) > > +#define OPE_PP_CLC_WB_GAIN_WB_CFG(ch) (0x200 + 0x68 + 4 * (ch)) > > +#define OPE_PP_CLC_WB_GAIN_WB_CFG_GAIN GENMASK(14, 0) > > +#define OPE_PP_CLC_WB_GAIN_WB_SUB_CFG(ch) (0x200 + 0x74 + 4 * (ch)) > > +#define OPE_PP_CLC_WB_GAIN_WB_SUB_CFG_VAL GENMASK(31, 20) > > +#define OPE_PP_CLC_WB_GAIN_WB_ADD_CFG(ch) (0x200 + 0x80 + 4 * (ch)) > > +#define OPE_PP_CLC_WB_GAIN_WB_ADD_CFG_VAL GENMASK(31, 20) > > + > > +#define OPE_PP_CLC_CC_BASE 0x400 > > Is this actually the correct register base for CCM ? Nope, you're right. > > I think you should check again. > > Same comment for each of these blocks HW_VERSION should be the first > register. Ack I will define generic macro for them. Regards, Loic