public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
To: "Niklas Söderlund" <niklas.soderlund+renesas@ragnatech.se>
Cc: Jai Luthra <jai.luthra+renesas@ideasonboard.com>,
	 Mauro Carvalho Chehab <mchehab@kernel.org>,
	Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>,
	 Jacopo Mondi <jacopo.mondi@ideasonboard.com>,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	 linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [v8 02/14] media: rppx1: Add framework to support Dreamchip RPPX1 ISP
Date: Wed, 6 May 2026 10:53:19 +0200	[thread overview]
Message-ID: <afrxmrw2BZLT1tRJ@zed> (raw)
In-Reply-To: <20260504010556.2796398-3-niklas.soderlund+renesas@ragnatech.se>

Hi Niklas

On Mon, May 04, 2026 at 03:05:44AM +0200, Niklas Söderlund wrote:
> Add a framework driver for Dreamchip RPPX1 ISP. The driver aims to
> provide a framework for other V4L2 based drivers to drive the RPPX1
> functionality. The reason for this split is that the RPPX1 IP itself do
> not provide any DMA engines to drive data to/from the device, instead it
> depends on other IP blocks to implement these features.
>
> While the peripherals around the RPPX1 ISP used in different designs and
> by different vendors are different the RPPX1 core itself is the same.
> For this reason the framework solution to be able to split the Dreamchip
> RPPX1 driver from vendors usage of it have been picked in hope to reduce
> duplication of the common parts.
>
> The design is to try and keep the surface of this framework as small as
> possible. The intention of this change is to be able to fill all needs
> of this.
>
>   * Two functions to create and destroy a RPPX1 instance, rppx1_create()
>     and rppx1_destory(). These are intended to be called in the users
>     probe and remove code paths.
>
>   * Two functions to start and stop the RPPX1 processing, rppx1_start()
>     and rppx1_stop(). These are intended to be called in the users
>     stream on and stream off code paths.
>
>   * One function to ask the RPPX1 to process parameters buffer prepared
>     by user space, rppx1_params(). The intention is to call this
>     function when the parameter buffer is queued to the V4L2 driver and
>     the result stored by the driver until the time it needs to be
>     written to the RPPX1. It's the users responsibility to write it
>     either using MMIO or other means.
>
>   * One function to fill in a statistic buffer based on the current
>     status of the RPPX1, rppx1_stats_fill_isr(). The intention is that
>     the user call's this in its interrupt handler when it knows the
>     RPPX1 is done processing a frame.
>
>   * One function to ack and retrieve the interrupts generated by the
>     RPPX1, rppx1_interrupt(). The intention is to call this function
>     when the users interrupt handler detects the RPPX1 have raised and
>     interrupt. There is no need for the user to understand, or act, on
>     the actual RPPX1 interrupt, but it can if it wants too.
>
> The initial support in the framework is limited and do not implement any
> ISP processing algorithms other then configuring the RPPX1 to process
> any Bayer (8-, 10, or 12-bit) image and produce either a RGB or YUYV
> output. It do however probe all function blocks of the RPPX1 and provide
> an interface to interact with both parameter and statistic bufferers.
> The user of the framework will not change as algorithms for the
> different function blocks of the ISP are being added.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> Signed-off-by: Jai Luthra <jai.luthra+renesas@ideasonboard.com>
> ---
> * Changes since v7
> - Merge with fixups done before the pixel format change.

Me and Jai have piled almost 60 fixup commits here
https://git.ideasonboard.com/renesas-v4h-isp/linux/commits/branch/v4h/jmondi/rppx1

which include the introduction of the uAPI header and porting of the
driver to new uAPI. I think it's fair to ask for this work to be
recorded even if it won't be visible upstream:

Please add:

Co-developed-by: Jai Luthra <jai.luthra+renesas@ideasonboard.com>
Signed-off-by: Jai Luthra <jai.luthra+renesas@ideasonboard.com>
Co-developed-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi+renesas@ideasonboard.com>

to the next patches in the series (and this one if you want to
introduce the empty uAPI header here. More below on this).

>
> * Changes since v6
> - Use kzalloc_obj
> - Set device pointer
>
> * Changes since v5
> - Make use of v4l2-isp.
> - Make VIDEO_DCT_RPPX1 a non visible symbol. It makes no sens to build
>   it without a consumer.
>
> * Changes since v2
> - Add missing include to slab.h
>
> * Changes since v3
> - Fix small build issues found by 0day on non-arm ARCH.
> ---
>  MAINTAINERS                                   |   7 +
>  drivers/media/platform/Kconfig                |   1 +
>  drivers/media/platform/Makefile               |   1 +
>  drivers/media/platform/dreamchip/Kconfig      |   3 +
>  drivers/media/platform/dreamchip/Makefile     |   6 +
>  .../media/platform/dreamchip/rppx1/Kconfig    |  12 +
>  .../media/platform/dreamchip/rppx1/Makefile   |  33 ++
>  .../platform/dreamchip/rppx1/rpp_module.c     |  40 +++
>  .../platform/dreamchip/rppx1/rpp_module.h     | 145 ++++++++
>  .../platform/dreamchip/rppx1/rpp_params.c     |  72 ++++
>  .../platform/dreamchip/rppx1/rpp_stats.c      |  27 ++
>  .../media/platform/dreamchip/rppx1/rppx1.c    | 339 ++++++++++++++++++
>  .../media/platform/dreamchip/rppx1/rppx1.h    |  99 +++++
>  .../platform/dreamchip/rppx1/rppx1_acq.c      | 147 ++++++++
>  .../platform/dreamchip/rppx1/rppx1_awbg.c     |  30 ++
>  .../media/platform/dreamchip/rppx1/rppx1_bd.c |  52 +++
>  .../platform/dreamchip/rppx1/rppx1_bdrgb.c    |  80 +++++
>  .../platform/dreamchip/rppx1/rppx1_bls.c      |  59 +++
>  .../platform/dreamchip/rppx1/rppx1_cac.c      |  29 ++
>  .../platform/dreamchip/rppx1/rppx1_ccor.c     | 106 ++++++
>  .../media/platform/dreamchip/rppx1/rppx1_db.c |  44 +++
>  .../platform/dreamchip/rppx1/rppx1_dpcc.c     |  76 ++++
>  .../platform/dreamchip/rppx1/rppx1_exm.c      |  51 +++
>  .../media/platform/dreamchip/rppx1/rppx1_ga.c |  49 +++
>  .../platform/dreamchip/rppx1/rppx1_hist.c     |  76 ++++
>  .../platform/dreamchip/rppx1/rppx1_hist256.c  |  46 +++
>  .../media/platform/dreamchip/rppx1/rppx1_is.c |  42 +++
>  .../platform/dreamchip/rppx1/rppx1_lin.c      |  58 +++
>  .../platform/dreamchip/rppx1/rppx1_lsc.c      |  68 ++++
>  .../platform/dreamchip/rppx1/rppx1_ltm.c      |  48 +++
>  .../platform/dreamchip/rppx1/rppx1_ltmmeas.c  |  41 +++
>  .../platform/dreamchip/rppx1/rppx1_outif.c    |  45 +++
>  .../platform/dreamchip/rppx1/rppx1_outregs.c  |  75 ++++
>  .../platform/dreamchip/rppx1/rppx1_rmap.c     |  64 ++++
>  .../platform/dreamchip/rppx1/rppx1_rmapmeas.c |  47 +++
>  .../platform/dreamchip/rppx1/rppx1_shrp.c     |  64 ++++
>  .../platform/dreamchip/rppx1/rppx1_wbmeas.c   |  61 ++++
>  .../platform/dreamchip/rppx1/rppx1_xyz2luv.c  |  26 ++
>  include/media/rppx1.h                         |  34 ++
>  .../uapi/linux/media/dreamchip/rppx1-config.h |  66 ++++

If you want to do it this way (add an empty uapi file and populate it
as we add blocks) please break the introduction of the uAPI header out
to a separate commit and retain Jai's authorship.

I don't think it it necessary to split adding blocks in different
commits and I think it would be better to add the uapi file in one go
for easier bisection.

>  40 files changed, 2369 insertions(+)
>  create mode 100644 drivers/media/platform/dreamchip/Kconfig
>  create mode 100644 drivers/media/platform/dreamchip/Makefile
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/Kconfig
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/Makefile
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rpp_module.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rpp_module.h
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rpp_params.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rpp_stats.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1.h
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_acq.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_awbg.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_bd.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_bdrgb.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_bls.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_cac.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_ccor.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_db.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_dpcc.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_exm.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_ga.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_hist.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_hist256.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_is.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_lin.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_lsc.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_ltm.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_ltmmeas.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_outif.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_outregs.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_rmap.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_rmapmeas.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_shrp.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_wbmeas.c
>  create mode 100644 drivers/media/platform/dreamchip/rppx1/rppx1_xyz2luv.c
>  create mode 100644 include/media/rppx1.h
>  create mode 100644 include/uapi/linux/media/dreamchip/rppx1-config.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index fb3c08e42a66..b7bdfa1b4816 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7787,6 +7787,13 @@ F:	drivers/block/drbd/
>  F:	include/linux/drbd*
>  F:	lib/lru_cache.c
>
> +DREAMCHIP RPPX1 ISP
> +M:	Niklas Söderlund <niklas.soderlund@ragnatech.se>

Please add me and Jai here

> +L:	linux-media@vger.kernel.org
> +S:	Maintained
> +F:	drivers/media/platform/dreamchip/rppx1/
> +F:	include/uapi/linux/media/dreamchip/rppx1-config.h

Once the formats are documented they should be added here

> +
>  DRIVER COMPONENT FRAMEWORK
>  L:	dri-devel@lists.freedesktop.org
>  F:	drivers/base/component.c
> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> index 3f0b7bb68cc9..3621b46e1e8d 100644
> --- a/drivers/media/platform/Kconfig
> +++ b/drivers/media/platform/Kconfig
> @@ -71,6 +71,7 @@ source "drivers/media/platform/atmel/Kconfig"
>  source "drivers/media/platform/broadcom/Kconfig"
>  source "drivers/media/platform/cadence/Kconfig"
>  source "drivers/media/platform/chips-media/Kconfig"
> +source "drivers/media/platform/dreamchip/Kconfig"
>  source "drivers/media/platform/imagination/Kconfig"
>  source "drivers/media/platform/intel/Kconfig"
>  source "drivers/media/platform/marvell/Kconfig"
> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
> index 6d5f79ddfcc3..0cc4bfe0da32 100644
> --- a/drivers/media/platform/Makefile
> +++ b/drivers/media/platform/Makefile
> @@ -14,6 +14,7 @@ obj-y += atmel/
>  obj-y += broadcom/
>  obj-y += cadence/
>  obj-y += chips-media/
> +obj-y += dreamchip/
>  obj-y += imagination/
>  obj-y += intel/
>  obj-y += marvell/
> diff --git a/drivers/media/platform/dreamchip/Kconfig b/drivers/media/platform/dreamchip/Kconfig
> new file mode 100644
> index 000000000000..d177d4ee79ae
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/Kconfig
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +source "drivers/media/platform/dreamchip/rppx1/Kconfig"
> diff --git a/drivers/media/platform/dreamchip/Makefile b/drivers/media/platform/dreamchip/Makefile
> new file mode 100644
> index 000000000000..ba47ba2d136e
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# Makefile for the Dreamchip device drivers.
> +#
> +
> +obj-y += rppx1/
> diff --git a/drivers/media/platform/dreamchip/rppx1/Kconfig b/drivers/media/platform/dreamchip/rppx1/Kconfig
> new file mode 100644
> index 000000000000..0998a7d10bf2
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/Kconfig
> @@ -0,0 +1,12 @@
> +# SPDX-License-Identifier: GPL-2.0
> +config VIDEO_DCT_RPPX1
> +	tristate
> +	depends on V4L_PLATFORM_DRIVERS
> +	select V4L2_ISP
> +	help
> +	  Support library for Dreamchip HDR RPP X1 High Dynamic Range Real-time
> +	  Pixel Processor (RPP). The library can be used by other drivers who
> +	  utilises the RPP as part of an ISP implementation.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called rppx1.
> diff --git a/drivers/media/platform/dreamchip/rppx1/Makefile b/drivers/media/platform/dreamchip/rppx1/Makefile
> new file mode 100644
> index 000000000000..b2bd6b5d68bc
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/Makefile
> @@ -0,0 +1,33 @@
> +# SPDX-License-Identifier: GPL-2.0
> +dct-rpp-x1-objs = \
> +	rpp_module.o \
> +	rpp_params.o \
> +	rpp_stats.o \
> +	rppx1.o \
> +	rppx1_acq.o \
> +	rppx1_awbg.o \
> +	rppx1_bd.o \
> +	rppx1_bdrgb.o \
> +	rppx1_bls.o \
> +	rppx1_cac.o \
> +	rppx1_ccor.o \
> +	rppx1_db.o \
> +	rppx1_dpcc.o \
> +	rppx1_exm.o \
> +	rppx1_ga.o \
> +	rppx1_hist.o \
> +	rppx1_hist256.o \
> +	rppx1_is.o \
> +	rppx1_lin.o \
> +	rppx1_lsc.o \
> +	rppx1_ltm.o \
> +	rppx1_ltmmeas.o \
> +	rppx1_outif.o \
> +	rppx1_outregs.o \
> +	rppx1_rmap.o \
> +	rppx1_rmapmeas.o \
> +	rppx1_shrp.o \
> +	rppx1_wbmeas.o \
> +	rppx1_xyz2luv.o
> +
> +obj-$(CONFIG_VIDEO_DCT_RPPX1) += dct-rpp-x1.o
> diff --git a/drivers/media/platform/dreamchip/rppx1/rpp_module.c b/drivers/media/platform/dreamchip/rppx1/rpp_module.c
> new file mode 100644
> index 000000000000..cd923b7ff5c1
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rpp_module.c
> @@ -0,0 +1,40 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include <linux/slab.h>

I don't think this is needed

