1 From 1a28fde906ac8a8268b72879dd035e536d4c09c5 Mon Sep 17 00:00:00 2001
2 From: Lee Jackson <info@arducam.com>
3 Date: Fri, 13 May 2022 17:11:35 +0800
4 Subject: [PATCH] media: i2c: Add driver of Arducam 64MP camera
6 Add a driver for the Arducam 64MP camera sensor.
7 Whilst the sensor supports 2 or 4 CSI2 data lanes, this driver
8 currently only supports 2 lanes.
10 The following Bayer modes are currently available:
12 9152x6944 10-bit @ 2.7fps
13 4624x3472 10-bit (binned) @ 10fps
14 3840x2160 10-bit (cropped/binned) @ 20fps
15 2312x1736 10-bit (binned) @ 30fps
16 1920x1080 10-bit (cropped/binned) @ 60fps
17 1280x720 10-bit (cropped/binned) @ 120fps
19 Signed-off-by: Lee Jackson <info@arducam.com>
21 drivers/media/i2c/Kconfig | 11 +
22 drivers/media/i2c/Makefile | 1 +
23 drivers/media/i2c/arducam_64mp.c | 2399 ++++++++++++++++++++++++++++++
24 3 files changed, 2411 insertions(+)
25 create mode 100644 drivers/media/i2c/arducam_64mp.c
27 --- a/drivers/media/i2c/Kconfig
28 +++ b/drivers/media/i2c/Kconfig
29 @@ -54,6 +54,17 @@ config VIDEO_AR0521
30 To compile this driver as a module, choose M here: the
31 module will be called ar0521.
33 +config VIDEO_ARDUCAM_64MP
34 + tristate "Arducam 64MP sensor support"
35 + depends on I2C && VIDEO_DEV
36 + select VIDEO_V4L2_SUBDEV_API
38 + This is a Video4Linux2 sensor driver for the Arducam
41 + To compile this driver as a module, choose M here: the
42 + module will be called arducam_64mp.
44 config VIDEO_ARDUCAM_PIVARIETY
45 tristate "Arducam Pivariety sensor support"
46 depends on I2C && VIDEO_DEV
47 --- a/drivers/media/i2c/Makefile
48 +++ b/drivers/media/i2c/Makefile
49 @@ -21,6 +21,7 @@ obj-$(CONFIG_VIDEO_AK7375) += ak7375.o
50 obj-$(CONFIG_VIDEO_AK881X) += ak881x.o
51 obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o
52 obj-$(CONFIG_VIDEO_AR0521) += ar0521.o
53 +obj-$(CONFIG_VIDEO_ARDUCAM_64MP) += arducam_64mp.o
54 obj-$(CONFIG_VIDEO_ARDUCAM_PIVARIETY) += arducam-pivariety.o
55 obj-$(CONFIG_VIDEO_BT819) += bt819.o
56 obj-$(CONFIG_VIDEO_BT856) += bt856.o
58 +++ b/drivers/media/i2c/arducam_64mp.c
60 +// SPDX-License-Identifier: GPL-2.0
62 + * A V4L2 driver for Arducam 64MP cameras.
63 + * Copyright (C) 2021 Arducam Technology co., Ltd.
65 + * Based on Sony IMX477 camera driver
66 + * Copyright (C) 2020 Raspberry Pi (Trading) Ltd
68 +#include <asm/unaligned.h>
69 +#include <linux/clk.h>
70 +#include <linux/delay.h>
71 +#include <linux/gpio/consumer.h>
72 +#include <linux/i2c.h>
73 +#include <linux/module.h>
74 +#include <linux/of_device.h>
75 +#include <linux/pm_runtime.h>
76 +#include <linux/regulator/consumer.h>
77 +#include <media/v4l2-ctrls.h>
78 +#include <media/v4l2-device.h>
79 +#include <media/v4l2-event.h>
80 +#include <media/v4l2-fwnode.h>
81 +#include <media/v4l2-mediabus.h>
83 +#define ARDUCAM_64MP_REG_VALUE_08BIT 1
84 +#define ARDUCAM_64MP_REG_VALUE_16BIT 2
87 +#define ARDUCAM_64MP_REG_CHIP_ID 0x005E
88 +#define ARDUCAM_64MP_CHIP_ID 0x4136
90 +#define ARDUCAM_64MP_REG_MODE_SELECT 0x0100
91 +#define ARDUCAM_64MP_MODE_STANDBY 0x00
92 +#define ARDUCAM_64MP_MODE_STREAMING 0x01
94 +#define ARDUCAM_64MP_REG_ORIENTATION 0x101
96 +#define ARDUCAM_64MP_XCLK_FREQ 24000000
98 +#define ARDUCAM_64MP_DEFAULT_LINK_FREQ 456000000
100 +/* Pixel rate is fixed at 900MHz for all the modes */
101 +#define ARDUCAM_64MP_PIXEL_RATE 900000000
103 +/* V_TIMING internal */
104 +#define ARDUCAM_64MP_REG_FRAME_LENGTH 0x0340
105 +#define ARDUCAM_64MP_FRAME_LENGTH_MAX 0xffff
107 +/* Long exposure multiplier */
108 +#define ARDUCAM_64MP_LONG_EXP_SHIFT_MAX 7
109 +#define ARDUCAM_64MP_LONG_EXP_SHIFT_REG 0x3100
111 +/* Exposure control */
112 +#define ARDUCAM_64MP_REG_EXPOSURE 0x0202
113 +#define ARDUCAM_64MP_EXPOSURE_OFFSET 48
114 +#define ARDUCAM_64MP_EXPOSURE_MIN 9
115 +#define ARDUCAM_64MP_EXPOSURE_STEP 1
116 +#define ARDUCAM_64MP_EXPOSURE_DEFAULT 0x3e8
117 +#define ARDUCAM_64MP_EXPOSURE_MAX (ARDUCAM_64MP_FRAME_LENGTH_MAX - \
118 + ARDUCAM_64MP_EXPOSURE_OFFSET)
120 +/* Analog gain control */
121 +#define ARDUCAM_64MP_REG_ANALOG_GAIN 0x0204
122 +#define ARDUCAM_64MP_ANA_GAIN_MIN 0
123 +#define ARDUCAM_64MP_ANA_GAIN_MAX 1008
124 +#define ARDUCAM_64MP_ANA_GAIN_STEP 1
125 +#define ARDUCAM_64MP_ANA_GAIN_DEFAULT 0x0
127 +/* Digital gain control */
128 +#define ARDUCAM_64MP_REG_DIGITAL_GAIN 0x020e
129 +#define ARDUCAM_64MP_DGTL_GAIN_MIN 0x0100
130 +#define ARDUCAM_64MP_DGTL_GAIN_MAX 0x0fff
131 +#define ARDUCAM_64MP_DGTL_GAIN_DEFAULT 0x0100
132 +#define ARDUCAM_64MP_DGTL_GAIN_STEP 1
134 +/* Test Pattern Control */
135 +#define ARDUCAM_64MP_REG_TEST_PATTERN 0x0600
136 +#define ARDUCAM_64MP_TEST_PATTERN_DISABLE 0
137 +#define ARDUCAM_64MP_TEST_PATTERN_SOLID_COLOR 1
138 +#define ARDUCAM_64MP_TEST_PATTERN_COLOR_BARS 2
139 +#define ARDUCAM_64MP_TEST_PATTERN_GREY_COLOR 3
140 +#define ARDUCAM_64MP_TEST_PATTERN_PN9 4
142 +/* Test pattern colour components */
143 +#define ARDUCAM_64MP_REG_TEST_PATTERN_R 0x0602
144 +#define ARDUCAM_64MP_REG_TEST_PATTERN_GR 0x0604
145 +#define ARDUCAM_64MP_REG_TEST_PATTERN_B 0x0606
146 +#define ARDUCAM_64MP_REG_TEST_PATTERN_GB 0x0608
147 +#define ARDUCAM_64MP_TEST_PATTERN_COLOUR_MIN 0
148 +#define ARDUCAM_64MP_TEST_PATTERN_COLOUR_MAX 0x0fff
149 +#define ARDUCAM_64MP_TEST_PATTERN_COLOUR_STEP 1
150 +#define ARDUCAM_64MP_TEST_PATTERN_R_DEFAULT \
151 + ARDUCAM_64MP_TEST_PATTERN_COLOUR_MAX
152 +#define ARDUCAM_64MP_TEST_PATTERN_GR_DEFAULT 0
153 +#define ARDUCAM_64MP_TEST_PATTERN_B_DEFAULT 0
154 +#define ARDUCAM_64MP_TEST_PATTERN_GB_DEFAULT 0
156 +/* ARDUCAM_64MP native and active pixel array size. */
157 +#define ARDUCAM_64MP_NATIVE_WIDTH 9344U
158 +#define ARDUCAM_64MP_NATIVE_HEIGHT 7032U
159 +#define ARDUCAM_64MP_PIXEL_ARRAY_LEFT 48U
160 +#define ARDUCAM_64MP_PIXEL_ARRAY_TOP 40U
161 +#define ARDUCAM_64MP_PIXEL_ARRAY_WIDTH 9248U
162 +#define ARDUCAM_64MP_PIXEL_ARRAY_HEIGHT 6944U
164 +struct arducam_64mp_reg {
169 +struct arducam_64mp_reg_list {
170 + unsigned int num_of_regs;
171 + const struct arducam_64mp_reg *regs;
174 +/* Mode : resolution and related config&values */
175 +struct arducam_64mp_mode {
177 + unsigned int width;
180 + unsigned int height;
182 + /* H-timing in pixels */
183 + unsigned int line_length_pix;
185 + /* Analog crop rectangle. */
186 + struct v4l2_rect crop;
188 + /* Default framerate. */
189 + struct v4l2_fract timeperframe_default;
191 + /* Default register values */
192 + struct arducam_64mp_reg_list reg_list;
195 +static const struct arducam_64mp_reg mode_common_regs[] = {
842 +/* 64 mpix 2.7fps */
843 +static const struct arducam_64mp_reg mode_9152x6944_regs[] = {
902 +static const struct arducam_64mp_reg mode_4624x3472_regs[] = {
955 +static const struct arducam_64mp_reg mode_3840x2160_regs[] = {
1007 +/* 4x4 binned 30fps mode */
1008 +static const struct arducam_64mp_reg mode_2312x1736_regs[] = {
1060 +/* 1080p 60fps mode */
1061 +static const struct arducam_64mp_reg mode_1920x1080_regs[] = {
1113 +/* 720p 120fps mode */
1114 +static const struct arducam_64mp_reg mode_1280x720_regs[] = {
1167 +static const struct arducam_64mp_mode supported_modes[] = {
1171 + .line_length_pix = 0xb6b2,
1173 + .left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT,
1174 + .top = ARDUCAM_64MP_PIXEL_ARRAY_TOP,
1178 + .timeperframe_default = {
1180 + .denominator = 270
1183 + .num_of_regs = ARRAY_SIZE(mode_9152x6944_regs),
1184 + .regs = mode_9152x6944_regs,
1189 + .line_length_pix = 0x6397,
1191 + .left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT,
1192 + .top = ARDUCAM_64MP_PIXEL_ARRAY_TOP,
1196 + .timeperframe_default = {
1198 + .denominator = 1000
1201 + .num_of_regs = ARRAY_SIZE(mode_4624x3472_regs),
1202 + .regs = mode_4624x3472_regs,
1207 + .line_length_pix = 0x4eb7,
1209 + .left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT + 784,
1210 + .top = ARDUCAM_64MP_PIXEL_ARRAY_TOP + 1312,
1214 + .timeperframe_default = {
1216 + .denominator = 2000
1219 + .num_of_regs = ARRAY_SIZE(mode_3840x2160_regs),
1220 + .regs = mode_3840x2160_regs,
1225 + .line_length_pix = 0x3360,
1227 + .left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT,
1228 + .top = ARDUCAM_64MP_PIXEL_ARRAY_TOP,
1232 + .timeperframe_default = {
1234 + .denominator = 3000
1237 + .num_of_regs = ARRAY_SIZE(mode_2312x1736_regs),
1238 + .regs = mode_2312x1736_regs,
1243 + .line_length_pix = 0x29e3,
1245 + .left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT + 784,
1246 + .top = ARDUCAM_64MP_PIXEL_ARRAY_TOP + 1312,
1250 + .timeperframe_default = {
1252 + .denominator = 6000
1255 + .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),
1256 + .regs = mode_1920x1080_regs,
1261 + .line_length_pix = 0x1dc4,
1263 + .left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT + 2064,
1264 + .top = ARDUCAM_64MP_PIXEL_ARRAY_TOP + 2032,
1268 + .timeperframe_default = {
1270 + .denominator = 12000
1273 + .num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
1274 + .regs = mode_1280x720_regs,
1280 + * The supported formats.
1281 + * This table MUST contain 4 entries per format, to cover the various flip
1282 + * combinations in the order
1288 +static const u32 codes[] = {
1289 + /* 10-bit modes. */
1290 + MEDIA_BUS_FMT_SRGGB10_1X10,
1291 + MEDIA_BUS_FMT_SGRBG10_1X10,
1292 + MEDIA_BUS_FMT_SGBRG10_1X10,
1293 + MEDIA_BUS_FMT_SBGGR10_1X10,
1296 +static const char * const arducam_64mp_test_pattern_menu[] = {
1300 + "Grey Color Bars",
1304 +static const int arducam_64mp_test_pattern_val[] = {
1305 + ARDUCAM_64MP_TEST_PATTERN_DISABLE,
1306 + ARDUCAM_64MP_TEST_PATTERN_COLOR_BARS,
1307 + ARDUCAM_64MP_TEST_PATTERN_SOLID_COLOR,
1308 + ARDUCAM_64MP_TEST_PATTERN_GREY_COLOR,
1309 + ARDUCAM_64MP_TEST_PATTERN_PN9,
1312 +/* regulator supplies */
1313 +static const char * const arducam_64mp_supply_name[] = {
1314 + /* Supplies can be enabled in any order */
1315 + "VANA", /* Analog (2.8V) supply */
1316 + "VDIG", /* Digital Core (1.05V) supply */
1317 + "VDDL", /* IF (1.8V) supply */
1320 +#define ARDUCAM_64MP_NUM_SUPPLIES ARRAY_SIZE(arducam_64mp_supply_name)
1323 + * Initialisation delay between XCLR low->high and the moment when the sensor
1324 + * can start capture (i.e. can leave software standby), given by T7 in the
1325 + * datasheet is 7.7ms. This does include I2C setup time as well.
1327 + * Note, that delay between XCLR low->high and reading the CCI ID register (T6
1328 + * in the datasheet) is much smaller - 1ms.
1330 +#define ARDUCAM_64MP_XCLR_MIN_DELAY_US 8000
1331 +#define ARDUCAM_64MP_XCLR_DELAY_RANGE_US 1000
1333 +struct arducam_64mp {
1334 + struct v4l2_subdev sd;
1335 + struct media_pad pad;
1337 + unsigned int fmt_code;
1341 + struct gpio_desc *reset_gpio;
1342 + struct regulator_bulk_data supplies[ARDUCAM_64MP_NUM_SUPPLIES];
1344 + struct v4l2_ctrl_handler ctrl_handler;
1345 + /* V4L2 Controls */
1346 + struct v4l2_ctrl *pixel_rate;
1347 + struct v4l2_ctrl *exposure;
1348 + struct v4l2_ctrl *vflip;
1349 + struct v4l2_ctrl *hflip;
1350 + struct v4l2_ctrl *vblank;
1351 + struct v4l2_ctrl *hblank;
1353 + /* Current mode */
1354 + const struct arducam_64mp_mode *mode;
1357 + * Mutex for serialized access:
1358 + * Protect sensor module set pad format and start/stop streaming safely.
1360 + struct mutex mutex;
1362 + /* Streaming on/off */
1365 + /* Rewrite common registers on stream on? */
1366 + bool common_regs_written;
1368 + /* Current long exposure factor in use. Set through V4L2_CID_VBLANK */
1369 + unsigned int long_exp_shift;
1372 +static inline struct arducam_64mp *to_arducam_64mp(struct v4l2_subdev *_sd)
1374 + return container_of(_sd, struct arducam_64mp, sd);
1377 +/* Read registers up to 2 at a time */
1378 +static int arducam_64mp_read_reg(struct i2c_client *client,
1379 + u16 reg, u32 len, u32 *val)
1381 + struct i2c_msg msgs[2];
1382 + u8 addr_buf[2] = { reg >> 8, reg & 0xff };
1383 + u8 data_buf[4] = { 0, };
1389 + /* Write register address */
1390 + msgs[0].addr = client->addr;
1391 + msgs[0].flags = 0;
1392 + msgs[0].len = ARRAY_SIZE(addr_buf);
1393 + msgs[0].buf = addr_buf;
1395 + /* Read data from register */
1396 + msgs[1].addr = client->addr;
1397 + msgs[1].flags = I2C_M_RD;
1398 + msgs[1].len = len;
1399 + msgs[1].buf = &data_buf[4 - len];
1401 + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
1402 + if (ret != ARRAY_SIZE(msgs))
1405 + *val = get_unaligned_be32(data_buf);
1410 +/* Write registers up to 2 at a time */
1411 +static int arducam_64mp_write_reg(struct arducam_64mp *arducam_64mp,
1412 + u16 reg, u32 len, u32 val)
1414 + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd);
1420 + put_unaligned_be16(reg, buf);
1421 + put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
1422 + if (i2c_master_send(client, buf, len + 2) != len + 2)
1428 +/* Write a list of registers */
1429 +static int arducam_64mp_write_regs(struct arducam_64mp *arducam_64mp,
1430 + const struct arducam_64mp_reg *regs, u32 len)
1432 + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd);
1436 + for (i = 0; i < len; i++) {
1437 + ret = arducam_64mp_write_reg(arducam_64mp, regs[i].address, 1,
1440 + dev_err_ratelimited(&client->dev,
1441 + "Failed to write reg 0x%4.4x. error = %d\n",
1442 + regs[i].address, ret);
1451 +/* Get bayer order based on flip setting. */
1452 +static u32 arducam_64mp_get_format_code(struct arducam_64mp *arducam_64mp)
1456 + lockdep_assert_held(&arducam_64mp->mutex);
1458 + i = (arducam_64mp->vflip->val ? 2 : 0) |
1459 + (arducam_64mp->hflip->val ? 1 : 0);
1464 +static int arducam_64mp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1466 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
1467 + struct v4l2_mbus_framefmt *try_fmt_img =
1468 + v4l2_subdev_get_try_format(sd, fh->state, 0);
1469 + struct v4l2_rect *try_crop;
1471 + mutex_lock(&arducam_64mp->mutex);
1473 + /* Initialize try_fmt for the image pad */
1474 + try_fmt_img->width = supported_modes[0].width;
1475 + try_fmt_img->height = supported_modes[0].height;
1476 + try_fmt_img->code = arducam_64mp_get_format_code(arducam_64mp);
1477 + try_fmt_img->field = V4L2_FIELD_NONE;
1479 + /* Initialize try_crop */
1480 + try_crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
1481 + try_crop->left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT;
1482 + try_crop->top = ARDUCAM_64MP_PIXEL_ARRAY_TOP;
1483 + try_crop->width = ARDUCAM_64MP_PIXEL_ARRAY_WIDTH;
1484 + try_crop->height = ARDUCAM_64MP_PIXEL_ARRAY_HEIGHT;
1486 + mutex_unlock(&arducam_64mp->mutex);
1492 +arducam_64mp_adjust_exposure_range(struct arducam_64mp *arducam_64mp)
1494 + int exposure_max, exposure_def;
1496 + /* Honour the VBLANK limits when setting exposure. */
1497 + exposure_max = arducam_64mp->mode->height + arducam_64mp->vblank->val -
1498 + ARDUCAM_64MP_EXPOSURE_OFFSET;
1499 + exposure_def = min(exposure_max, arducam_64mp->exposure->val);
1500 + __v4l2_ctrl_modify_range(arducam_64mp->exposure,
1501 + arducam_64mp->exposure->minimum,
1502 + exposure_max, arducam_64mp->exposure->step,
1506 +static int arducam_64mp_set_frame_length(struct arducam_64mp *arducam_64mp,
1507 + unsigned int vblank)
1509 + unsigned int val = vblank + arducam_64mp->mode->height;
1512 + arducam_64mp->long_exp_shift = 0;
1514 + while (val > ARDUCAM_64MP_FRAME_LENGTH_MAX) {
1515 + arducam_64mp->long_exp_shift++;
1519 + ret = arducam_64mp_write_reg(arducam_64mp,
1520 + ARDUCAM_64MP_REG_FRAME_LENGTH,
1521 + ARDUCAM_64MP_REG_VALUE_16BIT, val);
1525 + return arducam_64mp_write_reg(arducam_64mp,
1526 + ARDUCAM_64MP_LONG_EXP_SHIFT_REG,
1527 + ARDUCAM_64MP_REG_VALUE_08BIT,
1528 + arducam_64mp->long_exp_shift);
1531 +static int arducam_64mp_set_ctrl(struct v4l2_ctrl *ctrl)
1533 + struct arducam_64mp *arducam_64mp =
1534 + container_of(ctrl->handler, struct arducam_64mp, ctrl_handler);
1535 + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd);
1539 + * The VBLANK control may change the limits of usable exposure, so check
1540 + * and adjust if necessary.
1542 + if (ctrl->id == V4L2_CID_VBLANK)
1543 + arducam_64mp_adjust_exposure_range(arducam_64mp);
1546 + * Applying V4L2 control value only happens
1547 + * when power is up for streaming
1549 + if (pm_runtime_get_if_in_use(&client->dev) == 0)
1552 + switch (ctrl->id) {
1553 + case V4L2_CID_ANALOGUE_GAIN:
1554 + ret = arducam_64mp_write_reg(arducam_64mp,
1555 + ARDUCAM_64MP_REG_ANALOG_GAIN,
1556 + ARDUCAM_64MP_REG_VALUE_16BIT,
1559 + case V4L2_CID_EXPOSURE:
1560 + val = ctrl->val >> arducam_64mp->long_exp_shift;
1561 + ret = arducam_64mp_write_reg(arducam_64mp,
1562 + ARDUCAM_64MP_REG_EXPOSURE,
1563 + ARDUCAM_64MP_REG_VALUE_16BIT,
1566 + case V4L2_CID_DIGITAL_GAIN:
1567 + ret = arducam_64mp_write_reg(arducam_64mp,
1568 + ARDUCAM_64MP_REG_DIGITAL_GAIN,
1569 + ARDUCAM_64MP_REG_VALUE_16BIT,
1572 + case V4L2_CID_TEST_PATTERN:
1573 + val = arducam_64mp_test_pattern_val[ctrl->val];
1574 + ret = arducam_64mp_write_reg(arducam_64mp,
1575 + ARDUCAM_64MP_REG_TEST_PATTERN,
1576 + ARDUCAM_64MP_REG_VALUE_16BIT,
1579 + case V4L2_CID_TEST_PATTERN_RED:
1580 + ret = arducam_64mp_write_reg(arducam_64mp,
1581 + ARDUCAM_64MP_REG_TEST_PATTERN_R,
1582 + ARDUCAM_64MP_REG_VALUE_16BIT,
1585 + case V4L2_CID_TEST_PATTERN_GREENR:
1586 + ret = arducam_64mp_write_reg(arducam_64mp,
1587 + ARDUCAM_64MP_REG_TEST_PATTERN_GR,
1588 + ARDUCAM_64MP_REG_VALUE_16BIT,
1591 + case V4L2_CID_TEST_PATTERN_BLUE:
1592 + ret = arducam_64mp_write_reg(arducam_64mp,
1593 + ARDUCAM_64MP_REG_TEST_PATTERN_B,
1594 + ARDUCAM_64MP_REG_VALUE_16BIT,
1597 + case V4L2_CID_TEST_PATTERN_GREENB:
1598 + ret = arducam_64mp_write_reg(arducam_64mp,
1599 + ARDUCAM_64MP_REG_TEST_PATTERN_GB,
1600 + ARDUCAM_64MP_REG_VALUE_16BIT,
1603 + case V4L2_CID_HFLIP:
1604 + case V4L2_CID_VFLIP:
1605 + ret = arducam_64mp_write_reg(arducam_64mp,
1606 + ARDUCAM_64MP_REG_ORIENTATION, 1,
1607 + arducam_64mp->hflip->val |
1608 + arducam_64mp->vflip->val << 1);
1610 + case V4L2_CID_VBLANK:
1611 + ret = arducam_64mp_set_frame_length(arducam_64mp, ctrl->val);
1614 + dev_info(&client->dev,
1615 + "ctrl(id:0x%x,val:0x%x) is not handled\n",
1616 + ctrl->id, ctrl->val);
1621 + pm_runtime_put(&client->dev);
1626 +static const struct v4l2_ctrl_ops arducam_64mp_ctrl_ops = {
1627 + .s_ctrl = arducam_64mp_set_ctrl,
1630 +static int arducam_64mp_enum_mbus_code(struct v4l2_subdev *sd,
1631 + struct v4l2_subdev_state *sd_state,
1632 + struct v4l2_subdev_mbus_code_enum *code)
1634 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
1636 + if (code->index > 0)
1639 + code->code = arducam_64mp_get_format_code(arducam_64mp);
1644 +static int arducam_64mp_enum_frame_size(struct v4l2_subdev *sd,
1645 + struct v4l2_subdev_state *sd_state,
1646 + struct v4l2_subdev_frame_size_enum *fse)
1648 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
1650 + if (fse->index >= ARRAY_SIZE(supported_modes))
1653 + if (fse->code != arducam_64mp_get_format_code(arducam_64mp))
1656 + fse->min_width = supported_modes[fse->index].width;
1657 + fse->max_width = fse->min_width;
1658 + fse->min_height = supported_modes[fse->index].height;
1659 + fse->max_height = fse->min_height;
1664 +static void arducam_64mp_reset_colorspace(struct v4l2_mbus_framefmt *fmt)
1666 + fmt->colorspace = V4L2_COLORSPACE_RAW;
1667 + fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
1668 + fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
1671 + fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
1675 +arducam_64mp_update_image_pad_format(struct arducam_64mp *arducam_64mp,
1676 + const struct arducam_64mp_mode *mode,
1677 + struct v4l2_subdev_format *fmt)
1679 + fmt->format.width = mode->width;
1680 + fmt->format.height = mode->height;
1681 + fmt->format.field = V4L2_FIELD_NONE;
1682 + arducam_64mp_reset_colorspace(&fmt->format);
1685 +static int arducam_64mp_get_pad_format(struct v4l2_subdev *sd,
1686 + struct v4l2_subdev_state *sd_state,
1687 + struct v4l2_subdev_format *fmt)
1689 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
1691 + if (fmt->pad != 0)
1694 + mutex_lock(&arducam_64mp->mutex);
1696 + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1697 + struct v4l2_mbus_framefmt *try_fmt =
1698 + v4l2_subdev_get_try_format(&arducam_64mp->sd, sd_state,
1700 + /* update the code which could change due to vflip or hflip: */
1701 + try_fmt->code = arducam_64mp_get_format_code(arducam_64mp);
1702 + fmt->format = *try_fmt;
1704 + arducam_64mp_update_image_pad_format(arducam_64mp,
1705 + arducam_64mp->mode,
1707 + fmt->format.code =
1708 + arducam_64mp_get_format_code(arducam_64mp);
1711 + mutex_unlock(&arducam_64mp->mutex);
1715 +static unsigned int
1716 +arducam_64mp_get_frame_length(const struct arducam_64mp_mode *mode,
1717 + const struct v4l2_fract *timeperframe)
1721 + frame_length = (u64)timeperframe->numerator * ARDUCAM_64MP_PIXEL_RATE;
1722 + do_div(frame_length,
1723 + (u64)timeperframe->denominator * mode->line_length_pix);
1725 + if (WARN_ON(frame_length > ARDUCAM_64MP_FRAME_LENGTH_MAX))
1726 + frame_length = ARDUCAM_64MP_FRAME_LENGTH_MAX;
1728 + return max_t(unsigned int, frame_length, mode->height);
1731 +static void arducam_64mp_set_framing_limits(struct arducam_64mp *arducam_64mp)
1733 + unsigned int frm_length_min, frm_length_default, hblank;
1734 + const struct arducam_64mp_mode *mode = arducam_64mp->mode;
1736 + /* The default framerate is highest possible framerate. */
1738 + arducam_64mp_get_frame_length(mode,
1739 + &mode->timeperframe_default);
1740 + frm_length_default =
1741 + arducam_64mp_get_frame_length(mode,
1742 + &mode->timeperframe_default);
1744 + /* Default to no long exposure multiplier. */
1745 + arducam_64mp->long_exp_shift = 0;
1747 + /* Update limits and set FPS to default */
1748 + __v4l2_ctrl_modify_range(arducam_64mp->vblank,
1749 + frm_length_min - mode->height,
1750 + ((1 << ARDUCAM_64MP_LONG_EXP_SHIFT_MAX) *
1751 + ARDUCAM_64MP_FRAME_LENGTH_MAX) - mode->height,
1752 + 1, frm_length_default - mode->height);
1754 + /* Setting this will adjust the exposure limits as well. */
1755 + __v4l2_ctrl_s_ctrl(arducam_64mp->vblank,
1756 + frm_length_default - mode->height);
1759 + * Currently PPL is fixed to the mode specified value, so hblank
1760 + * depends on mode->width only, and is not changeable in any
1761 + * way other than changing the mode.
1763 + hblank = mode->line_length_pix - mode->width;
1764 + __v4l2_ctrl_modify_range(arducam_64mp->hblank, hblank, hblank, 1,
1768 +static int arducam_64mp_set_pad_format(struct v4l2_subdev *sd,
1769 + struct v4l2_subdev_state *sd_state,
1770 + struct v4l2_subdev_format *fmt)
1772 + struct v4l2_mbus_framefmt *framefmt;
1773 + const struct arducam_64mp_mode *mode;
1774 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
1776 + if (fmt->pad != 0)
1779 + mutex_lock(&arducam_64mp->mutex);
1781 + /* Bayer order varies with flips */
1782 + fmt->format.code = arducam_64mp_get_format_code(arducam_64mp);
1784 + mode = v4l2_find_nearest_size(supported_modes,
1785 + ARRAY_SIZE(supported_modes),
1787 + fmt->format.width,
1788 + fmt->format.height);
1789 + arducam_64mp_update_image_pad_format(arducam_64mp, mode, fmt);
1790 + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1791 + framefmt = v4l2_subdev_get_try_format(sd, sd_state,
1793 + *framefmt = fmt->format;
1795 + arducam_64mp->mode = mode;
1796 + arducam_64mp->fmt_code = fmt->format.code;
1797 + arducam_64mp_set_framing_limits(arducam_64mp);
1800 + mutex_unlock(&arducam_64mp->mutex);
1805 +static const struct v4l2_rect *
1806 +__arducam_64mp_get_pad_crop(struct arducam_64mp *arducam_64mp,
1807 + struct v4l2_subdev_state *sd_state,
1809 + enum v4l2_subdev_format_whence which)
1812 + case V4L2_SUBDEV_FORMAT_TRY:
1813 + return v4l2_subdev_get_try_crop(&arducam_64mp->sd, sd_state,
1815 + case V4L2_SUBDEV_FORMAT_ACTIVE:
1816 + return &arducam_64mp->mode->crop;
1822 +static int arducam_64mp_get_selection(struct v4l2_subdev *sd,
1823 + struct v4l2_subdev_state *sd_state,
1824 + struct v4l2_subdev_selection *sel)
1826 + switch (sel->target) {
1827 + case V4L2_SEL_TGT_CROP: {
1828 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
1830 + mutex_lock(&arducam_64mp->mutex);
1831 + sel->r = *__arducam_64mp_get_pad_crop(arducam_64mp, sd_state,
1832 + sel->pad, sel->which);
1833 + mutex_unlock(&arducam_64mp->mutex);
1838 + case V4L2_SEL_TGT_NATIVE_SIZE:
1841 + sel->r.width = ARDUCAM_64MP_NATIVE_WIDTH;
1842 + sel->r.height = ARDUCAM_64MP_NATIVE_HEIGHT;
1846 + case V4L2_SEL_TGT_CROP_DEFAULT:
1847 + case V4L2_SEL_TGT_CROP_BOUNDS:
1848 + sel->r.left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT;
1849 + sel->r.top = ARDUCAM_64MP_PIXEL_ARRAY_TOP;
1850 + sel->r.width = ARDUCAM_64MP_PIXEL_ARRAY_WIDTH;
1851 + sel->r.height = ARDUCAM_64MP_PIXEL_ARRAY_HEIGHT;
1859 +/* Start streaming */
1860 +static int arducam_64mp_start_streaming(struct arducam_64mp *arducam_64mp)
1862 + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd);
1863 + const struct arducam_64mp_reg_list *reg_list;
1866 + if (!arducam_64mp->common_regs_written) {
1867 + ret = arducam_64mp_write_regs(arducam_64mp, mode_common_regs,
1868 + ARRAY_SIZE(mode_common_regs));
1871 + dev_err(&client->dev, "%s failed to set common settings\n",
1875 + arducam_64mp->common_regs_written = true;
1878 + /* Apply default values of current mode */
1879 + reg_list = &arducam_64mp->mode->reg_list;
1880 + ret = arducam_64mp_write_regs(arducam_64mp, reg_list->regs,
1881 + reg_list->num_of_regs);
1883 + dev_err(&client->dev, "%s failed to set mode\n", __func__);
1887 + /* Apply customized values from user */
1888 + ret = __v4l2_ctrl_handler_setup(arducam_64mp->sd.ctrl_handler);
1892 + /* set stream on register */
1893 + return arducam_64mp_write_reg(arducam_64mp,
1894 + ARDUCAM_64MP_REG_MODE_SELECT,
1895 + ARDUCAM_64MP_REG_VALUE_08BIT,
1896 + ARDUCAM_64MP_MODE_STREAMING);
1899 +/* Stop streaming */
1900 +static void arducam_64mp_stop_streaming(struct arducam_64mp *arducam_64mp)
1902 + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd);
1905 + /* set stream off register */
1906 + ret = arducam_64mp_write_reg(arducam_64mp, ARDUCAM_64MP_REG_MODE_SELECT,
1907 + ARDUCAM_64MP_REG_VALUE_08BIT,
1908 + ARDUCAM_64MP_MODE_STANDBY);
1910 + dev_err(&client->dev, "%s failed to set stream\n", __func__);
1913 +static int arducam_64mp_set_stream(struct v4l2_subdev *sd, int enable)
1915 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
1916 + struct i2c_client *client = v4l2_get_subdevdata(sd);
1919 + mutex_lock(&arducam_64mp->mutex);
1920 + if (arducam_64mp->streaming == enable) {
1921 + mutex_unlock(&arducam_64mp->mutex);
1926 + ret = pm_runtime_get_sync(&client->dev);
1928 + pm_runtime_put_noidle(&client->dev);
1933 + * Apply default & customized values
1934 + * and then start streaming.
1936 + ret = arducam_64mp_start_streaming(arducam_64mp);
1940 + arducam_64mp_stop_streaming(arducam_64mp);
1941 + pm_runtime_put(&client->dev);
1944 + arducam_64mp->streaming = enable;
1946 + /* vflip and hflip cannot change during streaming */
1947 + __v4l2_ctrl_grab(arducam_64mp->vflip, enable);
1948 + __v4l2_ctrl_grab(arducam_64mp->hflip, enable);
1950 + mutex_unlock(&arducam_64mp->mutex);
1955 + pm_runtime_put(&client->dev);
1957 + mutex_unlock(&arducam_64mp->mutex);
1962 +/* Power/clock management functions */
1963 +static int arducam_64mp_power_on(struct device *dev)
1965 + struct i2c_client *client = to_i2c_client(dev);
1966 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
1967 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
1970 + ret = regulator_bulk_enable(ARDUCAM_64MP_NUM_SUPPLIES,
1971 + arducam_64mp->supplies);
1973 + dev_err(&client->dev, "%s: failed to enable regulators\n",
1978 + ret = clk_prepare_enable(arducam_64mp->xclk);
1980 + dev_err(&client->dev, "%s: failed to enable clock\n",
1985 + gpiod_set_value_cansleep(arducam_64mp->reset_gpio, 1);
1986 + usleep_range(ARDUCAM_64MP_XCLR_MIN_DELAY_US,
1987 + ARDUCAM_64MP_XCLR_MIN_DELAY_US +
1988 + ARDUCAM_64MP_XCLR_DELAY_RANGE_US);
1993 + regulator_bulk_disable(ARDUCAM_64MP_NUM_SUPPLIES,
1994 + arducam_64mp->supplies);
1998 +static int arducam_64mp_power_off(struct device *dev)
2000 + struct i2c_client *client = to_i2c_client(dev);
2001 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
2002 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
2004 + gpiod_set_value_cansleep(arducam_64mp->reset_gpio, 0);
2005 + regulator_bulk_disable(ARDUCAM_64MP_NUM_SUPPLIES,
2006 + arducam_64mp->supplies);
2007 + clk_disable_unprepare(arducam_64mp->xclk);
2009 + /* Force reprogramming of the common registers when powered up again. */
2010 + arducam_64mp->common_regs_written = false;
2015 +static int __maybe_unused arducam_64mp_suspend(struct device *dev)
2017 + struct i2c_client *client = to_i2c_client(dev);
2018 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
2019 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
2021 + if (arducam_64mp->streaming)
2022 + arducam_64mp_stop_streaming(arducam_64mp);
2027 +static int __maybe_unused arducam_64mp_resume(struct device *dev)
2029 + struct i2c_client *client = to_i2c_client(dev);
2030 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
2031 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
2034 + if (arducam_64mp->streaming) {
2035 + ret = arducam_64mp_start_streaming(arducam_64mp);
2043 + arducam_64mp_stop_streaming(arducam_64mp);
2044 + arducam_64mp->streaming = 0;
2048 +static int arducam_64mp_get_regulators(struct arducam_64mp *arducam_64mp)
2050 + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd);
2053 + for (i = 0; i < ARDUCAM_64MP_NUM_SUPPLIES; i++)
2054 + arducam_64mp->supplies[i].supply = arducam_64mp_supply_name[i];
2056 + return devm_regulator_bulk_get(&client->dev,
2057 + ARDUCAM_64MP_NUM_SUPPLIES,
2058 + arducam_64mp->supplies);
2061 +/* Verify chip ID */
2062 +static int arducam_64mp_identify_module(struct arducam_64mp *arducam_64mp)
2064 + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd);
2065 + struct i2c_client *arducam_identifier;
2069 + arducam_identifier = i2c_new_dummy_device(client->adapter, 0x50);
2070 + if (IS_ERR(arducam_identifier)) {
2071 + dev_err(&client->dev, "failed to create arducam_identifier\n");
2072 + return PTR_ERR(arducam_identifier);
2075 + ret = arducam_64mp_read_reg(arducam_identifier,
2076 + ARDUCAM_64MP_REG_CHIP_ID,
2077 + ARDUCAM_64MP_REG_VALUE_16BIT, &val);
2079 + dev_err(&client->dev, "failed to read chip id %x, with error %d\n",
2080 + ARDUCAM_64MP_CHIP_ID, ret);
2084 + if (val != ARDUCAM_64MP_CHIP_ID) {
2085 + dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
2086 + ARDUCAM_64MP_CHIP_ID, val);
2091 + dev_info(&client->dev, "Device found Arducam 64MP.\n");
2094 + i2c_unregister_device(arducam_identifier);
2099 +static const struct v4l2_subdev_core_ops arducam_64mp_core_ops = {
2100 + .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
2101 + .unsubscribe_event = v4l2_event_subdev_unsubscribe,
2104 +static const struct v4l2_subdev_video_ops arducam_64mp_video_ops = {
2105 + .s_stream = arducam_64mp_set_stream,
2108 +static const struct v4l2_subdev_pad_ops arducam_64mp_pad_ops = {
2109 + .enum_mbus_code = arducam_64mp_enum_mbus_code,
2110 + .get_fmt = arducam_64mp_get_pad_format,
2111 + .set_fmt = arducam_64mp_set_pad_format,
2112 + .get_selection = arducam_64mp_get_selection,
2113 + .enum_frame_size = arducam_64mp_enum_frame_size,
2116 +static const struct v4l2_subdev_ops arducam_64mp_subdev_ops = {
2117 + .core = &arducam_64mp_core_ops,
2118 + .video = &arducam_64mp_video_ops,
2119 + .pad = &arducam_64mp_pad_ops,
2122 +static const struct v4l2_subdev_internal_ops arducam_64mp_internal_ops = {
2123 + .open = arducam_64mp_open,
2126 +/* Initialize control handlers */
2127 +static int arducam_64mp_init_controls(struct arducam_64mp *arducam_64mp)
2129 + struct v4l2_ctrl_handler *ctrl_hdlr;
2130 + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd);
2131 + struct v4l2_fwnode_device_properties props;
2134 + u8 test_pattern_max;
2136 + ctrl_hdlr = &arducam_64mp->ctrl_handler;
2137 + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 16);
2141 + mutex_init(&arducam_64mp->mutex);
2142 + ctrl_hdlr->lock = &arducam_64mp->mutex;
2144 + /* By default, PIXEL_RATE is read only */
2145 + arducam_64mp->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr,
2146 + &arducam_64mp_ctrl_ops,
2147 + V4L2_CID_PIXEL_RATE,
2148 + ARDUCAM_64MP_PIXEL_RATE,
2149 + ARDUCAM_64MP_PIXEL_RATE, 1,
2150 + ARDUCAM_64MP_PIXEL_RATE);
2153 + * Create the controls here, but mode specific limits are setup
2154 + * in the arducam_64mp_set_framing_limits() call below.
2156 + arducam_64mp->vblank = v4l2_ctrl_new_std(ctrl_hdlr,
2157 + &arducam_64mp_ctrl_ops,
2160 + arducam_64mp->hblank = v4l2_ctrl_new_std(ctrl_hdlr,
2161 + &arducam_64mp_ctrl_ops,
2165 + /* HBLANK is read-only, but does change with mode. */
2166 + if (arducam_64mp->hblank)
2167 + arducam_64mp->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
2169 + arducam_64mp->exposure =
2170 + v4l2_ctrl_new_std(ctrl_hdlr,
2171 + &arducam_64mp_ctrl_ops,
2172 + V4L2_CID_EXPOSURE,
2173 + ARDUCAM_64MP_EXPOSURE_MIN,
2174 + ARDUCAM_64MP_EXPOSURE_MAX,
2175 + ARDUCAM_64MP_EXPOSURE_STEP,
2176 + ARDUCAM_64MP_EXPOSURE_DEFAULT);
2178 + v4l2_ctrl_new_std(ctrl_hdlr, &arducam_64mp_ctrl_ops,
2179 + V4L2_CID_ANALOGUE_GAIN, ARDUCAM_64MP_ANA_GAIN_MIN,
2180 + ARDUCAM_64MP_ANA_GAIN_MAX, ARDUCAM_64MP_ANA_GAIN_STEP,
2181 + ARDUCAM_64MP_ANA_GAIN_DEFAULT);
2183 + v4l2_ctrl_new_std(ctrl_hdlr, &arducam_64mp_ctrl_ops,
2184 + V4L2_CID_DIGITAL_GAIN, ARDUCAM_64MP_DGTL_GAIN_MIN,
2185 + ARDUCAM_64MP_DGTL_GAIN_MAX,
2186 + ARDUCAM_64MP_DGTL_GAIN_STEP,
2187 + ARDUCAM_64MP_DGTL_GAIN_DEFAULT);
2189 + arducam_64mp->hflip = v4l2_ctrl_new_std(ctrl_hdlr,
2190 + &arducam_64mp_ctrl_ops,
2191 + V4L2_CID_HFLIP, 0, 1, 1, 0);
2192 + if (arducam_64mp->hflip)
2193 + arducam_64mp->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
2195 + arducam_64mp->vflip = v4l2_ctrl_new_std(ctrl_hdlr,
2196 + &arducam_64mp_ctrl_ops,
2197 + V4L2_CID_VFLIP, 0, 1, 1, 0);
2198 + if (arducam_64mp->vflip)
2199 + arducam_64mp->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
2201 + test_pattern_max = ARRAY_SIZE(arducam_64mp_test_pattern_menu) - 1;
2202 + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &arducam_64mp_ctrl_ops,
2203 + V4L2_CID_TEST_PATTERN,
2205 + 0, 0, arducam_64mp_test_pattern_menu);
2206 + for (i = 0; i < 4; i++) {
2208 + * The assumption is that
2209 + * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1
2210 + * V4L2_CID_TEST_PATTERN_BLUE == V4L2_CID_TEST_PATTERN_RED + 2
2211 + * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3
2213 + v4l2_ctrl_new_std(ctrl_hdlr, &arducam_64mp_ctrl_ops,
2214 + V4L2_CID_TEST_PATTERN_RED + i,
2215 + ARDUCAM_64MP_TEST_PATTERN_COLOUR_MIN,
2216 + ARDUCAM_64MP_TEST_PATTERN_COLOUR_MAX,
2217 + ARDUCAM_64MP_TEST_PATTERN_COLOUR_STEP,
2218 + ARDUCAM_64MP_TEST_PATTERN_COLOUR_MAX);
2219 + /* The "Solid color" pattern is white by default */
2222 + if (ctrl_hdlr->error) {
2223 + ret = ctrl_hdlr->error;
2224 + dev_err(&client->dev, "%s control init failed (%d)\n",
2229 + ret = v4l2_fwnode_device_parse(&client->dev, &props);
2233 + ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &arducam_64mp_ctrl_ops,
2238 + arducam_64mp->sd.ctrl_handler = ctrl_hdlr;
2240 + /* Setup exposure and frame/line length limits. */
2241 + arducam_64mp_set_framing_limits(arducam_64mp);
2246 + v4l2_ctrl_handler_free(ctrl_hdlr);
2247 + mutex_destroy(&arducam_64mp->mutex);
2252 +static void arducam_64mp_free_controls(struct arducam_64mp *arducam_64mp)
2254 + v4l2_ctrl_handler_free(arducam_64mp->sd.ctrl_handler);
2255 + mutex_destroy(&arducam_64mp->mutex);
2258 +static int arducam_64mp_check_hwcfg(struct device *dev)
2260 + struct fwnode_handle *endpoint;
2261 + struct v4l2_fwnode_endpoint ep_cfg = {
2262 + .bus_type = V4L2_MBUS_CSI2_DPHY
2264 + int ret = -EINVAL;
2266 + endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
2268 + dev_err(dev, "endpoint node not found\n");
2272 + if (v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep_cfg)) {
2273 + dev_err(dev, "could not parse endpoint\n");
2277 + /* Check the number of MIPI CSI2 data lanes */
2278 + if (ep_cfg.bus.mipi_csi2.num_data_lanes != 2) {
2279 + dev_err(dev, "only 2 data lanes are currently supported\n");
2283 + /* Check the link frequency set in device tree */
2284 + if (!ep_cfg.nr_of_link_frequencies) {
2285 + dev_err(dev, "link-frequency property not found in DT\n");
2289 + if (ep_cfg.nr_of_link_frequencies != 1 ||
2290 + ep_cfg.link_frequencies[0] != ARDUCAM_64MP_DEFAULT_LINK_FREQ) {
2291 + dev_err(dev, "Link frequency not supported: %lld\n",
2292 + ep_cfg.link_frequencies[0]);
2299 + v4l2_fwnode_endpoint_free(&ep_cfg);
2300 + fwnode_handle_put(endpoint);
2305 +static const struct of_device_id arducam_64mp_dt_ids[] = {
2306 + { .compatible = "arducam,64mp"},
2307 + { /* sentinel */ }
2310 +static int arducam_64mp_probe(struct i2c_client *client)
2312 + struct device *dev = &client->dev;
2313 + struct arducam_64mp *arducam_64mp;
2314 + const struct of_device_id *match;
2318 + arducam_64mp = devm_kzalloc(&client->dev, sizeof(*arducam_64mp),
2320 + if (!arducam_64mp)
2323 + v4l2_i2c_subdev_init(&arducam_64mp->sd, client,
2324 + &arducam_64mp_subdev_ops);
2326 + match = of_match_device(arducam_64mp_dt_ids, dev);
2330 + /* Check the hardware configuration in device tree */
2331 + if (arducam_64mp_check_hwcfg(dev))
2334 + /* Get system clock (xclk) */
2335 + arducam_64mp->xclk = devm_clk_get(dev, NULL);
2336 + if (IS_ERR(arducam_64mp->xclk)) {
2337 + dev_err(dev, "failed to get xclk\n");
2338 + return PTR_ERR(arducam_64mp->xclk);
2341 + xclk_freq = clk_get_rate(arducam_64mp->xclk);
2342 + if (xclk_freq != ARDUCAM_64MP_XCLK_FREQ) {
2343 + dev_err(dev, "xclk frequency not supported: %d Hz\n",
2348 + ret = arducam_64mp_get_regulators(arducam_64mp);
2350 + dev_err(dev, "failed to get regulators\n");
2354 + /* Request optional enable pin */
2355 + arducam_64mp->reset_gpio = devm_gpiod_get_optional(dev, "reset",
2359 + * The sensor must be powered for arducam_64mp_identify_module()
2360 + * to be able to read the CHIP_ID from arducam_identifier.
2362 + ret = arducam_64mp_power_on(dev);
2366 + ret = arducam_64mp_identify_module(arducam_64mp);
2368 + goto error_power_off;
2370 + /* Set default mode to max resolution */
2371 + arducam_64mp->mode = &supported_modes[0];
2372 + arducam_64mp->fmt_code = MEDIA_BUS_FMT_SRGGB10_1X10;
2374 + /* Enable runtime PM and turn off the device */
2375 + pm_runtime_set_active(dev);
2376 + pm_runtime_enable(dev);
2377 + pm_runtime_idle(dev);
2379 + /* This needs the pm runtime to be registered. */
2380 + ret = arducam_64mp_init_controls(arducam_64mp);
2382 + goto error_power_off;
2384 + /* Initialize subdev */
2385 + arducam_64mp->sd.internal_ops = &arducam_64mp_internal_ops;
2386 + arducam_64mp->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
2387 + V4L2_SUBDEV_FL_HAS_EVENTS;
2388 + arducam_64mp->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
2390 + /* Initialize source pads */
2391 + arducam_64mp->pad.flags = MEDIA_PAD_FL_SOURCE;
2393 + ret = media_entity_pads_init(&arducam_64mp->sd.entity, 1,
2394 + &arducam_64mp->pad);
2396 + dev_err(dev, "failed to init entity pads: %d\n", ret);
2397 + goto error_handler_free;
2400 + ret = v4l2_async_register_subdev_sensor(&arducam_64mp->sd);
2402 + dev_err(dev, "failed to register sensor sub-device: %d\n", ret);
2403 + goto error_media_entity;
2408 +error_media_entity:
2409 + media_entity_cleanup(&arducam_64mp->sd.entity);
2411 +error_handler_free:
2412 + arducam_64mp_free_controls(arducam_64mp);
2415 + pm_runtime_disable(&client->dev);
2416 + pm_runtime_set_suspended(&client->dev);
2417 + arducam_64mp_power_off(&client->dev);
2422 +static void arducam_64mp_remove(struct i2c_client *client)
2424 + struct v4l2_subdev *sd = i2c_get_clientdata(client);
2425 + struct arducam_64mp *arducam_64mp = to_arducam_64mp(sd);
2427 + v4l2_async_unregister_subdev(sd);
2428 + media_entity_cleanup(&sd->entity);
2429 + arducam_64mp_free_controls(arducam_64mp);
2431 + pm_runtime_disable(&client->dev);
2432 + if (!pm_runtime_status_suspended(&client->dev))
2433 + arducam_64mp_power_off(&client->dev);
2434 + pm_runtime_set_suspended(&client->dev);
2437 +MODULE_DEVICE_TABLE(of, arducam_64mp_dt_ids);
2439 +static const struct dev_pm_ops arducam_64mp_pm_ops = {
2440 + SET_SYSTEM_SLEEP_PM_OPS(arducam_64mp_suspend, arducam_64mp_resume)
2441 + SET_RUNTIME_PM_OPS(arducam_64mp_power_off, arducam_64mp_power_on, NULL)
2444 +static struct i2c_driver arducam_64mp_i2c_driver = {
2446 + .name = "arducam_64mp",
2447 + .of_match_table = arducam_64mp_dt_ids,
2448 + .pm = &arducam_64mp_pm_ops,
2450 + .probe_new = arducam_64mp_probe,
2451 + .remove = arducam_64mp_remove,
2454 +module_i2c_driver(arducam_64mp_i2c_driver);
2456 +MODULE_AUTHOR("Lee Jackson <info@arducam.com>");
2457 +MODULE_DESCRIPTION("Arducam 64MP sensor driver");
2458 +MODULE_LICENSE("GPL v2");