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 */
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
2425LOG_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+
4346enum 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
5356struct 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
6365struct 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 */
120142struct 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+
126170struct 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-
189216static 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". */
197225static 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
313344static 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
318351static 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