xref: /linux/drivers/media/platform/dreamchip/rppx1/rppx1_acq.c (revision f4cdf7ca9a1fdcca413157df19753f388a5a224e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2026 Renesas Electronics Corp.
4  * Copyright (C) 2026 Ideas on Board Oy
5  * Copyright (C) 2026 Ragnatech AB
6  */
7 
8 #include "rpp_module.h"
9 
10 #define ACQ_VERSION_REG				0x0000
11 
12 #define ACQ_CTRL_REG				0x0004
13 #define ACQ_CTRL_ALTERNATIVE_CFG_MODE_ENABLE	BIT(8)
14 #define ACQ_CTRL_RPP_MODE_MASK			GENMASK(3, 1)
15 #define ACQ_CTRL_RPP_MODE_RAWBT601		(0 << 1)
16 #define ACQ_CTRL_RPP_MODE_BT656			(1 << 1)
17 #define ACQ_CTRL_RPP_MODE_BT601			(2 << 1)
18 #define ACQ_CTRL_RPP_MODE_BAYER			(3 << 1)
19 #define ACQ_CTRL_RPP_MODE_DATA			(4 << 1)
20 #define ACQ_CTRL_RPP_MODE_BAYERRGB		(5 << 1)
21 #define ACQ_CTRL_RPP_MODE_RAWBT656		(6 << 1)
22 #define ACQ_CTRL_INFORM_EN_ENABLE		BIT(0)
23 
24 #define ACQ_PROP_REG				0x0008
25 
26 #define ACQ_PROP_SENSOR_IN_LSB_ALIGNED_IN_LSB	BIT(30)
27 #define ACQ_PROP_YUV_OUT_SEL			BIT(25)
28 #define ACQ_PROP_MUX_DMA_SEL			BIT(24)
29 #define ACQ_PROP_SECOND_INPUT_TYPE		BIT(18)
30 #define ACQ_PROP_LATENCY_FIFO_INPUT_SELECTION	BIT(15)
31 #define ACQ_PROP_INPUT_SELECTION_MASK		GENMASK(14, 12)
32 #define ACQ_PROP_INPUT_SELECTION_8BIT		(0 << 12)
33 #define ACQ_PROP_INPUT_SELECTION_10BIT		(1 << 12)
34 #define ACQ_PROP_INPUT_SELECTION_12BIT		(2 << 12)
35 #define ACQ_PROP_BAYER_PAT_MASK			GENMASK(4, 3)
36 #define ACQ_PROP_BAYER_PAT_RGRG			(0 << 3)
37 #define ACQ_PROP_BAYER_PAT_GRGR			(1 << 3)
38 #define ACQ_PROP_BAYER_PAT_GBGB			(2 << 3)
39 #define ACQ_PROP_BAYER_PAT_BGBG			(3 << 3)
40 #define ACQ_PROP_VSYNC_POL			BIT(2)
41 #define ACQ_PROP_HSYNC_POL			BIT(1)
42 #define ACQ_PROP_SAMPLE_EDGE			BIT(0)
43 
44 #define ACQ_H_OFFS_REG				0x000c
45 #define ACQ_V_OFFS_REG				0x0010
46 #define ACQ_H_SIZE_REG				0x0014
47 #define ACQ_V_SIZE_REG				0x0018
48 #define ACQ_OUT_H_OFFS_REG			0x001c
49 #define ACQ_OUT_V_OFFS_REG			0x0020
50 #define ACQ_OUT_H_SIZE_REG			0x0024
51 #define ACQ_OUT_V_SIZE_REG			0x0028
52 #define FLAGS_SHD_REG				0x002c
53 #define ACQ_OUT_H_OFFS_SHD_REG			0x0030
54 #define ACQ_OUT_V_OFFS_SHD_REG			0x0034
55 #define ACQ_OUT_H_SIZE_SHD_REG			0x0038
56 #define ACQ_OUT_V_SIZE_SHD_REG			0x003c
57 
58 static int rppx1_acq_probe(struct rpp_module *mod)
59 {
60 	/* Version check. */
61 	if (rpp_module_read(mod, ACQ_VERSION_REG) != 0x0b)
62 		return -EINVAL;
63 
64 	return 0;
65 }
66 
67 static int rppx1_acq_start(struct rpp_module *mod,
68 			   const struct v4l2_mbus_framefmt *fmt)
69 {
70 	u32 bayerpat, selection;
71 
72 	rpp_module_clrset(mod, ACQ_CTRL_REG, ACQ_CTRL_RPP_MODE_MASK,
73 			  ACQ_CTRL_RPP_MODE_BAYER);
74 
75 	rpp_module_write(mod, ACQ_H_OFFS_REG, 0);
76 	rpp_module_write(mod, ACQ_V_OFFS_REG, 0);
77 	rpp_module_write(mod, ACQ_H_SIZE_REG, fmt->width);
78 	rpp_module_write(mod, ACQ_V_SIZE_REG, fmt->height);
79 	rpp_module_write(mod, ACQ_OUT_H_OFFS_REG, 0);
80 	rpp_module_write(mod, ACQ_OUT_V_OFFS_REG, 0);
81 	rpp_module_write(mod, ACQ_OUT_H_SIZE_REG, fmt->width);
82 	rpp_module_write(mod, ACQ_OUT_V_SIZE_REG, fmt->height);
83 
84 	switch (fmt->code) {
85 	case MEDIA_BUS_FMT_SBGGR8_1X8:
86 	case MEDIA_BUS_FMT_SBGGR10_1X10:
87 	case MEDIA_BUS_FMT_SBGGR12_1X12:
88 		mod->info.acq.raw_pattern = RPP_BGGR;
89 		bayerpat = ACQ_PROP_BAYER_PAT_BGBG;
90 		break;
91 	case MEDIA_BUS_FMT_SGBRG8_1X8:
92 	case MEDIA_BUS_FMT_SGBRG10_1X10:
93 	case MEDIA_BUS_FMT_SGBRG12_1X12:
94 		mod->info.acq.raw_pattern = RPP_GBRG;
95 		bayerpat = ACQ_PROP_BAYER_PAT_GBGB;
96 		break;
97 	case MEDIA_BUS_FMT_SGRBG8_1X8:
98 	case MEDIA_BUS_FMT_SGRBG10_1X10:
99 	case MEDIA_BUS_FMT_SGRBG12_1X12:
100 		mod->info.acq.raw_pattern = RPP_GRBG;
101 		bayerpat = ACQ_PROP_BAYER_PAT_GRGR;
102 		break;
103 	case MEDIA_BUS_FMT_SRGGB8_1X8:
104 	case MEDIA_BUS_FMT_SRGGB10_1X10:
105 	case MEDIA_BUS_FMT_SRGGB12_1X12:
106 		mod->info.acq.raw_pattern = RPP_RGGB;
107 		bayerpat = ACQ_PROP_BAYER_PAT_RGRG;
108 		break;
109 	default:
110 		return -EINVAL;
111 	}
112 
113 	switch (fmt->code) {
114 	case MEDIA_BUS_FMT_SBGGR8_1X8:
115 	case MEDIA_BUS_FMT_SGBRG8_1X8:
116 	case MEDIA_BUS_FMT_SGRBG8_1X8:
117 	case MEDIA_BUS_FMT_SRGGB8_1X8:
118 		selection = ACQ_PROP_INPUT_SELECTION_8BIT;
119 		break;
120 	case MEDIA_BUS_FMT_SBGGR10_1X10:
121 	case MEDIA_BUS_FMT_SGBRG10_1X10:
122 	case MEDIA_BUS_FMT_SGRBG10_1X10:
123 	case MEDIA_BUS_FMT_SRGGB10_1X10:
124 		selection = ACQ_PROP_INPUT_SELECTION_10BIT;
125 		break;
126 	case MEDIA_BUS_FMT_SBGGR12_1X12:
127 	case MEDIA_BUS_FMT_SGBRG12_1X12:
128 	case MEDIA_BUS_FMT_SGRBG12_1X12:
129 	case MEDIA_BUS_FMT_SRGGB12_1X12:
130 		selection = ACQ_PROP_INPUT_SELECTION_12BIT;
131 		break;
132 	default:
133 		return -EINVAL;
134 	}
135 
136 	rpp_module_write(mod, ACQ_PROP_REG, bayerpat | selection |
137 			 ACQ_PROP_SENSOR_IN_LSB_ALIGNED_IN_LSB);
138 
139 	rpp_module_clrset(mod, ACQ_CTRL_REG, ACQ_CTRL_INFORM_EN_ENABLE,
140 			  ACQ_CTRL_INFORM_EN_ENABLE);
141 
142 	return 0;
143 }
144 
145 const struct rpp_module_ops rppx1_acq_ops = {
146 	.probe = rppx1_acq_probe,
147 	.start = rppx1_acq_start,
148 };
149