> +
> +#include "rppx1.h"
> +#include "rpp_module.h"
> +
> +int rpp_module_probe(struct rpp_module *mod, struct rppx1 *rpp,
> +		     const struct rpp_module_ops *ops, u32 base)
> +{
> +	mod->rpp = rpp;
> +	mod->base = base;
> +	mod->ops = ops;
> +
> +	if (ops->probe)
> +		return ops->probe(mod);
> +
> +	return 0;
> +}
> +
> +void rpp_module_write(struct rpp_module *mod, u32 offset, u32 value)
> +{
> +	rppx1_write(mod->rpp, mod->base + offset, value);
> +}
> +
> +u32 rpp_module_read(struct rpp_module *mod, u32 offset)
> +{
> +	return rppx1_read(mod->rpp, mod->base + offset);
> +}
> +
> +void rpp_module_clrset(struct rpp_module *mod, u32 offset, u32 mask, u32 value)
> +{
> +	u32 reg = rpp_module_read(mod, offset) & ~mask;
> +
> +	rpp_module_write(mod, offset, reg | value);
> +}
> diff --git a/drivers/media/platform/dreamchip/rppx1/rpp_module.h b/drivers/media/platform/dreamchip/rppx1/rpp_module.h
> new file mode 100644
> index 000000000000..742904973e35
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rpp_module.h
> @@ -0,0 +1,145 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#ifndef __RPPX1_MODULE_H__
> +#define __RPPX1_MODULE_H__
> +
> +#include <linux/errno.h>
> +#include <linux/types.h>
> +#include <linux/v4l2-mediabus.h>
> +
> +#include <linux/media/dreamchip/rppx1-config.h>
> +
> +#include <media/rppx1.h>
> +
> +struct rpp_module_ops;
> +
> +enum rpp_raw_pattern {
> +	RPP_RGGB = 0,
> +	RPP_GRBG,
> +	RPP_GBRG,
> +	RPP_BGGR,
> +};
> +
> +struct rpp_module {
> +	struct rppx1 *rpp;
> +	u32 base;
> +
> +	const struct rpp_module_ops *ops;
> +
> +	union {
> +		struct {
> +			enum rpp_raw_pattern raw_pattern;
> +		} acq;
> +		struct {
> +			unsigned int colorbits;
> +		} bdrgb;
> +		struct {
> +			unsigned int colorbits;
> +		} bls;
> +		struct {
> +			unsigned int colorbits;
> +			unsigned int type;
> +		} ccor;
> +		struct {
> +			unsigned int colorbits;
> +		} dpcc;
> +		struct {
> +			unsigned int resultbits;
> +		} exm;
> +		struct {
> +			unsigned int colorbits;
> +		} ga;
> +		struct {
> +			unsigned int colorbits;
> +		} hist;
> +		struct {
> +			unsigned int colorbits;
> +		} lin;
> +		struct {
> +			unsigned int colorbits_high;
> +			unsigned int colorbits_low;
> +		} rmap;
> +		struct {
> +			unsigned int colorbits_high;
> +			unsigned int colorbits_low;
> +		} rmapmeas;
> +		struct {
> +			unsigned int colorbits;
> +		} shrp;
> +		struct {
> +			unsigned int colorbits;
> +		} wbmeas;
> +	} info;
> +};
> +
> +int rpp_module_probe(struct rpp_module *mod, struct rppx1 *rpp,
> +		     const struct rpp_module_ops *ops, u32 base);
> +
> +void rpp_module_write(struct rpp_module *mod, u32 offset, u32 value);
> +u32 rpp_module_read(struct rpp_module *mod, u32 offset);
> +void rpp_module_clrset(struct rpp_module *mod, u32 offset, u32 mask, u32 value);
> +
> +union rppx1_params_block {
> +	struct v4l2_isp_params_block_header header;
> +};
> +
> +union rppx1_stats_block {
> +	struct v4l2_isp_params_block_header header;
> +};
> +
> +struct rpp_module_ops {
> +	int (*probe)(struct rpp_module *mod);
> +	int (*start)(struct rpp_module *mod, const struct v4l2_mbus_framefmt *fmt);
> +
> +	int (*fill_params)(struct rpp_module *mod,
> +			   const union rppx1_params_block *block,
> +			   rppx1_reg_write write, void *priv);
> +	int (*fill_stats)(struct rpp_module *mod,
> +			  union rppx1_stats_block *block);
> +};
> +
> +extern const struct rpp_module_ops rppx1_acq_ops;
> +extern const struct rpp_module_ops rppx1_awbg_ops;
> +extern const struct rpp_module_ops rppx1_bd_ops;
> +extern const struct rpp_module_ops rppx1_bdrgb_ops;
> +extern const struct rpp_module_ops rppx1_bls_ops;
> +extern const struct rpp_module_ops rppx1_cac_ops;
> +extern const struct rpp_module_ops rppx1_ccor_ops;
> +extern const struct rpp_module_ops rppx1_ccor_csm_ops;
> +extern const struct rpp_module_ops rppx1_db_ops;
> +extern const struct rpp_module_ops rppx1_dpcc_ops;
> +extern const struct rpp_module_ops rppx1_exm_ops;
> +extern const struct rpp_module_ops rppx1_ga_ops;
> +extern const struct rpp_module_ops rppx1_hist256_ops;
> +extern const struct rpp_module_ops rppx1_hist_ops;
> +extern const struct rpp_module_ops rppx1_is_ops;
> +extern const struct rpp_module_ops rppx1_lin_ops;
> +extern const struct rpp_module_ops rppx1_lsc_ops;
> +extern const struct rpp_module_ops rppx1_ltm_ops;
> +extern const struct rpp_module_ops rppx1_ltmmeas_ops;
> +extern const struct rpp_module_ops rppx1_outif_ops;
> +extern const struct rpp_module_ops rppx1_outregs_ops;
> +extern const struct rpp_module_ops rppx1_rmapmeas_ops;
> +extern const struct rpp_module_ops rppx1_rmap_ops;
> +extern const struct rpp_module_ops rppx1_shrp_ops;
> +extern const struct rpp_module_ops rppx1_wbmeas_ops;
> +extern const struct rpp_module_ops rppx1_xyz2luv_ops;
> +
> +#define rpp_module_call(mod, op, args...)				\
> +	({								\
> +		struct rpp_module *__mod = (mod);			\
> +		int __result;						\
> +		if (!__mod)						\
> +			__result = -ENODEV;				\
> +		else if (!__mod->ops->op)				\
> +			__result = 0;					\
> +		else							\
> +			__result = __mod->ops->op(__mod, ##args);	\
> +		__result;						\
> +	})
> +
> +#endif /* __RPPX1_MODULE_H__ */
> diff --git a/drivers/media/platform/dreamchip/rppx1/rpp_params.c b/drivers/media/platform/dreamchip/rppx1/rpp_params.c
> new file mode 100644
> index 000000000000..a5feb18f3bd5
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rpp_params.c
> @@ -0,0 +1,72 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include <media/v4l2-isp.h>
> +#include <media/videobuf2-v4l2.h>
> +
> +#include "rppx1.h"
> +
> +#define RPPX1_PARAMS_BLOCK_INFO(block, data) \
> +	[RPPX1_PARAMS_BLOCK_TYPE_ ## block] = { \
> +		.size = sizeof(struct rppx1_ ## data ## _params), \
> +	}
> +
> +static const struct v4l2_isp_block_type_info
> +rppx1_ext_params_blocks_info[] = {
> +};
> +
> +int rppx1_params(struct rppx1 *rpp, struct vb2_buffer *vb, size_t max_size,
> +		 rppx1_reg_write write, void *priv)
> +{
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct v4l2_isp_params_buffer *cfg;
> +	size_t block_offset;
> +	int ret;
> +
> +	ret = v4l2_isp_params_validate_buffer_size(rpp->dev, vb, max_size);
> +	if (ret)
> +		return ret;
> +
> +	cfg = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
> +
> +	ret = v4l2_isp_params_validate_buffer(rpp->dev, vb,
> +					      (struct v4l2_isp_params_buffer *)cfg,

The cast is probably not needed

> +					      rppx1_ext_params_blocks_info,
> +					      ARRAY_SIZE(rppx1_ext_params_blocks_info));
> +	if (ret)
> +		return ret;
> +
> +	/* Walk the list of parameter blocks and process them. */
> +	block_offset = 0;
> +	while (block_offset < cfg->data_size) {
> +		const union rppx1_params_block *block =
> +			(const union rppx1_params_block *)&cfg->data[block_offset];
> +		struct rpp_module *module;
> +		int ret;
> +
> +		block_offset += block->header.size;
> +
> +		switch (block->header.type) {
> +		default:
> +			module = NULL;
> +			break;
> +		}
> +
> +		if (!module) {

If you want to do this you should initialize module to NULL. Otherwise
you can simply pr_warn (why not dev_warn() or even _dbg() ?) and
continue inside the switch ?

> +			pr_warn("Not handled RPPX1 block type: 0x%04x\n", block->header.type);
> +			continue;
> +		}
> +
> +		ret = rpp_module_call(module, fill_params, block, write, priv);
> +		if (ret) {
> +			pr_err("Error processing RPPX1 block type: 0x%04x\n", block->header.type);

Similar here, you have access to rpp->dev, use dev_err() (or _dbg() as
the error can be triggered by a userspace)

> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(rppx1_params);
> diff --git a/drivers/media/platform/dreamchip/rppx1/rpp_stats.c b/drivers/media/platform/dreamchip/rppx1/rpp_stats.c
> new file mode 100644
> index 000000000000..8f43e56ba361
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rpp_stats.c
> @@ -0,0 +1,27 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rppx1.h"
> +#include "rpp_module.h"
> +
> +#include <media/v4l2-isp.h>
> +
> +#define RPPX1_STATS_BLOCK_INFO(type, block) \
> +	[RPPX1_STATS_BLOCK_TYPE_ ## type] = { \
> +		.size = sizeof(struct rppx1_ ## block ## _stats), \
> +	}
> +
> +#define rppx1_init_stats_block(rpp, buf, type)				\
> +	((union rppx1_stats_block *)					\
> +	v4l2_isp_stats_init_block((rpp)->dev, (buf),			\
> +				  rppx1_stats_blocks_info,		\
> +				  ARRAY_SIZE(rppx1_stats_blocks_info),	\
> +				  (type), RPPX1_STATS_MAX_SIZE))	\
> +
> +void rppx1_stats_fill_isr(struct rppx1 *rpp, u32 isc, void *buf)
> +{
> +}
> +EXPORT_SYMBOL_GPL(rppx1_stats_fill_isr);

You will need to rebase on https://patchwork.linuxtv.org/project/linux-media/list/?series=24772

> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1.c b/drivers/media/platform/dreamchip/rppx1/rppx1.c
> new file mode 100644
> index 000000000000..2998c5f2a42e
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1.c
> @@ -0,0 +1,339 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + *
> + * Support library for Dreamchip HDR RPPX1 High Dynamic Range Real-time Pixel
> + * Processor.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +
> +#include "rppx1.h"
> +
> +/* RPP_HDR Base Addresses */
> +#define RPPX1_HDRREGS_BASE			0x0000
> +#define RPPX1_HDR_IRQ_BASE			0x0200
> +#define RPPX1_RPP_OUT_BASE			0x0800
> +#define RPPX1_RPP_RMAP_BASE			0x0c00
> +#define RPPX1_RPP_RMAP_MEAS_BASE		0x1000
> +#define RPPX1_RPP_MAIN_PRE1_BASE		0x2000
> +#define RPPX1_RPP_MAIN_PRE2_BASE		0x4000
> +#define RPPX1_RPP_MAIN_POST_BASE		0xa000
> +#define RPPX1_RPP_MVOUT_BASE			0xc000
> +#define RPPX1_RPP_FUSA_BASE			0xf000
> +
> +#define RPPX1_RPP_HDRREGS_VERSION_REG			(RPPX1_HDRREGS_BASE + 0x0000)
> +#define RPPX1_RPP_HDR_UPD_REG				(RPPX1_HDRREGS_BASE + 0x0004)
> +#define RPPX1_RESERVED_3_REG				(RPPX1_HDRREGS_BASE + 0x0008)
> +#define RPPX1_RPP_HDR_INFORM_ENABLE_REG			(RPPX1_HDRREGS_BASE + 0x000c)
> +#define RPPX1_RPP_HDR_OUT_IF_ON_REG			(RPPX1_HDRREGS_BASE + 0x0010)
> +#define RPPX1_RPP_HDR_OUT_IF_OFF_REG			(RPPX1_HDRREGS_BASE + 0x0014)
> +#define RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_REG	(RPPX1_HDRREGS_BASE + 0x0018)
> +
> +#define RPPX1_RPP_ISM				(RPPX1_HDR_IRQ_BASE + 0x00)
> +#define RPPX1_RPP_RIS				(RPPX1_HDR_IRQ_BASE + 0x04)
> +#define RPPX1_RPP_MIS				(RPPX1_HDR_IRQ_BASE + 0x08)
> +#define RPPX1_RPP_ISC				(RPPX1_HDR_IRQ_BASE + 0x0c)
> +
> +/* RPP_OUT/MV_OUT Pipelines - Base Addresses */
> +#define RPPX1_GAMMA_OUT_BASE			0x0000 /* HV, MV */
> +#define RPPX1_IS_BASE				0x00c0 /* HV, MV */
> +#define RPPX1_CSM_BASE				0x0100 /* HV, MV */
> +#define RPPX1_OUT_IF_BASE			0x0200 /* HV, MV */
> +#define RPPX1_RPP_OUTREGS_BASE			0x02c0 /* HV, MV */
> +#define RPPX1_LUV_BASE				0x0300 /* MV */
> +
> +/* PRE1/PRE2/POST Pipelines - Base Addresses */
> +#define RPPX1_ACQ_BASE				0x0080 /* PRE1, PRE2 */
> +#define RPPX1_BLS_BASE				0x0100 /* PRE1, PRE2 */
> +#define RPPX1_GAMMA_IN_BASE			0x0200 /* PRE1, PRE2 */
> +#define RPPX1_LSC_BASE				0x0400 /* PRE1, PRE2 */
> +#define RPPX1_AWB_GAIN_BASE			0x0500 /* PRE1, PRE2, POST */
> +#define RPPX1_DPCC_BASE				0x0600 /* PRE1, PRE2 */
> +#define RPPX1_DPF_BASE				0x0700 /* PRE1, PRE2 */
> +#define RPPX1_FILT_BASE				0x0800 /* POST */
> +#define RPPX1_CAC_BASE				0x0880 /* POST */
> +#define RPPX1_CCOR_BASE				0x0900 /* POST */
> +#define RPPX1_HIST_BASE				0x0a00 /* PRE1, PRE2, POST */
> +#define RPPX1_HIST256_BASE			0x0b00 /* PRE1 */
> +#define RPPX1_EXM_BASE				0x0c00 /* PRE1, PRE2 */
> +#define RPPX1_LTM_BASE				0x1000 /* POST */
> +#define RPPX1_LTM_MEAS_BASE			0x1200 /* POST */
> +#define RPPX1_WBMEAS_BASE			0x1700 /* POST */
> +#define RPPX1_BDRGB_BASE			0x1800 /* POST */
> +#define RPPX1_SHRP_BASE				0x1a00 /* POST */
> +
> +/* Functional Safety Module Base Addresses */
> +#define RPPX1_FMU_BASE				0x0100
> +
> +#define RPPX1_RPP_HDR_FMU_FSM			(RPPX1_RPP_FUSA_BASE + RPPX1_FMU_BASE + 0x00)
> +#define RPPX1_RPP_HDR_FMU_RFS			(RPPX1_RPP_FUSA_BASE + RPPX1_FMU_BASE + 0x04)
> +#define RPPX1_RPP_HDR_FMU_MFS			(RPPX1_RPP_FUSA_BASE + RPPX1_FMU_BASE + 0x08)
> +#define RPPX1_RPP_HDR_FMU_FSC			(RPPX1_RPP_FUSA_BASE + RPPX1_FMU_BASE + 0x0c)
> +
> +void rppx1_write(struct rppx1 *rpp, u32 offset, u32 value)
> +{
> +	iowrite32(value, rpp->base + offset);
> +}
> +
> +u32 rppx1_read(struct rppx1 *rpp, u32 offset)
> +{
> +	u32 ret = ioread32(rpp->base + offset);
> +	return ret;

        return ioread32(rpp->base + offset);

> +}
> +
> +bool rppx1_interrupt(struct rppx1 *rpp, u32 *isc)
> +{
> +	u32 status, raw, fault;
> +
> +	fault = rppx1_read(rpp, RPPX1_RPP_HDR_FMU_MFS);
> +	if (fault) {
> +		pr_err("%s: fault 0x%08x\n", __func__, fault);

Can't you use dev_err() ?
Please have a look at all the usages of pr_err/pr_warn and replace
them with dev_dbg()

> +		rppx1_write(rpp, RPPX1_RPP_HDR_FMU_FSC, fault);
> +	}
> +
> +	/* Read raw interrupt status. */
> +	raw = rppx1_read(rpp, RPPX1_RPP_RIS);
> +	status = rppx1_read(rpp, RPPX1_RPP_MIS);
> +
> +	/* Propagate the isc status. */
> +	if (isc)
> +		*isc = status | raw;
> +
> +	/* Clear enabled interrupts */
> +	rppx1_write(rpp, RPPX1_RPP_ISC, status);
> +
> +	return !!(status & RPPX1_IRQ_ID_OUT_FRAME);
> +}
> +EXPORT_SYMBOL_GPL(rppx1_interrupt);
> +
> +void rppx1_destroy(struct rppx1 *rpp)
> +{
> +	kfree(rpp);
> +}
> +EXPORT_SYMBOL_GPL(rppx1_destroy);
> +
> +/*
> + * Allocate the private data structure and verify the hardware is present.
> + */
> +struct rppx1 *rppx1_create(void __iomem *base, struct device *dev)
> +{
> +	struct rppx1 *rpp;
> +	u32 reg;
> +
> +	/* Allocate library structure */
> +	rpp = kzalloc_obj(*rpp);
> +	if (!rpp)
> +		return NULL;

I wonder if we can use the managed version of devm_kzalloc or we're
going to create dependencies between the rcar-isp platform device and
the rpp library driver.

> +
> +	rpp->base = base;
> +	rpp->dev = dev;
> +
> +	/* Check communication with RPP and verify it truly is a X1. */
> +	reg = rppx1_read(rpp, RPPX1_RPP_HDRREGS_VERSION_REG);
> +	if (reg != 3) {
> +		pr_err("Unsupported HDR version (%u)\n", reg);

ditto

> +		rppx1_destroy(rpp);
> +		return NULL;
> +	}
> +
> +	/* Probe the PRE1 pipeline. */
> +	if (rpp_module_probe(&rpp->pre1.acq, rpp, &rppx1_acq_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_ACQ_BASE) ||
> +	    rpp_module_probe(&rpp->pre1.bls, rpp, &rppx1_bls_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_BLS_BASE) ||
> +	    rpp_module_probe(&rpp->pre1.lin, rpp, &rppx1_lin_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_GAMMA_IN_BASE) ||
> +	    rpp_module_probe(&rpp->pre1.lsc, rpp, &rppx1_lsc_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_LSC_BASE) ||
> +	    rpp_module_probe(&rpp->pre1.awbg, rpp, &rppx1_awbg_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_AWB_GAIN_BASE) ||
> +	    rpp_module_probe(&rpp->pre1.dpcc, rpp, &rppx1_dpcc_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_DPCC_BASE) ||
> +	    rpp_module_probe(&rpp->pre1.bd, rpp, &rppx1_bd_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_DPF_BASE) ||
> +	    rpp_module_probe(&rpp->pre1.hist, rpp, &rppx1_hist_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_HIST_BASE) ||
> +	    rpp_module_probe(&rpp->pre1.hist256, rpp, &rppx1_hist256_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_HIST256_BASE) ||
> +	    rpp_module_probe(&rpp->pre1.exm, rpp, &rppx1_exm_ops,
> +			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_EXM_BASE))
> +		goto err;
> +
> +	/* Probe the PRE2 pipeline. */
> +	if (rpp_module_probe(&rpp->pre2.acq, rpp, &rppx1_acq_ops,
> +			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_ACQ_BASE) ||
> +	    rpp_module_probe(&rpp->pre2.bls, rpp, &rppx1_bls_ops,
> +			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_BLS_BASE) ||
> +	    rpp_module_probe(&rpp->pre2.lin, rpp, &rppx1_lin_ops,
> +			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_GAMMA_IN_BASE) ||
> +	    rpp_module_probe(&rpp->pre2.lsc, rpp, &rppx1_lsc_ops,
> +			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_LSC_BASE) ||
> +	    rpp_module_probe(&rpp->pre2.awbg, rpp, &rppx1_awbg_ops,
> +			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_AWB_GAIN_BASE) ||
> +	    rpp_module_probe(&rpp->pre2.dpcc, rpp, &rppx1_dpcc_ops,
> +			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_DPCC_BASE) ||
> +	    rpp_module_probe(&rpp->pre2.bd, rpp, &rppx1_bd_ops,
> +			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_DPF_BASE) ||
> +	    rpp_module_probe(&rpp->pre2.hist, rpp, &rppx1_hist_ops,
> +			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_HIST_BASE) ||
> +	    rpp_module_probe(&rpp->pre2.exm, rpp, &rppx1_exm_ops,
> +			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_EXM_BASE))
> +		goto err;
> +
> +	/* Probe the POST pipeline. */
> +	if (rpp_module_probe(&rpp->post.awbg, rpp, &rppx1_awbg_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_AWB_GAIN_BASE) ||
> +	    rpp_module_probe(&rpp->post.ccor, rpp, &rppx1_ccor_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_CCOR_BASE) ||
> +	    rpp_module_probe(&rpp->post.hist, rpp, &rppx1_hist_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_HIST_BASE) ||
> +	    rpp_module_probe(&rpp->post.db, rpp, &rppx1_db_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_FILT_BASE) ||
> +	    rpp_module_probe(&rpp->post.cac, rpp, &rppx1_cac_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_CAC_BASE) ||
> +	    rpp_module_probe(&rpp->post.ltm, rpp, &rppx1_ltm_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_LTM_BASE) ||
> +	    rpp_module_probe(&rpp->post.ltmmeas, rpp, &rppx1_ltmmeas_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_LTM_MEAS_BASE) ||
> +	    rpp_module_probe(&rpp->post.wbmeas, rpp, &rppx1_wbmeas_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_WBMEAS_BASE) ||
> +	    rpp_module_probe(&rpp->post.bdrgb, rpp, &rppx1_bdrgb_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_BDRGB_BASE) ||
> +	    rpp_module_probe(&rpp->post.shrp, rpp, &rppx1_shrp_ops,
> +			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_SHRP_BASE))
> +		goto err;
> +
> +	/* Probe the Human Vision pipeline. */
> +	if (rpp_module_probe(&rpp->hv.ga, rpp, &rppx1_ga_ops,
> +			     RPPX1_RPP_OUT_BASE + RPPX1_GAMMA_OUT_BASE) ||
> +	    rpp_module_probe(&rpp->hv.is, rpp, &rppx1_is_ops,
> +			     RPPX1_RPP_OUT_BASE + RPPX1_IS_BASE) ||
> +	    rpp_module_probe(&rpp->hv.ccor, rpp, &rppx1_ccor_csm_ops,
> +			     RPPX1_RPP_OUT_BASE + RPPX1_CSM_BASE) ||
> +	    rpp_module_probe(&rpp->hv.outif, rpp, &rppx1_outif_ops,
> +			     RPPX1_RPP_OUT_BASE + RPPX1_OUT_IF_BASE) ||
> +	    rpp_module_probe(&rpp->hv.outregs, rpp, &rppx1_outregs_ops,
> +			     RPPX1_RPP_OUT_BASE + RPPX1_RPP_OUTREGS_BASE))
> +		goto err;
> +
> +	/* Probe the Machine Vision pipeline. */
> +	if (rpp_module_probe(&rpp->mv.ga, rpp, &rppx1_ga_ops,
> +			     RPPX1_RPP_MVOUT_BASE + RPPX1_GAMMA_OUT_BASE) ||
> +	    rpp_module_probe(&rpp->mv.is, rpp, &rppx1_is_ops,
> +			     RPPX1_RPP_MVOUT_BASE + RPPX1_IS_BASE) ||
> +	    rpp_module_probe(&rpp->mv.ccor, rpp, &rppx1_ccor_csm_ops,
> +			     RPPX1_RPP_MVOUT_BASE + RPPX1_CSM_BASE) ||
> +	    rpp_module_probe(&rpp->mv.outif, rpp, &rppx1_outif_ops,
> +			     RPPX1_RPP_MVOUT_BASE + RPPX1_OUT_IF_BASE) ||
> +	    rpp_module_probe(&rpp->mv.outregs, rpp, &rppx1_outregs_ops,
> +			     RPPX1_RPP_MVOUT_BASE + RPPX1_RPP_OUTREGS_BASE) ||
> +	    rpp_module_probe(&rpp->mv.xyz2luv, rpp, &rppx1_xyz2luv_ops,
> +			     RPPX1_RPP_MVOUT_BASE + RPPX1_LUV_BASE))
> +		goto err;
> +
> +	/* Probe the standalone Radiance Mapping modules. */
> +	if (rpp_module_probe(&rpp->rmap, rpp, &rppx1_rmap_ops,
> +			     RPPX1_RPP_RMAP_BASE) ||
> +	    rpp_module_probe(&rpp->rmapmeas, rpp, &rppx1_rmapmeas_ops,
> +			     RPPX1_RPP_RMAP_MEAS_BASE))
> +		goto err;

Should we only probe the modules we currently support with params and
stats ?

> +
> +	return rpp;
> +err:
> +	rppx1_destroy(rpp);
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(rppx1_create);
> +
> +int rppx1_start(struct rppx1 *rpp,
> +		const struct v4l2_mbus_framefmt *input,
> +		const struct v4l2_mbus_framefmt *hv,
> +		const struct v4l2_mbus_framefmt *mv)
> +{
> +	if (rpp_module_call(&rpp->pre1.acq, start, input) ||
> +	    rpp_module_call(&rpp->pre1.bls, start, input) ||
> +	    rpp_module_call(&rpp->pre1.lin, start, input) ||
> +	    rpp_module_call(&rpp->pre1.lsc, start, input) ||
> +	    rpp_module_call(&rpp->pre1.awbg, start, input) ||
> +	    rpp_module_call(&rpp->pre1.dpcc, start, input) ||
> +	    rpp_module_call(&rpp->pre1.bd, start, input) ||
> +	    rpp_module_call(&rpp->pre1.hist, start, input) ||
> +	    rpp_module_call(&rpp->pre1.exm, start, input) ||
> +	    rpp_module_call(&rpp->pre1.hist256, start, input))
> +		return -EINVAL;
> +
> +	if (rpp_module_call(&rpp->rmap, start, NULL) ||
> +	    rpp_module_call(&rpp->rmapmeas, start, NULL))
> +		return -EINVAL;
> +
> +	if (rpp_module_call(&rpp->post.awbg, start, input) ||
> +	    rpp_module_call(&rpp->post.db, start, input) ||
> +	    rpp_module_call(&rpp->post.cac, start, input) ||
> +	    rpp_module_call(&rpp->post.ccor, start, input) ||
> +	    rpp_module_call(&rpp->post.ltm, start, input) ||
> +	    rpp_module_call(&rpp->post.bdrgb, start, input) ||
> +	    rpp_module_call(&rpp->post.shrp, start, input) ||
> +	    rpp_module_call(&rpp->post.ltmmeas, start, input) ||
> +	    rpp_module_call(&rpp->post.wbmeas, start, input) ||
> +	    rpp_module_call(&rpp->post.hist, start, input))
> +		return -EINVAL;
> +
> +	if (hv && (rpp_module_call(&rpp->hv.ga, start, hv) ||
> +		   rpp_module_call(&rpp->hv.ccor, start, hv) ||
> +		   rpp_module_call(&rpp->hv.outregs, start, hv) ||
> +		   rpp_module_call(&rpp->hv.is, start, hv) ||
> +		   rpp_module_call(&rpp->hv.outif, start, hv)))
> +		return -EINVAL;
> +
> +	if (mv && (rpp_module_call(&rpp->mv.ga, start, mv) ||
> +		   rpp_module_call(&rpp->mv.ccor, start, mv) ||
> +		   rpp_module_call(&rpp->mv.xyz2luv, start, mv) ||
> +		   rpp_module_call(&rpp->mv.outregs, start, mv) ||
> +		   rpp_module_call(&rpp->mv.is, start, mv) ||
> +		   rpp_module_call(&rpp->mv.outif, start, mv)))
> +		return -EINVAL;
> +
> +	rppx1_write(rpp, RPPX1_RPP_HDR_UPD_REG, 0x00000001);
> +
> +	/* Clear fault interrupts. */
> +	rppx1_write(rpp, RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_REG, 0x00000001);
> +	rppx1_write(rpp, RPPX1_RPP_HDR_FMU_FSM, 0x000001c0);
> +	rppx1_write(rpp, RPPX1_RPP_HDR_FMU_FSC, rppx1_read(rpp, RPPX1_RPP_HDR_FMU_MFS));
> +	rppx1_write(rpp, RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_REG, 0x00000000);
> +
> +	/* Set interrupt mask. */
> +	rppx1_write(rpp, RPPX1_RPP_ISM, RPPX1_IRQ_ID_OUT_FRAME);
> +
> +	rppx1_write(rpp, RPPX1_RPP_HDR_UPD_REG, 0x00000001);
> +	rppx1_write(rpp, RPPX1_RPP_HDR_UPD_REG, 0x00000002);
> +
> +	/* Clear any pending interrupts. */
> +	rppx1_interrupt(rpp, NULL);
> +
> +	/* Enable input formatters. */
> +	rppx1_write(rpp, RPPX1_RPP_HDR_INFORM_ENABLE_REG, 1);

Should magic numbers be replaced with macros ?

> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(rppx1_start);
> +
> +int rppx1_stop(struct rppx1 *rpp)
> +{
> +	/* Disable input formatters. */
> +	rppx1_write(rpp, RPPX1_RPP_HDR_INFORM_ENABLE_REG, 0);
> +
> +	/* Clear any pending interrupts. */
> +	rppx1_interrupt(rpp, NULL);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(rppx1_stop);
> +
> +MODULE_AUTHOR("Niklas Söderlund <niklas.soderlund@ragnatech.se>");
> +MODULE_DESCRIPTION("Dreamchip HDR RPPX1 support library");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1.h b/drivers/media/platform/dreamchip/rppx1/rppx1.h
> new file mode 100644
> index 000000000000..dcf43826d308
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1.h
> @@ -0,0 +1,99 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef __MEDIA_RPPX1_H__
> +#define __MEDIA_RPPX1_H__
> +
> +#include <linux/types.h>
> +
> +#include "rpp_module.h"
> +
> +#define RPPX1_IRQ_ID_256HIST			BIT(27)
> +#define RPPX1_IRQ_ID_PRE2_DPCC			BIT(25)
> +#define RPPX1_IRQ_ID_PRE1_DPCC			BIT(24)
> +#define RPPX1_IRQ_ID_MV_OUT_FRAME_OUT		BIT(23)
> +#define RPPX1_IRQ_ID_MV_OUT_OFF			BIT(22)
> +#define RPPX1_IRQ_ID_POST_AWB_MEAS		BIT(21)
> +#define RPPX1_IRQ_ID_POST_HIST_MEAS		BIT(20)
> +#define RPPX1_IRQ_ID_POST_TM			BIT(19)
> +#define RPPX1_IRQ_ID_PRE1_EXM			BIT(18)
> +#define RPPX1_IRQ_ID_PRE1_HIST			BIT(17)
> +#define RPPX1_IRQ_ID_PRE1_FRAME_IN		BIT(16)
> +#define RPPX1_IRQ_ID_PRE1_HSTART		BIT(15)
> +#define RPPX1_IRQ_ID_PRE1_VSTART		BIT(14)
> +#define RPPX1_IRQ_ID_PRE2_EXM			BIT(13)
> +#define RPPX1_IRQ_ID_PRE2_HIST			BIT(12)
> +#define RPPX1_IRQ_ID_PRE2_FRAME_IN		BIT(11)
> +#define RPPX1_IRQ_ID_PRE2_HSTART		BIT(10)
> +#define RPPX1_IRQ_ID_PRE2_VSTART		BIT(9)
> +#define RPPX1_IRQ_ID_OUT_FRAME			BIT(3)
> +#define RPPX1_IRQ_ID_OUT_OFF			BIT(2)
> +#define RPPX1_IRQ_ID_RMAP_MEAS			BIT(1)
> +#define RPPX1_IRQ_ID_RMAP_DONE			BIT(0)
> +
> +struct rppx1 {
> +	struct device *dev;

#include <linux/device.h>

> +	void __iomem *base;

Does __iomem come from
#include <linux/compiler_types.h> ?

> +
> +	struct {
> +		struct rpp_module acq;
> +		struct rpp_module bls;
> +		struct rpp_module lin;
> +		struct rpp_module lsc;
> +		struct rpp_module awbg;
> +		struct rpp_module dpcc;
> +		struct rpp_module bd;
> +		struct rpp_module hist;
> +		struct rpp_module hist256;
> +		struct rpp_module exm;
> +	} pre1;
> +
> +	struct {
> +		struct rpp_module acq;
> +		struct rpp_module bls;
> +		struct rpp_module lin;
> +		struct rpp_module lsc;
> +		struct rpp_module awbg;
> +		struct rpp_module dpcc;
> +		struct rpp_module bd;
> +		struct rpp_module hist;
> +		struct rpp_module exm;
> +	} pre2;
> +
> +	struct {
> +		struct rpp_module awbg;
> +		struct rpp_module ccor;
> +		struct rpp_module hist;
> +		struct rpp_module db;
> +		struct rpp_module cac;
> +		struct rpp_module ltm;
> +		struct rpp_module ltmmeas;
> +		struct rpp_module wbmeas;
> +		struct rpp_module bdrgb;
> +		struct rpp_module shrp;
> +	} post;
> +
> +	struct {
> +		struct rpp_module ga;
> +		struct rpp_module is;
> +		struct rpp_module ccor;
> +		struct rpp_module outif;
> +		struct rpp_module outregs;
> +	} hv;
> +
> +	struct {
> +		struct rpp_module ga;
> +		struct rpp_module is;
> +		struct rpp_module ccor;
> +		struct rpp_module outif;
> +		struct rpp_module outregs;
> +		struct rpp_module xyz2luv;
> +	} mv;
> +
> +	struct rpp_module rmap;
> +	struct rpp_module rmapmeas;
> +};
> +
> +void rppx1_write(struct rppx1 *rpp, u32 offset, u32 value);
> +u32 rppx1_read(struct rppx1 *rpp, u32 offset);
> +
> +#endif /* __MEDIA_RPPX1_H__ */
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_acq.c b/drivers/media/platform/dreamchip/rppx1/rppx1_acq.c
> new file mode 100644
> index 000000000000..45f619ccb684
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_acq.c
> @@ -0,0 +1,147 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define ACQ_VERSION_REG				0x0000
> +
> +#define ACQ_CTRL_REG				0x0004
> +#define ACQ_CTRL_ALTERNATIVE_CFG_MODE_ENABLE	BIT(8)
> +#define ACQ_CTRL_RPP_MODE_MASK			GENMASK(3, 1)
> +#define ACQ_CTRL_RPP_MODE_RAWBT601		(0 << 1)
> +#define ACQ_CTRL_RPP_MODE_BT656			(1 << 1)
> +#define ACQ_CTRL_RPP_MODE_BT601			(2 << 1)
> +#define ACQ_CTRL_RPP_MODE_BAYER			(3 << 1)
> +#define ACQ_CTRL_RPP_MODE_DATA			(4 << 1)
> +#define ACQ_CTRL_RPP_MODE_BAYERRGB		(5 << 1)
> +#define ACQ_CTRL_RPP_MODE_RAWBT656		(6 << 1)
> +#define ACQ_CTRL_INFORM_EN_ENABLE		BIT(0)
> +
> +#define ACQ_PROP_REG				0x0008
> +
> +#define ACQ_PROP_SENSOR_IN_LSB_ALIGNED_IN_LSB	BIT(30)
> +#define ACQ_PROP_YUV_OUT_SEL			BIT(25)
> +#define ACQ_PROP_MUX_DMA_SEL			BIT(24)
> +#define ACQ_PROP_SECOND_INPUT_TYPE		BIT(18)
> +#define ACQ_PROP_LATENCY_FIFO_INPUT_SELECTION	BIT(15)
> +#define ACQ_PROP_INPUT_SELECTION_MASK		GENMASK(14, 12)
> +#define ACQ_PROP_INPUT_SELECTION_8BIT		(0 << 12)
> +#define ACQ_PROP_INPUT_SELECTION_10BIT		(1 << 12)
> +#define ACQ_PROP_INPUT_SELECTION_12BIT		(2 << 12)
> +#define ACQ_PROP_BAYER_PAT_MASK			GENMASK(4, 3)
> +#define ACQ_PROP_BAYER_PAT_RGRG			(0 << 3)
> +#define ACQ_PROP_BAYER_PAT_GRGR			(1 << 3)
> +#define ACQ_PROP_BAYER_PAT_GBGB			(2 << 3)
> +#define ACQ_PROP_BAYER_PAT_BGBG			(3 << 3)
> +#define ACQ_PROP_VSYNC_POL			BIT(2)
> +#define ACQ_PROP_HSYNC_POL			BIT(1)
> +#define ACQ_PROP_SAMPLE_EDGE			BIT(0)
> +
> +#define ACQ_H_OFFS_REG				0x000c
> +#define ACQ_V_OFFS_REG				0x0010
> +#define ACQ_H_SIZE_REG				0x0014
> +#define ACQ_V_SIZE_REG				0x0018
> +#define ACQ_OUT_H_OFFS_REG			0x001c
> +#define ACQ_OUT_V_OFFS_REG			0x0020
> +#define ACQ_OUT_H_SIZE_REG			0x0024
> +#define ACQ_OUT_V_SIZE_REG			0x0028
> +#define FLAGS_SHD_REG				0x002c
> +#define ACQ_OUT_H_OFFS_SHD_REG			0x0030
> +#define ACQ_OUT_V_OFFS_SHD_REG			0x0034
> +#define ACQ_OUT_H_SIZE_SHD_REG			0x0038
> +#define ACQ_OUT_V_SIZE_SHD_REG			0x003c
> +
> +static int rppx1_acq_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, ACQ_VERSION_REG) != 0x0b)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int rppx1_acq_start(struct rpp_module *mod,
> +			   const struct v4l2_mbus_framefmt *fmt)
> +{
> +	u32 bayerpat, selection;
> +
> +	rpp_module_clrset(mod, ACQ_CTRL_REG, ACQ_CTRL_RPP_MODE_MASK,
> +			  ACQ_CTRL_RPP_MODE_BAYER);
> +
> +	rpp_module_write(mod, ACQ_H_OFFS_REG, 0);
> +	rpp_module_write(mod, ACQ_V_OFFS_REG, 0);
> +	rpp_module_write(mod, ACQ_H_SIZE_REG, fmt->width);
> +	rpp_module_write(mod, ACQ_V_SIZE_REG, fmt->height);
> +	rpp_module_write(mod, ACQ_OUT_H_OFFS_REG, 0);
> +	rpp_module_write(mod, ACQ_OUT_V_OFFS_REG, 0);
> +	rpp_module_write(mod, ACQ_OUT_H_SIZE_REG, fmt->width);
> +	rpp_module_write(mod, ACQ_OUT_V_SIZE_REG, fmt->height);
> +
> +	switch (fmt->code) {
> +	case MEDIA_BUS_FMT_SBGGR8_1X8:
> +	case MEDIA_BUS_FMT_SBGGR10_1X10:
> +	case MEDIA_BUS_FMT_SBGGR12_1X12:
> +		mod->info.acq.raw_pattern = RPP_BGGR;
> +		bayerpat = ACQ_PROP_BAYER_PAT_BGBG;
> +		break;
> +	case MEDIA_BUS_FMT_SGBRG8_1X8:
> +	case MEDIA_BUS_FMT_SGBRG10_1X10:
> +	case MEDIA_BUS_FMT_SGBRG12_1X12:
> +		mod->info.acq.raw_pattern = RPP_GBRG;
> +		bayerpat = ACQ_PROP_BAYER_PAT_GBGB;
> +		break;
> +	case MEDIA_BUS_FMT_SGRBG8_1X8:
> +	case MEDIA_BUS_FMT_SGRBG10_1X10:
> +	case MEDIA_BUS_FMT_SGRBG12_1X12:
> +		mod->info.acq.raw_pattern = RPP_GRBG;
> +		bayerpat = ACQ_PROP_BAYER_PAT_GRGR;
> +		break;
> +	case MEDIA_BUS_FMT_SRGGB8_1X8:
> +	case MEDIA_BUS_FMT_SRGGB10_1X10:
> +	case MEDIA_BUS_FMT_SRGGB12_1X12:
> +		mod->info.acq.raw_pattern = RPP_RGGB;
> +		bayerpat = ACQ_PROP_BAYER_PAT_RGRG;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	switch (fmt->code) {
> +	case MEDIA_BUS_FMT_SBGGR8_1X8:
> +	case MEDIA_BUS_FMT_SGBRG8_1X8:
> +	case MEDIA_BUS_FMT_SGRBG8_1X8:
> +	case MEDIA_BUS_FMT_SRGGB8_1X8:
> +		selection = ACQ_PROP_INPUT_SELECTION_8BIT;
> +		break;
> +	case MEDIA_BUS_FMT_SBGGR10_1X10:
> +	case MEDIA_BUS_FMT_SGBRG10_1X10:
> +	case MEDIA_BUS_FMT_SGRBG10_1X10:
> +	case MEDIA_BUS_FMT_SRGGB10_1X10:
> +		selection = ACQ_PROP_INPUT_SELECTION_10BIT;
> +		break;
> +	case MEDIA_BUS_FMT_SBGGR12_1X12:
> +	case MEDIA_BUS_FMT_SGBRG12_1X12:
> +	case MEDIA_BUS_FMT_SGRBG12_1X12:
> +	case MEDIA_BUS_FMT_SRGGB12_1X12:
> +		selection = ACQ_PROP_INPUT_SELECTION_12BIT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	rpp_module_write(mod, ACQ_PROP_REG, bayerpat | selection |
> +			 ACQ_PROP_SENSOR_IN_LSB_ALIGNED_IN_LSB);
> +
> +	rpp_module_clrset(mod, ACQ_CTRL_REG, ACQ_CTRL_INFORM_EN_ENABLE,
> +			  ACQ_CTRL_INFORM_EN_ENABLE);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_acq_ops = {
> +	.probe = rppx1_acq_probe,
> +	.start = rppx1_acq_start,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_awbg.c b/drivers/media/platform/dreamchip/rppx1/rppx1_awbg.c
> new file mode 100644
> index 000000000000..e20bc369ca8c
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_awbg.c
> @@ -0,0 +1,30 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define AWB_GAIN_VERSION_REG		0x0000
> +
> +#define AWB_ENABLE_REG			0x0004
> +#define AWB_ENABLE_AWB_GAIN_EN		BIT(0)
> +
> +#define AWB_GAIN_GR_REG			0x0008
> +#define AWB_GAIN_GB_REG			0x000c
> +#define AWB_GAIN_R_REG			0x0010
> +#define AWB_GAIN_B_REG			0x0014
> +
> +static int rppx1_awbg_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, AWB_GAIN_VERSION_REG) != 3)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_awbg_ops = {
> +	.probe = rppx1_awbg_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_bd.c b/drivers/media/platform/dreamchip/rppx1/rppx1_bd.c
> new file mode 100644
> index 000000000000..acbfbcd59591
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_bd.c
> @@ -0,0 +1,52 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define DPF_VERSION_REG			0x0000
> +
> +#define DPF_MODE_REG			0x0004
> +#define DPF_MODE_USE_NF_GAIN		BIT(9)
> +#define DPF_MODE_LSC_GAIN_COMP		BIT(8)
> +#define DPF_MODE_NLL_SEGMENTATION	BIT(6)
> +#define DPF_MODE_RB_FILTER_SIZE		BIT(5)
> +#define DPF_MODE_R_FILTER_OFF		BIT(4)
> +#define DPF_MODE_GR_FILTER_OFF		BIT(3)
> +#define DPF_MODE_GB_FILTER_OFF		BIT(2)
> +#define DPF_MODE_B_FILTER_OFF		BIT(1)
> +#define DPF_MODE_DPF_ENABLE		BIT(0)
> +
> +#define DPF_STRENGTH_R_REG		0x0008
> +#define DPF_STRENGTH_G_REG		0x000c
> +#define DPF_STRENGTH_B_REG		0x0010
> +#define DPF_S_WEIGHT_G_1_4_REG		0x0014
> +#define DPF_S_WEIGHT_G_5_6_REG		0x0018
> +#define DPF_S_WEIGHT_RB_1_4_REG		0x001c
> +#define DPF_S_WEIGHT_RB_5_6_REG		0x0020
> +
> +#define DPF_NLL_G_COEFF_REG_NUM		17
> +#define DPF_NLL_G_COEFF_REG(n)		(0x0024 + (4 * (n)))
> +
> +#define DPF_NLL_RB_COEFF_REG_NUM	17
> +#define DPF_NLL_RB_COEFF_REG(n)		(0x0068 + (4 * (n)))
> +
> +#define DPF_NF_GAIN_R_REG		0x00ac
> +#define DPF_NF_GAIN_GR_REG		0x00b0
> +#define DPF_NF_GAIN_GB_REG		0x00b4
> +#define DPF_NF_GAIN_B_REG		0x00b8
> +
> +static int rppx1_bd_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, DPF_VERSION_REG) != 5)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_bd_ops = {
> +	.probe = rppx1_bd_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_bdrgb.c b/drivers/media/platform/dreamchip/rppx1/rppx1_bdrgb.c
> new file mode 100644
> index 000000000000..292f0b7bfd3f
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_bdrgb.c
> @@ -0,0 +1,80 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define RGBDENOISE_VERSION_REG					0x0000
> +
> +#define RGBDENOISE_HW_BYPASS_REG				0x0004
> +#define RGBDENOISE_HW_BYPASS_BYPASS_EN				BIT(0)
> +
> +#define RGBDENOISE_SPNR_CTRL_REG				0x0008
> +#define RGBDENOISE_SPNR_CTRL_C2NR_INTENSITY_SHIFT_C_MASK	GENMASK(11, 8)
> +#define RGBDENOISE_SPNR_CTRL_C2NR_INTENSITY_SHIFT_Y_MASK	GENMASK(7, 4)
> +#define RGBDENOISE_SPNR_CTRL_C2NR_EN				BIT(0)
> +
> +#define RGBDENOISE_SPNR_LUMA_IF_COEF_00_07_REG			0x000c
> +#define RGBDENOISE_SPNR_LUMA_IF_COEF_08_15_REG			0x0010
> +#define RGBDENOISE_SPNR_LUMA_IF_COEF_16_23_REG			0x0014
> +#define RGBDENOISE_SPNR_LUMA_IF_COEF_24_31_REG			0x0018
> +#define RGBDENOISE_SPNR_CHROMA_IF_COEF_00_07_REG		0x001c
> +#define RGBDENOISE_SPNR_CHROMA_IF_COEF_08_15_REG		0x0020
> +#define RGBDENOISE_SPNR_CHROMA_IF_COEF_16_23_REG		0x0024
> +#define RGBDENOISE_SPNR_CHROMA_IF_COEF_24_31_REG		0x0028
> +#define RGBDENOISE_SPNR_SPATIAL_COEF_0_3_REG			0x002c
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_0_REG			0x0030
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_1_REG			0x0034
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_2_REG			0x0038
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_3_REG			0x003c
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_4_REG			0x0040
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_5_REG			0x0044
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_6_REG			0x0048
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_7_REG			0x004c
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_8_REG			0x0050
> +#define RGBDENOISE_RGB2YUV_CCOR_OFFSET_R_REG			0x0054
> +#define RGBDENOISE_RGB2YUV_CCOR_OFFSET_G_REG			0x0058
> +#define RGBDENOISE_RGB2YUV_CCOR_OFFSET_B_REG			0x005c
> +#define RGBDENOISE_HW_BYPASS_SDW_REG				0x0060
> +#define RGBDENOISE_SPNR_CTRL_SDW_REG				0x0064
> +#define RGBDENOISE_SPNR_LUMA_IF_COEF_00_07_SDW_REG		0x0068
> +#define RGBDENOISE_SPNR_LUMA_IF_COEF_08_15_SDW_REG		0x006c
> +#define RGBDENOISE_SPNR_LUMA_IF_COEF_16_23_SDW_REG		0x0070
> +#define RGBDENOISE_SPNR_LUMA_IF_COEF_24_31_SDW_REG		0x0074
> +#define RGBDENOISE_SPNR_CHROMA_IF_COEF_00_07_SDW_REG		0x0078
> +#define RGBDENOISE_SPNR_CHROMA_IF_COEF_08_15_SDW_REG		0x007c
> +#define RGBDENOISE_SPNR_CHROMA_IF_COEF_16_23_SDW_REG		0x0080
> +#define RGBDENOISE_SPNR_CHROMA_IF_COEF_24_31_SDW_REG		0x0084
> +#define RGBDENOISE_SPNR_SPATIAL_COEFF_0_3_SDW_REG		0x0088
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_0_SDW_REG			0x008c
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_1_SDW_REG			0x0090
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_2_SDW_REG			0x0094
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_3_SDW_REG			0x0098
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_4_SDW_REG			0x009c
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_5_SDW_REG			0x00a0
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_6_SDW_REG			0x00a4
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_7_SDW_REG			0x00a8
> +#define RGBDENOISE_RGB2YUV_CCOR_COEFF_8_SDW_REG			0x00ac
> +#define RGBDENOISE_RGB2YUV_CCOR_OFFSET_R_SDW_REG		0x00b0
> +#define RGBDENOISE_RGB2YUV_CCOR_OFFSET_G_SDW_REG		0x00b4
> +#define RGBDENOISE_RGB2YUV_CCOR_OFFSET_B_SDW_REG		0x00b8
> +
> +static int rppx1_bdrgb_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, RGBDENOISE_VERSION_REG)) {
> +	case 6:
> +		mod->info.bdrgb.colorbits = 12;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_bdrgb_ops = {
> +	.probe = rppx1_bdrgb_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_bls.c b/drivers/media/platform/dreamchip/rppx1/rppx1_bls.c
> new file mode 100644
> index 000000000000..de7008befd8e
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_bls.c
> @@ -0,0 +1,59 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define BLS_VERSION_REG				0x0000
> +
> +#define BLS_CTRL_REG				0x0004
> +#define BLS_CTRL_BLS_WIN2			BIT(3)
> +#define BLS_CTRL_BLS_WIN1			BIT(2)
> +#define BLS_CTRL_BLS_MODE_MEASURED		BIT(1)
> +#define BLS_CTRL_BLS_EN				BIT(0)
> +
> +#define BLS_SAMPLES_REG				0x0008
> +#define BLS_H1_START_REG			0x000c
> +#define BLS_H1_STOP_REG				0x0010
> +#define BLS_V1_START_REG			0x0014
> +#define BLS_V1_STOP_REG				0x0018
> +#define BLS_H2_START_REG			0x001c
> +#define BLS_H2_STOP_REG				0x0020
> +#define BLS_V2_START_REG			0x0024
> +#define BLS_V2_STOP_REG				0x0028
> +#define BLS_A_FIXED_REG				0x002c
> +#define BLS_B_FIXED_REG				0x0030
> +#define BLS_C_FIXED_REG				0x0034
> +#define BLS_D_FIXED_REG				0x0038
> +#define BLS_A_MEASURED_REG			0x003c
> +#define BLS_B_MEASURED_REG			0x0040
> +#define BLS_C_MEASURED_REG			0x0044
> +#define BLS_D_MEASURED_REG			0x0048
> +
> +static int rppx1_bls_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, BLS_VERSION_REG)) {
> +	case 3:
> +	case 5:
> +		mod->info.bls.colorbits = 12;
> +		break;
> +	case 2:
> +	case 4:
> +		mod->info.bls.colorbits = 20;
> +		break;
> +	case 6:
> +		mod->info.bls.colorbits = 24;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_bls_ops = {
> +	.probe = rppx1_bls_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_cac.c b/drivers/media/platform/dreamchip/rppx1/rppx1_cac.c
> new file mode 100644
> index 000000000000..5ed8c60982ba
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_cac.c
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define CAC_VERSION_REG			0x0000
> +#define CAC_CTRL_REG			0x0004
> +#define CAC_COUNT_START_REG		0x0008
> +#define CAC_A_REG			0x000c
> +#define CAC_B_REG			0x0010
> +#define CAC_C_REG			0x0014
> +#define CAC_X_NORM_REG			0x0018
> +#define CAC_Y_NORM_REG			0x001c
> +
> +static int rppx1_cac_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, CAC_VERSION_REG) != 3)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_cac_ops = {
> +	.probe = rppx1_cac_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_ccor.c b/drivers/media/platform/dreamchip/rppx1/rppx1_ccor.c
> new file mode 100644
> index 000000000000..4754b0bbce0a
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_ccor.c
> @@ -0,0 +1,106 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define CCOR_VERSION_REG				0x0000
> +
> +#define CCOR_COEFF_REG_NUM				9
> +#define CCOR_COEFF_REG(n)				(0x0004 + (4 * (n)))
> +
> +#define CCOR_OFFSET_R_REG				0x0028
> +#define CCOR_OFFSET_G_REG				0x002c
> +#define CCOR_OFFSET_B_REG				0x0030
> +
> +#define CCOR_CONFIG_TYPE_REG				0x0034
> +#define CCOR_CONFIG_TYPE_USE_OFFSETS_AS_PRE_OFFSETS	BIT(1)
> +#define CCOR_CONFIG_TYPE_CCOR_RANGE_AVAILABLE		BIT(0)
> +
> +#define CCOR_RANGE_REG					0x0038
> +#define CCOR_RANGE_CCOR_C_RANGE				BIT(1)
> +#define CCOR_RANGE_CCOR_Y_RANGE				BIT(0)
> +
> +static int rppx1_ccor_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, CCOR_VERSION_REG)) {
> +	case 3:
> +		mod->info.ccor.colorbits = 12;
> +		break;
> +	case 4:
> +		mod->info.ccor.colorbits = 20;
> +		break;
> +	case 5:
> +		mod->info.ccor.colorbits = 24;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	mod->info.ccor.type = rpp_module_read(mod, CCOR_CONFIG_TYPE_REG);
> +
> +	return 0;
> +}
> +
> +static int rppx1_ccor_start(struct rpp_module *mod,
> +			    const struct v4l2_mbus_framefmt *fmt)
> +{
> +	/* Configure matrix in bypass mode. */
> +	rpp_module_write(mod, CCOR_COEFF_REG(0), 0x1000);
> +	rpp_module_write(mod, CCOR_COEFF_REG(1), 0x0000);
> +	rpp_module_write(mod, CCOR_COEFF_REG(2), 0x0000);
> +
> +	rpp_module_write(mod, CCOR_COEFF_REG(3), 0x0000);
> +	rpp_module_write(mod, CCOR_COEFF_REG(4), 0x1000);
> +	rpp_module_write(mod, CCOR_COEFF_REG(5), 0x0000);
> +
> +	rpp_module_write(mod, CCOR_COEFF_REG(6), 0x0000);
> +	rpp_module_write(mod, CCOR_COEFF_REG(7), 0x0000);
> +	rpp_module_write(mod, CCOR_COEFF_REG(8), 0x1000);
> +
> +	rpp_module_write(mod, CCOR_OFFSET_R_REG, 0x00000000);
> +	rpp_module_write(mod, CCOR_OFFSET_G_REG, 0x00000000);
> +	rpp_module_write(mod, CCOR_OFFSET_B_REG, 0x00000000);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_ccor_ops = {
> +	.probe = rppx1_ccor_probe,
> +	.start = rppx1_ccor_start,
> +};
> +
> +static int rppx1_ccor_csm_start(struct rpp_module *mod,
> +				const struct v4l2_mbus_framefmt *fmt)
> +{
> +	/* Reuse bypass matrix setup. */
> +	if (fmt->code == MEDIA_BUS_FMT_RGB888_1X24)
> +		return rppx1_ccor_start(mod, fmt);
> +
> +	/* Color Transformation RGB to YUV according to ITU-R BT.709. */
> +	rpp_module_write(mod, CCOR_COEFF_REG(0), 0x0367);
> +	rpp_module_write(mod, CCOR_COEFF_REG(1), 0x0b71);
> +	rpp_module_write(mod, CCOR_COEFF_REG(2), 0x0128);
> +
> +	rpp_module_write(mod, CCOR_COEFF_REG(3), 0xfe2b);
> +	rpp_module_write(mod, CCOR_COEFF_REG(4), 0xf9d5);
> +	rpp_module_write(mod, CCOR_COEFF_REG(5), 0x0800);
> +
> +	rpp_module_write(mod, CCOR_COEFF_REG(6), 0x0800);
> +	rpp_module_write(mod, CCOR_COEFF_REG(7), 0xf8bc);
> +	rpp_module_write(mod, CCOR_COEFF_REG(8), 0xff44);
> +
> +	rpp_module_write(mod, CCOR_OFFSET_R_REG, 0x00000000);
> +	rpp_module_write(mod, CCOR_OFFSET_G_REG, 0x00000800);
> +	rpp_module_write(mod, CCOR_OFFSET_B_REG, 0x00000800);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_ccor_csm_ops = {
> +	.probe = rppx1_ccor_probe,
> +	.start = rppx1_ccor_csm_start,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_db.c b/drivers/media/platform/dreamchip/rppx1/rppx1_db.c
> new file mode 100644
> index 000000000000..5e233896cfc8
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_db.c
> @@ -0,0 +1,44 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define FILT_VERSION_REG		0x0000
> +
> +#define DEMOSAIC_REG			0x0004
> +#define DEMOSAIC_DEMOSAIC_BYPASS	BIT(16)
> +#define DEMOSAIC_DEMOSAIC_TH_MASK	GENMASK(15, 0)
> +
> +#define FILT_MODE_REG			0x0008
> +#define FILT_MODE_FILT_LP_SELECT_MASK	GENMASK(11, 8)
> +#define FILT_MODE_FILT_CHR_H_MODE_MASK	GENMASK(7, 6)
> +#define FILT_MODE_FILT_CHR_V_MODE_MASK	GENMASK(5, 4)
> +#define FILT_MODE_FILT_MODE		BIT(1)
> +#define FILT_MODE_FILT_ENABLE		BIT(0)
> +
> +#define FILT_THRESH_BL0_REG		0x000c
> +#define FILT_THRESH_BL1_REG		0x0010
> +#define FILT_THRESH_SH0_REG		0x0014
> +#define FILT_THRESH_SH1_REG		0x0018
> +#define FILT_LUM_WEIGHT_REG		0x001c
> +#define FILT_FAC_SH1_REG		0x0020
> +#define FILT_FAC_SH0_REG		0x0024
> +#define FILT_FAC_MID_REG		0x0028
> +#define FILT_FAC_BL0_REG		0x002c
> +#define FILT_FAC_BL1_REG		0x0030
> +
> +static int rppx1_db_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, FILT_VERSION_REG) != 5)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_db_ops = {
> +	.probe = rppx1_db_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_dpcc.c b/drivers/media/platform/dreamchip/rppx1/rppx1_dpcc.c
> new file mode 100644
> index 000000000000..ae0b65976452
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_dpcc.c
> @@ -0,0 +1,76 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define DPCC_VERSION_REG			0x0000
> +
> +#define DPCC_MODE_REG				0x0004
> +#define DPCC_MODE_STAGE1_ENABLE			BIT(2)
> +#define DPCC_MODE_GRAYSCALE_MODE		BIT(1)
> +#define DPCC_MODE_DPCC_ENABLE			BIT(0)
> +
> +#define DPCC_OUTPUT_MODE_REG			0x0008
> +#define DPCC_SET_USE_REG			0x000c
> +#define DPCC_METHODS_SET_1_REG			0x0010
> +#define DPCC_METHODS_SET_2_REG			0x0014
> +#define DPCC_METHODS_SET_3_REG			0x0018
> +#define DPCC_LINE_THRESH_1_REG			0x001c
> +#define DPCC_LINE_MAD_FAC_1_REG			0x0020
> +#define DPCC_PG_FAC_1_REG			0x0024
> +#define DPCC_RND_THRESH_1_REG			0x0028
> +#define DPCC_RG_FAC_1_REG			0x002c
> +#define DPCC_LINE_THRESH_2_REG			0x0030
> +#define DPCC_LINE_MAD_FAC_2_REG			0x0034
> +#define DPCC_PG_FAC_2_REG			0x0038
> +#define DPCC_RND_THRESH_2_REG			0x003c
> +#define DPCC_RG_FAC_2_REG			0x0040
> +#define DPCC_LINE_THRESH_3_REG			0x0044
> +#define DPCC_LINE_MAD_FAC_3_REG			0x0048
> +#define DPCC_PG_FAC_3_REG			0x004c
> +#define DPCC_RND_THRESH_3_REG			0x0050
> +#define DPCC_RG_FAC_3_REG			0x0054
> +#define DPCC_RO_LIMITS_REG			0x0058
> +#define DPCC_RND_OFFS_REG			0x005c
> +#define DPCC_BPT_CTRL_REG			0x0060
> +#define DPCC_BP_NUMBER_REG			0x0064
> +#define DPCC_BP_TADDR_REG			0x0068
> +#define DPCC_BP_POSITION_REG			0x006c
> +
> +static int rppx1_dpcc_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, DPCC_VERSION_REG)) {
> +	case 2:
> +	case 4:
> +	case 6:
> +		mod->info.dpcc.colorbits = 12;
> +		break;
> +	case 3:
> +	case 5:
> +	case 7:
> +		mod->info.dpcc.colorbits = 24;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}

Here and in all other modules, now that userspace is expected to
perform the right shifting by itself, 'colorbits' is probably not
needed anymore in any module.

> +
> +	return 0;
> +}
> +
> +static int rppx1_dpcc_start(struct rpp_module *mod,
> +			    const struct v4l2_mbus_framefmt *fmt)
> +{
> +	/* Bypass stage1 and DPCC. */
> +	rpp_module_write(mod, DPCC_MODE_REG, 0);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_dpcc_ops = {
> +	.probe = rppx1_dpcc_probe,
> +	.start = rppx1_dpcc_start,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_exm.c b/drivers/media/platform/dreamchip/rppx1/rppx1_exm.c
> new file mode 100644
> index 000000000000..0c40300e13ad
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_exm.c
> @@ -0,0 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define EXM_VERSION_REG			0x0000
> +#define EXM_START_REG			0x0004
> +
> +#define EXM_CTRL_REG			0x0008
> +#define EXM_CTRL_EXM_UPDATE_ENABLE	BIT(0)
> +
> +#define EXM_MODE_REG			0x000c
> +#define EXM_CHANNEL_SEL_REG		0x0010
> +#define EXM_LAST_MEAS_LINE_REG		0x0014
> +#define EXM_COEFF_R_REG			0x0018
> +#define EXM_COEFF_G_GR_REG		0x001c
> +#define EXM_COEFF_B_REG			0x0020
> +#define EXM_COEFF_GB_REG		0x0024
> +#define EXM_H_OFFS_REG			0x0028
> +#define EXM_V_OFFS_REG			0x002c
> +#define EXM_H_SIZE_REG			0x0030
> +#define EXM_V_SIZE_REG			0x0034
> +#define EXM_FORCED_UPD_START_LINE_REG	0x0038
> +#define EXM_VSTART_STATUS_REG		0x003c
> +
> +#define EXM_MEAN_REG_NUM		25
> +#define EXM_MEAN_REG(n)			(0x0040 + (4 * (n)))
> +
> +static int rppx1_exm_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, EXM_VERSION_REG)) {
> +	case 1:
> +		mod->info.exm.resultbits = 8;
> +		break;
> +	case 3:
> +		mod->info.exm.resultbits = 20;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_exm_ops = {
> +	.probe = rppx1_exm_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_ga.c b/drivers/media/platform/dreamchip/rppx1/rppx1_ga.c
> new file mode 100644
> index 000000000000..d6c7f951cf29
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_ga.c
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define GAMMA_OUT_VERSION_REG			0x0000
> +
> +#define GAMMA_OUT_ENABLE_REG			0x0004
> +#define GAMMA_OUT_ENABLE_GAMMA_OUT_EN		BIT(0)
> +
> +#define GAMMA_OUT_MODE_REG			0x0008
> +#define GAMMA_OUT_MODE_GAMMA_OUT_EQU_SEGM	BIT(0)
> +
> +#define GAMMA_OUT_Y_REG_NUM			17
> +#define GAMMA_OUT_Y_REG(n)			(0x000c + (4 * (n)))
> +
> +static int rppx1_ga_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, GAMMA_OUT_VERSION_REG)) {
> +	case 1:
> +		mod->info.ga.colorbits = 12;
> +		break;
> +	case 2:
> +		mod->info.ga.colorbits = 24;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rppx1_ga_start(struct rpp_module *mod,
> +			  const struct v4l2_mbus_framefmt *fmt)
> +{
> +	/* Disable stage. */
> +	rpp_module_write(mod, GAMMA_OUT_ENABLE_REG, 0);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_ga_ops = {
> +	.probe = rppx1_ga_probe,
> +	.start = rppx1_ga_start,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_hist.c b/drivers/media/platform/dreamchip/rppx1/rppx1_hist.c
> new file mode 100644
> index 000000000000..cab498ece5a8
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_hist.c
> @@ -0,0 +1,76 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define HIST_VERSION_REG			0x0000
> +
> +#define HIST_CTRL_REG				0x0004
> +#define HIST_CTRL_HIST_UPDATE_ENABLE		BIT(0)
> +
> +#define HIST_MODE_REG				0x0008
> +#define HIST_MODE_HIST_MODE_MASK		GENMASK(2, 0)
> +#define HIST_MODE_HIST_MODE_DISABLE		0
> +#define HIST_MODE_HIST_MODE_YRGB		1
> +#define HIST_MODE_HIST_MODE_R			2
> +#define HIST_MODE_HIST_MODE_GR			3
> +#define HIST_MODE_HIST_MODE_B			4
> +#define HIST_MODE_HIST_MODE_GB			5
> +
> +#define HIST_CHANNEL_SEL_REG			0x000c
> +#define HIST_CHANNEL_SEL_CHANNEL_SELECT_MASK	GENMASK(2, 0)
> +
> +#define HIST_LAST_MEAS_LINE_REG			0x0010
> +#define HIST_SUBSAMPLING_REG			0x0014
> +#define HIST_COEFF_R_REG			0x0018
> +#define HIST_COEFF_G_REG			0x001c
> +#define HIST_COEFF_B_REG			0x0020
> +#define HIST_H_OFFS_REG				0x0024
> +#define HIST_V_OFFS_REG				0x0028
> +#define HIST_H_SIZE_REG				0x002c
> +#define HIST_V_SIZE_REG				0x0030
> +
> +#define HIST_SAMPLE_RANGE_REG			0x0034
> +#define HIST_SAMPLE_RANGE_SAMPLE_SHIFT_MASK	GENMASK(28, 24)
> +#define HIST_SAMPLE_RANGE_SAMPLE_OFFSET_MASK	GENMASK(23, 0)
> +
> +#define HIST_WEIGHT_00TO30_REG			0x0038
> +#define HIST_WEIGHT_40TO21_REG			0x003c
> +#define HIST_WEIGHT_31TO12_REG			0x0040
> +#define HIST_WEIGHT_22TO03_REG			0x0044
> +#define HIST_WEIGHT_13TO43_REG			0x0048
> +#define HIST_WEIGHT_04TO34_REG			0x004c
> +#define HIST_WEIGHT_44_REG			0x0050
> +#define HIST_FORCED_UPD_START_LINE_REG		0x0054
> +#define HIST_FORCED_UPDATE_REG			0x0058
> +#define HIST_VSTART_STATUS_REG			0x005c
> +
> +#define HIST_BIN_REG_NUM			32
> +#define HIST_BIN_REG(n)				(0x0060 + (4 * (n)))
> +
> +static int rppx1_hist_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, HIST_VERSION_REG)) {
> +	case 3:
> +		mod->info.hist.colorbits = 12;
> +		break;
> +	case 4:
> +		mod->info.hist.colorbits = 20;
> +		break;
> +	case 5:
> +		mod->info.hist.colorbits = 24;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_hist_ops = {
> +	.probe = rppx1_hist_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_hist256.c b/drivers/media/platform/dreamchip/rppx1/rppx1_hist256.c
> new file mode 100644
> index 000000000000..5b846b415a49
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_hist256.c
> @@ -0,0 +1,46 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define HIST256_VERSION_REG			0x0000
> +#define HIST256_MODE_REG			0x0004
> +#define HIST256_MODE_HIST256_MODE		BIT(0)
> +
> +#define HIST256_CHANNEL_SEL_REG			0x0008
> +#define HIST256_CHANNEL_SEL_CHANNEL_SELECT	GENMASK(2, 0)
> +
> +#define HIST256_H_OFFS_REG			0x000c
> +#define HIST256_V_OFFS_REG			0x0010
> +#define HIST256_H_SIZE_REG			0x0014
> +#define HIST256_V_SIZE_REG			0x0018
> +#define HIST256_SAMPLE_OFFSET_REG		0x001c
> +#define HIST256_SAMPLE_SCALE_REG		0x0020
> +#define HIST256_MEAS_RESULT_ADDR_AUTOINCR_REG	0x0024
> +#define HIST256_MEAS_RESULT_ADDR_REG		0x0028
> +#define HIST256_MEAS_RESULT_DATA_REG		0x002c
> +
> +#define HIST256_LOG_ENABLE_REG			0x0030
> +#define HIST256_LOG_ENABLE_HIST256_LOG_EN	BIT(0)
> +
> +#define HIST256_LOG_DX_LO_REG			0x0034
> +#define HIST256_LOG_DX_HI_REG			0x0038
> +
> +#define HIST256_Y_REG_NUM			17
> +#define HIST256_Y_REG(n)			(0x0040 + (4 * (n)))
> +
> +static int rppx1_hist256_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, HIST256_VERSION_REG) != 2)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_hist256_ops = {
> +	.probe = rppx1_hist256_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_is.c b/drivers/media/platform/dreamchip/rppx1/rppx1_is.c
> new file mode 100644
> index 000000000000..3637a2e677ca
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_is.c
> @@ -0,0 +1,42 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define IS_VERSION			0x0000
> +#define IS_H_OFFS			0x0008
> +#define IS_V_OFFS			0x000c
> +#define IS_H_SIZE			0x0010
> +#define IS_V_SIZE			0x0014
> +#define IS_H_OFFS_SHD			0x0024
> +#define IS_V_OFFS_SHD			0x0028
> +#define IS_H_SIZE_SHD			0x002c
> +#define IS_V_SIZE_SHD			0x0030
> +
> +static int rppx1_is_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, IS_VERSION) != 1)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int rppx1_is_start(struct rpp_module *mod,
> +			  const struct v4l2_mbus_framefmt *fmt)
> +{
> +	rpp_module_write(mod, IS_H_OFFS, 0);
> +	rpp_module_write(mod, IS_V_OFFS, 0);
> +	rpp_module_write(mod, IS_H_SIZE, fmt->width);
> +	rpp_module_write(mod, IS_V_SIZE, fmt->height);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_is_ops = {
> +	.probe = rppx1_is_probe,
> +	.start = rppx1_is_start,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_lin.c b/drivers/media/platform/dreamchip/rppx1/rppx1_lin.c
> new file mode 100644
> index 000000000000..f595f56a292e
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_lin.c
> @@ -0,0 +1,58 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +/* NOTE: The module is called LIN the registers GAMMA_IN. */
> +#define LIN_VERSION_REG				0x0000
> +
> +#define LIN_ENABLE_REG				0x0004
> +#define LIN_ENABLE_GAMMA_IN_EN			BIT(0)
> +
> +#define LIN_DX_LO_REG				0x0008
> +#define LIN_DX_HI_REG				0x000c
> +
> +#define LIN_R_Y_REG_NUM				17
> +#define LIN_R_Y_REG(n)				(0x0010 + (4 * (n)))
> +
> +#define LIN_G_Y_REG_NUM				17
> +#define LIN_G_Y_REG(n)				(0x0054 + (4 * (n)))
> +
> +#define LIN_B_Y_REG_NUM				17
> +#define LIN_B_Y_REG(n)				(0x0098 + (4 * (n)))
> +
> +static int rppx1_lin_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, LIN_VERSION_REG)) {
> +	case 7:
> +		mod->info.lin.colorbits = 12;
> +		break;
> +	case 8:
> +		mod->info.lin.colorbits = 20;
> +		break;
> +	case 9:
> +		mod->info.lin.colorbits = 24;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rppx1_lin_start(struct rpp_module *mod,
> +			   const struct v4l2_mbus_framefmt *fmt)
> +{
> +	rpp_module_clrset(mod, LIN_ENABLE_REG, LIN_ENABLE_GAMMA_IN_EN, 0);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_lin_ops = {
> +	.probe = rppx1_lin_probe,
> +	.start = rppx1_lin_start,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_lsc.c b/drivers/media/platform/dreamchip/rppx1/rppx1_lsc.c
> new file mode 100644
> index 000000000000..e8acdf744956
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_lsc.c
> @@ -0,0 +1,68 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define LSC_VERSION_REG		0x0000
> +
> +#define LSC_CTRL_REG		0x0004
> +#define LSC_CTRL_LSC_EN		BIT(0)
> +
> +#define LSC_R_TABLE_ADDR_REG	0x0008
> +#define LSC_GR_TABLE_ADDR_REG	0x000c
> +#define LSC_B_TABLE_ADDR_REG	0x0010
> +#define LSC_GB_TABLE_ADDR_REG	0x0014
> +#define LSC_R_TABLE_DATA_REG	0x0018
> +#define LSC_GR_TABLE_DATA_REG	0x001c
> +#define LSC_B_TABLE_DATA_REG	0x0020
> +#define LSC_GB_TABLE_DATA_REG	0x0024
> +#define LSC_XGRAD_01_REG	0x0028
> +#define LSC_XGRAD_23_REG	0x002c
> +#define LSC_XGRAD_45_REG	0x0030
> +#define LSC_XGRAD_67_REG	0x0034
> +#define LSC_XGRAD_89_REG	0x0038
> +#define LSC_XGRAD_1011_REG	0x003c
> +#define LSC_XGRAD_1213_REG	0x0040
> +#define LSC_XGRAD_1415_REG	0x0044
> +#define LSC_YGRAD_01_REG	0x0048
> +#define LSC_YGRAD_23_REG	0x004c
> +#define LSC_YGRAD_45_REG	0x0050
> +#define LSC_YGRAD_67_REG	0x0054
> +#define LSC_YGRAD_89_REG	0x0058
> +#define LSC_YGRAD_1011_REG	0x005c
> +#define LSC_YGRAD_1213_REG	0x0060
> +#define LSC_YGRAD_1415_REG	0x0064
> +#define LSC_XSIZE_01_REG	0x0068
> +#define LSC_XSIZE_23_REG	0x006c
> +#define LSC_XSIZE_45_REG	0x0070
> +#define LSC_XSIZE_67_REG	0x0074
> +#define LSC_XSIZE_89_REG	0x0078
> +#define LSC_XSIZE_1011_REG	0x007c
> +#define LSC_XSIZE_1213_REG	0x0080
> +#define LSC_XSIZE_1415_REG	0x0084
> +#define LSC_YSIZE_01_REG	0x0088
> +#define LSC_YSIZE_23_REG	0x008c
> +#define LSC_YSIZE_45_REG	0x0090
> +#define LSC_YSIZE_67_REG	0x0094
> +#define LSC_YSIZE_89_REG	0x0098
> +#define LSC_YSIZE_1011_REG	0x009c
> +#define LSC_YSIZE_1213_REG	0x00a0
> +#define LSC_YSIZE_1415_REG	0x00a4
> +#define LSC_TABLE_SEL_REG	0x00a8
> +#define LSC_STATUS_REG		0x00ac
> +
> +static int rppx1_lsc_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, LSC_VERSION_REG) != 0x04)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_lsc_ops = {
> +	.probe = rppx1_lsc_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_ltm.c b/drivers/media/platform/dreamchip/rppx1/rppx1_ltm.c
> new file mode 100644
> index 000000000000..693cf5ed1689
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_ltm.c
> @@ -0,0 +1,48 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define LTM_VERSION_REG				0x0000
> +
> +#define LTM_CTRL_REG				0x0004
> +#define LTM_CTRL_LTM_ENABLE			BIT(0)
> +
> +#define LTM_RGB_WEIGHTS_REG			0x0008
> +#define LTM_CLB_LINESIZE_REG			0x000c
> +#define LTM_TONECURVE_1_REG			0x0010
> +#define LTM_TONECURVE_2_REG			0x0014
> +#define LTM_TONECURVE_3_REG			0x0018
> +#define LTM_TONECURVE_4_REG			0x001c
> +#define LTM_TONECURVE_5_REG			0x0020
> +#define LTM_TONECURVE_6_REG			0x0024
> +#define LTM_TONECURVE_YM_REG(n)			(0x0028 + (4 * (n)))
> +#define LTM_L0W_REG				0x00ec
> +#define LTM_L0W_R_REG				0x00f0
> +#define LTM_L0D_REG				0x00f4
> +#define LTM_L0D_R_REG				0x00f8
> +#define LTM_KMIND_REG				0x00fc
> +#define LTM_KMAXD_REG				0x0100
> +#define LTM_KDIFFD_REG				0x0104
> +#define LTM_KDIFFD_R_REG			0x0108
> +#define LTM_KW_REG				0x010c
> +#define LTM_KW_R_REG				0x0110
> +#define LTM_CGAIN_REG				0x0114
> +#define LTM_LPRCH_R_HIGH_REG			0x0118
> +#define LTM_LPRCH_R_LOW_REG			0x011c
> +
> +static int rppx1_ltm_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, LTM_VERSION_REG) != 8)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_ltm_ops = {
> +	.probe = rppx1_ltm_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_ltmmeas.c b/drivers/media/platform/dreamchip/rppx1/rppx1_ltmmeas.c
> new file mode 100644
> index 000000000000..efc3d09db5eb
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_ltmmeas.c
> @@ -0,0 +1,41 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define LTM_MEAS_VERSION_REG		0x0000
> +
> +#define LTM_MEAS_CTRL_REG		0x0004
> +#define LTM_MEAS_CTRL_LTM_MEAS_ENABLE	BIT(0)
> +
> +#define LTM_MEAS_RGB_WEIGHTS_REG	0x0008
> +#define LTM_MEAS_H_OFFS_REG		0x000c
> +#define LTM_MEAS_V_OFFS_REG		0x0010
> +#define LTM_MEAS_H_SIZE_REG		0x0014
> +#define LTM_MEAS_V_SIZE_REG		0x0018
> +
> +#define LTM_MEAS_PRC_THRESH_NUM		8
> +#define LTM_MEAS_PRC_THRESH_REG(n)	(0x001c + (4 * (n)))
> +
> +#define LTM_MEAS_PRC_REG_NUM		8
> +#define LTM_MEAS_PRC_REG(n)		(0x003c + (4 * (n)))
> +
> +#define LTM_MEAS_L_MIN_REG		0x005c
> +#define LTM_MEAS_L_MAX_REG		0x0060
> +#define LTM_MEAS_L_GMEAN_REG		0x0064
> +
> +static int rppx1_ltmmeas_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, LTM_MEAS_VERSION_REG) != 1)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_ltmmeas_ops = {
> +	.probe = rppx1_ltmmeas_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_outif.c b/drivers/media/platform/dreamchip/rppx1/rppx1_outif.c
> new file mode 100644
> index 000000000000..742c81844912
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_outif.c
> @@ -0,0 +1,45 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define OUT_IF_VERSION_REG			0x0000
> +
> +#define OUT_IF_ON_REG				0x0004
> +#define OUT_IF_ON_RPP_ON			BIT(0)
> +
> +#define OUT_IF_OFF_REG				0x0008
> +
> +#define OUT_IF_NR_FRAMES_REG			0x000c
> +#define OUT_IF_NR_FRAMES_NR_FRAMES		GENMASK(9, 0)
> +
> +#define OUT_IF_NR_FRAMES_CNT_REG		0x0010
> +#define FLAGS_SHD_REG				0x0018
> +
> +static int rppx1_outif_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, OUT_IF_VERSION_REG) != 1)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int rppx1_outif_start(struct rpp_module *mod,
> +			     const struct v4l2_mbus_framefmt *fmt)
> +{
> +	rpp_module_clrset(mod, OUT_IF_NR_FRAMES_REG,
> +			  OUT_IF_NR_FRAMES_NR_FRAMES, 0);
> +
> +	rpp_module_write(mod, OUT_IF_ON_REG, OUT_IF_ON_RPP_ON);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_outif_ops = {
> +	.probe = rppx1_outif_probe,
> +	.start = rppx1_outif_start,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_outregs.c b/drivers/media/platform/dreamchip/rppx1/rppx1_outregs.c
> new file mode 100644
> index 000000000000..63d61e1dc447
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_outregs.c
> @@ -0,0 +1,75 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define OUTREGS_VERSION_REG					0x0000
> +
> +#define OUT_MODE_REG						0x0004
> +#define OUT_MODE_UNSELECTED_MODE_MASK				GENMASK(11, 8)
> +#define OUT_MODE_UNSELECTED_MODE_MAIN				(0x1 << 8)
> +#define OUT_MODE_UNSELECTED_MODE_PRE1				(0x2 << 8)
> +#define OUT_MODE_UNSELECTED_MODE_PRE2				(0x4 << 8)
> +#define OUT_MODE_IN_SEL_MASK					GENMASK(3, 0)
> +#define OUT_MODE_IN_SEL_MAIN					1
> +#define OUT_MODE_IN_SEL_PRE1					2
> +#define OUT_MODE_IN_SEL_PRE2					4
> +
> +#define OUT_CONV_422_METHOD_REG					0x0008
> +#define OUT_CONV_422_METHOD_CONV_422_METHOD_MASK		GENMASK(1, 0)
> +#define OUT_CONV_422_METHOD_CONV_422_METHOD_CO_SITED1		0
> +#define OUT_CONV_422_METHOD_CONV_422_METHOD_CO_SITED2		1
> +#define OUT_CONV_422_METHOD_CONV_422_METHOD_NON_CO_SITED	2
> +
> +#define OUTREGS_FORMAT_REG					0x000c
> +#define OUTREGS_FORMAT_OUTPUT_FORMAT_MASK			GENMASK(1, 0)
> +#define OUTREGS_FORMAT_OUTPUT_FORMAT_RGB			0
> +#define OUTREGS_FORMAT_OUTPUT_FORMAT_YUV422			1
> +#define OUTREGS_FORMAT_OUTPUT_FORMAT_YUV420			2
> +
> +static int rppx1_outregs_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, OUTREGS_VERSION_REG) != 2)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int rppx1_outregs_start(struct rpp_module *mod,
> +			       const struct v4l2_mbus_framefmt *fmt)
> +{
> +	u32 format;
> +
> +	switch (fmt->code) {
> +	case MEDIA_BUS_FMT_YUYV12_1X24:
> +		format = OUTREGS_FORMAT_OUTPUT_FORMAT_YUV422;
> +		break;
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +		format = OUTREGS_FORMAT_OUTPUT_FORMAT_RGB;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	rpp_module_clrset(mod, OUT_MODE_REG,
> +			  OUT_MODE_UNSELECTED_MODE_MASK | OUT_MODE_IN_SEL_MASK,
> +			  OUT_MODE_UNSELECTED_MODE_MASK | OUT_MODE_IN_SEL_MAIN);
> +
> +	rpp_module_clrset(mod, OUT_CONV_422_METHOD_REG,
> +			  OUT_CONV_422_METHOD_CONV_422_METHOD_MASK,
> +			  OUT_CONV_422_METHOD_CONV_422_METHOD_CO_SITED1);
> +
> +	rpp_module_clrset(mod, OUTREGS_FORMAT_REG,
> +			  OUTREGS_FORMAT_OUTPUT_FORMAT_MASK, format);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_outregs_ops = {
> +	.probe = rppx1_outregs_probe,
> +	.start = rppx1_outregs_start,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_rmap.c b/drivers/media/platform/dreamchip/rppx1/rppx1_rmap.c
> new file mode 100644
> index 000000000000..f6773a452bd1
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_rmap.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define RMAP_DATA_VERSION_REG		0x0000
> +
> +#define RMAP_CTRL_REG			0x0004
> +#define RMAP_CTRL_BYPASS_LONG		BIT(2)
> +
> +#define RMAP_WBTHRESHOLD_LONG_REG	0x0008
> +#define RMAP_WBTHRESHOLD_SHORT_REG	0x000c
> +#define RMAP_RESERVED_1_REG		0x0010
> +#define RMAP_WBGAIN_LONG_RED_REG	0x0014
> +#define RMAP_WBGAIN_LONG_BLUE_REG	0x0018
> +#define RMAP_WBGAIN_SHORT_RED_REG	0x001c
> +#define RMAP_WBGAIN_SHORT_BLUE_REG	0x0020
> +#define RMAP_RESERVED_2_REG		0x0024
> +#define RMAP_RESERVED_3_REG		0x0028
> +#define RMAP_MAP_FAC_SHORT_REG		0x002c
> +#define RMAP_RESERVED_4_REG		0x0030
> +#define RMAP_MIN_THRES_SHORT_REG	0x0034
> +#define RMAP_MAX_THRES_SHORT_REG	0x0038
> +#define RMAP_STEPSIZE_SHORT_REG		0x003c
> +#define RMAP_MIN_THRES_LONG_REG		0x0040
> +#define RMAP_MAX_THRES_LONG_REG		0x0044
> +#define RMAP_STEPSIZE_LONG_REG		0x0048
> +#define RMAP_CLB_LINESIZE_REG		0x004c
> +
> +static int rppx1_rmap_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, RMAP_DATA_VERSION_REG)) {
> +	case 8:
> +		mod->info.rmap.colorbits_high = 20;
> +		mod->info.rmap.colorbits_low = 12;
> +		break;
> +	case 9:
> +		mod->info.rmap.colorbits_high = 24;
> +		mod->info.rmap.colorbits_low = 12;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rppx1_rmap_start(struct rpp_module *mod,
> +			    const struct v4l2_mbus_framefmt *fmt)
> +{
> +	/* Bypass radiance mapping and use the long exposure channel (PRE1). */
> +	rpp_module_write(mod, RMAP_CTRL_REG, RMAP_CTRL_BYPASS_LONG);
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_rmap_ops = {
> +	.probe = rppx1_rmap_probe,
> +	.start = rppx1_rmap_start,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_rmapmeas.c b/drivers/media/platform/dreamchip/rppx1/rppx1_rmapmeas.c
> new file mode 100644
> index 000000000000..c04f92508f6d
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_rmapmeas.c
> @@ -0,0 +1,47 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define RMAP_MEAS_VERSION_REG			0x0000
> +#define RMAP_MEAS_MODE_REG			0x0004
> +#define RMAP_MEAS_SUBSAMPLING_REG		0x0008
> +#define RMAP_MEAS_RESERVED_1_REG		0x000c
> +#define RMAP_MEAS_MIN_THRES_SHORT_REG		0x0010
> +#define RMAP_MEAS_MAX_THRES_SHORT_REG		0x0014
> +#define RMAP_MEAS_MAX_THRES_LONG_REG		0x0018
> +#define RMAP_MEAS_H_OFFS_REG			0x001c
> +#define RMAP_MEAS_V_OFFS_REG			0x0020
> +#define RMAP_MEAS_H_SIZE_REG			0x0024
> +#define RMAP_MEAS_V_SIZE_REG			0x0028
> +#define RMAP_MEAS_LAST_MEAS_LINE_REG		0x002c
> +#define RMAP_MEAS_LS_RESULTSHORT0_REG		0x0030
> +#define RMAP_MEAS_LS_RESULTLONG0_REG		0x0034
> +#define RMAP_MEAS_RESERVED_2_REG		0x0038
> +#define RMAP_MEAS_RESERVED_3_REG		0x003c
> +#define RMAP_MEAS_LS_RESULTSHORT1_REG		0x0040
> +#define RMAP_MEAS_LS_RESULTLONG1_REG		0x0044
> +#define RMAP_MEAS_RESERVED_4_REG		0x0048
> +#define RMAP_MEAS_RESERVED_5_REG		0x004c
> +
> +static int rppx1_rmapmeas_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, RMAP_MEAS_VERSION_REG)) {
> +	case 3:
> +		mod->info.rmapmeas.colorbits_high = 24;
> +		mod->info.rmapmeas.colorbits_low = 12;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_rmapmeas_ops = {
> +	.probe = rppx1_rmapmeas_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_shrp.c b/drivers/media/platform/dreamchip/rppx1/rppx1_shrp.c
> new file mode 100644
> index 000000000000..5bec022e8f05
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_shrp.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define SHRPCNR_VERSION_REG				0x0000
> +
> +#define SHRPCNR_CTRL_REG				0x0004
> +#define SHRPCNR_CTRL_CAD_EN				BIT(3)
> +#define SHRPCNR_CTRL_DESAT_EN				BIT(2)
> +#define SHRPCNR_CTRL_CNR_EN				BIT(1)
> +#define SHRPCNR_CTRL_SHARPEN_EN				BIT(0)
> +
> +#define SHRPCNR_PARAM_REG				0x0008
> +#define SHRPCNR_PARAM_SHARP_FACTOR_MASK			GENMASK(19, 12)
> +#define SHRPCNR_PARAM_CORING_THR_MASK			GENMASK(11, 0)
> +
> +#define SHRPCNR_MAT_1_REG				0x000c
> +#define SHRPCNR_MAT_2_REG				0x0010
> +#define SHRPCNR_CLB_LINESIZE_REG			0x0014
> +#define SHRPCNR_YUV2RGB_CCOR_COEFF_0_REG		0x0018
> +#define SHRPCNR_YUV2RGB_CCOR_COEFF_1_REG		0x001c
> +#define SHRPCNR_YUV2RGB_CCOR_COEFF_2_REG		0x0020
> +#define SHRPCNR_YUV2RGB_CCOR_COEFF_3_REG		0x0024
> +#define SHRPCNR_YUV2RGB_CCOR_COEFF_4_REG		0x0028
> +#define SHRPCNR_YUV2RGB_CCOR_COEFF_5_REG		0x002c
> +#define SHRPCNR_YUV2RGB_CCOR_COEFF_6_REG		0x0030
> +#define SHRPCNR_YUV2RGB_CCOR_COEFF_7_REG		0x0034
> +#define SHRPCNR_YUV2RGB_CCOR_COEFF_8_REG		0x0038
> +#define SHRPCNR_YUV2RGB_CCOR_OFFSET_R_REG		0x003c
> +#define SHRPCNR_YUV2RGB_CCOR_OFFSET_G_REG		0x0040
> +#define SHRPCNR_YUV2RGB_CCOR_OFFSET_B_REG		0x0044
> +
> +#define SHRPCNR_CNR_THRES_REG				0x0048
> +#define SHRPCNR_CNR_THRES_CNR_THRES_CR_MASK		GENMASK(27, 16)
> +#define SHRPCNR_CNR_THRES_CNR_THRES_CB_MASK		GENMASK(11, 0)
> +
> +#define SHRPCNR_CRED_THRES_REG				0x004c
> +#define SHRPCNR_CRED_SLOPE_REG				0x0050
> +#define SHRPCNR_CAD_RESTORE_LVL_REG			0x0054
> +#define SHRPCNR_CAD_THRESH_V_UNEG_REG			0x0058
> +#define SHRPCNR_CAD_THRESH_V_UPOS_REG			0x005c
> +#define SHRPCNR_CAD_THRESH_U_REG			0x0060
> +
> +static int rppx1_shrp_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, SHRPCNR_VERSION_REG)) {
> +	case 2:
> +		mod->info.shrp.colorbits = 12;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_shrp_ops = {
> +	.probe = rppx1_shrp_probe,
> +};

There are quite some modules here that have no corresponding user in
libcamera and which are not exercized.

As long as we don't have a userspace user, I would refrein from adding
them to the driver to avoid committing to a uAPI before anyone
actually uses it.

If you want to keep the kernel module, fine, but no ABI for blocks
without a userspace user.

> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_wbmeas.c b/drivers/media/platform/dreamchip/rppx1/rppx1_wbmeas.c
> new file mode 100644
> index 000000000000..3d197d914d07
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_wbmeas.c
> @@ -0,0 +1,61 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define AWB_MEAS_VERSION_REG			0x0000
> +
> +#define AWB_MEAS_PROP_REG			0x0004
> +#define AWB_MEAS_PROP_MEAS_MODE_RGB		BIT(16) /* 0: YCbCr 1: RGB */
> +#define AWB_MEAS_PROP_YMAX			BIT(2)
> +#define AWB_MEAS_PROP_AWB_MODE_ON		BIT(1)
> +
> +#define AWB_MEAS_H_OFFS_REG			0x0008
> +#define AWB_MEAS_V_OFFS_REG			0x000c
> +#define AWB_MEAS_H_SIZE_REG			0x0010
> +#define AWB_MEAS_V_SIZE_REG			0x0014
> +#define AWB_MEAS_FRAMES_REG			0x0018
> +#define AWB_MEAS_REF_CB_MAX_B_REG		0x001c
> +#define AWB_MEAS_REF_CR_MAX_R_REG		0x0020
> +#define AWB_MEAS_MAX_Y_REG			0x0024
> +#define AWB_MEAS_MIN_Y_MAX_G_REG		0x0028
> +#define AWB_MEAS_MAX_CSUM_REG			0x002c
> +#define AWB_MEAS_MIN_C_REG			0x0030
> +#define AWB_MEAS_WHITE_CNT_REG			0x0034
> +#define AWB_MEAS_MEAN_Y_G_REG			0x0038
> +#define AWB_MEAS_MEAN_CB_B_REG			0x003c
> +#define AWB_MEAS_MEAN_CR_R_REG			0x0040
> +
> +#define AWB_MEAS_CCOR_COEFF_NUM			9
> +#define AWB_MEAS_CCOR_COEFF_REG(n)		(0x0044 + (4 * (n)))
> +
> +#define AWB_MEAS_CCOR_OFFSET_R_REG		0x0068
> +#define AWB_MEAS_CCOR_OFFSET_G_REG		0x006c
> +#define AWB_MEAS_CCOR_OFFSET_B_REG		0x0070
> +
> +static int rppx1_wbmeas_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	switch (rpp_module_read(mod, AWB_MEAS_VERSION_REG)) {
> +	case 1:
> +		mod->info.wbmeas.colorbits = 8;
> +		break;
> +	case 2:
> +		mod->info.wbmeas.colorbits = 20;
> +		break;
> +	case 3:
> +		mod->info.wbmeas.colorbits = 24;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_wbmeas_ops = {
> +	.probe = rppx1_wbmeas_probe,
> +};
> diff --git a/drivers/media/platform/dreamchip/rppx1/rppx1_xyz2luv.c b/drivers/media/platform/dreamchip/rppx1/rppx1_xyz2luv.c
> new file mode 100644
> index 000000000000..73789c48c057
> --- /dev/null
> +++ b/drivers/media/platform/dreamchip/rppx1/rppx1_xyz2luv.c
> @@ -0,0 +1,26 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +
> +#include "rpp_module.h"
> +
> +#define XYZ2LUV_VERSION_REG			0x0000
> +#define XYZ2LUV_U_REF_REG			0x0004
> +#define XYZ2LUV_V_REF_REG			0x0008
> +#define XYZ2LUV_LUMA_OUT_FAC_REG		0x000c
> +#define XYZ2LUV_CHROMA_OUT_FAC_REG		0x0010
> +
> +static int rppx1_xyz2luv_probe(struct rpp_module *mod)
> +{
> +	/* Version check. */
> +	if (rpp_module_read(mod, XYZ2LUV_VERSION_REG) != 4)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +const struct rpp_module_ops rppx1_xyz2luv_ops = {
> +	.probe = rppx1_xyz2luv_probe,
> +};
> diff --git a/include/media/rppx1.h b/include/media/rppx1.h
> new file mode 100644
> index 000000000000..cb3470c27ceb
> --- /dev/null
> +++ b/include/media/rppx1.h
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2025 Renesas Electronics Corp.
> + * Copyright 2025 Niklas Söderlund <niklas.soderlund@ragnatech.se>
> + */
> +#ifndef __MEDIA_DCT_RPPX1_H__
> +#define __MEDIA_DCT_RPPX1_H__
> +
> +#include <linux/v4l2-mediabus.h>
> +#include <linux/media/dreamchip/rppx1-config.h>
> +
> +#include <media/videobuf2-core.h>
> +
> +struct rppx1;
> +
> +struct rppx1 *rppx1_create(void __iomem *base, struct device *dev);
> +
> +void rppx1_destroy(struct rppx1 *rpp);
> +
> +int rppx1_start(struct rppx1 *rpp, const struct v4l2_mbus_framefmt *input,
> +		const struct v4l2_mbus_framefmt *hv,
> +		const struct v4l2_mbus_framefmt *mv);
> +
> +int rppx1_stop(struct rppx1 *rpp);
> +
> +bool rppx1_interrupt(struct rppx1 *rpp, u32 *isc);
> +
> +typedef int (*rppx1_reg_write)(void *priv, u32 offset, u32 value);
> +int rppx1_params(struct rppx1 *rpp, struct vb2_buffer *vb, size_t max_size,
> +		 rppx1_reg_write write, void *priv);
> +
> +void rppx1_stats_fill_isr(struct rppx1 *rpp, u32 isc, void *buf);
> +
> +#endif /* __MEDIA_DCT_RPPX1_H__ */
> diff --git a/include/uapi/linux/media/dreamchip/rppx1-config.h b/include/uapi/linux/media/dreamchip/rppx1-config.h
> new file mode 100644
> index 000000000000..26627be6f483
> --- /dev/null
> +++ b/include/uapi/linux/media/dreamchip/rppx1-config.h

As said, I don't think it makes much sense to add an almost empty uapi
file.

I would add it in one commit.

Please retain Jai's authorship and add my Co-developed-by tag as I
rewrote most of the documentation and reworked most blocks.

> @@ -0,0 +1,66 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * Dreamchip RPP-X1 ISP Driver - Userspace API
> + *
> + * Copyright (C) 2026 Renesas Electronics Corp.
> + * Copyright (C) 2026 Ideas on Board Oy
> + * Copyright (C) 2026 Ragnatech AB
> + */
> +
> +#ifndef __UAPI_RPP_X1_CONFIG_H
> +#define __UAPI_RPP_X1_CONFIG_H
> +
> +#include <linux/types.h>
> +#include <linux/media/v4l2-isp.h>
> +
> +/**
> + * struct rppx1_window - Measurement window
> + *
> + * RPP-X1 measurement window. Different blocks use a window or multiple
> + * windows for measurement purposes. This defines a common type for all of
> + * them. The number of relevant bits depends on the block where the window is
> + * used and is specified in the per-block description
> + *
> + * @h_offs: horizontal offset from the left of the frame in pixels
> + * @v_offs: vertical offset from the top of the frame in pixels
> + * @h_size: horizontal size of the window in pixels
> + * @v_size: vertical size of the window in pixels
> + */
> +struct rppx1_window {
> +	__u16 h_offs;
> +	__u16 v_offs;
> +	__u16 h_size;
> +	__u16 v_size;
> +};
> +
> +/* ---------------------------------------------------------------------------
> + * Parameter Structures
> + *
> + * Native RPP-X1 precision. Fields use __u32 where the hardware provides
> + * wider-than-8-bit results.

I think you could drop the first part: of course the RPP-X1 uAPI
header uses the RPP-X1 precision. You could add:

      The same ISP block might be instantiated in multiple pipeliness
      and operate on a different bitdepth/precision. For fields of
      varying length among different instances of the same block, use
      a data type that can accommodate the larger bitdepth/precision.

Or something similar

> + */
> +
> +/**
> + * RPPX1_PARAMS_MAX_SIZE - Maximum size of all RPP-X1 parameter blocks
> + *
> + * Some types are reported twice as the same block might be instantiated in
> + * multiple pipes.
> + */
> +#define RPPX1_PARAMS_MAX_SIZE 0
> +
> +/* ---------------------------------------------------------------------------
> + * Statistics Structures
> + *
> + * Native RPP-X1 precision. Fields use __u32 where the hardware provides
> + * wider-than-8-bit results.

Same here

> + */
> +
> +/**
> + * RPPX1_STATS_MAX_SIZE - Maximum size of all RPP-X1 statistics
> + *
> + * Some types are reported twice as the same block might be instantiated in
> + * multiple pipes.
> + */
> +#define RPPX1_STATS_MAX_SIZE 0
> +
> +#endif /* __UAPI_RPP_X1_CONFIG_H */
> --
> 2.54.0
>

  reply	other threads:[~2026-05-06  8:53 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-04  1:05 [v8 00/14] media: Add support for R-Car ISP using Dreamchip RPPX1 ISP Niklas Söderlund
2026-05-04  1:05 ` [v8 01/14] media: Add RPP_X1_PARAMS and RPP_X1_STATS meta formats Niklas Söderlund
2026-05-06  7:45   ` Jacopo Mondi
2026-05-04  1:05 ` [v8 02/14] media: rppx1: Add framework to support Dreamchip RPPX1 ISP Niklas Söderlund
2026-05-06  8:53   ` Jacopo Mondi [this message]
2026-05-04  1:05 ` [v8 03/14] media: rcar-isp: Add support for ISPCORE Niklas Söderlund
2026-05-06 15:02   ` Jacopo Mondi
2026-05-04  1:05 ` [v8 04/14] media: rppx1: wbmeas: Add support for white balance measurement Niklas Söderlund
2026-05-06 13:58   ` Antoine Bouyer
2026-05-06 14:22     ` Jacopo Mondi
2026-05-04  1:05 ` [v8 05/14] media: rppx1: awbg: Add support for white balance gain settings Niklas Söderlund
2026-05-04  1:05 ` [v8 06/14] media: rppx1: exm: Add support for exposure measurement Niklas Söderlund
2026-05-04  1:05 ` [v8 07/14] media: rppx1: hist: Add support histogram measurement Niklas Söderlund
2026-05-06 15:51   ` Jacopo Mondi
2026-05-04  1:05 ` [v8 08/14] media: rppx1: bls: Add support for black level compensation Niklas Söderlund
2026-05-06 15:25   ` Jacopo Mondi
2026-05-04  1:05 ` [v8 09/14] media: rppx1: ccor: Add support for color correction matrix Niklas Söderlund
2026-05-04  1:05 ` [v8 10/14] media: rppx1: lsc: Add support for lens shade correction Niklas Söderlund
2026-05-04  1:05 ` [v8 11/14] media: rppx1: ga: Add support for gamma out correction Niklas Söderlund
2026-05-04  1:05 ` [v8 12/14] media: rppx1: db: Add support for debayering filters Niklas Söderlund
2026-05-06 15:54   ` Jacopo Mondi
2026-05-04  1:05 ` [v8 13/14] media: rppx1: bd: Add support for bilateral denoising Niklas Söderlund
2026-05-04  1:05 ` [v8 14/14] media: rppx1: lin: Add support for gamma sensor linearization Niklas Söderlund
2026-05-06 15:57   ` Jacopo Mondi
2026-05-06 12:19 ` [v8 00/14] media: Add support for R-Car ISP using Dreamchip RPPX1 ISP Geert Uytterhoeven
2026-05-06 12:29   ` Niklas Söderlund
2026-05-06 12:49     ` Jacopo Mondi
2026-05-06 12:56       ` Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=afrxmrw2BZLT1tRJ@zed \
    --to=jacopo.mondi@ideasonboard.com \
    --cc=jai.luthra+renesas@ideasonboard.com \
    --cc=kuninori.morimoto.gx@renesas.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=mchehab@kernel.org \
    --cc=niklas.soderlund+renesas@ragnatech.se \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox