|
| 1 | +/* |
| 2 | + * Copyright (c) 2025 tinyVision.ai Inc. |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +#ifndef ZEPHYR_DRIVERS_VIDEO_COMMON_H_ |
| 8 | +#define ZEPHYR_DRIVERS_VIDEO_COMMON_H_ |
| 9 | + |
| 10 | +#include <stddef.h> |
| 11 | + |
| 12 | +#include <zephyr/device.h> |
| 13 | +#include <zephyr/drivers/i2c.h> |
| 14 | +#include <zephyr/kernel.h> |
| 15 | +#include <zephyr/sys/util.h> |
| 16 | +#include <zephyr/types.h> |
| 17 | + |
| 18 | +/** |
| 19 | + * Type used by register tables that have either the address or value 16-bit wide. |
| 20 | + */ |
| 21 | +struct video_reg { |
| 22 | + /** Address of the register, and other flags if used with the @ref video_cci API. */ |
| 23 | + uint32_t addr; |
| 24 | + /** Value to write to this address */ |
| 25 | + uint32_t data; |
| 26 | +}; |
| 27 | + |
| 28 | +/** |
| 29 | + * @defgroup video_cci Video Camera Control Interface (CCI) handling |
| 30 | + * |
| 31 | + * The Camera Control Interface (CCI) is an I2C communication scheme part of MIPI-CSI. |
| 32 | + * It defines how register addresses and register values are packed into I2C messages. |
| 33 | + * |
| 34 | + * After the I2C device address, I2C messages payload contain: |
| 35 | + * |
| 36 | + * 1. THe 8-bit or 16-bit of the address in big-endian, written to the device. |
| 37 | + * 3. The 8-bit of the register data either read or written. |
| 38 | + * |
| 39 | + * To write to registers larger than 8-bit, multiple read/writes messages are issued. |
| 40 | + * Endianness and segmentation of larger registers are defined on a per-sensor basis. |
| 41 | + * |
| 42 | + * @{ |
| 43 | + */ |
| 44 | + |
| 45 | +/** @cond INTERNAL_HIDDEN */ |
| 46 | +#define VIDEO_REG_ENDIANNESS_MASK (uint32_t)(GENMASK(24, 24)) |
| 47 | +#define VIDEO_REG_ADDR_SIZE_MASK (uint32_t)(GENMASK(23, 20)) |
| 48 | +#define VIDEO_REG_DATA_SIZE_MASK (uint32_t)(GENMASK(19, 16)) |
| 49 | +#define VIDEO_REG_ADDR_MASK (uint32_t)(GENMASK(15, 0)) |
| 50 | + |
| 51 | +#define VIDEO_REG(addr_size, data_size, endianness) \ |
| 52 | + (FIELD_PREP(VIDEO_REG_ADDR_SIZE_MASK, (addr_size)) | \ |
| 53 | + FIELD_PREP(VIDEO_REG_DATA_SIZE_MASK, (data_size)) | \ |
| 54 | + FIELD_PREP(VIDEO_REG_ENDIANNESS_MASK, (endianness))) |
| 55 | +/** @endcond */ |
| 56 | + |
| 57 | +/** Flag a register as 8-bit address size, 8-bit data size */ |
| 58 | +#define VIDEO_REG_ADDR8_DATA8 VIDEO_REG(1, 1, false) |
| 59 | +/** Flag a register as 8-bit address size, 16-bit data size, little-endian */ |
| 60 | +#define VIDEO_REG_ADDR8_DATA16_LE VIDEO_REG(1, 2, false) |
| 61 | +/** Flag a register as 8-bit address size, 16-bit data size, big-endian */ |
| 62 | +#define VIDEO_REG_ADDR8_DATA16_BE VIDEO_REG(1, 2, true) |
| 63 | +/** Flag a register as 8-bit address size, 24-bit data size, little-endian */ |
| 64 | +#define VIDEO_REG_ADDR8_DATA24_LE VIDEO_REG(1, 3, false) |
| 65 | +/** Flag a register as 8-bit address size, 24-bit data size, big-endian */ |
| 66 | +#define VIDEO_REG_ADDR8_DATA24_BE VIDEO_REG(1, 3, true) |
| 67 | +/** Flag a register as 8-bit address size, 32-bit data size, little-endian */ |
| 68 | +#define VIDEO_REG_ADDR8_DATA32_LE VIDEO_REG(1, 4, false) |
| 69 | +/** Flag a register as 8-bit address size, 32-bit data size, big-endian */ |
| 70 | +#define VIDEO_REG_ADDR8_DATA32_BE VIDEO_REG(1, 4, true) |
| 71 | +/** Flag a register as 16-bit address size, 8-bit data size */ |
| 72 | +#define VIDEO_REG_ADDR16_DATA8 VIDEO_REG(2, 1, false) |
| 73 | +/** Flag a register as 16-bit address size, 16-bit data size, little-endian */ |
| 74 | +#define VIDEO_REG_ADDR16_DATA16_LE VIDEO_REG(2, 2, false) |
| 75 | +/** Flag a register as 16-bit address size, 16-bit data size, big-endian */ |
| 76 | +#define VIDEO_REG_ADDR16_DATA16_BE VIDEO_REG(2, 2, true) |
| 77 | +/** Flag a register as 16-bit address size, 24-bit data size, little-endian */ |
| 78 | +#define VIDEO_REG_ADDR16_DATA24_LE VIDEO_REG(2, 3, false) |
| 79 | +/** Flag a register as 16-bit address size, 24-bit data size, big-endian */ |
| 80 | +#define VIDEO_REG_ADDR16_DATA24_BE VIDEO_REG(2, 3, true) |
| 81 | +/** Flag a register as 16-bit address size, 32-bit data size, little-endian */ |
| 82 | +#define VIDEO_REG_ADDR16_DATA32_LE VIDEO_REG(2, 4, false) |
| 83 | +/** Flag a register as 16-bit address size, 32-bit data size, big-endian */ |
| 84 | +#define VIDEO_REG_ADDR16_DATA32_BE VIDEO_REG(2, 4, true) |
| 85 | + |
| 86 | +/** |
| 87 | + * @brief Write a Camera Control Interface register value with the specified address and size. |
| 88 | + * |
| 89 | + * The size of the register address and register data passed as flags in the high bits of |
| 90 | + * @p reg_addr in the unused bits of the address. |
| 91 | + * |
| 92 | + * @brief i2c Reference to the video device on an I2C bus. |
| 93 | + * @brief reg_addr Address of the register to fill with @reg_value along with size information. |
| 94 | + * @brief reg_value Value to write at this address, the size to write is encoded in the address. |
| 95 | + */ |
| 96 | +int video_write_cci_reg(const struct i2c_dt_spec *i2c, uint32_t reg_addr, uint32_t reg_value); |
| 97 | + |
| 98 | + |
| 99 | +/** |
| 100 | + * @brief Perform a read-modify-write operation on a register given an address, mask and value. |
| 101 | + * |
| 102 | + * The size of the register address and register data passed as flags in the high bits of |
| 103 | + * @p reg_addr in the unused bits of the address. |
| 104 | + * |
| 105 | + * @brief i2c Reference to the video device on an I2C bus. |
| 106 | + * @brief reg_addr Address of the register to fill with @reg_value along with size information. |
| 107 | + * @brief field_mask Mask of the field to insert into the existing value. |
| 108 | + * @brief field_value Value to write at this address, the size to write is encoded in the address. |
| 109 | + */ |
| 110 | +int video_modify_cci_reg(const struct i2c_dt_spec *i2c, uint32_t reg_addr, uint32_t field_mask, |
| 111 | + uint32_t field_value); |
| 112 | + |
| 113 | +/** |
| 114 | + * @brief Read a Camera Control Interace register value from the specified address and size. |
| 115 | + * |
| 116 | + * The size of the register address and register data passed as flags in the high bits of |
| 117 | + * @p reg_addr in the unused bits of the address. |
| 118 | + * |
| 119 | + * @brief i2c Reference to the video device on an I2C bus. |
| 120 | + * @brief reg_addr Address of the register to fill with @reg_value along with size information. |
| 121 | + * @brief reg_value Value to write at this address, the size to write is encoded in the address. |
| 122 | + * This is a 32-bit integer pointer even when reading 8-bit or 16 bits value. |
| 123 | + */ |
| 124 | +int video_read_cci_reg(const struct i2c_dt_spec *i2c, uint32_t reg_addr, uint32_t *reg_value); |
| 125 | + |
| 126 | +/** |
| 127 | + * @brief Write a complete table of registers to a device one by one. |
| 128 | + * |
| 129 | + * The address present in the registers need to be encoding the size information using the macros |
| 130 | + * such as @ref VIDEO_ADDR16_REG8(). The last element must be empty (@c {0}) to mark the end of the |
| 131 | + * table. |
| 132 | + * |
| 133 | + * @brief i2c Reference to the video device on an I2C bus. |
| 134 | + * @brief regs Array of address/value pairs to write to the device sequentially. |
| 135 | + */ |
| 136 | +int video_write_cci_multiregs(const struct i2c_dt_spec *i2c, const struct video_reg *regs); |
| 137 | + |
| 138 | +#endif /* ZEPHYR_DRIVERS_VIDEO_COMMON_H_ */ |
0 commit comments