1616#include <zephyr/sys/util.h>
1717
1818#include "video_device.h"
19+ #include "video_ctrls.h"
1920#include "video_common.h"
2021
2122LOG_MODULE_REGISTER (hm01b0 , CONFIG_VIDEO_LOG_LEVEL );
@@ -27,6 +28,7 @@ LOG_MODULE_REGISTER(hm01b0, CONFIG_VIDEO_LOG_LEVEL);
2728#define HM01B0_REG8 (addr ) ((addr) | VIDEO_REG_ADDR16_DATA8)
2829#define HM01B0_REG16 (addr ) ((addr) | VIDEO_REG_ADDR16_DATA16_BE)
2930#define HM01B0_CCI_ID HM01B0_REG16(0x0000)
31+ #define HM01B0_CCI_IMG_ORIENTATION HM01B0_REG8(0x0101)
3032#define HM01B0_CCI_STS HM01B0_REG8(0x0100)
3133#define HM01B0_CCI_RESET HM01B0_REG8(0x0103)
3234#define HM01B0_CCI_GRP_PARAM_HOLD HM01B0_REG8(0x0104)
@@ -40,6 +42,9 @@ LOG_MODULE_REGISTER(hm01b0, CONFIG_VIDEO_LOG_LEVEL);
4042#define HM01B0_CCI_BIT_CONTROL HM01B0_REG8(0x3059)
4143#define HM01B0_CCI_OSC_CLOCK_DIV HM01B0_REG8(0x3060)
4244
45+ #define HM01B0_SET_HMIRROR (r , x ) ((r & 0xFE) | ((x & 1) << 0))
46+ #define HM01B0_SET_VMIRROR (r , x ) ((r & 0xFD) | ((x & 1) << 1))
47+
4348#define HM01B0_CTRL_VAL (data_bits ) \
4449 ((data_bits) == 8 ? 0x02 : \
4550 (data_bits) == 4 ? 0x42 : \
@@ -49,8 +54,12 @@ enum hm01b0_resolution {
4954 RESOLUTION_160x120 ,
5055 RESOLUTION_320x240 ,
5156 RESOLUTION_320x320 ,
52- RESOLUTION_324x244 ,
53- RESOLUTION_324x324 ,
57+ RESOLUTION_164x122 ,
58+ RESOLUTION_326x244 ,
59+ RESOLUTION_326x324 ,
60+ RESOLUTION_164x122_BAYER ,
61+ RESOLUTION_326x244_BAYER ,
62+ RESOLUTION_326x324_BAYER ,
5463};
5564
5665struct video_reg hm01b0_160x120_regs [] = {
@@ -84,11 +93,21 @@ struct video_reg *hm01b0_init_regs[] = {
8493 [RESOLUTION_160x120 ] = hm01b0_160x120_regs ,
8594 [RESOLUTION_320x240 ] = hm01b0_320x240_regs ,
8695 [RESOLUTION_320x320 ] = hm01b0_320x320_regs ,
87- [RESOLUTION_324x244 ] = hm01b0_320x240_regs ,
88- [RESOLUTION_324x324 ] = hm01b0_320x320_regs ,
96+ [RESOLUTION_164x122 ] = hm01b0_160x120_regs ,
97+ [RESOLUTION_326x244 ] = hm01b0_320x240_regs ,
98+ [RESOLUTION_326x324 ] = hm01b0_320x320_regs ,
99+ [RESOLUTION_164x122_BAYER ] = hm01b0_160x120_regs ,
100+ [RESOLUTION_326x244_BAYER ] = hm01b0_320x240_regs ,
101+ [RESOLUTION_326x324_BAYER ] = hm01b0_320x320_regs ,
102+ };
103+
104+ struct hm01b0_ctrls {
105+ struct video_ctrl hflip ;
106+ struct video_ctrl vflip ;
89107};
90108
91109struct hm01b0_data {
110+ struct hm01b0_ctrls ctrls ;
92111 struct video_format fmt ;
93112};
94113
@@ -119,8 +138,12 @@ static const struct video_format_cap hm01b0_fmts[] = {
119138 HM01B0_VIDEO_FORMAT_CAP (160 , 120 , VIDEO_PIX_FMT_GREY ),
120139 HM01B0_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_GREY ),
121140 HM01B0_VIDEO_FORMAT_CAP (320 , 320 , VIDEO_PIX_FMT_GREY ),
122- HM01B0_VIDEO_FORMAT_CAP (324 , 244 , VIDEO_PIX_FMT_GREY ),
123- HM01B0_VIDEO_FORMAT_CAP (324 , 324 , VIDEO_PIX_FMT_GREY ),
141+ HM01B0_VIDEO_FORMAT_CAP (164 , 122 , VIDEO_PIX_FMT_GREY ),
142+ HM01B0_VIDEO_FORMAT_CAP (326 , 244 , VIDEO_PIX_FMT_GREY ),
143+ HM01B0_VIDEO_FORMAT_CAP (326 , 324 , VIDEO_PIX_FMT_GREY ),
144+ HM01B0_VIDEO_FORMAT_CAP (164 , 122 , VIDEO_PIX_FMT_SBGGR8 ),
145+ HM01B0_VIDEO_FORMAT_CAP (326 , 324 , VIDEO_PIX_FMT_SBGGR8 ),
146+ HM01B0_VIDEO_FORMAT_CAP (326 , 244 , VIDEO_PIX_FMT_SBGGR8 ),
124147 {0 },
125148};
126149
@@ -252,9 +275,74 @@ static int hm01b0_soft_reset(const struct device *dev)
252275 return ret ;
253276}
254277
278+ static int hm01b0_init_controls (const struct device * dev )
279+ {
280+ int ret ;
281+ struct hm01b0_data * drv_data = dev -> data ;
282+ struct hm01b0_ctrls * ctrls = & drv_data -> ctrls ;
283+
284+ ret = video_init_ctrl (& ctrls -> hflip , dev , VIDEO_CID_HFLIP ,
285+ (struct video_ctrl_range ){.min = 0 , .max = 1 , .step = 1 , .def = 0 });
286+ if (ret ) {
287+ return ret ;
288+ }
289+
290+ return video_init_ctrl (& ctrls -> vflip , dev , VIDEO_CID_VFLIP ,
291+ (struct video_ctrl_range ){.min = 0 , .max = 1 , .step = 1 , .def = 0 });
292+ }
293+
294+ static int hm01b0_set_ctrl (const struct device * dev , uint32_t id )
295+ {
296+ const struct hm01b0_config * config = dev -> config ;
297+ struct hm01b0_data * drv_data = dev -> data ;
298+ struct hm01b0_ctrls * ctrls = & drv_data -> ctrls ;
299+
300+ int ret ;
301+ uint32_t data ;
302+
303+ switch (id ) {
304+ case VIDEO_CID_HFLIP :
305+ ret = video_read_cci_reg (& config -> i2c , HM01B0_CCI_IMG_ORIENTATION , & data );
306+ if (ret < 0 ) {
307+ return ret ;
308+ }
309+ ret = video_write_cci_reg (& config -> i2c , HM01B0_CCI_IMG_ORIENTATION ,
310+ HM01B0_SET_HMIRROR (data , ctrls -> hflip .val ));
311+ if (ret < 0 ) {
312+ return ret ;
313+ }
314+ ret = video_write_cci_reg (& config -> i2c , HM01B0_CCI_GRP_PARAM_HOLD , 0x01 );
315+ if (ret < 0 ) {
316+ return ret ;
317+ }
318+ break ;
319+ case VIDEO_CID_VFLIP :
320+ ret = video_read_cci_reg (& config -> i2c , HM01B0_CCI_IMG_ORIENTATION , & data );
321+ if (ret < 0 ) {
322+ return ret ;
323+ }
324+ ret = video_write_cci_reg (& config -> i2c , HM01B0_CCI_IMG_ORIENTATION ,
325+ HM01B0_SET_VMIRROR (data , ctrls -> vflip .val ));
326+ if (ret < 0 ) {
327+ return ret ;
328+ }
329+ ret = video_write_cci_reg (& config -> i2c , HM01B0_CCI_GRP_PARAM_HOLD , 0x01 );
330+ if (ret < 0 ) {
331+ return ret ;
332+ }
333+ break ;
334+ default :
335+ return - ENOTSUP ;
336+ }
337+
338+ return 0 ;
339+ }
340+
341+
255342static DEVICE_API (video , hm01b0_driver_api ) = {
256343 .set_format = hm01b0_set_fmt ,
257344 .get_format = hm01b0_get_fmt ,
345+ .set_ctrl = hm01b0_set_ctrl ,
258346 .set_stream = hm01b0_set_stream ,
259347 .get_caps = hm01b0_get_caps ,
260348};
@@ -310,7 +398,7 @@ static bool hm01b0_try_reset_pwdn_pins(const struct device *dev, uint8_t iter)
310398
311399static int hm01b0_init (const struct device * dev )
312400{
313- const struct hm01b0_config * config = dev -> config ;
401+ const struct hm01b0_config __maybe_unused * config = dev -> config ;
314402 int ret ;
315403
316404#if DT_ANY_INST_HAS_PROP_STATUS_OKAY (pwdn_gpios ) || DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
@@ -376,7 +464,9 @@ static int hm01b0_init(const struct device *dev)
376464 return ret ;
377465 }
378466
379- return 0 ;
467+
468+ /* Initialize controls */
469+ return hm01b0_init_controls (dev );
380470}
381471
382472#if DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
0 commit comments