xref: /linux/drivers/media/platform/dreamchip/rppx1/rppx1.c (revision f4cdf7ca9a1fdcca413157df19753f388a5a224e)
1*b562e72bSNiklas Söderlund // SPDX-License-Identifier: GPL-2.0
2*b562e72bSNiklas Söderlund /*
3*b562e72bSNiklas Söderlund  * Copyright (C) 2026 Renesas Electronics Corp.
4*b562e72bSNiklas Söderlund  * Copyright (C) 2026 Ideas on Board Oy
5*b562e72bSNiklas Söderlund  * Copyright (C) 2026 Ragnatech AB
6*b562e72bSNiklas Söderlund  *
7*b562e72bSNiklas Söderlund  * Support library for Dreamchip HDR RPPX1 High Dynamic Range Real-time Pixel
8*b562e72bSNiklas Söderlund  * Processor.
9*b562e72bSNiklas Söderlund  */
10*b562e72bSNiklas Söderlund 
11*b562e72bSNiklas Söderlund #include <linux/io.h>
12*b562e72bSNiklas Söderlund #include <linux/module.h>
13*b562e72bSNiklas Söderlund #include <linux/slab.h>
14*b562e72bSNiklas Söderlund 
15*b562e72bSNiklas Söderlund #include "rppx1.h"
16*b562e72bSNiklas Söderlund 
17*b562e72bSNiklas Söderlund /* RPP_HDR Base Addresses */
18*b562e72bSNiklas Söderlund #define RPPX1_HDRREGS_BASE			0x0000
19*b562e72bSNiklas Söderlund #define RPPX1_HDR_IRQ_BASE			0x0200
20*b562e72bSNiklas Söderlund #define RPPX1_RPP_OUT_BASE			0x0800
21*b562e72bSNiklas Söderlund #define RPPX1_RPP_RMAP_BASE			0x0c00
22*b562e72bSNiklas Söderlund #define RPPX1_RPP_RMAP_MEAS_BASE		0x1000
23*b562e72bSNiklas Söderlund #define RPPX1_RPP_MAIN_PRE1_BASE		0x2000
24*b562e72bSNiklas Söderlund #define RPPX1_RPP_MAIN_PRE2_BASE		0x4000
25*b562e72bSNiklas Söderlund #define RPPX1_RPP_MAIN_POST_BASE		0xa000
26*b562e72bSNiklas Söderlund #define RPPX1_RPP_MVOUT_BASE			0xc000
27*b562e72bSNiklas Söderlund #define RPPX1_RPP_FUSA_BASE			0xf000
28*b562e72bSNiklas Söderlund 
29*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDRREGS_VERSION_REG		(RPPX1_HDRREGS_BASE + 0x0000)
30*b562e72bSNiklas Söderlund 
31*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_UPD_REG			(RPPX1_HDRREGS_BASE + 0x0004)
32*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_UPD_REGS_GEN_CFG_UPD	BIT(1)
33*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_UPD_REGS_CFG_UPD		BIT(0)
34*b562e72bSNiklas Söderlund 
35*b562e72bSNiklas Söderlund #define RPPX1_RESERVED_3_REG			(RPPX1_HDRREGS_BASE + 0x0008)
36*b562e72bSNiklas Söderlund 
37*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_INFORM_ENABLE_REG		(RPPX1_HDRREGS_BASE + 0x000c)
38*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_INFORM_ENABLE_ENABLE	1
39*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_INFORM_ENABLE_DISABLE	0
40*b562e72bSNiklas Söderlund 
41*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_OUT_IF_ON_REG		(RPPX1_HDRREGS_BASE + 0x0010)
42*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_OUT_IF_OFF_REG		(RPPX1_HDRREGS_BASE + 0x0014)
43*b562e72bSNiklas Söderlund 
44*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_REG	(RPPX1_HDRREGS_BASE + 0x0018)
45*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_ENABLE	1
46*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_DISABLE	0
47*b562e72bSNiklas Söderlund 
48*b562e72bSNiklas Söderlund #define RPPX1_RPP_ISM				(RPPX1_HDR_IRQ_BASE + 0x00)
49*b562e72bSNiklas Söderlund #define RPPX1_RPP_RIS				(RPPX1_HDR_IRQ_BASE + 0x04)
50*b562e72bSNiklas Söderlund #define RPPX1_RPP_MIS				(RPPX1_HDR_IRQ_BASE + 0x08)
51*b562e72bSNiklas Söderlund #define RPPX1_RPP_ISC				(RPPX1_HDR_IRQ_BASE + 0x0c)
52*b562e72bSNiklas Söderlund 
53*b562e72bSNiklas Söderlund /* RPP_OUT/MV_OUT Pipelines - Base Addresses */
54*b562e72bSNiklas Söderlund #define RPPX1_GAMMA_OUT_BASE			0x0000 /* HV, MV */
55*b562e72bSNiklas Söderlund #define RPPX1_IS_BASE				0x00c0 /* HV, MV */
56*b562e72bSNiklas Söderlund #define RPPX1_CSM_BASE				0x0100 /* HV, MV */
57*b562e72bSNiklas Söderlund #define RPPX1_OUT_IF_BASE			0x0200 /* HV, MV */
58*b562e72bSNiklas Söderlund #define RPPX1_RPP_OUTREGS_BASE			0x02c0 /* HV, MV */
59*b562e72bSNiklas Söderlund #define RPPX1_LUV_BASE				0x0300 /* MV */
60*b562e72bSNiklas Söderlund 
61*b562e72bSNiklas Söderlund /* PRE1/PRE2/POST Pipelines - Base Addresses */
62*b562e72bSNiklas Söderlund #define RPPX1_ACQ_BASE				0x0080 /* PRE1, PRE2 */
63*b562e72bSNiklas Söderlund #define RPPX1_BLS_BASE				0x0100 /* PRE1, PRE2 */
64*b562e72bSNiklas Söderlund #define RPPX1_GAMMA_IN_BASE			0x0200 /* PRE1, PRE2 */
65*b562e72bSNiklas Söderlund #define RPPX1_LSC_BASE				0x0400 /* PRE1, PRE2 */
66*b562e72bSNiklas Söderlund #define RPPX1_AWB_GAIN_BASE			0x0500 /* PRE1, PRE2, POST */
67*b562e72bSNiklas Söderlund #define RPPX1_DPCC_BASE				0x0600 /* PRE1, PRE2 */
68*b562e72bSNiklas Söderlund #define RPPX1_DPF_BASE				0x0700 /* PRE1, PRE2 */
69*b562e72bSNiklas Söderlund #define RPPX1_FILT_BASE				0x0800 /* POST */
70*b562e72bSNiklas Söderlund #define RPPX1_CAC_BASE				0x0880 /* POST */
71*b562e72bSNiklas Söderlund #define RPPX1_CCOR_BASE				0x0900 /* POST */
72*b562e72bSNiklas Söderlund #define RPPX1_HIST_BASE				0x0a00 /* PRE1, PRE2, POST */
73*b562e72bSNiklas Söderlund #define RPPX1_HIST256_BASE			0x0b00 /* PRE1 */
74*b562e72bSNiklas Söderlund #define RPPX1_EXM_BASE				0x0c00 /* PRE1, PRE2 */
75*b562e72bSNiklas Söderlund #define RPPX1_LTM_BASE				0x1000 /* POST */
76*b562e72bSNiklas Söderlund #define RPPX1_LTM_MEAS_BASE			0x1200 /* POST */
77*b562e72bSNiklas Söderlund #define RPPX1_WBMEAS_BASE			0x1700 /* POST */
78*b562e72bSNiklas Söderlund #define RPPX1_BDRGB_BASE			0x1800 /* POST */
79*b562e72bSNiklas Söderlund #define RPPX1_SHRP_BASE				0x1a00 /* POST */
80*b562e72bSNiklas Söderlund 
81*b562e72bSNiklas Söderlund /* Functional Safety Module Base Addresses */
82*b562e72bSNiklas Söderlund #define RPPX1_FMU_BASE				0x0100
83*b562e72bSNiklas Söderlund 
84*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_REG		(RPPX1_RPP_FUSA_BASE + RPPX1_FMU_BASE + 0x00)
85*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_FSM_IRQM_FAULT	BIT(23)
86*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE2_SIZE_FAULT	BIT(20)
87*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE2_TIME_FAULT	BIT(19)
88*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE1_SIZE_FAULT	BIT(18)
89*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE1_TIME_FAULT	BIT(17)
90*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_SIZE_FAULT	BIT(16)
91*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_TIME_FAULT	BIT(15)
92*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_MV_OUT_SIZE_FAULT	BIT(14)
93*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_MV_OUT_TIME_FAULT	BIT(13)
94*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_HV_OUT_SIZE_FAULT	BIT(12)
95*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_HV_OUT_TIME_FAULT	BIT(11)
96*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_MV_OUT_SIZE_ERR	BIT(10)
97*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_IS_OUT_SIZE_ERR	BIT(9)
98*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE2_FIFO_OVFLW	BIT(7)
99*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE1_FIFO_OVFLW	BIT(6)
100*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE1_INFORM_SIZE	BIT(5)
101*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE1_OUTFORM_SIZE	BIT(4)
102*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE2_INFORM_SIZE	BIT(3)
103*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSM_PRE2_OUTFORM_SIZE	BIT(2)
104*b562e72bSNiklas Söderlund 
105*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_RFS_REG		(RPPX1_RPP_FUSA_BASE + RPPX1_FMU_BASE + 0x04)
106*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_MFS_REG		(RPPX1_RPP_FUSA_BASE + RPPX1_FMU_BASE + 0x08)
107*b562e72bSNiklas Söderlund #define RPPX1_RPP_HDR_FMU_FSC_REG		(RPPX1_RPP_FUSA_BASE + RPPX1_FMU_BASE + 0x0c)
108*b562e72bSNiklas Söderlund 
109*b562e72bSNiklas Söderlund void rppx1_write(struct rppx1 *rpp, u32 offset, u32 value)
110*b562e72bSNiklas Söderlund {
111*b562e72bSNiklas Söderlund 	iowrite32(value, rpp->base + offset);
112*b562e72bSNiklas Söderlund }
113*b562e72bSNiklas Söderlund 
114*b562e72bSNiklas Söderlund u32 rppx1_read(struct rppx1 *rpp, u32 offset)
115*b562e72bSNiklas Söderlund {
116*b562e72bSNiklas Söderlund 	return ioread32(rpp->base + offset);
117*b562e72bSNiklas Söderlund }
118*b562e72bSNiklas Söderlund 
119*b562e72bSNiklas Söderlund bool rppx1_interrupt(struct rppx1 *rpp, u32 *isc)
120*b562e72bSNiklas Söderlund {
121*b562e72bSNiklas Söderlund 	u32 status, raw, fault;
122*b562e72bSNiklas Söderlund 
123*b562e72bSNiklas Söderlund 	fault = rppx1_read(rpp, RPPX1_RPP_HDR_FMU_MFS_REG);
124*b562e72bSNiklas Söderlund 	if (fault) {
125*b562e72bSNiklas Söderlund 		dev_err(rpp->dev, "%s: fault 0x%08x\n", __func__, fault);
126*b562e72bSNiklas Söderlund 		rppx1_write(rpp, RPPX1_RPP_HDR_FMU_FSC_REG, fault);
127*b562e72bSNiklas Söderlund 	}
128*b562e72bSNiklas Söderlund 
129*b562e72bSNiklas Söderlund 	/* Read raw interrupt status. */
130*b562e72bSNiklas Söderlund 	raw = rppx1_read(rpp, RPPX1_RPP_RIS);
131*b562e72bSNiklas Söderlund 	status = rppx1_read(rpp, RPPX1_RPP_MIS);
132*b562e72bSNiklas Söderlund 
133*b562e72bSNiklas Söderlund 	/* Propagate the isc status. */
134*b562e72bSNiklas Söderlund 	if (isc)
135*b562e72bSNiklas Söderlund 		*isc = status | raw;
136*b562e72bSNiklas Söderlund 
137*b562e72bSNiklas Söderlund 	/* Clear enabled interrupts */
138*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_ISC, status);
139*b562e72bSNiklas Söderlund 
140*b562e72bSNiklas Söderlund 	return !!(status & RPPX1_IRQ_ID_OUT_FRAME);
141*b562e72bSNiklas Söderlund }
142*b562e72bSNiklas Söderlund EXPORT_SYMBOL_GPL(rppx1_interrupt);
143*b562e72bSNiklas Söderlund 
144*b562e72bSNiklas Söderlund void rppx1_destroy(struct rppx1 *rpp)
145*b562e72bSNiklas Söderlund {
146*b562e72bSNiklas Söderlund 	kfree(rpp);
147*b562e72bSNiklas Söderlund }
148*b562e72bSNiklas Söderlund EXPORT_SYMBOL_GPL(rppx1_destroy);
149*b562e72bSNiklas Söderlund 
150*b562e72bSNiklas Söderlund /*
151*b562e72bSNiklas Söderlund  * Allocate the private data structure and verify the hardware is present.
152*b562e72bSNiklas Söderlund  */
153*b562e72bSNiklas Söderlund struct rppx1 *rppx1_create(void __iomem *base, struct device *dev)
154*b562e72bSNiklas Söderlund {
155*b562e72bSNiklas Söderlund 	struct rppx1 *rpp;
156*b562e72bSNiklas Söderlund 	u32 reg;
157*b562e72bSNiklas Söderlund 
158*b562e72bSNiklas Söderlund 	/* Allocate library structure */
159*b562e72bSNiklas Söderlund 	rpp = kzalloc_obj(*rpp);
160*b562e72bSNiklas Söderlund 	if (!rpp)
161*b562e72bSNiklas Söderlund 		return NULL;
162*b562e72bSNiklas Söderlund 
163*b562e72bSNiklas Söderlund 	rpp->base = base;
164*b562e72bSNiklas Söderlund 	rpp->dev = dev;
165*b562e72bSNiklas Söderlund 
166*b562e72bSNiklas Söderlund 	/* Check communication with RPP and verify it truly is a X1. */
167*b562e72bSNiklas Söderlund 	reg = rppx1_read(rpp, RPPX1_RPP_HDRREGS_VERSION_REG);
168*b562e72bSNiklas Söderlund 	if (reg != 3) {
169*b562e72bSNiklas Söderlund 		dev_err(rpp->dev, "Unsupported HDR version (%u)\n", reg);
170*b562e72bSNiklas Söderlund 		rppx1_destroy(rpp);
171*b562e72bSNiklas Söderlund 		return NULL;
172*b562e72bSNiklas Söderlund 	}
173*b562e72bSNiklas Söderlund 
174*b562e72bSNiklas Söderlund 	/* Probe the PRE1 pipeline. */
175*b562e72bSNiklas Söderlund 	if (rpp_module_probe(&rpp->pre1.acq, rpp, &rppx1_acq_ops,
176*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_ACQ_BASE) ||
177*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre1.bls, rpp, &rppx1_bls_ops,
178*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_BLS_BASE) ||
179*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre1.lin, rpp, &rppx1_lin_ops,
180*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_GAMMA_IN_BASE) ||
181*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre1.lsc, rpp, &rppx1_lsc_ops,
182*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_LSC_BASE) ||
183*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre1.awbg, rpp, &rppx1_awbg_ops,
184*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_AWB_GAIN_BASE) ||
185*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre1.dpcc, rpp, &rppx1_dpcc_ops,
186*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_DPCC_BASE) ||
187*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre1.bd, rpp, &rppx1_bd_ops,
188*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_DPF_BASE) ||
189*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre1.hist, rpp, &rppx1_hist_ops,
190*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_HIST_BASE) ||
191*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre1.hist256, rpp, &rppx1_hist256_ops,
192*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_HIST256_BASE) ||
193*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre1.exm, rpp, &rppx1_exm_ops,
194*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE1_BASE + RPPX1_EXM_BASE))
195*b562e72bSNiklas Söderlund 		goto err;
196*b562e72bSNiklas Söderlund 
197*b562e72bSNiklas Söderlund 	/* Probe the PRE2 pipeline. */
198*b562e72bSNiklas Söderlund 	if (rpp_module_probe(&rpp->pre2.acq, rpp, &rppx1_acq_ops,
199*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_ACQ_BASE) ||
200*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre2.bls, rpp, &rppx1_bls_ops,
201*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_BLS_BASE) ||
202*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre2.lin, rpp, &rppx1_lin_ops,
203*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_GAMMA_IN_BASE) ||
204*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre2.lsc, rpp, &rppx1_lsc_ops,
205*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_LSC_BASE) ||
206*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre2.awbg, rpp, &rppx1_awbg_ops,
207*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_AWB_GAIN_BASE) ||
208*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre2.dpcc, rpp, &rppx1_dpcc_ops,
209*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_DPCC_BASE) ||
210*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre2.bd, rpp, &rppx1_bd_ops,
211*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_DPF_BASE) ||
212*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre2.hist, rpp, &rppx1_hist_ops,
213*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_HIST_BASE) ||
214*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->pre2.exm, rpp, &rppx1_exm_ops,
215*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_PRE2_BASE + RPPX1_EXM_BASE))
216*b562e72bSNiklas Söderlund 		goto err;
217*b562e72bSNiklas Söderlund 
218*b562e72bSNiklas Söderlund 	/* Probe the POST pipeline. */
219*b562e72bSNiklas Söderlund 	if (rpp_module_probe(&rpp->post.awbg, rpp, &rppx1_awbg_ops,
220*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_AWB_GAIN_BASE) ||
221*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->post.ccor, rpp, &rppx1_ccor_ops,
222*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_CCOR_BASE) ||
223*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->post.hist, rpp, &rppx1_hist_ops,
224*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_HIST_BASE) ||
225*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->post.db, rpp, &rppx1_db_ops,
226*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_FILT_BASE) ||
227*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->post.cac, rpp, &rppx1_cac_ops,
228*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_CAC_BASE) ||
229*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->post.ltm, rpp, &rppx1_ltm_ops,
230*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_LTM_BASE) ||
231*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->post.ltmmeas, rpp, &rppx1_ltmmeas_ops,
232*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_LTM_MEAS_BASE) ||
233*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->post.wbmeas, rpp, &rppx1_wbmeas_ops,
234*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_WBMEAS_BASE) ||
235*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->post.bdrgb, rpp, &rppx1_bdrgb_ops,
236*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_BDRGB_BASE) ||
237*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->post.shrp, rpp, &rppx1_shrp_ops,
238*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MAIN_POST_BASE + RPPX1_SHRP_BASE))
239*b562e72bSNiklas Söderlund 		goto err;
240*b562e72bSNiklas Söderlund 
241*b562e72bSNiklas Söderlund 	/* Probe the Human Vision pipeline. */
242*b562e72bSNiklas Söderlund 	if (rpp_module_probe(&rpp->hv.ga, rpp, &rppx1_ga_ops,
243*b562e72bSNiklas Söderlund 			     RPPX1_RPP_OUT_BASE + RPPX1_GAMMA_OUT_BASE) ||
244*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->hv.is, rpp, &rppx1_is_ops,
245*b562e72bSNiklas Söderlund 			     RPPX1_RPP_OUT_BASE + RPPX1_IS_BASE) ||
246*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->hv.ccor, rpp, &rppx1_ccor_csm_ops,
247*b562e72bSNiklas Söderlund 			     RPPX1_RPP_OUT_BASE + RPPX1_CSM_BASE) ||
248*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->hv.outif, rpp, &rppx1_outif_ops,
249*b562e72bSNiklas Söderlund 			     RPPX1_RPP_OUT_BASE + RPPX1_OUT_IF_BASE) ||
250*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->hv.outregs, rpp, &rppx1_outregs_ops,
251*b562e72bSNiklas Söderlund 			     RPPX1_RPP_OUT_BASE + RPPX1_RPP_OUTREGS_BASE))
252*b562e72bSNiklas Söderlund 		goto err;
253*b562e72bSNiklas Söderlund 
254*b562e72bSNiklas Söderlund 	/* Probe the Machine Vision pipeline. */
255*b562e72bSNiklas Söderlund 	if (rpp_module_probe(&rpp->mv.ga, rpp, &rppx1_ga_ops,
256*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MVOUT_BASE + RPPX1_GAMMA_OUT_BASE) ||
257*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->mv.is, rpp, &rppx1_is_ops,
258*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MVOUT_BASE + RPPX1_IS_BASE) ||
259*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->mv.ccor, rpp, &rppx1_ccor_csm_ops,
260*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MVOUT_BASE + RPPX1_CSM_BASE) ||
261*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->mv.outif, rpp, &rppx1_outif_ops,
262*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MVOUT_BASE + RPPX1_OUT_IF_BASE) ||
263*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->mv.outregs, rpp, &rppx1_outregs_ops,
264*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MVOUT_BASE + RPPX1_RPP_OUTREGS_BASE) ||
265*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->mv.xyz2luv, rpp, &rppx1_xyz2luv_ops,
266*b562e72bSNiklas Söderlund 			     RPPX1_RPP_MVOUT_BASE + RPPX1_LUV_BASE))
267*b562e72bSNiklas Söderlund 		goto err;
268*b562e72bSNiklas Söderlund 
269*b562e72bSNiklas Söderlund 	/* Probe the standalone Radiance Mapping modules. */
270*b562e72bSNiklas Söderlund 	if (rpp_module_probe(&rpp->rmap, rpp, &rppx1_rmap_ops,
271*b562e72bSNiklas Söderlund 			     RPPX1_RPP_RMAP_BASE) ||
272*b562e72bSNiklas Söderlund 	    rpp_module_probe(&rpp->rmapmeas, rpp, &rppx1_rmapmeas_ops,
273*b562e72bSNiklas Söderlund 			     RPPX1_RPP_RMAP_MEAS_BASE))
274*b562e72bSNiklas Söderlund 		goto err;
275*b562e72bSNiklas Söderlund 
276*b562e72bSNiklas Söderlund 	return rpp;
277*b562e72bSNiklas Söderlund err:
278*b562e72bSNiklas Söderlund 	rppx1_destroy(rpp);
279*b562e72bSNiklas Söderlund 
280*b562e72bSNiklas Söderlund 	return NULL;
281*b562e72bSNiklas Söderlund }
282*b562e72bSNiklas Söderlund EXPORT_SYMBOL_GPL(rppx1_create);
283*b562e72bSNiklas Söderlund 
284*b562e72bSNiklas Söderlund int rppx1_start(struct rppx1 *rpp,
285*b562e72bSNiklas Söderlund 		const struct v4l2_mbus_framefmt *input,
286*b562e72bSNiklas Söderlund 		const struct v4l2_mbus_framefmt *hv,
287*b562e72bSNiklas Söderlund 		const struct v4l2_mbus_framefmt *mv)
288*b562e72bSNiklas Söderlund {
289*b562e72bSNiklas Söderlund 	if (rpp_module_call(&rpp->pre1.acq, start, input) ||
290*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->pre1.bls, start, input) ||
291*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->pre1.lin, start, input) ||
292*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->pre1.lsc, start, input) ||
293*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->pre1.awbg, start, input) ||
294*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->pre1.dpcc, start, input) ||
295*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->pre1.bd, start, input) ||
296*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->pre1.hist, start, input) ||
297*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->pre1.exm, start, input) ||
298*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->pre1.hist256, start, input))
299*b562e72bSNiklas Söderlund 		return -EINVAL;
300*b562e72bSNiklas Söderlund 
301*b562e72bSNiklas Söderlund 	if (rpp_module_call(&rpp->rmap, start, NULL) ||
302*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->rmapmeas, start, NULL))
303*b562e72bSNiklas Söderlund 		return -EINVAL;
304*b562e72bSNiklas Söderlund 
305*b562e72bSNiklas Söderlund 	if (rpp_module_call(&rpp->post.awbg, start, input) ||
306*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->post.db, start, input) ||
307*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->post.cac, start, input) ||
308*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->post.ccor, start, input) ||
309*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->post.ltm, start, input) ||
310*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->post.bdrgb, start, input) ||
311*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->post.shrp, start, input) ||
312*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->post.ltmmeas, start, input) ||
313*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->post.wbmeas, start, input) ||
314*b562e72bSNiklas Söderlund 	    rpp_module_call(&rpp->post.hist, start, input))
315*b562e72bSNiklas Söderlund 		return -EINVAL;
316*b562e72bSNiklas Söderlund 
317*b562e72bSNiklas Söderlund 	if (hv && (rpp_module_call(&rpp->hv.ga, start, hv) ||
318*b562e72bSNiklas Söderlund 		   rpp_module_call(&rpp->hv.ccor, start, hv) ||
319*b562e72bSNiklas Söderlund 		   rpp_module_call(&rpp->hv.outregs, start, hv) ||
320*b562e72bSNiklas Söderlund 		   rpp_module_call(&rpp->hv.is, start, hv) ||
321*b562e72bSNiklas Söderlund 		   rpp_module_call(&rpp->hv.outif, start, hv)))
322*b562e72bSNiklas Söderlund 		return -EINVAL;
323*b562e72bSNiklas Söderlund 
324*b562e72bSNiklas Söderlund 	if (mv && (rpp_module_call(&rpp->mv.ga, start, mv) ||
325*b562e72bSNiklas Söderlund 		   rpp_module_call(&rpp->mv.ccor, start, mv) ||
326*b562e72bSNiklas Söderlund 		   rpp_module_call(&rpp->mv.xyz2luv, start, mv) ||
327*b562e72bSNiklas Söderlund 		   rpp_module_call(&rpp->mv.outregs, start, mv) ||
328*b562e72bSNiklas Söderlund 		   rpp_module_call(&rpp->mv.is, start, mv) ||
329*b562e72bSNiklas Söderlund 		   rpp_module_call(&rpp->mv.outif, start, mv)))
330*b562e72bSNiklas Söderlund 		return -EINVAL;
331*b562e72bSNiklas Söderlund 
332*b562e72bSNiklas Söderlund 	/* Immediate update for shadows. */
333*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_HDR_UPD_REG, RPPX1_RPP_HDR_UPD_REGS_CFG_UPD);
334*b562e72bSNiklas Söderlund 
335*b562e72bSNiklas Söderlund 	/* Clear fault interrupts. */
336*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_REG,
337*b562e72bSNiklas Söderlund 		    RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_ENABLE);
338*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_HDR_FMU_FSM_REG,
339*b562e72bSNiklas Söderlund 		    RPPX1_RPP_HDR_FMU_FSM_PRE2_FIFO_OVFLW |
340*b562e72bSNiklas Söderlund 		    RPPX1_RPP_HDR_FMU_FSM_PRE1_FIFO_OVFLW);
341*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_HDR_FMU_FSC_REG,
342*b562e72bSNiklas Söderlund 		    rppx1_read(rpp, RPPX1_RPP_HDR_FMU_MFS_REG));
343*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_REG,
344*b562e72bSNiklas Söderlund 		    RPPX1_RPP_HDR_SAFETY_ACCESS_PROTECTION_DISABLE);
345*b562e72bSNiklas Söderlund 
346*b562e72bSNiklas Söderlund 	/* Set interrupt mask. */
347*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_ISM, RPPX1_IRQ_ID_OUT_FRAME);
348*b562e72bSNiklas Söderlund 
349*b562e72bSNiklas Söderlund 	/* Immediate commit update for shadows. */
350*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_HDR_UPD_REG, RPPX1_RPP_HDR_UPD_REGS_CFG_UPD);
351*b562e72bSNiklas Söderlund 
352*b562e72bSNiklas Söderlund 	/* Then for operation update shadows with picture synchronization. */
353*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_HDR_UPD_REG, RPPX1_RPP_HDR_UPD_REGS_GEN_CFG_UPD);
354*b562e72bSNiklas Söderlund 
355*b562e72bSNiklas Söderlund 	/* Clear any pending interrupts. */
356*b562e72bSNiklas Söderlund 	rppx1_interrupt(rpp, NULL);
357*b562e72bSNiklas Söderlund 
358*b562e72bSNiklas Söderlund 	/* Enable input formatters. */
359*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_HDR_INFORM_ENABLE_REG,
360*b562e72bSNiklas Söderlund 		    RPPX1_RPP_HDR_INFORM_ENABLE_ENABLE);
361*b562e72bSNiklas Söderlund 
362*b562e72bSNiklas Söderlund 	return 0;
363*b562e72bSNiklas Söderlund }
364*b562e72bSNiklas Söderlund EXPORT_SYMBOL_GPL(rppx1_start);
365*b562e72bSNiklas Söderlund 
366*b562e72bSNiklas Söderlund int rppx1_stop(struct rppx1 *rpp)
367*b562e72bSNiklas Söderlund {
368*b562e72bSNiklas Söderlund 	/* Disable input formatters. */
369*b562e72bSNiklas Söderlund 	rppx1_write(rpp, RPPX1_RPP_HDR_INFORM_ENABLE_REG,
370*b562e72bSNiklas Söderlund 		    RPPX1_RPP_HDR_INFORM_ENABLE_DISABLE);
371*b562e72bSNiklas Söderlund 
372*b562e72bSNiklas Söderlund 	/* Clear any pending interrupts. */
373*b562e72bSNiklas Söderlund 	rppx1_interrupt(rpp, NULL);
374*b562e72bSNiklas Söderlund 
375*b562e72bSNiklas Söderlund 	return 0;
376*b562e72bSNiklas Söderlund }
377*b562e72bSNiklas Söderlund EXPORT_SYMBOL_GPL(rppx1_stop);
378*b562e72bSNiklas Söderlund 
379*b562e72bSNiklas Söderlund MODULE_AUTHOR("Niklas Söderlund <niklas.soderlund@ragnatech.se>");
380*b562e72bSNiklas Söderlund MODULE_DESCRIPTION("Dreamchip HDR RPPX1 support library");
381*b562e72bSNiklas Söderlund MODULE_LICENSE("GPL");
382