Skip to content

Commit 78999d6

Browse files
committed
drivers: video: emul_imager: switch to the CCI library for I2C
Use the newly introduced CCI library instead of local implementation of I2C read/write commands. Modify the emulated imager registers to make the need for the CCI library appear. Signed-off-by: Josuah Demangeon <me@josuah.net>
1 parent 76c1762 commit 78999d6

File tree

1 file changed

+121
-85
lines changed

1 file changed

+121
-85
lines changed

drivers/video/video_emul_imager.c

Lines changed: 121 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 tinyVision.ai Inc.
2+
* Copyright (c) 2024-2025 tinyVision.ai Inc.
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -18,36 +18,39 @@
1818
#include <zephyr/drivers/i2c_emul.h>
1919
#include <zephyr/logging/log.h>
2020

21+
#include "video_common.h"
2122
#include "video_ctrls.h"
2223
#include "video_device.h"
2324

2425
LOG_MODULE_REGISTER(video_emul_imager, CONFIG_VIDEO_LOG_LEVEL);
2526

26-
#define EMUL_IMAGER_REG_SENSOR_ID 0x00
27-
#define EMUL_IMAGER_SENSOR_ID 0x99
28-
#define EMUL_IMAGER_REG_CTRL 0x01
29-
#define EMUL_IMAGER_REG_INIT1 0x02
30-
#define EMUL_IMAGER_REG_INIT2 0x03
31-
#define EMUL_IMAGER_REG_TIMING1 0x04
32-
#define EMUL_IMAGER_REG_TIMING2 0x05
33-
#define EMUL_IMAGER_REG_TIMING3 0x06
34-
#define EMUL_IMAGER_REG_CUSTOM 0x07
35-
#define EMUL_IMAGER_REG_FORMAT 0x0a
36-
#define EMUL_IMAGER_PATTERN_OFF 0x00
37-
#define EMUL_IMAGER_PATTERN_BARS1 0x01
38-
#define EMUL_IMAGER_PATTERN_BARS2 0x02
27+
#define EMUL_IMAGER_REG8(addr) ((addr) | VIDEO_REG_ADDR8_DATA8)
28+
#define EMUL_IMAGER_REG16(addr) ((addr) | VIDEO_REG_ADDR8_DATA16_BE)
29+
#define EMUL_IMAGER_REG24(addr) ((addr) | VIDEO_REG_ADDR8_DATA24_BE)
30+
31+
#define EMUL_IMAGER_REG_SENSOR_ID EMUL_IMAGER_REG16(0x00)
32+
#define EMUL_IMAGER_SENSOR_ID 0x2025
33+
#define EMUL_IMAGER_REG_CTRL EMUL_IMAGER_REG8(0x02)
34+
#define EMUL_IMAGER_REG_TIMING1 EMUL_IMAGER_REG16(0x04)
35+
#define EMUL_IMAGER_REG_TIMING2 EMUL_IMAGER_REG16(0x06)
36+
#define EMUL_IMAGER_REG_TIMING3 EMUL_IMAGER_REG16(0x08)
37+
#define EMUL_IMAGER_REG_CUSTOM EMUL_IMAGER_REG24(0x10)
38+
#define EMUL_IMAGER_REG_FORMAT EMUL_IMAGER_REG8(0x20)
3939

4040
/* Custom control that is just an I2C write for example and test purpose */
4141
#define EMUL_IMAGER_CID_CUSTOM (VIDEO_CID_PRIVATE_BASE + 0x01)
4242

43+
/* Helper to avoid repetition */
44+
#define EMUL_IMAGER_REG_LIST(array) {.regs = (array), .size = ARRAY_SIZE(array)}
45+
4346
enum emul_imager_fmt_id {
4447
RGB565_320x240,
4548
YUYV_320x240,
4649
};
4750

48-
struct emul_imager_reg {
49-
uint16_t addr;
50-
uint8_t value;
51+
struct emul_imager_reg_list {
52+
const struct video_reg *regs;
53+
size_t size;
5154
};
5255

5356
struct emul_imager_mode {
@@ -56,8 +59,7 @@ struct emul_imager_mode {
5659
* This permits to deduplicate the list of registers in case some lare sections
5760
* are repeated across modes, such as the resolution for different FPS.
5861
*/
59-
const struct emul_imager_reg *regs[3];
60-
/* More fields can be added according to the needs of the sensor driver */
62+
const struct emul_imager_reg_list lists[3];
6163
};
6264

6365
struct emul_imager_config {
@@ -79,53 +81,109 @@ struct emul_imager_data {
7981
};
8082

8183
/* All the I2C registers sent on various scenario */
82-
static const struct emul_imager_reg emul_imager_init_regs[] = {
83-
{EMUL_IMAGER_REG_CTRL, 0x00},
84-
{EMUL_IMAGER_REG_INIT1, 0x10},
85-
{EMUL_IMAGER_REG_INIT2, 0x00},
84+
static const struct video_reg8 emul_imager_init_regs[] = {
8685
/* Undocumented registers from the vendor */
87-
{0x80, 0x01},
88-
{0x84, 0x01},
89-
{0x85, 0x20},
90-
{0x89, 0x7f},
91-
{0},
86+
{0xe3, 0x60},
87+
{0x9e, 0xd3},
88+
{0x05, 0x5d},
89+
{0x39, 0xf7},
90+
{0xf0, 0xef},
91+
{0xe8, 0x40},
92+
{0x6d, 0x16},
93+
{0x16, 0x33},
94+
{0xeb, 0xa7},
95+
{0xb8, 0x1f},
96+
{0x45, 0xb7},
97+
{0x26, 0x3a},
98+
{0x6e, 0x32},
99+
{0x1b, 0x9e},
100+
{0xd3, 0xf7},
101+
{0xd3, 0xb3},
102+
{0x7b, 0x64},
103+
{0xa3, 0xaf},
104+
{0x3c, 0x6e},
105+
{0x11, 0x2d},
106+
{0x15, 0x67},
107+
{0xb9, 0xc8},
108+
{0x12, 0xc8},
109+
{0xa6, 0x31},
110+
{0x0e, 0x7c},
111+
{0x7b, 0x64},
112+
{0xf8, 0x5f},
113+
{0x44, 0x27},
114+
{0xc5, 0x9a},
115+
{0x8d, 0x54},
92116
};
93-
static const struct emul_imager_reg emul_imager_rgb565[] = {
117+
static const struct video_reg emul_imager_rgb565[] = {
94118
{EMUL_IMAGER_REG_FORMAT, 0x01},
95-
{0},
96119
};
97-
static const struct emul_imager_reg emul_imager_yuyv[] = {
120+
static const struct video_reg emul_imager_yuyv[] = {
98121
{EMUL_IMAGER_REG_FORMAT, 0x02},
99-
{0},
100122
};
101-
static const struct emul_imager_reg emul_imager_320x240[] = {
102-
{EMUL_IMAGER_REG_TIMING1, 0x32},
103-
{EMUL_IMAGER_REG_TIMING2, 0x24},
104-
{0},
123+
static const struct video_reg emul_imager_320x240[] = {
124+
{EMUL_IMAGER_REG_TIMING1, 320},
125+
{EMUL_IMAGER_REG_TIMING2, 240},
126+
};
127+
static const struct video_reg emul_imager_160x120[] = {
128+
{EMUL_IMAGER_REG_TIMING1, 160},
129+
{EMUL_IMAGER_REG_TIMING2, 120},
105130
};
106-
static const struct emul_imager_reg emul_imager_15fps[] = {
131+
static const struct video_reg emul_imager_15fps[] = {
107132
{EMUL_IMAGER_REG_TIMING3, 15},
108-
{0},
109133
};
110-
static const struct emul_imager_reg emul_imager_30fps[] = {
134+
static const struct video_reg emul_imager_30fps[] = {
111135
{EMUL_IMAGER_REG_TIMING3, 30},
112-
{0},
113136
};
114-
static const struct emul_imager_reg emul_imager_60fps[] = {
137+
static const struct video_reg emul_imager_60fps[] = {
115138
{EMUL_IMAGER_REG_TIMING3, 60},
116-
{0},
117139
};
118140

119141
/* Description of "modes", that pick lists of registesr that will be all sentto the imager */
120142
struct emul_imager_mode emul_imager_rgb565_320x240_modes[] = {
121-
{.fps = 15, .regs = {emul_imager_320x240, emul_imager_rgb565, emul_imager_15fps}},
122-
{.fps = 30, .regs = {emul_imager_320x240, emul_imager_rgb565, emul_imager_30fps}},
123-
{.fps = 60, .regs = {emul_imager_320x240, emul_imager_rgb565, emul_imager_60fps}},
143+
{
144+
.fps = 15,
145+
.lists = {
146+
EMUL_IMAGER_REG_LIST(emul_imager_320x240),
147+
EMUL_IMAGER_REG_LIST(emul_imager_rgb565),
148+
EMUL_IMAGER_REG_LIST(emul_imager_15fps),
149+
},
150+
},
151+
{
152+
.fps = 30,
153+
.lists = {
154+
EMUL_IMAGER_REG_LIST(emul_imager_320x240),
155+
EMUL_IMAGER_REG_LIST(emul_imager_rgb565),
156+
EMUL_IMAGER_REG_LIST(emul_imager_30fps),
157+
},
158+
},
159+
{
160+
.fps = 60,
161+
.lists = {
162+
EMUL_IMAGER_REG_LIST(emul_imager_320x240),
163+
EMUL_IMAGER_REG_LIST(emul_imager_rgb565),
164+
EMUL_IMAGER_REG_LIST(emul_imager_60fps),
165+
},
166+
},
124167
{0},
125168
};
169+
126170
struct emul_imager_mode emul_imager_yuyv_320x240_modes[] = {
127-
{.fps = 15, .regs = {emul_imager_320x240, emul_imager_yuyv, emul_imager_15fps}},
128-
{.fps = 30, .regs = {emul_imager_320x240, emul_imager_yuyv, emul_imager_30fps}},
171+
{
172+
.fps = 15,
173+
.lists = {
174+
EMUL_IMAGER_REG_LIST(emul_imager_320x240),
175+
EMUL_IMAGER_REG_LIST(emul_imager_yuyv),
176+
EMUL_IMAGER_REG_LIST(emul_imager_15fps),
177+
}
178+
},
179+
{
180+
.fps = 30,
181+
.lists = {
182+
EMUL_IMAGER_REG_LIST(emul_imager_320x240),
183+
EMUL_IMAGER_REG_LIST(emul_imager_yuyv),
184+
EMUL_IMAGER_REG_LIST(emul_imager_30fps),
185+
}
186+
},
129187
{0},
130188
};
131189

@@ -155,47 +213,18 @@ static const struct video_format_cap fmts[] = {
155213
{0},
156214
};
157215

158-
/* Emulated I2C register interface, to replace with actual I2C calls for real hardware */
159-
static int emul_imager_read_reg(const struct device *const dev, uint8_t reg_addr, uint8_t *value)
160-
{
161-
const struct emul_imager_config *cfg = dev->config;
162-
163-
return i2c_write_read_dt(&cfg->i2c, &reg_addr, 1, value, 1);
164-
}
165-
166-
/* Some sensors will need reg8 or reg16 variants. */
167-
static int emul_imager_write_reg(const struct device *const dev, uint8_t reg_addr, uint8_t value)
168-
{
169-
const struct emul_imager_config *cfg = dev->config;
170-
uint8_t buf_w[] = {reg_addr, value};
171-
172-
return i2c_write_dt(&cfg->i2c, buf_w, 2);
173-
}
174-
175-
static int emul_imager_write_multi(const struct device *const dev,
176-
const struct emul_imager_reg *regs)
177-
{
178-
int ret;
179-
180-
for (int i = 0; regs[i].addr != 0; i++) {
181-
ret = emul_imager_write_reg(dev, regs[i].addr, regs[i].value);
182-
if (ret < 0) {
183-
return ret;
184-
}
185-
}
186-
return 0;
187-
}
188-
189216
static int emul_imager_set_ctrl(const struct device *dev, uint32_t id)
190217
{
218+
const struct emul_imager_config *cfg = dev->config;
191219
struct emul_imager_data *data = dev->data;
192220

193-
return emul_imager_write_reg(dev, EMUL_IMAGER_REG_CUSTOM, data->ctrls.custom.val);
221+
return video_write_cci_reg(&cfg->i2c, EMUL_IMAGER_REG_CUSTOM, data->ctrls.custom.val);
194222
}
195223

196224
/* Customize this function according to your "struct emul_imager_mode". */
197225
static int emul_imager_set_mode(const struct device *dev, const struct emul_imager_mode *mode)
198226
{
227+
const struct emul_imager_config *cfg = dev->config;
199228
struct emul_imager_data *data = dev->data;
200229
int ret;
201230

@@ -207,7 +236,9 @@ static int emul_imager_set_mode(const struct device *dev, const struct emul_imag
207236

208237
/* Apply all the configuration registers for that mode */
209238
for (int i = 0; i < 2; i++) {
210-
ret = emul_imager_write_multi(dev, mode->regs[i]);
239+
const struct emul_imager_reg_list *list = &mode->lists[i];
240+
241+
ret = video_write_cci_multiregs(&cfg->i2c, list->regs, list->size);
211242
if (ret < 0) {
212243
goto err;
213244
}
@@ -312,7 +343,9 @@ static int emul_imager_get_caps(const struct device *dev, struct video_caps *cap
312343

313344
static int emul_imager_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
314345
{
315-
return emul_imager_write_reg(dev, EMUL_IMAGER_REG_CTRL, enable ? 1 : 0);
346+
const struct emul_imager_config *cfg = dev->config;
347+
348+
return video_write_cci_reg(&cfg->i2c, EMUL_IMAGER_REG_CTRL, enable ? 1 : 0);
316349
}
317350

318351
static DEVICE_API(video, emul_imager_driver_api) = {
@@ -339,21 +372,22 @@ int emul_imager_init(const struct device *dev)
339372
{
340373
const struct emul_imager_config *cfg = dev->config;
341374
struct video_format fmt;
342-
uint8_t sensor_id;
375+
uint32_t sensor_id;
343376
int ret;
344377

345378
if (!i2c_is_ready_dt(&cfg->i2c)) {
346379
LOG_ERR("Bus %s is not ready", cfg->i2c.bus->name);
347380
return -ENODEV;
348381
}
349382

350-
ret = emul_imager_read_reg(dev, EMUL_IMAGER_REG_SENSOR_ID, &sensor_id);
383+
ret = video_read_cci_reg(&cfg->i2c, EMUL_IMAGER_REG_SENSOR_ID, &sensor_id);
351384
if (ret < 0 || sensor_id != EMUL_IMAGER_SENSOR_ID) {
352385
LOG_ERR("Failed to get a correct sensor ID 0x%x", sensor_id);
353386
return ret;
354387
}
355388

356-
ret = emul_imager_write_multi(dev, emul_imager_init_regs);
389+
ret = video_write_cci_multiregs(&cfg->i2c, emul_imager_init_regs,
390+
ARRAY_SIZE(emul_imager_init_regs));
357391
if (ret < 0) {
358392
LOG_ERR("Could not set initial registers");
359393
return ret;
@@ -395,7 +429,9 @@ static int emul_imager_transfer_i2c(const struct emul *target, struct i2c_msg ms
395429
int addr)
396430
{
397431
static uint8_t fake_regs[UINT8_MAX] = {
398-
[EMUL_IMAGER_REG_SENSOR_ID] = EMUL_IMAGER_SENSOR_ID,
432+
/* SENSOR_ID_LO */
433+
[0x00] = EMUL_IMAGER_SENSOR_ID & 0xff,
434+
[0x01] = EMUL_IMAGER_SENSOR_ID >> 8,
399435
};
400436

401437
if (num_msgs == 0) {

0 commit comments

Comments
 (0)