drivers: video: common: introduce CCI utilities
Add a library for the Camera Common Interface, part of the MIPI CSI protocol standard defining methods to configure a camera device over I2C, such as which size for the register address/data. Signed-off-by: Josuah Demangeon <me@josuah.net>
This commit is contained in:
parent
f47f3fe410
commit
c8ff2b89d9
3 changed files with 442 additions and 2 deletions
|
@ -50,6 +50,14 @@ config VIDEO_BUFFER_SMH_ATTRIBUTE
|
||||||
1: SMH_REG_ATTR_NON_CACHEABLE
|
1: SMH_REG_ATTR_NON_CACHEABLE
|
||||||
2: SMH_REG_ATTR_EXTERNAL
|
2: SMH_REG_ATTR_EXTERNAL
|
||||||
|
|
||||||
|
config VIDEO_I2C_RETRY_NUM
|
||||||
|
int "Number of retries after a failed I2C communication"
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
If set to 0, only a single write attempt will be done with no retry.
|
||||||
|
The default is to not retry. Board configuration files or user project can then
|
||||||
|
use the number of retries that matches their situation.
|
||||||
|
|
||||||
source "drivers/video/Kconfig.esp32_dvp"
|
source "drivers/video/Kconfig.esp32_dvp"
|
||||||
|
|
||||||
source "drivers/video/Kconfig.mcux_csi"
|
source "drivers/video/Kconfig.mcux_csi"
|
||||||
|
|
|
@ -1,14 +1,23 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Linaro Limited
|
* Copyright (c) 2019, Linaro Limited
|
||||||
* Copyright (c) 2024, tinyVision.ai Inc.
|
* Copyright (c) 2024-2025, tinyVision.ai Inc.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/i2c.h>
|
||||||
#include <zephyr/drivers/video.h>
|
#include <zephyr/drivers/video.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/sys/byteorder.h>
|
||||||
|
#include <zephyr/sys/util.h>
|
||||||
|
|
||||||
|
#include "video_common.h"
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(video_common, CONFIG_VIDEO_LOG_LEVEL);
|
||||||
|
|
||||||
#if defined(CONFIG_VIDEO_BUFFER_USE_SHARED_MULTI_HEAP)
|
#if defined(CONFIG_VIDEO_BUFFER_USE_SHARED_MULTI_HEAP)
|
||||||
#include <zephyr/multi_heap/shared_multi_heap.h>
|
#include <zephyr/multi_heap/shared_multi_heap.h>
|
||||||
|
@ -166,3 +175,193 @@ void video_closest_frmival(const struct device *dev, struct video_frmival_enum *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int video_read_reg_retry(const struct i2c_dt_spec *i2c, uint8_t *buf_w, size_t size_w,
|
||||||
|
uint8_t *buf_r, size_t size_r)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (int i = 0;; i++) {
|
||||||
|
ret = i2c_write_read_dt(i2c, buf_w, size_w, buf_r, size_r);
|
||||||
|
if (ret == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == CONFIG_VIDEO_I2C_RETRY_NUM) {
|
||||||
|
LOG_HEXDUMP_ERR(buf_w, size_w, "failed to write-read to I2C register");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sleep(K_MSEC(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int video_read_cci_reg(const struct i2c_dt_spec *i2c, uint32_t reg_addr, uint32_t *reg_data)
|
||||||
|
{
|
||||||
|
size_t addr_size = FIELD_GET(VIDEO_REG_ADDR_SIZE_MASK, reg_addr);
|
||||||
|
size_t data_size = FIELD_GET(VIDEO_REG_DATA_SIZE_MASK, reg_addr);
|
||||||
|
bool big_endian = FIELD_GET(VIDEO_REG_ENDIANNESS_MASK, reg_addr);
|
||||||
|
uint16_t addr = FIELD_GET(VIDEO_REG_ADDR_MASK, reg_addr);
|
||||||
|
uint8_t buf_w[sizeof(uint16_t)] = {0};
|
||||||
|
uint8_t *data_ptr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
__ASSERT(addr_size > 0, "The address must have a address size flag");
|
||||||
|
__ASSERT(data_size > 0, "The address must have a data size flag");
|
||||||
|
|
||||||
|
*reg_data = 0;
|
||||||
|
|
||||||
|
if (big_endian) {
|
||||||
|
/* Casting between data sizes in big-endian requires re-aligning */
|
||||||
|
data_ptr = (uint8_t *)reg_data + sizeof(*reg_data) - data_size;
|
||||||
|
} else {
|
||||||
|
/* Casting between data sizes in little-endian is a no-op */
|
||||||
|
data_ptr = (uint8_t *)reg_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < data_size; i++) {
|
||||||
|
if (addr_size == 1) {
|
||||||
|
buf_w[0] = addr + i;
|
||||||
|
} else {
|
||||||
|
sys_put_be16(addr + i, &buf_w[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = video_read_reg_retry(i2c, buf_w, addr_size, &data_ptr[i], 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to read from register 0x%x", addr + i);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_HEXDUMP_DBG(buf_w, addr_size, "Data written to the I2C device...");
|
||||||
|
LOG_HEXDUMP_DBG(&data_ptr[i], 1, "... data read back from the I2C device");
|
||||||
|
}
|
||||||
|
|
||||||
|
*reg_data = big_endian ? sys_be32_to_cpu(*reg_data) : sys_le32_to_cpu(*reg_data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int video_write_reg_retry(const struct i2c_dt_spec *i2c, uint8_t *buf_w, size_t size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (int i = 0;; i++) {
|
||||||
|
ret = i2c_write_dt(i2c, buf_w, size);
|
||||||
|
if (ret == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == CONFIG_VIDEO_I2C_RETRY_NUM) {
|
||||||
|
LOG_HEXDUMP_ERR(buf_w, size, "failed to write to I2C register");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sleep(K_MSEC(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int video_write_cci_reg(const struct i2c_dt_spec *i2c, uint32_t reg_addr, uint32_t reg_data)
|
||||||
|
{
|
||||||
|
size_t addr_size = FIELD_GET(VIDEO_REG_ADDR_SIZE_MASK, reg_addr);
|
||||||
|
size_t data_size = FIELD_GET(VIDEO_REG_DATA_SIZE_MASK, reg_addr);
|
||||||
|
bool big_endian = FIELD_GET(VIDEO_REG_ENDIANNESS_MASK, reg_addr);
|
||||||
|
uint16_t addr = FIELD_GET(VIDEO_REG_ADDR_MASK, reg_addr);
|
||||||
|
uint8_t buf_w[sizeof(uint16_t) + sizeof(uint32_t)] = {0};
|
||||||
|
uint8_t *data_ptr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
__ASSERT(addr_size > 0, "The address must have a address size flag");
|
||||||
|
__ASSERT(data_size > 0, "The address must have a data size flag");
|
||||||
|
|
||||||
|
if (big_endian) {
|
||||||
|
/* Casting between data sizes in big-endian requires re-aligning */
|
||||||
|
reg_data = sys_cpu_to_be32(reg_data);
|
||||||
|
data_ptr = (uint8_t *)®_data + sizeof(reg_data) - data_size;
|
||||||
|
} else {
|
||||||
|
/* Casting between data sizes in little-endian is a no-op */
|
||||||
|
reg_data = sys_cpu_to_le32(reg_data);
|
||||||
|
data_ptr = (uint8_t *)®_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < data_size; i++) {
|
||||||
|
/* The address is always big-endian as per CCI standard */
|
||||||
|
if (addr_size == 1) {
|
||||||
|
buf_w[0] = addr + i;
|
||||||
|
} else {
|
||||||
|
sys_put_be16(addr + i, &buf_w[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_w[addr_size] = data_ptr[i];
|
||||||
|
|
||||||
|
LOG_HEXDUMP_DBG(buf_w, addr_size + 1, "Data written to the I2C device");
|
||||||
|
|
||||||
|
ret = video_write_reg_retry(i2c, buf_w, addr_size + 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to write to register 0x%x", addr + i);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int video_modify_cci_reg(const struct i2c_dt_spec *i2c, uint32_t reg_addr, uint32_t field_mask,
|
||||||
|
uint32_t field_value)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = video_read_cci_reg(i2c, reg_addr, ®);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return video_write_cci_reg(i2c, reg_addr, (reg & ~field_mask) | field_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int video_write_cci_multiregs(const struct i2c_dt_spec *i2c, const struct video_reg *regs,
|
||||||
|
size_t num_regs)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_regs; i++) {
|
||||||
|
ret = video_write_cci_reg(i2c, regs[i].addr, regs[i].data);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int video_write_cci_multiregs8(const struct i2c_dt_spec *i2c, const struct video_reg8 *regs,
|
||||||
|
size_t num_regs)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_regs; i++) {
|
||||||
|
ret = video_write_cci_reg(i2c, regs[i].addr | VIDEO_REG_ADDR8_DATA8, regs[i].data);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int video_write_cci_multiregs16(const struct i2c_dt_spec *i2c, const struct video_reg16 *regs,
|
||||||
|
size_t num_regs)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (int i = 0; i < num_regs; i++) {
|
||||||
|
ret = video_write_cci_reg(i2c, regs[i].addr | VIDEO_REG_ADDR16_DATA8, regs[i].data);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
233
drivers/video/video_common.h
Normal file
233
drivers/video/video_common.h
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 tinyVision.ai Inc.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_DRIVERS_VIDEO_COMMON_H_
|
||||||
|
#define ZEPHYR_DRIVERS_VIDEO_COMMON_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/i2c.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register for building tables supporting 8/16 bit address and 8/16/24/32 bit value sizes.
|
||||||
|
*
|
||||||
|
* A flag in the address indicates the size of the register address, and the size and endianness of
|
||||||
|
* the value.
|
||||||
|
*
|
||||||
|
* If willing to save space on large register tables, a more compact version @ref video_reg8 and
|
||||||
|
* @ref video_reg16 can be used, however only supporting 8-bit values .
|
||||||
|
*
|
||||||
|
* The data field is in CPU-native endianness, and the library functions will perform the
|
||||||
|
* endianness swap as needed while transmitting data.
|
||||||
|
*/
|
||||||
|
struct video_reg {
|
||||||
|
/** Address of the register, and other flags if used with the @ref video_cci API. */
|
||||||
|
uint32_t addr;
|
||||||
|
/** Value to write to this address */
|
||||||
|
uint32_t data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Register for building tables supporting 8-bit addresses and 8-bit value sizes */
|
||||||
|
struct video_reg8 {
|
||||||
|
/** Address of the register */
|
||||||
|
uint8_t addr;
|
||||||
|
/** Value to write to this address */
|
||||||
|
uint8_t data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Register for building tables supporting 16-bit addresses and 8-bit value sizes */
|
||||||
|
struct video_reg16 {
|
||||||
|
/** Address of the register */
|
||||||
|
uint16_t addr;
|
||||||
|
/** Value to write to this address */
|
||||||
|
uint8_t data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup video_cci Video Camera Control Interface (CCI) handling
|
||||||
|
*
|
||||||
|
* The Camera Control Interface (CCI) is an I2C communication scheme part of MIPI-CSI.
|
||||||
|
* It defines how register addresses and register values are packed into I2C messages.
|
||||||
|
*
|
||||||
|
* After the I2C device address, I2C messages payload contain:
|
||||||
|
*
|
||||||
|
* 1. The 8-bit or 16-bit of the address in big-endian, written to the device.
|
||||||
|
* 2. The 8-bit of the register data either read or written.
|
||||||
|
*
|
||||||
|
* To write to registers larger than 8-bit, multiple read/writes messages are issued.
|
||||||
|
* Endianness and segmentation of larger registers are defined on a per-sensor basis.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @cond INTERNAL_HIDDEN */
|
||||||
|
#define VIDEO_REG_ENDIANNESS_MASK (uint32_t)(GENMASK(24, 24))
|
||||||
|
#define VIDEO_REG_ADDR_SIZE_MASK (uint32_t)(GENMASK(23, 20))
|
||||||
|
#define VIDEO_REG_DATA_SIZE_MASK (uint32_t)(GENMASK(19, 16))
|
||||||
|
#define VIDEO_REG_ADDR_MASK (uint32_t)(GENMASK(15, 0))
|
||||||
|
|
||||||
|
#define VIDEO_REG(addr_size, data_size, endianness) \
|
||||||
|
(FIELD_PREP(VIDEO_REG_ADDR_SIZE_MASK, (addr_size)) | \
|
||||||
|
FIELD_PREP(VIDEO_REG_DATA_SIZE_MASK, (data_size)) | \
|
||||||
|
FIELD_PREP(VIDEO_REG_ENDIANNESS_MASK, (endianness)))
|
||||||
|
/** @endcond */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup video_cci_reg_flags Flags describing a Video CCI register
|
||||||
|
*
|
||||||
|
* For a given drivers, register sizes are not expected to change, so macros can be used when
|
||||||
|
* defining registers:
|
||||||
|
*
|
||||||
|
* @code{.c}
|
||||||
|
* #define SENSORNAME_REG8(addr) ((uint32_t)(addr) | VIDEO_REG_ADDR16_DATA8)
|
||||||
|
* #define SENSORNAME_REG16(addr) ((uint32_t)(addr) | VIDEO_REG_ADDR16_DATA16_LE)
|
||||||
|
* #define SENSORNAME_REG24(addr) ((uint32_t)(addr) | VIDEO_REG_ADDR16_DATA24_LE)
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Then the macros can be used directly in register definitions:
|
||||||
|
*
|
||||||
|
* @code{.c}
|
||||||
|
* #define SENSORNAME_REG_EXPOSURE_LEVEL SENSORNAME_REG16(0x3060)
|
||||||
|
* #define SENSORNAME_REG_AN_GAIN_LEVEL SENSORNAME_REG8(0x3062)
|
||||||
|
* ...
|
||||||
|
* video_write_cci_reg(&cfg->i2c, SENSORNAME_REG_EXPOSURE_LEVEL, 3000);
|
||||||
|
* video_write_cci_reg(&cfg->i2c, SENSORNAME_REG_AN_GAIN_LEVEL, 220);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Or used directly inline:
|
||||||
|
* @code{.c}
|
||||||
|
* video_write_cci_reg(&cfg->i2c, SENSORNAME_REG16(0x3060), 3000);
|
||||||
|
* video_write_cci_reg(&cfg->i2c, SENSORNAME_REG8(0x3062), 220);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* As well as in register tables:
|
||||||
|
*
|
||||||
|
* @code{.c}
|
||||||
|
* struct video_reg init_regs[] = {
|
||||||
|
* {SENSORNAME_REG_EXPOSURE_LEVEL, 2000},
|
||||||
|
* {SENSORNAME_REG_AN_GAIN_LEVEL, 180},
|
||||||
|
* ...
|
||||||
|
* {0},
|
||||||
|
* };
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/** Flag a register as 8-bit address size, 8-bit data size */
|
||||||
|
#define VIDEO_REG_ADDR8_DATA8 VIDEO_REG(1, 1, false)
|
||||||
|
/** Flag a register as 8-bit address size, 16-bit data size, little-endian */
|
||||||
|
#define VIDEO_REG_ADDR8_DATA16_LE VIDEO_REG(1, 2, false)
|
||||||
|
/** Flag a register as 8-bit address size, 16-bit data size, big-endian */
|
||||||
|
#define VIDEO_REG_ADDR8_DATA16_BE VIDEO_REG(1, 2, true)
|
||||||
|
/** Flag a register as 8-bit address size, 24-bit data size, little-endian */
|
||||||
|
#define VIDEO_REG_ADDR8_DATA24_LE VIDEO_REG(1, 3, false)
|
||||||
|
/** Flag a register as 8-bit address size, 24-bit data size, big-endian */
|
||||||
|
#define VIDEO_REG_ADDR8_DATA24_BE VIDEO_REG(1, 3, true)
|
||||||
|
/** Flag a register as 8-bit address size, 32-bit data size, little-endian */
|
||||||
|
#define VIDEO_REG_ADDR8_DATA32_LE VIDEO_REG(1, 4, false)
|
||||||
|
/** Flag a register as 8-bit address size, 32-bit data size, big-endian */
|
||||||
|
#define VIDEO_REG_ADDR8_DATA32_BE VIDEO_REG(1, 4, true)
|
||||||
|
/** Flag a register as 16-bit address size, 8-bit data size */
|
||||||
|
#define VIDEO_REG_ADDR16_DATA8 VIDEO_REG(2, 1, false)
|
||||||
|
/** Flag a register as 16-bit address size, 16-bit data size, little-endian */
|
||||||
|
#define VIDEO_REG_ADDR16_DATA16_LE VIDEO_REG(2, 2, false)
|
||||||
|
/** Flag a register as 16-bit address size, 16-bit data size, big-endian */
|
||||||
|
#define VIDEO_REG_ADDR16_DATA16_BE VIDEO_REG(2, 2, true)
|
||||||
|
/** Flag a register as 16-bit address size, 24-bit data size, little-endian */
|
||||||
|
#define VIDEO_REG_ADDR16_DATA24_LE VIDEO_REG(2, 3, false)
|
||||||
|
/** Flag a register as 16-bit address size, 24-bit data size, big-endian */
|
||||||
|
#define VIDEO_REG_ADDR16_DATA24_BE VIDEO_REG(2, 3, true)
|
||||||
|
/** Flag a register as 16-bit address size, 32-bit data size, little-endian */
|
||||||
|
#define VIDEO_REG_ADDR16_DATA32_LE VIDEO_REG(2, 4, false)
|
||||||
|
/** Flag a register as 16-bit address size, 32-bit data size, big-endian */
|
||||||
|
#define VIDEO_REG_ADDR16_DATA32_BE VIDEO_REG(2, 4, true)
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write a Camera Control Interface register value with the specified address and size.
|
||||||
|
*
|
||||||
|
* The size of the register address and register data passed as flags in the high bits of
|
||||||
|
* @p reg_addr in the unused bits of the address.
|
||||||
|
*
|
||||||
|
* @brief i2c Reference to the video device on an I2C bus.
|
||||||
|
* @brief reg_addr Address of the register to fill with @p reg_data along with size information.
|
||||||
|
* @brief reg_data Value to write at this address, the size to write is encoded in the address.
|
||||||
|
*/
|
||||||
|
int video_write_cci_reg(const struct i2c_dt_spec *i2c, uint32_t reg_addr, uint32_t reg_data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform a read-modify-write operation on a register given an address, mask and value.
|
||||||
|
*
|
||||||
|
* The size of the register address and register data passed as flags in the high bits of
|
||||||
|
* @p reg_addr in the unused bits of the address.
|
||||||
|
*
|
||||||
|
* @brief i2c Reference to the video device on an I2C bus.
|
||||||
|
* @brief reg_addr Address of the register to fill with @p reg_data along with size information.
|
||||||
|
* @brief field_mask Mask of the field to insert into the existing value.
|
||||||
|
* @brief field_value Value to write at this address, the size to write is encoded in the address.
|
||||||
|
*/
|
||||||
|
int video_modify_cci_reg(const struct i2c_dt_spec *i2c, uint32_t reg_addr, uint32_t field_mask,
|
||||||
|
uint32_t field_value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read a Camera Control Interace register value from the specified address and size.
|
||||||
|
*
|
||||||
|
* The size of the register address and register data passed as flags in the high bits of
|
||||||
|
* @p reg_addr in the unused bits of the address.
|
||||||
|
*
|
||||||
|
* @brief i2c Reference to the video device on an I2C bus.
|
||||||
|
* @brief reg_addr Address of the register to fill with @p reg_data along with size information.
|
||||||
|
* @brief reg_data Value to write at this address, the size to write is encoded in the address.
|
||||||
|
* This is a 32-bit integer pointer even when reading 8-bit or 16 bits value.
|
||||||
|
*/
|
||||||
|
int video_read_cci_reg(const struct i2c_dt_spec *i2c, uint32_t reg_addr, uint32_t *reg_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write a complete table of registers to a device one by one.
|
||||||
|
*
|
||||||
|
* The address present in the registers need to be encoding the size information using the macros
|
||||||
|
* such as @ref VIDEO_REG_ADDR16_DATA8. The last element must be empty (@c {0}) to mark the end of
|
||||||
|
* the table.
|
||||||
|
*
|
||||||
|
* @brief i2c Reference to the video device on an I2C bus.
|
||||||
|
* @brief regs Array of address/value pairs to write to the device sequentially.
|
||||||
|
* @brief num_regs Number of registers entries in the table.
|
||||||
|
*/
|
||||||
|
int video_write_cci_multiregs(const struct i2c_dt_spec *i2c, const struct video_reg *regs,
|
||||||
|
size_t num_regs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write a complete table of registers to a device one by one.
|
||||||
|
*
|
||||||
|
* The registers address are 8-bit wide and values are 8-bit wide.
|
||||||
|
*
|
||||||
|
* @brief i2c Reference to the video device on an I2C bus.
|
||||||
|
* @brief regs Array of address/value pairs to write to the device sequentially.
|
||||||
|
* @brief num_regs Number of registers entries in the table.
|
||||||
|
*/
|
||||||
|
int video_write_cci_multiregs8(const struct i2c_dt_spec *i2c, const struct video_reg8 *regs,
|
||||||
|
size_t num_regs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write a complete table of registers to a device one by one.
|
||||||
|
*
|
||||||
|
* The registers address are 16-bit wide and values are 8-bit wide.
|
||||||
|
*
|
||||||
|
* @brief i2c Reference to the video device on an I2C bus.
|
||||||
|
* @brief regs Array of address/value pairs to write to the device sequentially.
|
||||||
|
* @brief num_regs Number of registers entries in the table.
|
||||||
|
*/
|
||||||
|
int video_write_cci_multiregs16(const struct i2c_dt_spec *i2c, const struct video_reg16 *regs,
|
||||||
|
size_t num_regs);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_DRIVERS_VIDEO_COMMON_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue