1
1
/*
2
- * Copyright (c) 2024 tinyVision.ai Inc.
2
+ * Copyright (c) 2024-2025 tinyVision.ai Inc.
3
3
*
4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*/
18
18
#include <zephyr/drivers/i2c_emul.h>
19
19
#include <zephyr/logging/log.h>
20
20
21
+ #include "video_common.h"
21
22
#include "video_ctrls.h"
22
23
#include "video_device.h"
23
24
24
25
LOG_MODULE_REGISTER (video_emul_imager , CONFIG_VIDEO_LOG_LEVEL );
25
26
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)
39
39
40
40
/* Custom control that is just an I2C write for example and test purpose */
41
41
#define EMUL_IMAGER_CID_CUSTOM (VIDEO_CID_PRIVATE_BASE + 0x01)
42
42
43
+ /* Helper to avoid repetition */
44
+ #define EMUL_IMAGER_REG_LIST (array ) {.regs = (array), .size = ARRAY_SIZE(array)}
45
+
43
46
enum emul_imager_fmt_id {
44
47
RGB565_320x240 ,
45
48
YUYV_320x240 ,
46
49
};
47
50
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 ;
51
54
};
52
55
53
56
struct emul_imager_mode {
@@ -56,8 +59,7 @@ struct emul_imager_mode {
56
59
* This permits to deduplicate the list of registers in case some lare sections
57
60
* are repeated across modes, such as the resolution for different FPS.
58
61
*/
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 ];
61
63
};
62
64
63
65
struct emul_imager_config {
@@ -79,53 +81,109 @@ struct emul_imager_data {
79
81
};
80
82
81
83
/* 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 [] = {
86
85
/* 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 },
92
116
};
93
- static const struct emul_imager_reg emul_imager_rgb565 [] = {
117
+ static const struct video_reg emul_imager_rgb565 [] = {
94
118
{EMUL_IMAGER_REG_FORMAT , 0x01 },
95
- {0 },
96
119
};
97
- static const struct emul_imager_reg emul_imager_yuyv [] = {
120
+ static const struct video_reg emul_imager_yuyv [] = {
98
121
{EMUL_IMAGER_REG_FORMAT , 0x02 },
99
- {0 },
100
122
};
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 },
105
130
};
106
- static const struct emul_imager_reg emul_imager_15fps [] = {
131
+ static const struct video_reg emul_imager_15fps [] = {
107
132
{EMUL_IMAGER_REG_TIMING3 , 15 },
108
- {0 },
109
133
};
110
- static const struct emul_imager_reg emul_imager_30fps [] = {
134
+ static const struct video_reg emul_imager_30fps [] = {
111
135
{EMUL_IMAGER_REG_TIMING3 , 30 },
112
- {0 },
113
136
};
114
- static const struct emul_imager_reg emul_imager_60fps [] = {
137
+ static const struct video_reg emul_imager_60fps [] = {
115
138
{EMUL_IMAGER_REG_TIMING3 , 60 },
116
- {0 },
117
139
};
118
140
119
141
/* Description of "modes", that pick lists of registesr that will be all sentto the imager */
120
142
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
+ },
124
167
{0 },
125
168
};
169
+
126
170
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
+ },
129
187
{0 },
130
188
};
131
189
@@ -155,47 +213,18 @@ static const struct video_format_cap fmts[] = {
155
213
{0 },
156
214
};
157
215
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
-
189
216
static int emul_imager_set_ctrl (const struct device * dev , uint32_t id )
190
217
{
218
+ const struct emul_imager_config * cfg = dev -> config ;
191
219
struct emul_imager_data * data = dev -> data ;
192
220
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 );
194
222
}
195
223
196
224
/* Customize this function according to your "struct emul_imager_mode". */
197
225
static int emul_imager_set_mode (const struct device * dev , const struct emul_imager_mode * mode )
198
226
{
227
+ const struct emul_imager_config * cfg = dev -> config ;
199
228
struct emul_imager_data * data = dev -> data ;
200
229
int ret ;
201
230
@@ -207,7 +236,9 @@ static int emul_imager_set_mode(const struct device *dev, const struct emul_imag
207
236
208
237
/* Apply all the configuration registers for that mode */
209
238
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 );
211
242
if (ret < 0 ) {
212
243
goto err ;
213
244
}
@@ -312,7 +343,9 @@ static int emul_imager_get_caps(const struct device *dev, struct video_caps *cap
312
343
313
344
static int emul_imager_set_stream (const struct device * dev , bool enable , enum video_buf_type type )
314
345
{
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 );
316
349
}
317
350
318
351
static DEVICE_API (video , emul_imager_driver_api ) = {
@@ -339,21 +372,22 @@ int emul_imager_init(const struct device *dev)
339
372
{
340
373
const struct emul_imager_config * cfg = dev -> config ;
341
374
struct video_format fmt ;
342
- uint8_t sensor_id ;
375
+ uint32_t sensor_id ;
343
376
int ret ;
344
377
345
378
if (!i2c_is_ready_dt (& cfg -> i2c )) {
346
379
LOG_ERR ("Bus %s is not ready" , cfg -> i2c .bus -> name );
347
380
return - ENODEV ;
348
381
}
349
382
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 );
351
384
if (ret < 0 || sensor_id != EMUL_IMAGER_SENSOR_ID ) {
352
385
LOG_ERR ("Failed to get a correct sensor ID 0x%x" , sensor_id );
353
386
return ret ;
354
387
}
355
388
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 ));
357
391
if (ret < 0 ) {
358
392
LOG_ERR ("Could not set initial registers" );
359
393
return ret ;
@@ -395,7 +429,9 @@ static int emul_imager_transfer_i2c(const struct emul *target, struct i2c_msg ms
395
429
int addr )
396
430
{
397
431
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 ,
399
435
};
400
436
401
437
if (num_msgs == 0 ) {
0 commit comments