1 From ae0e1b70f675f6ac7966e427f0d8f57812dbc312 Mon Sep 17 00:00:00 2001
2 From: Hans de Goede <hdegoede@redhat.com>
3 Date: Tue, 27 Jun 2023 14:51:04 +0200
4 Subject: [PATCH] media: Add MIPI CCI register access helper functions
6 The CSI2 specification specifies a standard method to access camera sensor
7 registers called "Camera Control Interface (CCI)".
9 This uses either 8 or 16 bit (big-endian wire order) register addresses
10 and supports 8, 16, 24 or 32 bit (big-endian wire order) register widths.
12 Currently a lot of Linux camera sensor drivers all have their own custom
13 helpers for this, often copy and pasted from other drivers.
15 Add a set of generic helpers for this so that all sensor drivers can
16 switch to a single common implementation.
18 These helpers take an extra optional "int *err" function parameter,
19 this can be used to chain a bunch of register accesses together with
20 only a single error check at the end, rather than needing to error
21 check each individual register access. The first failing call will
22 set the contents of err to a non 0 value and all other calls will
25 Link: https://lore.kernel.org/linux-media/59aefa7f-7bf9-6736-6040-39551329cd0a@redhat.com/
27 Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
28 Tested-by: Tommaso Merciai <tomm.merciai@gmail.com>
29 Reviewed-by: Tommaso Merciai <tomm.merciai@gmail.com>
30 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
31 Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
32 Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
33 (cherry picked from commit 613cbb91e9cee7cf5a61f0816d2acab7bc117407)
35 Documentation/driver-api/media/v4l2-cci.rst | 5 +
36 Documentation/driver-api/media/v4l2-core.rst | 1 +
37 drivers/media/v4l2-core/Kconfig | 9 +
38 drivers/media/v4l2-core/Makefile | 1 +
39 drivers/media/v4l2-core/v4l2-cci.c | 166 +++++++++++++++++++
40 include/media/v4l2-cci.h | 125 ++++++++++++++
41 6 files changed, 307 insertions(+)
42 create mode 100644 Documentation/driver-api/media/v4l2-cci.rst
43 create mode 100644 drivers/media/v4l2-core/v4l2-cci.c
44 create mode 100644 include/media/v4l2-cci.h
47 +++ b/Documentation/driver-api/media/v4l2-cci.rst
49 +.. SPDX-License-Identifier: GPL-2.0
53 +.. kernel-doc:: include/media/v4l2-cci.h
54 --- a/Documentation/driver-api/media/v4l2-core.rst
55 +++ b/Documentation/driver-api/media/v4l2-core.rst
56 @@ -22,6 +22,7 @@ Video4Linux devices
64 --- a/drivers/media/v4l2-core/Kconfig
65 +++ b/drivers/media/v4l2-core/Kconfig
66 @@ -74,6 +74,15 @@ config V4L2_FWNODE
79 # Used by drivers that need Videobuf modules
82 --- a/drivers/media/v4l2-core/Makefile
83 +++ b/drivers/media/v4l2-core/Makefile
84 @@ -25,6 +25,7 @@ videodev-$(CONFIG_VIDEO_V4L2_I2C) += v4l
85 # (e. g. LC_ALL=C sort Makefile)
87 obj-$(CONFIG_V4L2_ASYNC) += v4l2-async.o
88 +obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o
89 obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o
90 obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o
91 obj-$(CONFIG_V4L2_H264) += v4l2-h264.o
93 +++ b/drivers/media/v4l2-core/v4l2-cci.c
95 +// SPDX-License-Identifier: GPL-2.0
97 + * MIPI Camera Control Interface (CCI) register access helpers.
99 + * Copyright (C) 2023 Hans de Goede <hansg@kernel.org>
102 +#include <linux/bitfield.h>
103 +#include <linux/delay.h>
104 +#include <linux/dev_printk.h>
105 +#include <linux/module.h>
106 +#include <linux/regmap.h>
107 +#include <linux/types.h>
109 +#include <asm/unaligned.h>
111 +#include <media/v4l2-cci.h>
113 +int cci_read(struct regmap *map, u32 reg, u64 *val, int *err)
122 + len = FIELD_GET(CCI_REG_WIDTH_MASK, reg);
123 + reg = FIELD_GET(CCI_REG_ADDR_MASK, reg);
125 + ret = regmap_bulk_read(map, reg, buf, len);
127 + dev_err(regmap_get_device(map), "Error reading reg 0x%4x: %d\n",
137 + *val = get_unaligned_be16(buf);
140 + *val = get_unaligned_be24(buf);
143 + *val = get_unaligned_be32(buf);
146 + *val = get_unaligned_be64(buf);
149 + dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n",
161 +EXPORT_SYMBOL_GPL(cci_read);
163 +int cci_write(struct regmap *map, u32 reg, u64 val, int *err)
172 + len = FIELD_GET(CCI_REG_WIDTH_MASK, reg);
173 + reg = FIELD_GET(CCI_REG_ADDR_MASK, reg);
180 + put_unaligned_be16(val, buf);
183 + put_unaligned_be24(val, buf);
186 + put_unaligned_be32(val, buf);
189 + put_unaligned_be64(val, buf);
192 + dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n",
198 + ret = regmap_bulk_write(map, reg, buf, len);
200 + dev_err(regmap_get_device(map), "Error writing reg 0x%4x: %d\n",
209 +EXPORT_SYMBOL_GPL(cci_write);
211 +int cci_update_bits(struct regmap *map, u32 reg, u64 mask, u64 val, int *err)
216 + ret = cci_read(map, reg, &readval, err);
220 + val = (readval & ~mask) | (val & mask);
222 + return cci_write(map, reg, val, err);
224 +EXPORT_SYMBOL_GPL(cci_update_bits);
226 +int cci_multi_reg_write(struct regmap *map, const struct cci_reg_sequence *regs,
227 + unsigned int num_regs, int *err)
232 + for (i = 0; i < num_regs; i++) {
233 + ret = cci_write(map, regs[i].reg, regs[i].val, err);
240 +EXPORT_SYMBOL_GPL(cci_multi_reg_write);
242 +#if IS_ENABLED(CONFIG_V4L2_CCI_I2C)
243 +struct regmap *devm_cci_regmap_init_i2c(struct i2c_client *client,
246 + struct regmap_config config = {
247 + .reg_bits = reg_addr_bits,
249 + .reg_format_endian = REGMAP_ENDIAN_BIG,
250 + .disable_locking = true,
253 + return devm_regmap_init_i2c(client, &config);
255 +EXPORT_SYMBOL_GPL(devm_cci_regmap_init_i2c);
258 +MODULE_LICENSE("GPL");
259 +MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>");
260 +MODULE_DESCRIPTION("MIPI Camera Control Interface (CCI) support");
262 +++ b/include/media/v4l2-cci.h
264 +/* SPDX-License-Identifier: GPL-2.0 */
266 + * MIPI Camera Control Interface (CCI) register access helpers.
268 + * Copyright (C) 2023 Hans de Goede <hansg@kernel.org>
273 +#include <linux/types.h>
279 + * struct cci_reg_sequence - An individual write from a sequence of CCI writes
281 + * @reg: Register address, use CCI_REG#() macros to encode reg width
282 + * @val: Register value
284 + * Register/value pairs for sequences of writes.
286 +struct cci_reg_sequence {
292 + * Macros to define register address with the register width encoded
293 + * into the higher bits.
295 +#define CCI_REG_ADDR_MASK GENMASK(15, 0)
296 +#define CCI_REG_WIDTH_SHIFT 16
297 +#define CCI_REG_WIDTH_MASK GENMASK(19, 16)
299 +#define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x))
300 +#define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x))
301 +#define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x))
302 +#define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x))
303 +#define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x))
306 + * cci_read() - Read a value from a single CCI register
308 + * @map: Register map to read from
309 + * @reg: Register address to read, use CCI_REG#() macros to encode reg width
310 + * @val: Pointer to store read value
311 + * @err: Optional pointer to store errors, if a previous error is set
312 + * then the read will be skipped
314 + * Return: %0 on success or a negative error code on failure.
316 +int cci_read(struct regmap *map, u32 reg, u64 *val, int *err);
319 + * cci_write() - Write a value to a single CCI register
321 + * @map: Register map to write to
322 + * @reg: Register address to write, use CCI_REG#() macros to encode reg width
323 + * @val: Value to be written
324 + * @err: Optional pointer to store errors, if a previous error is set
325 + * then the write will be skipped
327 + * Return: %0 on success or a negative error code on failure.
329 +int cci_write(struct regmap *map, u32 reg, u64 val, int *err);
332 + * cci_update_bits() - Perform a read/modify/write cycle on
333 + * a single CCI register
335 + * @map: Register map to update
336 + * @reg: Register address to update, use CCI_REG#() macros to encode reg width
337 + * @mask: Bitmask to change
338 + * @val: New value for bitmask
339 + * @err: Optional pointer to store errors, if a previous error is set
340 + * then the update will be skipped
342 + * Note this uses read-modify-write to update the bits, atomicity with regards
343 + * to other cci_*() register access functions is NOT guaranteed.
345 + * Return: %0 on success or a negative error code on failure.
347 +int cci_update_bits(struct regmap *map, u32 reg, u64 mask, u64 val, int *err);
350 + * cci_multi_reg_write() - Write multiple registers to the device
352 + * @map: Register map to write to
353 + * @regs: Array of structures containing register-address, -value pairs to be
354 + * written, register-addresses use CCI_REG#() macros to encode reg width
355 + * @num_regs: Number of registers to write
356 + * @err: Optional pointer to store errors, if a previous error is set
357 + * then the write will be skipped
359 + * Write multiple registers to the device where the set of register, value
360 + * pairs are supplied in any order, possibly not all in a single range.
362 + * Use of the CCI_REG#() macros to encode reg width is mandatory.
364 + * For raw lists of register-address, -value pairs with only 8 bit
365 + * wide writes regmap_multi_reg_write() can be used instead.
367 + * Return: %0 on success or a negative error code on failure.
369 +int cci_multi_reg_write(struct regmap *map, const struct cci_reg_sequence *regs,
370 + unsigned int num_regs, int *err);
372 +#if IS_ENABLED(CONFIG_V4L2_CCI_I2C)
374 + * devm_cci_regmap_init_i2c() - Create regmap to use with cci_*() register
377 + * @client: i2c_client to create the regmap for
378 + * @reg_addr_bits: register address width to use (8 or 16)
380 + * Note the memory for the created regmap is devm() managed, tied to the client.
382 + * Return: %0 on success or a negative error code on failure.
384 +struct regmap *devm_cci_regmap_init_i2c(struct i2c_client *client,
385 + int reg_addr_bits);