1 // SPDX-License-Identifier: GPL-2.0
3 * Allied Vision Technologies GmbH Alvium camera driver
5 * Copyright (C) 2023 Tommaso Merciai
6 * Copyright (C) 2023 Martin Hecht
7 * Copyright (C) 2023 Avnet EMG GmbH
10 #include <linux/i2c.h>
11 #include <linux/module.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/regmap.h>
14 #include <linux/regulator/consumer.h>
15 #include <media/mipi-csi2.h>
16 #include <media/v4l2-async.h>
17 #include <media/v4l2-ctrls.h>
18 #include <media/v4l2-device.h>
19 #include <media/v4l2-fwnode.h>
20 #include <media/v4l2-subdev.h>
22 #include "alvium-csi2.h"
24 static const struct v4l2_mbus_framefmt alvium_csi2_default_fmt
= {
25 .code
= MEDIA_BUS_FMT_UYVY8_1X16
,
28 .colorspace
= V4L2_COLORSPACE_SRGB
,
29 .ycbcr_enc
= V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB
),
30 .quantization
= V4L2_QUANTIZATION_FULL_RANGE
,
31 .xfer_func
= V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB
),
32 .field
= V4L2_FIELD_NONE
,
35 static const struct alvium_pixfmt alvium_csi2_fmts
[] = {
38 .id
= ALVIUM_FMT_UYVY8_2X8
,
39 .code
= MEDIA_BUS_FMT_UYVY8_2X8
,
40 .colorspace
= V4L2_COLORSPACE_SRGB
,
41 .fmt_av_bit
= ALVIUM_BIT_YUV422_8
,
42 .bay_av_bit
= ALVIUM_BIT_BAY_NONE
,
43 .mipi_fmt_regval
= MIPI_CSI2_DT_YUV422_8B
,
48 .id
= ALVIUM_FMT_UYVY8_1X16
,
49 .code
= MEDIA_BUS_FMT_UYVY8_1X16
,
50 .colorspace
= V4L2_COLORSPACE_SRGB
,
51 .fmt_av_bit
= ALVIUM_BIT_YUV422_8
,
52 .bay_av_bit
= ALVIUM_BIT_BAY_NONE
,
53 .mipi_fmt_regval
= MIPI_CSI2_DT_YUV422_8B
,
58 .id
= ALVIUM_FMT_YUYV8_1X16
,
59 .code
= MEDIA_BUS_FMT_YUYV8_1X16
,
60 .colorspace
= V4L2_COLORSPACE_SRGB
,
61 .fmt_av_bit
= ALVIUM_BIT_YUV422_8
,
62 .bay_av_bit
= ALVIUM_BIT_BAY_NONE
,
63 .mipi_fmt_regval
= MIPI_CSI2_DT_YUV422_8B
,
68 .id
= ALVIUM_FMT_YUYV8_2X8
,
69 .code
= MEDIA_BUS_FMT_YUYV8_2X8
,
70 .colorspace
= V4L2_COLORSPACE_SRGB
,
71 .fmt_av_bit
= ALVIUM_BIT_YUV422_8
,
72 .bay_av_bit
= ALVIUM_BIT_BAY_NONE
,
73 .mipi_fmt_regval
= MIPI_CSI2_DT_YUV422_8B
,
78 .id
= ALVIUM_FMT_YUYV10_1X20
,
79 .code
= MEDIA_BUS_FMT_YUYV10_1X20
,
80 .colorspace
= V4L2_COLORSPACE_SRGB
,
81 .fmt_av_bit
= ALVIUM_BIT_YUV422_10
,
82 .bay_av_bit
= ALVIUM_BIT_BAY_NONE
,
83 .mipi_fmt_regval
= MIPI_CSI2_DT_YUV422_10B
,
88 .id
= ALVIUM_FMT_RGB888_1X24
,
89 .code
= MEDIA_BUS_FMT_RGB888_1X24
,
90 .colorspace
= V4L2_COLORSPACE_SRGB
,
91 .fmt_av_bit
= ALVIUM_BIT_RGB888
,
92 .bay_av_bit
= ALVIUM_BIT_BAY_NONE
,
93 .mipi_fmt_regval
= MIPI_CSI2_DT_RGB888
,
98 .id
= ALVIUM_FMT_RBG888_1X24
,
99 .code
= MEDIA_BUS_FMT_RBG888_1X24
,
100 .colorspace
= V4L2_COLORSPACE_SRGB
,
101 .fmt_av_bit
= ALVIUM_BIT_RGB888
,
102 .bay_av_bit
= ALVIUM_BIT_BAY_NONE
,
103 .mipi_fmt_regval
= MIPI_CSI2_DT_RGB888
,
104 .bay_fmt_regval
= -1,
108 .id
= ALVIUM_FMT_BGR888_1X24
,
109 .code
= MEDIA_BUS_FMT_BGR888_1X24
,
110 .colorspace
= V4L2_COLORSPACE_SRGB
,
111 .fmt_av_bit
= ALVIUM_BIT_RGB888
,
112 .bay_av_bit
= ALVIUM_BIT_BAY_NONE
,
113 .mipi_fmt_regval
= MIPI_CSI2_DT_RGB888
,
114 .bay_fmt_regval
= -1,
118 .id
= ALVIUM_FMT_RGB888_3X8
,
119 .code
= MEDIA_BUS_FMT_RGB888_3X8
,
120 .colorspace
= V4L2_COLORSPACE_SRGB
,
121 .fmt_av_bit
= ALVIUM_BIT_RGB888
,
122 .bay_av_bit
= ALVIUM_BIT_BAY_NONE
,
123 .mipi_fmt_regval
= MIPI_CSI2_DT_RGB888
,
124 .bay_fmt_regval
= -1,
128 .id
= ALVIUM_FMT_Y8_1X8
,
129 .code
= MEDIA_BUS_FMT_Y8_1X8
,
130 .colorspace
= V4L2_COLORSPACE_RAW
,
131 .fmt_av_bit
= ALVIUM_BIT_RAW8
,
132 .bay_av_bit
= ALVIUM_BIT_BAY_MONO
,
133 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW8
,
134 .bay_fmt_regval
= 0x00,
138 .id
= ALVIUM_FMT_SGRBG8_1X8
,
139 .code
= MEDIA_BUS_FMT_SGRBG8_1X8
,
140 .colorspace
= V4L2_COLORSPACE_RAW
,
141 .fmt_av_bit
= ALVIUM_BIT_RAW8
,
142 .bay_av_bit
= ALVIUM_BIT_BAY_GR
,
143 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW8
,
144 .bay_fmt_regval
= 0x01,
148 .id
= ALVIUM_FMT_SRGGB8_1X8
,
149 .code
= MEDIA_BUS_FMT_SRGGB8_1X8
,
150 .colorspace
= V4L2_COLORSPACE_RAW
,
151 .fmt_av_bit
= ALVIUM_BIT_RAW8
,
152 .bay_av_bit
= ALVIUM_BIT_BAY_RG
,
153 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW8
,
154 .bay_fmt_regval
= 0x02,
158 .id
= ALVIUM_FMT_SGBRG8_1X8
,
159 .code
= MEDIA_BUS_FMT_SGBRG8_1X8
,
160 .colorspace
= V4L2_COLORSPACE_RAW
,
161 .fmt_av_bit
= ALVIUM_BIT_RAW8
,
162 .bay_av_bit
= ALVIUM_BIT_BAY_GB
,
163 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW8
,
164 .bay_fmt_regval
= 0x03,
168 .id
= ALVIUM_FMT_SBGGR8_1X8
,
169 .code
= MEDIA_BUS_FMT_SBGGR8_1X8
,
170 .colorspace
= V4L2_COLORSPACE_RAW
,
171 .fmt_av_bit
= ALVIUM_BIT_RAW8
,
172 .bay_av_bit
= ALVIUM_BIT_BAY_BG
,
173 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW8
,
174 .bay_fmt_regval
= 0x04,
178 .id
= ALVIUM_FMT_Y10_1X10
,
179 .code
= MEDIA_BUS_FMT_Y10_1X10
,
180 .colorspace
= V4L2_COLORSPACE_RAW
,
181 .fmt_av_bit
= ALVIUM_BIT_RAW10
,
182 .bay_av_bit
= ALVIUM_BIT_BAY_MONO
,
183 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW10
,
184 .bay_fmt_regval
= 0x00,
188 .id
= ALVIUM_FMT_SGRBG10_1X10
,
189 .code
= MEDIA_BUS_FMT_SGRBG10_1X10
,
190 .colorspace
= V4L2_COLORSPACE_RAW
,
191 .fmt_av_bit
= ALVIUM_BIT_RAW10
,
192 .bay_av_bit
= ALVIUM_BIT_BAY_GR
,
193 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW10
,
194 .bay_fmt_regval
= 0x01,
198 .id
= ALVIUM_FMT_SRGGB10_1X10
,
199 .code
= MEDIA_BUS_FMT_SRGGB10_1X10
,
200 .colorspace
= V4L2_COLORSPACE_RAW
,
201 .fmt_av_bit
= ALVIUM_BIT_RAW10
,
202 .bay_av_bit
= ALVIUM_BIT_BAY_RG
,
203 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW10
,
204 .bay_fmt_regval
= 0x02,
208 .id
= ALVIUM_FMT_SGBRG10_1X10
,
209 .code
= MEDIA_BUS_FMT_SGBRG10_1X10
,
210 .colorspace
= V4L2_COLORSPACE_RAW
,
211 .fmt_av_bit
= ALVIUM_BIT_RAW10
,
212 .bay_av_bit
= ALVIUM_BIT_BAY_GB
,
213 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW10
,
214 .bay_fmt_regval
= 0x03,
218 .id
= ALVIUM_FMT_SBGGR10_1X10
,
219 .code
= MEDIA_BUS_FMT_SBGGR10_1X10
,
220 .colorspace
= V4L2_COLORSPACE_RAW
,
221 .fmt_av_bit
= ALVIUM_BIT_RAW10
,
222 .bay_av_bit
= ALVIUM_BIT_BAY_BG
,
223 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW10
,
224 .bay_fmt_regval
= 0x04,
228 .id
= ALVIUM_FMT_Y12_1X12
,
229 .code
= MEDIA_BUS_FMT_Y12_1X12
,
230 .colorspace
= V4L2_COLORSPACE_RAW
,
231 .fmt_av_bit
= ALVIUM_BIT_RAW12
,
232 .bay_av_bit
= ALVIUM_BIT_BAY_MONO
,
233 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW12
,
234 .bay_fmt_regval
= 0x00,
238 .id
= ALVIUM_FMT_SGRBG12_1X12
,
239 .code
= MEDIA_BUS_FMT_SGRBG12_1X12
,
240 .colorspace
= V4L2_COLORSPACE_RAW
,
241 .fmt_av_bit
= ALVIUM_BIT_RAW12
,
242 .bay_av_bit
= ALVIUM_BIT_BAY_GR
,
243 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW12
,
244 .bay_fmt_regval
= 0x01,
248 .id
= ALVIUM_FMT_SRGGB12_1X12
,
249 .code
= MEDIA_BUS_FMT_SRGGB12_1X12
,
250 .colorspace
= V4L2_COLORSPACE_RAW
,
251 .fmt_av_bit
= ALVIUM_BIT_RAW12
,
252 .bay_av_bit
= ALVIUM_BIT_BAY_RG
,
253 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW12
,
254 .bay_fmt_regval
= 0x02,
258 .id
= ALVIUM_FMT_SGBRG12_1X12
,
259 .code
= MEDIA_BUS_FMT_SGBRG12_1X12
,
260 .colorspace
= V4L2_COLORSPACE_RAW
,
261 .fmt_av_bit
= ALVIUM_BIT_RAW12
,
262 .bay_av_bit
= ALVIUM_BIT_BAY_GB
,
263 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW12
,
264 .bay_fmt_regval
= 0x03,
268 .id
= ALVIUM_FMT_SBGGR12_1X12
,
269 .code
= MEDIA_BUS_FMT_SBGGR12_1X12
,
270 .colorspace
= V4L2_COLORSPACE_RAW
,
271 .fmt_av_bit
= ALVIUM_BIT_RAW12
,
272 .bay_av_bit
= ALVIUM_BIT_BAY_BG
,
273 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW12
,
274 .bay_fmt_regval
= 0x04,
278 .id
= ALVIUM_FMT_SBGGR14_1X14
,
279 .code
= MEDIA_BUS_FMT_SBGGR14_1X14
,
280 .colorspace
= V4L2_COLORSPACE_RAW
,
281 .fmt_av_bit
= ALVIUM_BIT_RAW14
,
282 .bay_av_bit
= ALVIUM_BIT_BAY_GR
,
283 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW14
,
284 .bay_fmt_regval
= 0x01,
288 .id
= ALVIUM_FMT_SGBRG14_1X14
,
289 .code
= MEDIA_BUS_FMT_SGBRG14_1X14
,
290 .colorspace
= V4L2_COLORSPACE_RAW
,
291 .fmt_av_bit
= ALVIUM_BIT_RAW14
,
292 .bay_av_bit
= ALVIUM_BIT_BAY_RG
,
293 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW14
,
294 .bay_fmt_regval
= 0x02,
298 .id
= ALVIUM_FMT_SRGGB14_1X14
,
299 .code
= MEDIA_BUS_FMT_SRGGB14_1X14
,
300 .colorspace
= V4L2_COLORSPACE_RAW
,
301 .fmt_av_bit
= ALVIUM_BIT_RAW14
,
302 .bay_av_bit
= ALVIUM_BIT_BAY_GB
,
303 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW14
,
304 .bay_fmt_regval
= 0x03,
308 .id
= ALVIUM_FMT_SGRBG14_1X14
,
309 .code
= MEDIA_BUS_FMT_SGRBG14_1X14
,
310 .colorspace
= V4L2_COLORSPACE_RAW
,
311 .fmt_av_bit
= ALVIUM_BIT_RAW14
,
312 .bay_av_bit
= ALVIUM_BIT_BAY_BG
,
313 .mipi_fmt_regval
= MIPI_CSI2_DT_RAW14
,
314 .bay_fmt_regval
= 0x04,
320 static int alvium_read(struct alvium_dev
*alvium
, u32 reg
, u64
*val
, int *err
)
322 if (reg
& REG_BCRM_V4L2
) {
323 reg
&= ~REG_BCRM_V4L2
;
324 reg
+= alvium
->bcrm_addr
;
327 return cci_read(alvium
->regmap
, reg
, val
, err
);
330 static int alvium_write(struct alvium_dev
*alvium
, u32 reg
, u64 val
, int *err
)
332 if (reg
& REG_BCRM_V4L2
) {
333 reg
&= ~REG_BCRM_V4L2
;
334 reg
+= alvium
->bcrm_addr
;
337 return cci_write(alvium
->regmap
, reg
, val
, err
);
340 static int alvium_write_hshake(struct alvium_dev
*alvium
, u32 reg
, u64 val
)
342 struct device
*dev
= &alvium
->i2c_client
->dev
;
346 /* reset handshake bit and write alvium reg */
347 alvium_write(alvium
, REG_BCRM_WRITE_HANDSHAKE_RW
, 0, &ret
);
348 alvium_write(alvium
, reg
, val
, &ret
);
350 dev_err(dev
, "Fail to write reg\n");
354 /* poll handshake bit since bit0 = 1 */
355 read_poll_timeout(alvium_read
, hshake_bit
,
356 ((hshake_bit
& BCRM_HANDSHAKE_W_DONE_EN_BIT
) == 1),
358 alvium
, REG_BCRM_WRITE_HANDSHAKE_RW
,
361 dev_err(dev
, "poll bit[0] = 1, hshake reg fail\n");
365 /* reset handshake bit, write 0 to bit0 */
366 alvium_write(alvium
, REG_BCRM_WRITE_HANDSHAKE_RW
, 0, &ret
);
368 dev_err(dev
, "Fail to reset hshake reg\n");
372 /* poll handshake bit since bit0 = 0 */
373 read_poll_timeout(alvium_read
, hshake_bit
,
374 ((hshake_bit
& BCRM_HANDSHAKE_W_DONE_EN_BIT
) == 0),
376 alvium
, REG_BCRM_WRITE_HANDSHAKE_RW
,
379 dev_err(dev
, "poll bit[0] = 0, hshake reg fail\n");
386 static int alvium_get_bcrm_vers(struct alvium_dev
*alvium
)
388 struct device
*dev
= &alvium
->i2c_client
->dev
;
392 ret
= alvium_read(alvium
, REG_BCRM_MINOR_VERSION_R
, &min
, &ret
);
393 ret
= alvium_read(alvium
, REG_BCRM_MAJOR_VERSION_R
, &maj
, &ret
);
397 dev_info(dev
, "bcrm version: %llu.%llu\n", min
, maj
);
402 static int alvium_get_fw_version(struct alvium_dev
*alvium
)
404 struct device
*dev
= &alvium
->i2c_client
->dev
;
408 ret
= alvium_read(alvium
, REG_BCRM_DEVICE_FW
, &val
, NULL
);
412 dev_info(dev
, "fw version: %02u.%02u.%04u.%08x\n",
413 (u8
)((val
& BCRM_DEVICE_FW_SPEC_MASK
) >>
414 BCRM_DEVICE_FW_SPEC_SHIFT
),
415 (u8
)((val
& BCRM_DEVICE_FW_MAJOR_MASK
) >>
416 BCRM_DEVICE_FW_MAJOR_SHIFT
),
417 (u16
)((val
& BCRM_DEVICE_FW_MINOR_MASK
) >>
418 BCRM_DEVICE_FW_MINOR_SHIFT
),
419 (u32
)((val
& BCRM_DEVICE_FW_PATCH_MASK
) >>
420 BCRM_DEVICE_FW_PATCH_SHIFT
));
425 static int alvium_get_bcrm_addr(struct alvium_dev
*alvium
)
430 ret
= alvium_read(alvium
, REG_BCRM_REG_ADDR_R
, &val
, NULL
);
434 alvium
->bcrm_addr
= val
;
439 static int alvium_is_alive(struct alvium_dev
*alvium
)
444 alvium_read(alvium
, REG_BCRM_MINOR_VERSION_R
, &bcrm
, &ret
);
445 alvium_read(alvium
, REG_BCRM_HEARTBEAT_RW
, &hbeat
, &ret
);
452 static void alvium_print_avail_mipi_fmt(struct alvium_dev
*alvium
)
454 struct device
*dev
= &alvium
->i2c_client
->dev
;
456 dev_dbg(dev
, "avail mipi_fmt yuv420_8_leg: %u\n",
457 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_8_LEG
]);
458 dev_dbg(dev
, "avail mipi_fmt yuv420_8: %u\n",
459 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_8
]);
460 dev_dbg(dev
, "avail mipi_fmt yuv420_10: %u\n",
461 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_10
]);
462 dev_dbg(dev
, "avail mipi_fmt yuv420_8_csps: %u\n",
463 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_8_CSPS
]);
464 dev_dbg(dev
, "avail mipi_fmt yuv420_10_csps: %u\n",
465 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_10_CSPS
]);
466 dev_dbg(dev
, "avail mipi_fmt yuv422_8: %u\n",
467 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV422_8
]);
468 dev_dbg(dev
, "avail mipi_fmt yuv422_10: %u\n",
469 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV422_10
]);
470 dev_dbg(dev
, "avail mipi_fmt rgb888: %u\n",
471 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB888
]);
472 dev_dbg(dev
, "avail mipi_fmt rgb666: %u\n",
473 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB666
]);
474 dev_dbg(dev
, "avail mipi_fmt rgb565: %u\n",
475 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB565
]);
476 dev_dbg(dev
, "avail mipi_fmt rgb555: %u\n",
477 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB555
]);
478 dev_dbg(dev
, "avail mipi_fmt rgb444: %u\n",
479 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB444
]);
480 dev_dbg(dev
, "avail mipi_fmt raw6: %u\n",
481 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW6
]);
482 dev_dbg(dev
, "avail mipi_fmt raw7: %u\n",
483 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW7
]);
484 dev_dbg(dev
, "avail mipi_fmt raw8: %u\n",
485 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW8
]);
486 dev_dbg(dev
, "avail mipi_fmt raw10: %u\n",
487 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW10
]);
488 dev_dbg(dev
, "avail mipi_fmt raw12: %u\n",
489 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW12
]);
490 dev_dbg(dev
, "avail mipi_fmt raw14: %u\n",
491 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW14
]);
492 dev_dbg(dev
, "avail mipi_fmt jpeg: %u\n",
493 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_JPEG
]);
496 static void alvium_print_avail_feat(struct alvium_dev
*alvium
)
498 struct device
*dev
= &alvium
->i2c_client
->dev
;
500 dev_dbg(dev
, "feature rev_x: %u\n", alvium
->avail_ft
.rev_x
);
501 dev_dbg(dev
, "feature rev_y: %u\n", alvium
->avail_ft
.rev_y
);
502 dev_dbg(dev
, "feature int_autop: %u\n", alvium
->avail_ft
.int_autop
);
503 dev_dbg(dev
, "feature black_lvl: %u\n", alvium
->avail_ft
.black_lvl
);
504 dev_dbg(dev
, "feature gain: %u\n", alvium
->avail_ft
.gain
);
505 dev_dbg(dev
, "feature gamma: %u\n", alvium
->avail_ft
.gamma
);
506 dev_dbg(dev
, "feature contrast: %u\n", alvium
->avail_ft
.contrast
);
507 dev_dbg(dev
, "feature sat: %u\n", alvium
->avail_ft
.sat
);
508 dev_dbg(dev
, "feature hue: %u\n", alvium
->avail_ft
.hue
);
509 dev_dbg(dev
, "feature whiteb: %u\n", alvium
->avail_ft
.whiteb
);
510 dev_dbg(dev
, "feature sharp: %u\n", alvium
->avail_ft
.sharp
);
511 dev_dbg(dev
, "feature auto_exp: %u\n", alvium
->avail_ft
.auto_exp
);
512 dev_dbg(dev
, "feature auto_gain: %u\n", alvium
->avail_ft
.auto_gain
);
513 dev_dbg(dev
, "feature auto_whiteb: %u\n", alvium
->avail_ft
.auto_whiteb
);
514 dev_dbg(dev
, "feature dev_temp: %u\n", alvium
->avail_ft
.dev_temp
);
515 dev_dbg(dev
, "feature acq_abort: %u\n", alvium
->avail_ft
.acq_abort
);
516 dev_dbg(dev
, "feature acq_fr: %u\n", alvium
->avail_ft
.acq_fr
);
517 dev_dbg(dev
, "feature fr_trigger: %u\n", alvium
->avail_ft
.fr_trigger
);
518 dev_dbg(dev
, "feature exp_acq_line: %u\n",
519 alvium
->avail_ft
.exp_acq_line
);
522 static void alvium_print_avail_bayer(struct alvium_dev
*alvium
)
524 struct device
*dev
= &alvium
->i2c_client
->dev
;
526 dev_dbg(dev
, "avail bayer mono: %u\n",
527 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_MONO
]);
528 dev_dbg(dev
, "avail bayer gr: %u\n",
529 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_GR
]);
530 dev_dbg(dev
, "avail bayer rg: %u\n",
531 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_RG
]);
532 dev_dbg(dev
, "avail bayer gb: %u\n",
533 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_GB
]);
534 dev_dbg(dev
, "avail bayer bg: %u\n",
535 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_BG
]);
538 static int alvium_get_feat_inq(struct alvium_dev
*alvium
)
540 struct alvium_avail_feat
*f
;
544 ret
= alvium_read(alvium
, REG_BCRM_FEATURE_INQUIRY_R
, &val
, NULL
);
548 f
= (struct alvium_avail_feat
*)&val
;
549 alvium
->avail_ft
= *f
;
550 alvium_print_avail_feat(alvium
);
555 static int alvium_get_host_supp_csi_lanes(struct alvium_dev
*alvium
)
560 ret
= alvium_read(alvium
, REG_BCRM_CSI2_LANE_COUNT_RW
, &val
, NULL
);
564 alvium
->h_sup_csi_lanes
= val
;
569 static int alvium_set_csi_lanes(struct alvium_dev
*alvium
)
571 struct device
*dev
= &alvium
->i2c_client
->dev
;
575 num_lanes
= alvium
->ep
.bus
.mipi_csi2
.num_data_lanes
;
577 if (num_lanes
> alvium
->h_sup_csi_lanes
)
580 ret
= alvium_write_hshake(alvium
, REG_BCRM_CSI2_LANE_COUNT_RW
,
583 dev_err(dev
, "Fail to set csi lanes reg\n");
590 static int alvium_set_lp2hs_delay(struct alvium_dev
*alvium
)
592 struct device
*dev
= &alvium
->i2c_client
->dev
;
596 * The purpose of this reg is force a DPhy reset
597 * for the period described by the millisecond on
598 * the reg, before it starts streaming.
600 * To be clear, with that value bigger than 0 the
601 * Alvium forces a dphy-reset on all lanes for that period.
602 * That means all lanes go up into low power state.
605 alvium_write(alvium
, REG_BCRM_LP2HS_DELAY_RW
,
606 ALVIUM_LP2HS_DELAY_MS
, &ret
);
608 dev_err(dev
, "Fail to set lp2hs delay reg\n");
615 static int alvium_get_csi_clk_params(struct alvium_dev
*alvium
)
617 u64 min_csi_clk
, max_csi_clk
;
620 alvium_read(alvium
, REG_BCRM_CSI2_CLOCK_MIN_R
, &min_csi_clk
, &ret
);
621 alvium_read(alvium
, REG_BCRM_CSI2_CLOCK_MAX_R
, &max_csi_clk
, &ret
);
625 alvium
->min_csi_clk
= min_csi_clk
;
626 alvium
->max_csi_clk
= max_csi_clk
;
631 static int alvium_set_csi_clk(struct alvium_dev
*alvium
)
633 struct device
*dev
= &alvium
->i2c_client
->dev
;
637 csi_clk
= clamp(alvium
->ep
.link_frequencies
[0],
638 (u64
)alvium
->min_csi_clk
, (u64
)alvium
->max_csi_clk
);
640 if (alvium
->ep
.link_frequencies
[0] != (u64
)csi_clk
) {
642 "requested csi clock (%llu MHz) out of range [%u, %u] Adjusted to %llu\n",
643 alvium
->ep
.link_frequencies
[0],
644 alvium
->min_csi_clk
, alvium
->max_csi_clk
, csi_clk
);
647 ret
= alvium_write_hshake(alvium
, REG_BCRM_CSI2_CLOCK_RW
, csi_clk
);
649 dev_err(dev
, "Fail to set csi clock reg\n");
653 alvium
->link_freq
= csi_clk
;
658 static int alvium_get_img_width_params(struct alvium_dev
*alvium
)
660 u64 imgw
, imgw_min
, imgw_max
, imgw_inc
;
663 alvium_read(alvium
, REG_BCRM_IMG_WIDTH_RW
, &imgw
, &ret
);
664 alvium_read(alvium
, REG_BCRM_IMG_WIDTH_MIN_R
, &imgw_min
, &ret
);
665 alvium_read(alvium
, REG_BCRM_IMG_WIDTH_MAX_R
, &imgw_max
, &ret
);
666 alvium_read(alvium
, REG_BCRM_IMG_WIDTH_INC_R
, &imgw_inc
, &ret
);
670 alvium
->dft_img_width
= imgw
;
671 alvium
->img_min_width
= imgw_min
;
672 alvium
->img_max_width
= imgw_max
;
673 alvium
->img_inc_width
= imgw_inc
;
678 static int alvium_get_img_height_params(struct alvium_dev
*alvium
)
680 u64 imgh
, imgh_min
, imgh_max
, imgh_inc
;
683 alvium_read(alvium
, REG_BCRM_IMG_HEIGHT_RW
, &imgh
, &ret
);
684 alvium_read(alvium
, REG_BCRM_IMG_HEIGHT_MIN_R
, &imgh_min
, &ret
);
685 alvium_read(alvium
, REG_BCRM_IMG_HEIGHT_MAX_R
, &imgh_max
, &ret
);
686 alvium_read(alvium
, REG_BCRM_IMG_HEIGHT_INC_R
, &imgh_inc
, &ret
);
690 alvium
->dft_img_height
= imgh
;
691 alvium
->img_min_height
= imgh_min
;
692 alvium
->img_max_height
= imgh_max
;
693 alvium
->img_inc_height
= imgh_inc
;
698 static int alvium_set_img_width(struct alvium_dev
*alvium
, u32 width
)
700 struct device
*dev
= &alvium
->i2c_client
->dev
;
703 ret
= alvium_write_hshake(alvium
, REG_BCRM_IMG_WIDTH_RW
, width
);
705 dev_err(dev
, "Fail to set img width\n");
712 static int alvium_set_img_height(struct alvium_dev
*alvium
, u32 height
)
714 struct device
*dev
= &alvium
->i2c_client
->dev
;
717 ret
= alvium_write_hshake(alvium
, REG_BCRM_IMG_HEIGHT_RW
, height
);
719 dev_err(dev
, "Fail to set img height\n");
726 static int alvium_set_img_offx(struct alvium_dev
*alvium
, u32 offx
)
728 struct device
*dev
= &alvium
->i2c_client
->dev
;
731 ret
= alvium_write_hshake(alvium
, REG_BCRM_IMG_OFFSET_X_RW
, offx
);
733 dev_err(dev
, "Fail to set img offx\n");
740 static int alvium_set_img_offy(struct alvium_dev
*alvium
, u32 offy
)
742 struct device
*dev
= &alvium
->i2c_client
->dev
;
745 ret
= alvium_write_hshake(alvium
, REG_BCRM_IMG_OFFSET_Y_RW
, offy
);
747 dev_err(dev
, "Fail to set img offy\n");
754 static int alvium_get_offx_params(struct alvium_dev
*alvium
)
756 u64 min_offx
, max_offx
, inc_offx
;
759 alvium_read(alvium
, REG_BCRM_IMG_OFFSET_X_MIN_R
, &min_offx
, &ret
);
760 alvium_read(alvium
, REG_BCRM_IMG_OFFSET_X_MAX_R
, &max_offx
, &ret
);
761 alvium_read(alvium
, REG_BCRM_IMG_OFFSET_X_INC_R
, &inc_offx
, &ret
);
765 alvium
->min_offx
= min_offx
;
766 alvium
->max_offx
= max_offx
;
767 alvium
->inc_offx
= inc_offx
;
772 static int alvium_get_offy_params(struct alvium_dev
*alvium
)
774 u64 min_offy
, max_offy
, inc_offy
;
777 alvium_read(alvium
, REG_BCRM_IMG_OFFSET_Y_MIN_R
, &min_offy
, &ret
);
778 alvium_read(alvium
, REG_BCRM_IMG_OFFSET_Y_MAX_R
, &max_offy
, &ret
);
779 alvium_read(alvium
, REG_BCRM_IMG_OFFSET_Y_INC_R
, &inc_offy
, &ret
);
783 alvium
->min_offy
= min_offy
;
784 alvium
->max_offy
= max_offy
;
785 alvium
->inc_offy
= inc_offy
;
790 static int alvium_get_gain_params(struct alvium_dev
*alvium
)
792 u64 dft_gain
, min_gain
, max_gain
, inc_gain
;
795 alvium_read(alvium
, REG_BCRM_GAIN_RW
, &dft_gain
, &ret
);
796 alvium_read(alvium
, REG_BCRM_GAIN_MIN_R
, &min_gain
, &ret
);
797 alvium_read(alvium
, REG_BCRM_GAIN_MAX_R
, &max_gain
, &ret
);
798 alvium_read(alvium
, REG_BCRM_GAIN_INC_R
, &inc_gain
, &ret
);
802 alvium
->dft_gain
= dft_gain
;
803 alvium
->min_gain
= min_gain
;
804 alvium
->max_gain
= max_gain
;
805 alvium
->inc_gain
= inc_gain
;
810 static int alvium_get_exposure_params(struct alvium_dev
*alvium
)
812 u64 dft_exp
, min_exp
, max_exp
, inc_exp
;
815 alvium_read(alvium
, REG_BCRM_EXPOSURE_TIME_RW
, &dft_exp
, &ret
);
816 alvium_read(alvium
, REG_BCRM_EXPOSURE_TIME_MIN_R
, &min_exp
, &ret
);
817 alvium_read(alvium
, REG_BCRM_EXPOSURE_TIME_MAX_R
, &max_exp
, &ret
);
818 alvium_read(alvium
, REG_BCRM_EXPOSURE_TIME_INC_R
, &inc_exp
, &ret
);
822 alvium
->dft_exp
= dft_exp
;
823 alvium
->min_exp
= min_exp
;
824 alvium
->max_exp
= max_exp
;
825 alvium
->inc_exp
= inc_exp
;
830 static int alvium_get_red_balance_ratio_params(struct alvium_dev
*alvium
)
832 u64 dft_rb
, min_rb
, max_rb
, inc_rb
;
835 alvium_read(alvium
, REG_BCRM_RED_BALANCE_RATIO_RW
, &dft_rb
, &ret
);
836 alvium_read(alvium
, REG_BCRM_RED_BALANCE_RATIO_MIN_R
, &min_rb
, &ret
);
837 alvium_read(alvium
, REG_BCRM_RED_BALANCE_RATIO_MAX_R
, &max_rb
, &ret
);
838 alvium_read(alvium
, REG_BCRM_RED_BALANCE_RATIO_INC_R
, &inc_rb
, &ret
);
842 alvium
->dft_rbalance
= dft_rb
;
843 alvium
->min_rbalance
= min_rb
;
844 alvium
->max_rbalance
= max_rb
;
845 alvium
->inc_rbalance
= inc_rb
;
850 static int alvium_get_blue_balance_ratio_params(struct alvium_dev
*alvium
)
852 u64 dft_bb
, min_bb
, max_bb
, inc_bb
;
855 alvium_read(alvium
, REG_BCRM_BLUE_BALANCE_RATIO_RW
, &dft_bb
, &ret
);
856 alvium_read(alvium
, REG_BCRM_BLUE_BALANCE_RATIO_MIN_R
, &min_bb
, &ret
);
857 alvium_read(alvium
, REG_BCRM_BLUE_BALANCE_RATIO_MAX_R
, &max_bb
, &ret
);
858 alvium_read(alvium
, REG_BCRM_BLUE_BALANCE_RATIO_INC_R
, &inc_bb
, &ret
);
862 alvium
->dft_bbalance
= dft_bb
;
863 alvium
->min_bbalance
= min_bb
;
864 alvium
->max_bbalance
= max_bb
;
865 alvium
->inc_bbalance
= inc_bb
;
870 static int alvium_get_hue_params(struct alvium_dev
*alvium
)
872 u64 dft_hue
, min_hue
, max_hue
, inc_hue
;
875 alvium_read(alvium
, REG_BCRM_HUE_RW
, &dft_hue
, &ret
);
876 alvium_read(alvium
, REG_BCRM_HUE_MIN_R
, &min_hue
, &ret
);
877 alvium_read(alvium
, REG_BCRM_HUE_MAX_R
, &max_hue
, &ret
);
878 alvium_read(alvium
, REG_BCRM_HUE_INC_R
, &inc_hue
, &ret
);
882 alvium
->dft_hue
= (s32
)dft_hue
;
883 alvium
->min_hue
= (s32
)min_hue
;
884 alvium
->max_hue
= (s32
)max_hue
;
885 alvium
->inc_hue
= (s32
)inc_hue
;
890 static int alvium_get_black_lvl_params(struct alvium_dev
*alvium
)
892 u64 dft_blvl
, min_blvl
, max_blvl
, inc_blvl
;
895 alvium_read(alvium
, REG_BCRM_BLACK_LEVEL_RW
, &dft_blvl
, &ret
);
896 alvium_read(alvium
, REG_BCRM_BLACK_LEVEL_MIN_R
, &min_blvl
, &ret
);
897 alvium_read(alvium
, REG_BCRM_BLACK_LEVEL_MAX_R
, &max_blvl
, &ret
);
898 alvium_read(alvium
, REG_BCRM_BLACK_LEVEL_INC_R
, &inc_blvl
, &ret
);
902 alvium
->dft_black_lvl
= (s32
)dft_blvl
;
903 alvium
->min_black_lvl
= (s32
)min_blvl
;
904 alvium
->max_black_lvl
= (s32
)max_blvl
;
905 alvium
->inc_black_lvl
= (s32
)inc_blvl
;
910 static int alvium_get_gamma_params(struct alvium_dev
*alvium
)
912 u64 dft_g
, min_g
, max_g
, inc_g
;
915 alvium_read(alvium
, REG_BCRM_GAMMA_RW
, &dft_g
, &ret
);
916 alvium_read(alvium
, REG_BCRM_GAMMA_MIN_R
, &min_g
, &ret
);
917 alvium_read(alvium
, REG_BCRM_GAMMA_MAX_R
, &max_g
, &ret
);
918 alvium_read(alvium
, REG_BCRM_GAMMA_INC_R
, &inc_g
, &ret
);
922 alvium
->dft_gamma
= dft_g
;
923 alvium
->min_gamma
= min_g
;
924 alvium
->max_gamma
= max_g
;
925 alvium
->inc_gamma
= inc_g
;
930 static int alvium_get_sharpness_params(struct alvium_dev
*alvium
)
932 u64 dft_sh
, min_sh
, max_sh
, inc_sh
;
935 alvium_read(alvium
, REG_BCRM_SHARPNESS_RW
, &dft_sh
, &ret
);
936 alvium_read(alvium
, REG_BCRM_SHARPNESS_MIN_R
, &min_sh
, &ret
);
937 alvium_read(alvium
, REG_BCRM_BLACK_LEVEL_MAX_R
, &max_sh
, &ret
);
938 alvium_read(alvium
, REG_BCRM_SHARPNESS_INC_R
, &inc_sh
, &ret
);
942 alvium
->dft_sharp
= (s32
)dft_sh
;
943 alvium
->min_sharp
= (s32
)min_sh
;
944 alvium
->max_sharp
= (s32
)max_sh
;
945 alvium
->inc_sharp
= (s32
)inc_sh
;
950 static int alvium_get_contrast_params(struct alvium_dev
*alvium
)
952 u64 dft_c
, min_c
, max_c
, inc_c
;
955 alvium_read(alvium
, REG_BCRM_CONTRAST_VALUE_RW
, &dft_c
, &ret
);
956 alvium_read(alvium
, REG_BCRM_CONTRAST_VALUE_MIN_R
, &min_c
, &ret
);
957 alvium_read(alvium
, REG_BCRM_CONTRAST_VALUE_MAX_R
, &max_c
, &ret
);
958 alvium_read(alvium
, REG_BCRM_CONTRAST_VALUE_INC_R
, &inc_c
, &ret
);
962 alvium
->dft_contrast
= dft_c
;
963 alvium
->min_contrast
= min_c
;
964 alvium
->max_contrast
= max_c
;
965 alvium
->inc_contrast
= inc_c
;
970 static int alvium_get_saturation_params(struct alvium_dev
*alvium
)
972 u64 dft_sat
, min_sat
, max_sat
, inc_sat
;
975 alvium_read(alvium
, REG_BCRM_SATURATION_RW
, &dft_sat
, &ret
);
976 alvium_read(alvium
, REG_BCRM_SATURATION_MIN_R
, &min_sat
, &ret
);
977 alvium_read(alvium
, REG_BCRM_SATURATION_MAX_R
, &max_sat
, &ret
);
978 alvium_read(alvium
, REG_BCRM_SATURATION_INC_R
, &inc_sat
, &ret
);
982 alvium
->dft_sat
= dft_sat
;
983 alvium
->min_sat
= min_sat
;
984 alvium
->max_sat
= max_sat
;
985 alvium
->inc_sat
= inc_sat
;
990 static int alvium_set_bcm_mode(struct alvium_dev
*alvium
)
994 alvium_write(alvium
, REG_GENCP_CHANGEMODE_W
, ALVIUM_BCM_MODE
, &ret
);
995 alvium
->bcrm_mode
= ALVIUM_BCM_MODE
;
1000 static int alvium_get_mode(struct alvium_dev
*alvium
)
1005 ret
= alvium_read(alvium
, REG_GENCP_CURRENTMODE_R
, &bcrm_mode
, NULL
);
1009 switch (bcrm_mode
) {
1010 case ALVIUM_BCM_MODE
:
1011 alvium
->bcrm_mode
= ALVIUM_BCM_MODE
;
1013 case ALVIUM_GENCP_MODE
:
1014 alvium
->bcrm_mode
= ALVIUM_GENCP_MODE
;
1021 static int alvium_get_avail_mipi_data_format(struct alvium_dev
*alvium
)
1023 struct alvium_avail_mipi_fmt
*avail_fmt
;
1027 ret
= alvium_read(alvium
, REG_BCRM_IMG_AVAILABLE_MIPI_DATA_FORMATS_R
,
1032 avail_fmt
= (struct alvium_avail_mipi_fmt
*)&val
;
1034 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_8_LEG
] =
1035 avail_fmt
->yuv420_8_leg
;
1036 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_8
] =
1037 avail_fmt
->yuv420_8
;
1038 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_10
] =
1039 avail_fmt
->yuv420_10
;
1040 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_8_CSPS
] =
1041 avail_fmt
->yuv420_8_csps
;
1042 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV420_10_CSPS
] =
1043 avail_fmt
->yuv420_10_csps
;
1044 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV422_8
] =
1045 avail_fmt
->yuv422_8
;
1046 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_YUV422_10
] =
1047 avail_fmt
->yuv422_10
;
1048 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB888
] =
1050 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB666
] =
1052 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB565
] =
1054 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB555
] =
1056 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RGB444
] =
1058 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW6
] =
1060 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW7
] =
1062 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW8
] =
1064 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW10
] =
1066 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW12
] =
1068 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_RAW14
] =
1070 alvium
->is_mipi_fmt_avail
[ALVIUM_BIT_JPEG
] =
1073 alvium_print_avail_mipi_fmt(alvium
);
1078 static int alvium_setup_mipi_fmt(struct alvium_dev
*alvium
)
1080 unsigned int avail_fmt_cnt
= 0;
1081 unsigned int fmt
= 0;
1084 /* calculate fmt array size */
1085 for (fmt
= 0; fmt
< ALVIUM_NUM_SUPP_MIPI_DATA_FMT
; fmt
++) {
1086 if (!alvium
->is_mipi_fmt_avail
[alvium_csi2_fmts
[fmt
].fmt_av_bit
])
1089 if (!alvium_csi2_fmts
[fmt
].is_raw
||
1090 alvium
->is_bay_avail
[alvium_csi2_fmts
[fmt
].bay_av_bit
])
1094 /* init alvium_csi2_fmt array */
1095 alvium
->alvium_csi2_fmt_n
= sz
;
1096 alvium
->alvium_csi2_fmt
=
1097 kmalloc_array(sz
, sizeof(struct alvium_pixfmt
), GFP_KERNEL
);
1098 if (!alvium
->alvium_csi2_fmt
)
1101 /* Create the alvium_csi2 fmt array from formats available */
1102 for (fmt
= 0; fmt
< ALVIUM_NUM_SUPP_MIPI_DATA_FMT
; fmt
++) {
1103 if (!alvium
->is_mipi_fmt_avail
[alvium_csi2_fmts
[fmt
].fmt_av_bit
])
1106 if (!alvium_csi2_fmts
[fmt
].is_raw
||
1107 alvium
->is_bay_avail
[alvium_csi2_fmts
[fmt
].bay_av_bit
]) {
1108 alvium
->alvium_csi2_fmt
[avail_fmt_cnt
] =
1109 alvium_csi2_fmts
[fmt
];
1117 static int alvium_set_mipi_fmt(struct alvium_dev
*alvium
,
1118 const struct alvium_pixfmt
*pixfmt
)
1120 struct device
*dev
= &alvium
->i2c_client
->dev
;
1123 ret
= alvium_write_hshake(alvium
, REG_BCRM_IMG_MIPI_DATA_FORMAT_RW
,
1124 pixfmt
->mipi_fmt_regval
);
1126 dev_err(dev
, "Fail to set mipi fmt\n");
1133 static int alvium_get_avail_bayer(struct alvium_dev
*alvium
)
1135 struct alvium_avail_bayer
*avail_bay
;
1139 ret
= alvium_read(alvium
, REG_BCRM_IMG_BAYER_PATTERN_INQUIRY_R
,
1144 avail_bay
= (struct alvium_avail_bayer
*)&val
;
1146 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_MONO
] = avail_bay
->mono
;
1147 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_GR
] = avail_bay
->gr
;
1148 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_RG
] = avail_bay
->rg
;
1149 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_GB
] = avail_bay
->gb
;
1150 alvium
->is_bay_avail
[ALVIUM_BIT_BAY_BG
] = avail_bay
->bg
;
1152 alvium_print_avail_bayer(alvium
);
1157 static int alvium_set_bayer_pattern(struct alvium_dev
*alvium
,
1158 const struct alvium_pixfmt
*pixfmt
)
1160 struct device
*dev
= &alvium
->i2c_client
->dev
;
1163 ret
= alvium_write_hshake(alvium
, REG_BCRM_IMG_BAYER_PATTERN_RW
,
1164 pixfmt
->bay_fmt_regval
);
1166 dev_err(dev
, "Fail to set bayer pattern\n");
1173 static int alvium_get_frame_interval(struct alvium_dev
*alvium
,
1174 u64
*min_fr
, u64
*max_fr
)
1178 alvium_read(alvium
, REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R
,
1180 alvium_read(alvium
, REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R
,
1186 static int alvium_set_frame_rate(struct alvium_dev
*alvium
, u64 fr
)
1188 struct device
*dev
= &alvium
->i2c_client
->dev
;
1191 ret
= alvium_write_hshake(alvium
, REG_BCRM_ACQUISITION_FRAME_RATE_EN_RW
,
1194 dev_err(dev
, "Fail to set acquisition frame rate enable reg\n");
1198 ret
= alvium_write_hshake(alvium
, REG_BCRM_FRAME_START_TRIGGER_MODE_RW
,
1201 dev_err(dev
, "Fail to set frame start trigger mode reg\n");
1205 ret
= alvium_write_hshake(alvium
, REG_BCRM_ACQUISITION_FRAME_RATE_RW
,
1208 dev_err(dev
, "Fail to set frame rate lanes reg\n");
1212 dev_dbg(dev
, "set frame rate: %llu us\n", fr
);
1217 static int alvium_set_stream_mipi(struct alvium_dev
*alvium
, bool on
)
1219 struct device
*dev
= &alvium
->i2c_client
->dev
;
1222 ret
= alvium_write_hshake(alvium
, on
? REG_BCRM_ACQUISITION_START_RW
:
1223 REG_BCRM_ACQUISITION_STOP_RW
, 0x01);
1225 dev_err(dev
, "Fail set_stream_mipi\n");
1232 static int alvium_get_gain(struct alvium_dev
*alvium
)
1237 /* The unit is millibel (1 mB = 0.01 dB) */
1238 ret
= alvium_read(alvium
, REG_BCRM_GAIN_RW
, &gain
, NULL
);
1245 static int alvium_set_ctrl_gain(struct alvium_dev
*alvium
, int gain
)
1247 struct device
*dev
= &alvium
->i2c_client
->dev
;
1250 /* The unit is millibel (1 mB = 0.01 dB) */
1251 ret
= alvium_write_hshake(alvium
, REG_BCRM_GAIN_RW
, (u64
)gain
);
1253 dev_err(dev
, "Fail to set gain value reg\n");
1260 static int alvium_set_ctrl_auto_gain(struct alvium_dev
*alvium
, bool on
)
1262 struct device
*dev
= &alvium
->i2c_client
->dev
;
1265 ret
= alvium_write_hshake(alvium
, REG_BCRM_GAIN_AUTO_RW
,
1268 dev_err(dev
, "Fail to set autogain reg\n");
1275 static int alvium_get_exposure(struct alvium_dev
*alvium
)
1280 /* Exposure time in ns */
1281 ret
= alvium_read(alvium
, REG_BCRM_EXPOSURE_TIME_RW
, &exp
, NULL
);
1288 static int alvium_set_ctrl_auto_exposure(struct alvium_dev
*alvium
, bool on
)
1290 struct device
*dev
= &alvium
->i2c_client
->dev
;
1293 ret
= alvium_write_hshake(alvium
, REG_BCRM_WHITE_BALANCE_AUTO_RW
,
1296 dev_err(dev
, "Fail to set autoexposure reg\n");
1303 static int alvium_set_ctrl_exposure(struct alvium_dev
*alvium
, int exposure_ns
)
1305 struct device
*dev
= &alvium
->i2c_client
->dev
;
1308 ret
= alvium_write_hshake(alvium
, REG_BCRM_EXPOSURE_TIME_RW
,
1311 dev_err(dev
, "Fail to set exposure value reg\n");
1318 static int alvium_set_ctrl_blue_balance_ratio(struct alvium_dev
*alvium
,
1321 struct device
*dev
= &alvium
->i2c_client
->dev
;
1324 ret
= alvium_write_hshake(alvium
, REG_BCRM_BLUE_BALANCE_RATIO_RW
,
1327 dev_err(dev
, "Fail to set blue ratio value reg\n");
1334 static int alvium_set_ctrl_red_balance_ratio(struct alvium_dev
*alvium
, int red
)
1336 struct device
*dev
= &alvium
->i2c_client
->dev
;
1339 ret
= alvium_write_hshake(alvium
, REG_BCRM_RED_BALANCE_RATIO_RW
,
1342 dev_err(dev
, "Fail to set red ratio value reg\n");
1349 static int alvium_set_ctrl_awb(struct alvium_dev
*alvium
, bool on
)
1351 struct device
*dev
= &alvium
->i2c_client
->dev
;
1354 ret
= alvium_write_hshake(alvium
, REG_BCRM_WHITE_BALANCE_AUTO_RW
,
1357 dev_err(dev
, "Fail to set awb reg\n");
1364 static int alvium_set_ctrl_hue(struct alvium_dev
*alvium
, int val
)
1366 struct device
*dev
= &alvium
->i2c_client
->dev
;
1369 ret
= alvium_write_hshake(alvium
, REG_BCRM_HUE_RW
, (u64
)val
);
1371 dev_err(dev
, "Fail to set hue value reg\n");
1378 static int alvium_set_ctrl_contrast(struct alvium_dev
*alvium
, int val
)
1380 struct device
*dev
= &alvium
->i2c_client
->dev
;
1383 ret
= alvium_write_hshake(alvium
, REG_BCRM_CONTRAST_VALUE_RW
, (u64
)val
);
1385 dev_err(dev
, "Fail to set contrast value reg\n");
1392 static int alvium_set_ctrl_saturation(struct alvium_dev
*alvium
, int val
)
1394 struct device
*dev
= &alvium
->i2c_client
->dev
;
1397 ret
= alvium_write_hshake(alvium
, REG_BCRM_SATURATION_RW
, (u64
)val
);
1399 dev_err(dev
, "Fail to set contrast value reg\n");
1406 static int alvium_set_ctrl_gamma(struct alvium_dev
*alvium
, int val
)
1408 struct device
*dev
= &alvium
->i2c_client
->dev
;
1411 ret
= alvium_write_hshake(alvium
, REG_BCRM_GAMMA_RW
, (u64
)val
);
1413 dev_err(dev
, "Fail to set gamma value reg\n");
1420 static int alvium_set_ctrl_sharpness(struct alvium_dev
*alvium
, int val
)
1422 struct device
*dev
= &alvium
->i2c_client
->dev
;
1425 ret
= alvium_write_hshake(alvium
, REG_BCRM_SHARPNESS_RW
, (u64
)val
);
1427 dev_err(dev
, "Fail to set sharpness value reg\n");
1434 static int alvium_set_ctrl_hflip(struct alvium_dev
*alvium
, int val
)
1436 struct device
*dev
= &alvium
->i2c_client
->dev
;
1439 ret
= alvium_write_hshake(alvium
, REG_BCRM_IMG_REVERSE_X_RW
, (u64
)val
);
1441 dev_err(dev
, "Fail to set reverse_x value reg\n");
1448 static int alvium_set_ctrl_vflip(struct alvium_dev
*alvium
, int val
)
1450 struct device
*dev
= &alvium
->i2c_client
->dev
;
1453 ret
= alvium_write_hshake(alvium
, REG_BCRM_IMG_REVERSE_Y_RW
, (u64
)val
);
1455 dev_err(dev
, "Fail to set reverse_y value reg\n");
1462 static int alvium_get_hw_features_params(struct alvium_dev
*alvium
)
1464 struct device
*dev
= &alvium
->i2c_client
->dev
;
1467 ret
= alvium_get_csi_clk_params(alvium
);
1469 dev_err(dev
, "Fail to read min/max csi clock regs\n");
1473 ret
= alvium_get_img_width_params(alvium
);
1475 dev_err(dev
, "Fail to read img width regs\n");
1479 ret
= alvium_get_img_height_params(alvium
);
1481 dev_err(dev
, "Fail to read img height regs\n");
1485 ret
= alvium_get_offx_params(alvium
);
1487 dev_err(dev
, "Fail to read offx regs\n");
1491 ret
= alvium_get_offy_params(alvium
);
1493 dev_err(dev
, "Fail to read offy regs\n");
1497 ret
= alvium_get_gain_params(alvium
);
1499 dev_err(dev
, "Fail to read gain regs\n");
1503 ret
= alvium_get_exposure_params(alvium
);
1505 dev_err(dev
, "Fail to read min/max exp regs\n");
1509 ret
= alvium_get_red_balance_ratio_params(alvium
);
1511 dev_err(dev
, "Fail to read red balance ratio regs\n");
1515 ret
= alvium_get_blue_balance_ratio_params(alvium
);
1517 dev_err(dev
, "Fail to read blue balance ratio regs\n");
1521 ret
= alvium_get_hue_params(alvium
);
1523 dev_err(dev
, "Fail to read hue regs\n");
1527 ret
= alvium_get_contrast_params(alvium
);
1529 dev_err(dev
, "Fail to read contrast regs\n");
1533 ret
= alvium_get_saturation_params(alvium
);
1535 dev_err(dev
, "Fail to read saturation regs\n");
1539 ret
= alvium_get_black_lvl_params(alvium
);
1541 dev_err(dev
, "Fail to read black lvl regs\n");
1545 ret
= alvium_get_gamma_params(alvium
);
1547 dev_err(dev
, "Fail to read gamma regs\n");
1551 ret
= alvium_get_sharpness_params(alvium
);
1553 dev_err(dev
, "Fail to read sharpness regs\n");
1560 static int alvium_get_hw_info(struct alvium_dev
*alvium
)
1562 struct device
*dev
= &alvium
->i2c_client
->dev
;
1565 ret
= alvium_get_bcrm_vers(alvium
);
1567 dev_err(dev
, "Fail to read bcrm version reg\n");
1571 ret
= alvium_get_bcrm_addr(alvium
);
1573 dev_err(dev
, "Fail to bcrm address reg\n");
1577 ret
= alvium_get_fw_version(alvium
);
1579 dev_err(dev
, "Fail to read fw version reg\n");
1583 ret
= alvium_get_host_supp_csi_lanes(alvium
);
1585 dev_err(dev
, "Fail to read host supported csi lanes reg\n");
1589 ret
= alvium_get_feat_inq(alvium
);
1591 dev_err(dev
, "Fail to read bcrm feature inquiry reg\n");
1595 ret
= alvium_get_hw_features_params(alvium
);
1597 dev_err(dev
, "Fail to read features params regs\n");
1601 ret
= alvium_get_avail_mipi_data_format(alvium
);
1603 dev_err(dev
, "Fail to read available mipi data formats reg\n");
1607 ret
= alvium_get_avail_bayer(alvium
);
1609 dev_err(dev
, "Fail to read available Bayer patterns reg\n");
1613 ret
= alvium_get_mode(alvium
);
1615 dev_err(dev
, "Fail to get current mode reg\n");
1622 static int alvium_hw_init(struct alvium_dev
*alvium
)
1624 struct device
*dev
= &alvium
->i2c_client
->dev
;
1627 /* Set Alvium BCM mode*/
1628 ret
= alvium_set_bcm_mode(alvium
);
1630 dev_err(dev
, "Fail to set BCM mode\n");
1634 ret
= alvium_set_csi_lanes(alvium
);
1636 dev_err(dev
, "Fail to set csi lanes\n");
1640 ret
= alvium_set_csi_clk(alvium
);
1642 dev_err(dev
, "Fail to set csi clk\n");
1646 ret
= alvium_set_lp2hs_delay(alvium
);
1648 dev_err(dev
, "Fail to set lp2hs reg\n");
1655 /* --------------- Subdev Operations --------------- */
1656 static int alvium_s_frame_interval(struct v4l2_subdev
*sd
,
1657 struct v4l2_subdev_state
*sd_state
,
1658 struct v4l2_subdev_frame_interval
*fi
)
1660 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
1661 struct device
*dev
= &alvium
->i2c_client
->dev
;
1662 u64 req_fr
, min_fr
, max_fr
;
1663 struct v4l2_fract
*interval
;
1666 if (alvium
->streaming
)
1669 if (fi
->interval
.denominator
== 0)
1672 ret
= alvium_get_frame_interval(alvium
, &min_fr
, &max_fr
);
1674 dev_err(dev
, "Fail to get frame interval\n");
1678 dev_dbg(dev
, "fi->interval.numerator = %d\n",
1679 fi
->interval
.numerator
);
1680 dev_dbg(dev
, "fi->interval.denominator = %d\n",
1681 fi
->interval
.denominator
);
1683 req_fr
= (u64
)((fi
->interval
.denominator
* USEC_PER_SEC
) /
1684 fi
->interval
.numerator
);
1685 req_fr
= clamp(req_fr
, min_fr
, max_fr
);
1687 interval
= v4l2_subdev_state_get_interval(sd_state
, 0);
1689 interval
->numerator
= fi
->interval
.numerator
;
1690 interval
->denominator
= fi
->interval
.denominator
;
1692 if (fi
->which
!= V4L2_SUBDEV_FORMAT_ACTIVE
)
1695 return alvium_set_frame_rate(alvium
, req_fr
);
1698 static int alvium_enum_mbus_code(struct v4l2_subdev
*sd
,
1699 struct v4l2_subdev_state
*sd_state
,
1700 struct v4l2_subdev_mbus_code_enum
*code
)
1702 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
1704 if (code
->index
>= alvium
->alvium_csi2_fmt_n
)
1707 code
->code
= alvium
->alvium_csi2_fmt
[code
->index
].code
;
1712 static const struct alvium_pixfmt
*
1713 alvium_code_to_pixfmt(struct alvium_dev
*alvium
, u32 code
)
1717 for (i
= 0; alvium
->alvium_csi2_fmt
[i
].code
; ++i
)
1718 if (alvium
->alvium_csi2_fmt
[i
].code
== code
)
1719 return &alvium
->alvium_csi2_fmt
[i
];
1721 return &alvium
->alvium_csi2_fmt
[0];
1724 static int alvium_enum_frame_size(struct v4l2_subdev
*sd
,
1725 struct v4l2_subdev_state
*state
,
1726 struct v4l2_subdev_frame_size_enum
*fse
)
1728 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
1729 const struct alvium_pixfmt
*alvium_csi2_fmt
;
1734 alvium_csi2_fmt
= alvium_code_to_pixfmt(alvium
, fse
->code
);
1735 if (fse
->code
!= alvium_csi2_fmt
->code
)
1738 fse
->min_width
= alvium
->img_min_width
;
1739 fse
->max_width
= alvium
->img_max_width
;
1740 fse
->min_height
= alvium
->img_min_height
;
1741 fse
->max_height
= alvium
->img_max_height
;
1745 static int alvium_set_mode(struct alvium_dev
*alvium
,
1746 struct v4l2_subdev_state
*state
)
1748 struct v4l2_mbus_framefmt
*fmt
;
1749 struct v4l2_rect
*crop
;
1752 crop
= v4l2_subdev_state_get_crop(state
, 0);
1753 fmt
= v4l2_subdev_state_get_format(state
, 0);
1755 v4l_bound_align_image(&fmt
->width
, alvium
->img_min_width
,
1756 alvium
->img_max_width
, 0,
1757 &fmt
->height
, alvium
->img_min_height
,
1758 alvium
->img_max_height
, 0, 0);
1760 /* alvium don't accept negative crop left/top */
1761 crop
->left
= clamp((u32
)max(0, crop
->left
), alvium
->min_offx
,
1762 (u32
)(alvium
->img_max_width
- fmt
->width
));
1763 crop
->top
= clamp((u32
)max(0, crop
->top
), alvium
->min_offy
,
1764 (u32
)(alvium
->img_max_height
- fmt
->height
));
1766 ret
= alvium_set_img_width(alvium
, fmt
->width
);
1770 ret
= alvium_set_img_height(alvium
, fmt
->height
);
1774 ret
= alvium_set_img_offx(alvium
, crop
->left
);
1778 ret
= alvium_set_img_offy(alvium
, crop
->top
);
1785 static int alvium_set_framefmt(struct alvium_dev
*alvium
,
1786 struct v4l2_mbus_framefmt
*format
)
1788 struct device
*dev
= &alvium
->i2c_client
->dev
;
1789 const struct alvium_pixfmt
*alvium_csi2_fmt
;
1792 alvium_csi2_fmt
= alvium_code_to_pixfmt(alvium
, format
->code
);
1794 ret
= alvium_set_mipi_fmt(alvium
, alvium_csi2_fmt
);
1798 if (alvium_csi2_fmt
->is_raw
) {
1799 ret
= alvium_set_bayer_pattern(alvium
, alvium_csi2_fmt
);
1804 dev_dbg(dev
, "start: %s, mipi_fmt_regval regval = 0x%llx",
1805 __func__
, alvium_csi2_fmt
->mipi_fmt_regval
);
1810 static int alvium_s_stream(struct v4l2_subdev
*sd
, int enable
)
1812 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
1813 struct i2c_client
*client
= v4l2_get_subdevdata(&alvium
->sd
);
1814 struct v4l2_mbus_framefmt
*fmt
;
1815 struct v4l2_subdev_state
*state
;
1818 state
= v4l2_subdev_lock_and_get_active_state(sd
);
1821 ret
= pm_runtime_resume_and_get(&client
->dev
);
1825 ret
= __v4l2_ctrl_handler_setup(&alvium
->ctrls
.handler
);
1829 ret
= alvium_set_mode(alvium
, state
);
1833 fmt
= v4l2_subdev_state_get_format(state
, 0);
1834 ret
= alvium_set_framefmt(alvium
, fmt
);
1838 ret
= alvium_set_stream_mipi(alvium
, enable
);
1843 alvium_set_stream_mipi(alvium
, enable
);
1844 pm_runtime_mark_last_busy(&client
->dev
);
1845 pm_runtime_put_autosuspend(&client
->dev
);
1848 alvium
->streaming
= !!enable
;
1849 v4l2_subdev_unlock_state(state
);
1854 pm_runtime_put(&client
->dev
);
1855 v4l2_subdev_unlock_state(state
);
1859 static int alvium_init_state(struct v4l2_subdev
*sd
,
1860 struct v4l2_subdev_state
*state
)
1862 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
1863 struct alvium_mode
*mode
= &alvium
->mode
;
1864 struct v4l2_fract
*interval
;
1865 struct v4l2_subdev_format sd_fmt
= {
1866 .which
= V4L2_SUBDEV_FORMAT_TRY
,
1867 .format
= alvium_csi2_default_fmt
,
1869 struct v4l2_subdev_crop sd_crop
= {
1870 .which
= V4L2_SUBDEV_FORMAT_TRY
,
1872 .left
= mode
->crop
.left
,
1873 .top
= mode
->crop
.top
,
1874 .width
= mode
->crop
.width
,
1875 .height
= mode
->crop
.height
,
1879 *v4l2_subdev_state_get_crop(state
, 0) = sd_crop
.rect
;
1880 *v4l2_subdev_state_get_format(state
, 0) = sd_fmt
.format
;
1882 /* Setup initial frame interval*/
1883 interval
= v4l2_subdev_state_get_interval(state
, 0);
1884 interval
->numerator
= 1;
1885 interval
->denominator
= ALVIUM_DEFAULT_FR_HZ
;
1890 static int alvium_set_fmt(struct v4l2_subdev
*sd
,
1891 struct v4l2_subdev_state
*sd_state
,
1892 struct v4l2_subdev_format
*format
)
1894 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
1895 const struct alvium_pixfmt
*alvium_csi2_fmt
;
1896 struct v4l2_mbus_framefmt
*fmt
;
1897 struct v4l2_rect
*crop
;
1899 fmt
= v4l2_subdev_state_get_format(sd_state
, 0);
1900 crop
= v4l2_subdev_state_get_crop(sd_state
, 0);
1902 v4l_bound_align_image(&format
->format
.width
, alvium
->img_min_width
,
1903 alvium
->img_max_width
, 0,
1904 &format
->format
.height
, alvium
->img_min_height
,
1905 alvium
->img_max_height
, 0, 0);
1907 /* Adjust left and top to prevent roll over sensor area */
1908 crop
->left
= clamp((u32
)crop
->left
, (u32
)0,
1909 (alvium
->img_max_width
- fmt
->width
));
1910 crop
->top
= clamp((u32
)crop
->top
, (u32
)0,
1911 (alvium
->img_max_height
- fmt
->height
));
1913 /* Set also the crop width and height when set a new fmt */
1914 crop
->width
= fmt
->width
;
1915 crop
->height
= fmt
->height
;
1917 alvium_csi2_fmt
= alvium_code_to_pixfmt(alvium
, format
->format
.code
);
1918 fmt
->code
= alvium_csi2_fmt
->code
;
1920 *fmt
= format
->format
;
1925 static int alvium_set_selection(struct v4l2_subdev
*sd
,
1926 struct v4l2_subdev_state
*sd_state
,
1927 struct v4l2_subdev_selection
*sel
)
1929 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
1930 struct v4l2_mbus_framefmt
*fmt
;
1931 struct v4l2_rect
*crop
;
1933 if (sel
->target
!= V4L2_SEL_TGT_CROP
)
1936 crop
= v4l2_subdev_state_get_crop(sd_state
, 0);
1937 fmt
= v4l2_subdev_state_get_format(sd_state
, 0);
1940 * Alvium can only shift the origin of the img
1941 * then we accept only value with the same value of the actual fmt
1943 if (sel
->r
.width
!= fmt
->width
)
1944 sel
->r
.width
= fmt
->width
;
1946 if (sel
->r
.height
!= fmt
->height
)
1947 sel
->r
.height
= fmt
->height
;
1949 /* alvium don't accept negative crop left/top */
1950 crop
->left
= clamp((u32
)max(0, sel
->r
.left
), alvium
->min_offx
,
1951 alvium
->img_max_width
- sel
->r
.width
);
1952 crop
->top
= clamp((u32
)max(0, sel
->r
.top
), alvium
->min_offy
,
1953 alvium
->img_max_height
- sel
->r
.height
);
1960 static int alvium_get_selection(struct v4l2_subdev
*sd
,
1961 struct v4l2_subdev_state
*sd_state
,
1962 struct v4l2_subdev_selection
*sel
)
1964 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
1966 switch (sel
->target
) {
1967 /* Current cropping area */
1968 case V4L2_SEL_TGT_CROP
:
1969 sel
->r
= *v4l2_subdev_state_get_crop(sd_state
, 0);
1971 /* Cropping bounds */
1972 case V4L2_SEL_TGT_NATIVE_SIZE
:
1975 sel
->r
.width
= alvium
->img_max_width
;
1976 sel
->r
.height
= alvium
->img_max_height
;
1978 /* Default cropping area */
1979 case V4L2_SEL_TGT_CROP_BOUNDS
:
1980 case V4L2_SEL_TGT_CROP_DEFAULT
:
1981 sel
->r
.top
= alvium
->min_offy
;
1982 sel
->r
.left
= alvium
->min_offx
;
1983 sel
->r
.width
= alvium
->img_max_width
;
1984 sel
->r
.height
= alvium
->img_max_height
;
1993 static int alvium_g_volatile_ctrl(struct v4l2_ctrl
*ctrl
)
1995 struct v4l2_subdev
*sd
= ctrl_to_sd(ctrl
);
1996 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
2000 case V4L2_CID_ANALOGUE_GAIN
:
2001 val
= alvium_get_gain(alvium
);
2004 alvium
->ctrls
.gain
->val
= val
;
2006 case V4L2_CID_EXPOSURE
:
2007 val
= alvium_get_exposure(alvium
);
2010 alvium
->ctrls
.exposure
->val
= val
;
2017 static int alvium_s_ctrl(struct v4l2_ctrl
*ctrl
)
2019 struct v4l2_subdev
*sd
= ctrl_to_sd(ctrl
);
2020 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
2021 struct i2c_client
*client
= v4l2_get_subdevdata(&alvium
->sd
);
2025 * Applying V4L2 control value only happens
2026 * when power is up for streaming
2028 if (!pm_runtime_get_if_in_use(&client
->dev
))
2032 case V4L2_CID_ANALOGUE_GAIN
:
2033 ret
= alvium_set_ctrl_gain(alvium
, ctrl
->val
);
2035 case V4L2_CID_AUTOGAIN
:
2036 ret
= alvium_set_ctrl_auto_gain(alvium
, ctrl
->val
);
2038 case V4L2_CID_EXPOSURE
:
2039 ret
= alvium_set_ctrl_exposure(alvium
, ctrl
->val
);
2041 case V4L2_CID_EXPOSURE_AUTO
:
2042 ret
= alvium_set_ctrl_auto_exposure(alvium
, ctrl
->val
);
2044 case V4L2_CID_RED_BALANCE
:
2045 ret
= alvium_set_ctrl_red_balance_ratio(alvium
, ctrl
->val
);
2047 case V4L2_CID_BLUE_BALANCE
:
2048 ret
= alvium_set_ctrl_blue_balance_ratio(alvium
, ctrl
->val
);
2050 case V4L2_CID_AUTO_WHITE_BALANCE
:
2051 ret
= alvium_set_ctrl_awb(alvium
, ctrl
->val
);
2054 ret
= alvium_set_ctrl_hue(alvium
, ctrl
->val
);
2056 case V4L2_CID_CONTRAST
:
2057 ret
= alvium_set_ctrl_contrast(alvium
, ctrl
->val
);
2059 case V4L2_CID_SATURATION
:
2060 ret
= alvium_set_ctrl_saturation(alvium
, ctrl
->val
);
2062 case V4L2_CID_GAMMA
:
2063 ret
= alvium_set_ctrl_gamma(alvium
, ctrl
->val
);
2065 case V4L2_CID_SHARPNESS
:
2066 ret
= alvium_set_ctrl_sharpness(alvium
, ctrl
->val
);
2068 case V4L2_CID_HFLIP
:
2069 ret
= alvium_set_ctrl_hflip(alvium
, ctrl
->val
);
2071 case V4L2_CID_VFLIP
:
2072 ret
= alvium_set_ctrl_vflip(alvium
, ctrl
->val
);
2079 pm_runtime_put(&client
->dev
);
2084 static const struct v4l2_ctrl_ops alvium_ctrl_ops
= {
2085 .g_volatile_ctrl
= alvium_g_volatile_ctrl
,
2086 .s_ctrl
= alvium_s_ctrl
,
2089 static int alvium_ctrl_init(struct alvium_dev
*alvium
)
2091 const struct v4l2_ctrl_ops
*ops
= &alvium_ctrl_ops
;
2092 struct alvium_ctrls
*ctrls
= &alvium
->ctrls
;
2093 struct v4l2_ctrl_handler
*hdl
= &ctrls
->handler
;
2094 struct v4l2_fwnode_device_properties props
;
2097 v4l2_ctrl_handler_init(hdl
, 32);
2099 /* Pixel rate is fixed */
2100 ctrls
->pixel_rate
= v4l2_ctrl_new_std(hdl
, ops
,
2101 V4L2_CID_PIXEL_RATE
, 0,
2102 ALVIUM_DEFAULT_PIXEL_RATE_MHZ
, 1,
2103 ALVIUM_DEFAULT_PIXEL_RATE_MHZ
);
2104 ctrls
->pixel_rate
->flags
|= V4L2_CTRL_FLAG_READ_ONLY
;
2106 /* Link freq is fixed */
2107 ctrls
->link_freq
= v4l2_ctrl_new_int_menu(hdl
, ops
,
2109 0, 0, &alvium
->link_freq
);
2110 ctrls
->link_freq
->flags
|= V4L2_CTRL_FLAG_READ_ONLY
;
2112 /* Auto/manual white balance */
2113 if (alvium
->avail_ft
.auto_whiteb
) {
2114 ctrls
->auto_wb
= v4l2_ctrl_new_std(hdl
, ops
,
2115 V4L2_CID_AUTO_WHITE_BALANCE
,
2117 v4l2_ctrl_auto_cluster(3, &ctrls
->auto_wb
, 0, false);
2120 ctrls
->blue_balance
= v4l2_ctrl_new_std(hdl
, ops
,
2121 V4L2_CID_BLUE_BALANCE
,
2122 alvium
->min_bbalance
,
2123 alvium
->max_bbalance
,
2124 alvium
->inc_bbalance
,
2125 alvium
->dft_bbalance
);
2126 ctrls
->red_balance
= v4l2_ctrl_new_std(hdl
, ops
,
2127 V4L2_CID_RED_BALANCE
,
2128 alvium
->min_rbalance
,
2129 alvium
->max_rbalance
,
2130 alvium
->inc_rbalance
,
2131 alvium
->dft_rbalance
);
2133 /* Auto/manual exposure */
2134 if (alvium
->avail_ft
.auto_exp
) {
2136 v4l2_ctrl_new_std_menu(hdl
, ops
,
2137 V4L2_CID_EXPOSURE_AUTO
,
2138 V4L2_EXPOSURE_MANUAL
, 0,
2139 V4L2_EXPOSURE_AUTO
);
2140 v4l2_ctrl_auto_cluster(2, &ctrls
->auto_exp
, 1, true);
2143 ctrls
->exposure
= v4l2_ctrl_new_std(hdl
, ops
,
2149 ctrls
->exposure
->flags
|= V4L2_CTRL_FLAG_VOLATILE
;
2151 /* Auto/manual gain */
2152 if (alvium
->avail_ft
.auto_gain
) {
2153 ctrls
->auto_gain
= v4l2_ctrl_new_std(hdl
, ops
,
2156 v4l2_ctrl_auto_cluster(2, &ctrls
->auto_gain
, 0, true);
2159 if (alvium
->avail_ft
.gain
) {
2160 ctrls
->gain
= v4l2_ctrl_new_std(hdl
, ops
,
2161 V4L2_CID_ANALOGUE_GAIN
,
2166 ctrls
->gain
->flags
|= V4L2_CTRL_FLAG_VOLATILE
;
2169 if (alvium
->avail_ft
.sat
)
2170 ctrls
->saturation
= v4l2_ctrl_new_std(hdl
, ops
,
2171 V4L2_CID_SATURATION
,
2177 if (alvium
->avail_ft
.hue
)
2178 ctrls
->hue
= v4l2_ctrl_new_std(hdl
, ops
,
2185 if (alvium
->avail_ft
.contrast
)
2186 ctrls
->contrast
= v4l2_ctrl_new_std(hdl
, ops
,
2188 alvium
->min_contrast
,
2189 alvium
->max_contrast
,
2190 alvium
->inc_contrast
,
2191 alvium
->dft_contrast
);
2193 if (alvium
->avail_ft
.gamma
)
2194 ctrls
->gamma
= v4l2_ctrl_new_std(hdl
, ops
,
2201 if (alvium
->avail_ft
.sharp
)
2202 ctrls
->sharpness
= v4l2_ctrl_new_std(hdl
, ops
,
2209 if (alvium
->avail_ft
.rev_x
)
2210 ctrls
->hflip
= v4l2_ctrl_new_std(hdl
, ops
,
2214 if (alvium
->avail_ft
.rev_y
)
2215 ctrls
->vflip
= v4l2_ctrl_new_std(hdl
, ops
,
2224 ret
= v4l2_fwnode_device_parse(&alvium
->i2c_client
->dev
, &props
);
2228 ret
= v4l2_ctrl_new_fwnode_properties(hdl
, ops
, &props
);
2232 alvium
->sd
.ctrl_handler
= hdl
;
2236 v4l2_ctrl_handler_free(hdl
);
2240 static const struct v4l2_subdev_core_ops alvium_core_ops
= {
2241 .log_status
= v4l2_ctrl_subdev_log_status
,
2244 static const struct v4l2_subdev_video_ops alvium_video_ops
= {
2245 .s_stream
= alvium_s_stream
,
2248 static const struct v4l2_subdev_pad_ops alvium_pad_ops
= {
2249 .enum_mbus_code
= alvium_enum_mbus_code
,
2250 .enum_frame_size
= alvium_enum_frame_size
,
2251 .get_fmt
= v4l2_subdev_get_fmt
,
2252 .set_fmt
= alvium_set_fmt
,
2253 .get_selection
= alvium_get_selection
,
2254 .set_selection
= alvium_set_selection
,
2255 .get_frame_interval
= v4l2_subdev_get_frame_interval
,
2256 .set_frame_interval
= alvium_s_frame_interval
,
2259 static const struct v4l2_subdev_internal_ops alvium_internal_ops
= {
2260 .init_state
= alvium_init_state
,
2263 static const struct v4l2_subdev_ops alvium_subdev_ops
= {
2264 .core
= &alvium_core_ops
,
2265 .pad
= &alvium_pad_ops
,
2266 .video
= &alvium_video_ops
,
2269 static int alvium_subdev_init(struct alvium_dev
*alvium
)
2271 struct i2c_client
*client
= alvium
->i2c_client
;
2272 struct device
*dev
= &alvium
->i2c_client
->dev
;
2273 struct v4l2_subdev
*sd
= &alvium
->sd
;
2276 /* Setup the initial mode */
2277 alvium
->mode
.fmt
= alvium_csi2_default_fmt
;
2278 alvium
->mode
.width
= alvium_csi2_default_fmt
.width
;
2279 alvium
->mode
.height
= alvium_csi2_default_fmt
.height
;
2280 alvium
->mode
.crop
.left
= alvium
->min_offx
;
2281 alvium
->mode
.crop
.top
= alvium
->min_offy
;
2282 alvium
->mode
.crop
.width
= alvium_csi2_default_fmt
.width
;
2283 alvium
->mode
.crop
.height
= alvium_csi2_default_fmt
.height
;
2285 /* init alvium sd */
2286 v4l2_i2c_subdev_init(sd
, client
, &alvium_subdev_ops
);
2288 sd
->internal_ops
= &alvium_internal_ops
;
2289 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
2290 alvium
->pad
.flags
= MEDIA_PAD_FL_SOURCE
;
2291 sd
->entity
.function
= MEDIA_ENT_F_CAM_SENSOR
;
2293 ret
= media_entity_pads_init(&sd
->entity
, 1, &alvium
->pad
);
2295 dev_err(dev
, "Could not register media entity\n");
2299 ret
= alvium_ctrl_init(alvium
);
2301 dev_err(dev
, "Control initialization error %d\n", ret
);
2302 goto entity_cleanup
;
2305 alvium
->sd
.state_lock
= alvium
->ctrls
.handler
.lock
;
2307 ret
= v4l2_subdev_init_finalize(sd
);
2309 dev_err(dev
, "subdev initialization error %d\n", ret
);
2316 v4l2_ctrl_handler_free(&alvium
->ctrls
.handler
);
2318 media_entity_cleanup(&alvium
->sd
.entity
);
2322 static void alvium_subdev_cleanup(struct alvium_dev
*alvium
)
2324 v4l2_fwnode_endpoint_free(&alvium
->ep
);
2325 v4l2_subdev_cleanup(&alvium
->sd
);
2326 media_entity_cleanup(&alvium
->sd
.entity
);
2327 v4l2_ctrl_handler_free(&alvium
->ctrls
.handler
);
2330 static int alvium_get_dt_data(struct alvium_dev
*alvium
)
2332 struct device
*dev
= &alvium
->i2c_client
->dev
;
2333 struct fwnode_handle
*fwnode
= dev_fwnode(dev
);
2334 struct fwnode_handle
*endpoint
;
2339 /* Only CSI2 is supported for now: */
2340 alvium
->ep
.bus_type
= V4L2_MBUS_CSI2_DPHY
;
2342 endpoint
= fwnode_graph_get_endpoint_by_id(fwnode
, 0, 0, 0);
2344 dev_err(dev
, "endpoint node not found\n");
2348 if (v4l2_fwnode_endpoint_alloc_parse(endpoint
, &alvium
->ep
)) {
2349 dev_err(dev
, "could not parse endpoint\n");
2353 if (!alvium
->ep
.nr_of_link_frequencies
) {
2354 dev_err(dev
, "no link frequencies defined");
2361 v4l2_fwnode_endpoint_free(&alvium
->ep
);
2362 fwnode_handle_put(endpoint
);
2367 static int alvium_set_power(struct alvium_dev
*alvium
, bool on
)
2372 return regulator_disable(alvium
->reg_vcc
);
2374 ret
= regulator_enable(alvium
->reg_vcc
);
2378 /* alvium boot time 7s */
2383 static int alvium_runtime_resume(struct device
*dev
)
2385 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
2386 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
2389 ret
= alvium_set_power(alvium
, true);
2393 ret
= alvium_hw_init(alvium
);
2395 alvium_set_power(alvium
, false);
2402 static int alvium_runtime_suspend(struct device
*dev
)
2404 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
2405 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
2407 alvium_set_power(alvium
, false);
2412 static const struct dev_pm_ops alvium_pm_ops
= {
2413 RUNTIME_PM_OPS(alvium_runtime_suspend
, alvium_runtime_resume
, NULL
)
2416 static int alvium_probe(struct i2c_client
*client
)
2418 struct device
*dev
= &client
->dev
;
2419 struct alvium_dev
*alvium
;
2422 alvium
= devm_kzalloc(dev
, sizeof(*alvium
), GFP_KERNEL
);
2426 alvium
->i2c_client
= client
;
2428 alvium
->regmap
= devm_cci_regmap_init_i2c(client
, 16);
2429 if (IS_ERR(alvium
->regmap
))
2430 return PTR_ERR(alvium
->regmap
);
2432 ret
= alvium_get_dt_data(alvium
);
2436 alvium
->reg_vcc
= devm_regulator_get_optional(dev
, "vcc-ext-in");
2437 if (IS_ERR(alvium
->reg_vcc
))
2438 return dev_err_probe(dev
, PTR_ERR(alvium
->reg_vcc
),
2439 "no vcc-ext-in regulator provided\n");
2441 ret
= alvium_set_power(alvium
, true);
2445 if (!alvium_is_alive(alvium
)) {
2447 dev_err_probe(dev
, ret
, "Device detection failed\n");
2451 ret
= alvium_get_hw_info(alvium
);
2453 dev_err_probe(dev
, ret
, "get_hw_info fail\n");
2457 ret
= alvium_hw_init(alvium
);
2459 dev_err_probe(dev
, ret
, "hw_init fail\n");
2463 ret
= alvium_setup_mipi_fmt(alvium
);
2465 dev_err_probe(dev
, ret
, "setup_mipi_fmt fail\n");
2470 * Enable runtime PM without autosuspend:
2472 * Don't use pm autosuspend (alvium have ~7s boot time).
2473 * Alvium has been powered manually:
2474 * - mark it as active
2475 * - increase the usage count without resuming the device.
2477 pm_runtime_set_active(dev
);
2478 pm_runtime_get_noresume(dev
);
2479 pm_runtime_enable(dev
);
2481 /* Initialize the V4L2 subdev. */
2482 ret
= alvium_subdev_init(alvium
);
2486 ret
= v4l2_async_register_subdev(&alvium
->sd
);
2488 dev_err_probe(dev
, ret
, "Could not register v4l2 device\n");
2495 alvium_subdev_cleanup(alvium
);
2497 pm_runtime_disable(dev
);
2498 pm_runtime_put_noidle(dev
);
2499 kfree(alvium
->alvium_csi2_fmt
);
2501 alvium_set_power(alvium
, false);
2506 static void alvium_remove(struct i2c_client
*client
)
2508 struct v4l2_subdev
*sd
= i2c_get_clientdata(client
);
2509 struct alvium_dev
*alvium
= sd_to_alvium(sd
);
2510 struct device
*dev
= &alvium
->i2c_client
->dev
;
2512 v4l2_async_unregister_subdev(sd
);
2513 alvium_subdev_cleanup(alvium
);
2514 kfree(alvium
->alvium_csi2_fmt
);
2516 * Disable runtime PM. In case runtime PM is disabled in the kernel,
2517 * make sure to turn power off manually.
2519 pm_runtime_disable(dev
);
2520 if (!pm_runtime_status_suspended(dev
))
2521 alvium_set_power(alvium
, false);
2522 pm_runtime_set_suspended(dev
);
2525 static const struct of_device_id alvium_of_ids
[] = {
2526 { .compatible
= "alliedvision,alvium-csi2", },
2529 MODULE_DEVICE_TABLE(of
, alvium_of_ids
);
2531 static struct i2c_driver alvium_i2c_driver
= {
2533 .name
= "alvium-csi2",
2534 .pm
= pm_ptr(&alvium_pm_ops
),
2535 .of_match_table
= alvium_of_ids
,
2537 .probe
= alvium_probe
,
2538 .remove
= alvium_remove
,
2541 module_i2c_driver(alvium_i2c_driver
);
2543 MODULE_DESCRIPTION("Allied Vision's Alvium Camera Driver");
2544 MODULE_AUTHOR("Tommaso Merciai <tomm.merciai@gmail.com>");
2545 MODULE_AUTHOR("Martin Hecht <martin.hecht@avnet.eu>");
2546 MODULE_AUTHOR("Avnet Silica Software & Services EMEA");
2547 MODULE_LICENSE("GPL");