@@ -151,18 +151,103 @@ LOG_MODULE_REGISTER(video_ov2640, CONFIG_VIDEO_LOG_LEVEL);
151
151
#define REG32 0x32
152
152
#define REG32_UXGA 0x36
153
153
154
- /* Configuration arrays */
155
- #define SVGA_HSIZE (800)
156
- #define SVGA_VSIZE (600)
157
-
158
- #define UXGA_HSIZE (1600)
159
- #define UXGA_VSIZE (1200)
154
+ #define CIF_WIDTH 352
155
+ #define CIF_HEIGHT 288
156
+ #define HD_720_WIDTH 1280
157
+ #define HD_720_HEIGHT 720
158
+ #define HD_1080_WIDTH 1920
159
+ #define HD_1080_HEIGHT 1080
160
+ #define QCIF_WIDTH 176
161
+ #define QCIF_HEIGHT 144
162
+ #define QQCIF_WIDTH 88
163
+ #define QQCIF_HEIGHT 72
164
+ #define QQVGA_WIDTH 160
165
+ #define QQVGA_HEIGHT 120
166
+ #define QVGA_WIDTH 320
167
+ #define QVGA_HEIGHT 240
168
+ #define SVGA_WIDTH 800
169
+ #define SVGA_HEIGHT 600
170
+ #define SXGA_WIDTH 1280
171
+ #define SXGA_HEIGHT 1024
172
+ #define VGA_WIDTH 640
173
+ #define VGA_HEIGHT 480
174
+ #define UXGA_WIDTH 1600
175
+ #define UXGA_HEIGHT 1200
176
+ #define XGA_WIDTH 1024
177
+ #define XGA_HEIGHT 768
160
178
161
179
struct ov2640_reg {
162
180
uint8_t addr ;
163
181
uint8_t value ;
164
182
};
165
183
184
+ struct ov2640_win_size {
185
+ uint32_t width ;
186
+ uint32_t height ;
187
+ const struct ov2640_reg * regs ;
188
+ uint32_t regs_size ;
189
+ };
190
+
191
+ #define OV2640_ZOOM_CONFIG (x , y , v_div , h_div , pclk_div ) \
192
+ {CTRLI, \
193
+ CTRLI_LP_DP | FIELD_PREP(GENMASK(5, 3), v_div) | FIELD_PREP(GENMASK(2, 0), h_div)}, \
194
+ {ZMOW, FIELD_PREP(GENMASK(7, 0), (x) >> 2)}, \
195
+ {ZMOH, FIELD_PREP(GENMASK(7, 0), (y) >> 2)}, \
196
+ {ZMHH, FIELD_PREP(GENMASK(1, 0), (x) >> (8 + 2)) | \
197
+ FIELD_PREP(GENMASK(2, 2), (y) >> (8 + 2))}, \
198
+ {R_DVP_SP, pclk_div}, {RESET, 0x00}
199
+
200
+ static const struct ov2640_reg ov2640_qqvga_regs [] = {
201
+ OV2640_ZOOM_CONFIG (QQVGA_WIDTH , QQVGA_HEIGHT , 3 , 3 , 8 ),
202
+ };
203
+ static const struct ov2640_reg ov2640_qcif_regs [] = {
204
+ OV2640_ZOOM_CONFIG (QCIF_WIDTH , QCIF_HEIGHT , 3 , 3 , 4 ),
205
+ };
206
+ static const struct ov2640_reg ov2640_240x240_regs [] = {
207
+ OV2640_ZOOM_CONFIG (240 , 240 , 2 , 2 , 4 ),
208
+ };
209
+ static const struct ov2640_reg ov2640_qvga_regs [] = {
210
+ OV2640_ZOOM_CONFIG (QVGA_WIDTH , QVGA_HEIGHT , 2 , 2 , 4 ),
211
+ };
212
+ static const struct ov2640_reg ov2640_cif_regs [] = {
213
+ OV2640_ZOOM_CONFIG (CIF_WIDTH , CIF_HEIGHT , 2 , 2 , 8 ),
214
+ };
215
+ static const struct ov2640_reg ov2640_vga_regs [] = {
216
+ OV2640_ZOOM_CONFIG (VGA_WIDTH , VGA_HEIGHT , 0 , 0 , 2 ),
217
+ };
218
+ static const struct ov2640_reg ov2640_svga_regs [] = {
219
+ OV2640_ZOOM_CONFIG (SVGA_WIDTH , SVGA_HEIGHT , 1 , 1 , 2 ),
220
+ };
221
+ static const struct ov2640_reg ov2640_xga_regs [] = {
222
+ OV2640_ZOOM_CONFIG (XGA_WIDTH , XGA_HEIGHT , 0 , 0 , 2 ),
223
+ {CTRLI , 0x00 },
224
+ };
225
+ static const struct ov2640_reg ov2640_sxga_regs [] = {
226
+ OV2640_ZOOM_CONFIG (SXGA_WIDTH , SXGA_HEIGHT , 0 , 0 , 2 ),
227
+ {CTRLI , 0x00 },
228
+ {R_DVP_SP , 2 | R_DVP_SP_AUTO_MODE },
229
+ };
230
+ static const struct ov2640_reg ov2640_uxga_regs [] = {
231
+ OV2640_ZOOM_CONFIG (UXGA_WIDTH , UXGA_HEIGHT , 0 , 0 , 0 ),
232
+ {CTRLI , 0x00 },
233
+ {R_DVP_SP , 0 | R_DVP_SP_AUTO_MODE },
234
+ };
235
+
236
+ #define OV2640_SIZE (w , h , r ) {.width = w, .height = h, .regs = r, .regs_size = ARRAY_SIZE(r)}
237
+
238
+ static const struct ov2640_win_size ov2640_supported_win_sizes [] = {
239
+ OV2640_SIZE (QQVGA_WIDTH , QQVGA_HEIGHT , ov2640_qqvga_regs ),
240
+ OV2640_SIZE (QCIF_WIDTH , QCIF_HEIGHT , ov2640_qcif_regs ),
241
+ OV2640_SIZE (240 , 240 , ov2640_240x240_regs ),
242
+ OV2640_SIZE (QVGA_WIDTH , QVGA_HEIGHT , ov2640_qvga_regs ),
243
+ OV2640_SIZE (CIF_WIDTH , CIF_HEIGHT , ov2640_cif_regs ),
244
+ OV2640_SIZE (VGA_WIDTH , VGA_HEIGHT , ov2640_vga_regs ),
245
+ OV2640_SIZE (SVGA_WIDTH , SVGA_HEIGHT , ov2640_svga_regs ),
246
+ OV2640_SIZE (XGA_WIDTH , XGA_HEIGHT , ov2640_xga_regs ),
247
+ OV2640_SIZE (SXGA_WIDTH , SXGA_HEIGHT , ov2640_sxga_regs ),
248
+ OV2640_SIZE (UXGA_WIDTH , UXGA_HEIGHT , ov2640_uxga_regs ),
249
+ };
250
+
166
251
static const struct ov2640_reg default_regs [] = {
167
252
{ BANK_SEL , BANK_SEL_DSP },
168
253
{ 0x2c , 0xff },
@@ -376,20 +461,20 @@ static const struct ov2640_reg uxga_regs[] = {
376
461
{ R_BYPASS , R_BYPASS_DSP_BYPAS },
377
462
378
463
{ RESET , RESET_DVP },
379
- { HSIZE8 , ( UXGA_HSIZE >> 3 )}, /* Image Horizontal Size HSIZE[10:3] */
380
- { VSIZE8 , ( UXGA_VSIZE >> 3 )}, /* Image Vertical Size VSIZE[10:3] */
464
+ {HSIZE8 , ( UXGA_WIDTH >> 3 )}, /* Image Horizontal Size HSIZE[10:3] */
465
+ {VSIZE8 , ( UXGA_HEIGHT >> 3 )}, /* Image Vertical Size VSIZE[10:3] */
381
466
382
467
/* {HSIZE[11], HSIZE[2:0], VSIZE[2:0]} */
383
- { SIZEL , (( UXGA_HSIZE >> 6 ) & 0x40 ) | ((UXGA_HSIZE & 0x7 )<< 3 ) | (UXGA_VSIZE & 0x7 )},
468
+ {SIZEL , (( UXGA_WIDTH >> 6 ) & 0x40 ) | ((UXGA_WIDTH & 0x7 ) << 3 ) | (UXGA_HEIGHT & 0x7 )},
384
469
385
470
{ XOFFL , 0x00 }, /* OFFSET_X[7:0] */
386
471
{ YOFFL , 0x00 }, /* OFFSET_Y[7:0] */
387
- { HSIZE , (( UXGA_HSIZE >> 2 ) & 0xFF ) }, /* H_SIZE[7:0] real/4 */
388
- { VSIZE , (( UXGA_VSIZE >> 2 ) & 0xFF ) }, /* V_SIZE[7:0] real/4 */
472
+ {HSIZE , (( UXGA_WIDTH >> 2 ) & 0xFF )}, /* H_SIZE[7:0] real/4 */
473
+ {VSIZE , (( UXGA_HEIGHT >> 2 ) & 0xFF )}, /* V_SIZE[7:0] real/4 */
389
474
390
475
/* V_SIZE[8]/OFFSET_Y[10:8]/H_SIZE[8]/OFFSET_X[10:8] */
391
- { VHYX , (( UXGA_VSIZE >> 3 ) & 0x80 ) | ((UXGA_HSIZE >> 7 ) & 0x08 ) },
392
- { TEST , ( UXGA_HSIZE >> 4 ) & 0x80 }, /* H_SIZE[9] */
476
+ {VHYX , (( UXGA_HEIGHT >> 3 ) & 0x80 ) | ((UXGA_WIDTH >> 7 ) & 0x08 )},
477
+ {TEST , ( UXGA_WIDTH >> 4 ) & 0x80 }, /* H_SIZE[9] */
393
478
394
479
{ CTRL2 , CTRL2_DCW_EN | CTRL2_SDE_EN |
395
480
CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
@@ -400,7 +485,6 @@ static const struct ov2640_reg uxga_regs[] = {
400
485
{ R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x04 },
401
486
402
487
{ R_BYPASS , R_BYPASS_DSP_EN },
403
- { RESET , 0x00 },
404
488
{0 , 0 },
405
489
};
406
490
@@ -472,29 +556,31 @@ struct ov2640_data {
472
556
}
473
557
474
558
static const struct video_format_cap fmts [] = {
475
- OV2640_VIDEO_FORMAT_CAP (160 , 120 , VIDEO_PIX_FMT_RGB565 ), /* QQVGA */
476
- OV2640_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_RGB565 ), /* QCIF */
477
- OV2640_VIDEO_FORMAT_CAP (240 , 160 , VIDEO_PIX_FMT_RGB565 ), /* HQVGA */
478
- OV2640_VIDEO_FORMAT_CAP (240 , 240 , VIDEO_PIX_FMT_RGB565 ), /* 240x240 */
479
- OV2640_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_RGB565 ), /* QVGA */
480
- OV2640_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_RGB565 ), /* CIF */
481
- OV2640_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_RGB565 ), /* VGA */
482
- OV2640_VIDEO_FORMAT_CAP (800 , 600 , VIDEO_PIX_FMT_RGB565 ), /* SVGA */
483
- OV2640_VIDEO_FORMAT_CAP (1024 , 768 , VIDEO_PIX_FMT_RGB565 ), /* XVGA */
484
- OV2640_VIDEO_FORMAT_CAP (1280 , 1024 , VIDEO_PIX_FMT_RGB565 ), /* SXGA */
485
- OV2640_VIDEO_FORMAT_CAP (1600 , 1200 , VIDEO_PIX_FMT_RGB565 ), /* UXGA */
486
- OV2640_VIDEO_FORMAT_CAP (160 , 120 , VIDEO_PIX_FMT_JPEG ), /* QQVGA */
487
- OV2640_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_JPEG ), /* QCIF */
488
- OV2640_VIDEO_FORMAT_CAP (240 , 160 , VIDEO_PIX_FMT_JPEG ), /* HQVGA */
489
- OV2640_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_JPEG ), /* QVGA */
490
- OV2640_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_JPEG ), /* CIF */
491
- OV2640_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_JPEG ), /* VGA */
492
- OV2640_VIDEO_FORMAT_CAP (800 , 600 , VIDEO_PIX_FMT_JPEG ), /* SVGA */
493
- OV2640_VIDEO_FORMAT_CAP (1024 , 768 , VIDEO_PIX_FMT_JPEG ), /* XVGA */
494
- OV2640_VIDEO_FORMAT_CAP (1280 , 1024 , VIDEO_PIX_FMT_JPEG ), /* SXGA */
495
- OV2640_VIDEO_FORMAT_CAP (1600 , 1200 , VIDEO_PIX_FMT_JPEG ), /* UXGA */
496
- { 0 }
497
- };
559
+ OV2640_VIDEO_FORMAT_CAP (QQVGA_WIDTH , QQVGA_HEIGHT ,
560
+ VIDEO_PIX_FMT_RGB565 ), /* 160 x 120 QQVGA */
561
+ OV2640_VIDEO_FORMAT_CAP (QCIF_WIDTH , QCIF_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 176 x 144 QCIF */
562
+ OV2640_VIDEO_FORMAT_CAP (240 , 240 , VIDEO_PIX_FMT_RGB565 ),
563
+ OV2640_VIDEO_FORMAT_CAP (QVGA_WIDTH , QVGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 320 x 240 QVGA */
564
+ OV2640_VIDEO_FORMAT_CAP (CIF_WIDTH , CIF_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 352 x 288 CIF */
565
+ OV2640_VIDEO_FORMAT_CAP (VGA_WIDTH , VGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 640 x 480 VGA */
566
+ OV2640_VIDEO_FORMAT_CAP (SVGA_WIDTH , SVGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 800 x 600 SVGA */
567
+ OV2640_VIDEO_FORMAT_CAP (XGA_WIDTH , XGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 1024 x 768 XVGA */
568
+ OV2640_VIDEO_FORMAT_CAP (SXGA_WIDTH , SXGA_HEIGHT ,
569
+ VIDEO_PIX_FMT_RGB565 ), /* 1280 x 1024 SXGA */
570
+ OV2640_VIDEO_FORMAT_CAP (UXGA_WIDTH , UXGA_HEIGHT ,
571
+ VIDEO_PIX_FMT_RGB565 ), /* 1600 x 1200 UXGA */
572
+ OV2640_VIDEO_FORMAT_CAP (QQVGA_WIDTH , QQVGA_HEIGHT ,
573
+ VIDEO_PIX_FMT_JPEG ), /* 160 x 120 QQVGA */
574
+ OV2640_VIDEO_FORMAT_CAP (QCIF_WIDTH , QCIF_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 176 x 144 QCIF */
575
+ OV2640_VIDEO_FORMAT_CAP (CIF_WIDTH , CIF_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 352 x 288 CIF */
576
+ OV2640_VIDEO_FORMAT_CAP (240 , 240 , VIDEO_PIX_FMT_JPEG ),
577
+ OV2640_VIDEO_FORMAT_CAP (QVGA_WIDTH , QVGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 320 x 240 QVGA */
578
+ OV2640_VIDEO_FORMAT_CAP (VGA_WIDTH , VGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 640 x 480 VGA */
579
+ OV2640_VIDEO_FORMAT_CAP (SVGA_WIDTH , SVGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 800 x 600 SVGA */
580
+ OV2640_VIDEO_FORMAT_CAP (XGA_WIDTH , XGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 1024 x 768 XVGA */
581
+ OV2640_VIDEO_FORMAT_CAP (SXGA_WIDTH , SXGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 1280 x 1024 SXGA */
582
+ OV2640_VIDEO_FORMAT_CAP (UXGA_WIDTH , UXGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 1600 x 1200 UXGA */
583
+ {0 }};
498
584
499
585
static int ov2640_write_reg (const struct i2c_dt_spec * spec , uint8_t reg_addr ,
500
586
uint8_t value )
@@ -775,6 +861,17 @@ static int ov2640_set_vertical_flip(const struct device *dev, int enable)
775
861
return ret ;
776
862
}
777
863
864
+ static const struct ov2640_win_size * ov2640_select_win (uint32_t width , uint32_t height )
865
+ {
866
+ for (int i = 0 ; i < ARRAY_SIZE (ov2640_supported_win_sizes ); i ++ ) {
867
+ if (ov2640_supported_win_sizes [i ].width >= width &&
868
+ ov2640_supported_win_sizes [i ].height >= height ) {
869
+ return & ov2640_supported_win_sizes [i ];
870
+ }
871
+ }
872
+ return NULL ;
873
+ }
874
+
778
875
static int ov2640_set_resolution (const struct device * dev ,
779
876
uint16_t img_width , uint16_t img_height )
780
877
{
@@ -784,23 +881,30 @@ static int ov2640_set_resolution(const struct device *dev,
784
881
uint16_t w = img_width ;
785
882
uint16_t h = img_height ;
786
883
884
+ const struct ov2640_win_size * win = ov2640_select_win (w , h );
885
+
886
+ if (win == NULL ) {
887
+ LOG_ERR ("Couldn't find window size for desired resolution setting" );
888
+ return - EINVAL ;
889
+ }
890
+ LOG_INF ("Selected resolution %ux%u" , win -> width , win -> height );
891
+
892
+ /* Write DSP input registers */
893
+ ret = ov2640_write_all (dev , uxga_regs , ARRAY_SIZE (uxga_regs ));
894
+ if (ret < 0 ) {
895
+ return ret ;
896
+ }
897
+
787
898
/* Disable DSP */
788
899
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_DSP );
789
900
ret |= ov2640_write_reg (& cfg -> i2c , R_BYPASS , R_BYPASS_DSP_BYPAS );
790
901
791
- /* Write output width */
792
- ret |= ov2640_write_reg (& cfg -> i2c , ZMOW , (w >> 2 ) & 0xFF ); /* OUTW[7:0] (real/4) */
793
- ret |= ov2640_write_reg (& cfg -> i2c , ZMOH , (h >> 2 ) & 0xFF ); /* OUTH[7:0] (real/4) */
794
- ret |= ov2640_write_reg (& cfg -> i2c , ZMHH , ((h >> 8 ) & 0x04 ) |
795
- ((w >>10 ) & 0x03 )); /* OUTH[8]/OUTW[9:8] */
902
+ ret |= ov2640_write_all (dev , win -> regs , win -> regs_size );
796
903
797
904
/* Set CLKRC */
798
905
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_SENSOR );
799
906
ret |= ov2640_write_reg (& cfg -> i2c , CLKRC , cfg -> clock_rate_control );
800
907
801
- /* Write DSP input registers */
802
- ov2640_write_all (dev , uxga_regs , ARRAY_SIZE (uxga_regs ));
803
-
804
908
/* Enable DSP */
805
909
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_DSP );
806
910
ret |= ov2640_write_reg (& cfg -> i2c , R_BYPASS , R_BYPASS_DSP_EN );
@@ -1004,8 +1108,8 @@ static int ov2640_init(const struct device *dev)
1004
1108
/* set default/init format SVGA RGB565 */
1005
1109
struct video_format fmt = {
1006
1110
.pixelformat = VIDEO_PIX_FMT_RGB565 ,
1007
- .width = SVGA_HSIZE ,
1008
- .height = SVGA_VSIZE ,
1111
+ .width = SVGA_WIDTH ,
1112
+ .height = SVGA_HEIGHT ,
1009
1113
};
1010
1114
1011
1115
#if DT_INST_NODE_HAS_PROP (0 , reset_gpios )
0 commit comments