@@ -151,18 +151,100 @@ 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_qvga_regs [] = {
207
+ OV2640_ZOOM_CONFIG (QVGA_WIDTH , QVGA_HEIGHT , 2 , 2 , 4 ),
208
+ };
209
+ static const struct ov2640_reg ov2640_cif_regs [] = {
210
+ OV2640_ZOOM_CONFIG (CIF_WIDTH , CIF_HEIGHT , 2 , 2 , 8 ),
211
+ };
212
+ static const struct ov2640_reg ov2640_vga_regs [] = {
213
+ OV2640_ZOOM_CONFIG (VGA_WIDTH , VGA_HEIGHT , 0 , 0 , 2 ),
214
+ };
215
+ static const struct ov2640_reg ov2640_svga_regs [] = {
216
+ OV2640_ZOOM_CONFIG (SVGA_WIDTH , SVGA_HEIGHT , 1 , 1 , 2 ),
217
+ };
218
+ static const struct ov2640_reg ov2640_xga_regs [] = {
219
+ OV2640_ZOOM_CONFIG (XGA_WIDTH , XGA_HEIGHT , 0 , 0 , 2 ),
220
+ {CTRLI , 0x00 },
221
+ };
222
+ static const struct ov2640_reg ov2640_sxga_regs [] = {
223
+ OV2640_ZOOM_CONFIG (SXGA_WIDTH , SXGA_HEIGHT , 0 , 0 , 2 ),
224
+ {CTRLI , 0x00 },
225
+ {R_DVP_SP , 2 | R_DVP_SP_AUTO_MODE },
226
+ };
227
+ static const struct ov2640_reg ov2640_uxga_regs [] = {
228
+ OV2640_ZOOM_CONFIG (UXGA_WIDTH , UXGA_HEIGHT , 0 , 0 , 0 ),
229
+ {CTRLI , 0x00 },
230
+ {R_DVP_SP , 0 | R_DVP_SP_AUTO_MODE },
231
+ };
232
+
233
+ #define OV2640_SIZE (w , h , r ) {.width = w, .height = h, .regs = r, .regs_size = ARRAY_SIZE(r)}
234
+
235
+ static const struct ov2640_win_size ov2640_supported_win_sizes [] = {
236
+ OV2640_SIZE (QQVGA_WIDTH , QQVGA_HEIGHT , ov2640_qqvga_regs ),
237
+ OV2640_SIZE (QCIF_WIDTH , QCIF_HEIGHT , ov2640_qcif_regs ),
238
+ OV2640_SIZE (240 , 240 , ov2640_qvga_regs ),
239
+ OV2640_SIZE (QVGA_WIDTH , QVGA_HEIGHT , ov2640_qvga_regs ),
240
+ OV2640_SIZE (CIF_WIDTH , CIF_HEIGHT , ov2640_cif_regs ),
241
+ OV2640_SIZE (VGA_WIDTH , VGA_HEIGHT , ov2640_vga_regs ),
242
+ OV2640_SIZE (SVGA_WIDTH , SVGA_HEIGHT , ov2640_svga_regs ),
243
+ OV2640_SIZE (XGA_WIDTH , XGA_HEIGHT , ov2640_xga_regs ),
244
+ OV2640_SIZE (SXGA_WIDTH , SXGA_HEIGHT , ov2640_sxga_regs ),
245
+ OV2640_SIZE (UXGA_WIDTH , UXGA_HEIGHT , ov2640_uxga_regs ),
246
+ };
247
+
166
248
static const struct ov2640_reg default_regs [] = {
167
249
{ BANK_SEL , BANK_SEL_DSP },
168
250
{ 0x2c , 0xff },
@@ -376,20 +458,20 @@ static const struct ov2640_reg uxga_regs[] = {
376
458
{ R_BYPASS , R_BYPASS_DSP_BYPAS },
377
459
378
460
{ 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] */
461
+ {HSIZE8 , ( UXGA_WIDTH >> 3 )}, /* Image Horizontal Size HSIZE[10:3] */
462
+ {VSIZE8 , ( UXGA_HEIGHT >> 3 )}, /* Image Vertical Size VSIZE[10:3] */
381
463
382
464
/* {HSIZE[11], HSIZE[2:0], VSIZE[2:0]} */
383
- { SIZEL , (( UXGA_HSIZE >> 6 ) & 0x40 ) | ((UXGA_HSIZE & 0x7 )<< 3 ) | (UXGA_VSIZE & 0x7 )},
465
+ {SIZEL , (( UXGA_WIDTH >> 6 ) & 0x40 ) | ((UXGA_WIDTH & 0x7 ) << 3 ) | (UXGA_HEIGHT & 0x7 )},
384
466
385
467
{ XOFFL , 0x00 }, /* OFFSET_X[7:0] */
386
468
{ 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 */
469
+ {HSIZE , (( UXGA_WIDTH >> 2 ) & 0xFF )}, /* H_SIZE[7:0] real/4 */
470
+ {VSIZE , (( UXGA_HEIGHT >> 2 ) & 0xFF )}, /* V_SIZE[7:0] real/4 */
389
471
390
472
/* 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] */
473
+ {VHYX , (( UXGA_HEIGHT >> 3 ) & 0x80 ) | ((UXGA_WIDTH >> 7 ) & 0x08 )},
474
+ {TEST , ( UXGA_WIDTH >> 4 ) & 0x80 }, /* H_SIZE[9] */
393
475
394
476
{ CTRL2 , CTRL2_DCW_EN | CTRL2_SDE_EN |
395
477
CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
@@ -400,7 +482,6 @@ static const struct ov2640_reg uxga_regs[] = {
400
482
{ R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x04 },
401
483
402
484
{ R_BYPASS , R_BYPASS_DSP_EN },
403
- { RESET , 0x00 },
404
485
{0 , 0 },
405
486
};
406
487
@@ -472,29 +553,31 @@ struct ov2640_data {
472
553
}
473
554
474
555
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
- };
556
+ OV2640_VIDEO_FORMAT_CAP (QQVGA_WIDTH , QQVGA_HEIGHT ,
557
+ VIDEO_PIX_FMT_RGB565 ), /* 160 x 120 QQVGA */
558
+ OV2640_VIDEO_FORMAT_CAP (QCIF_WIDTH , QCIF_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 176 x 144 QCIF */
559
+ OV2640_VIDEO_FORMAT_CAP (240 , 240 , VIDEO_PIX_FMT_RGB565 ),
560
+ OV2640_VIDEO_FORMAT_CAP (QVGA_WIDTH , QVGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 320 x 240 QVGA */
561
+ OV2640_VIDEO_FORMAT_CAP (CIF_WIDTH , CIF_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 352 x 288 CIF */
562
+ OV2640_VIDEO_FORMAT_CAP (VGA_WIDTH , VGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 640 x 480 VGA */
563
+ OV2640_VIDEO_FORMAT_CAP (SVGA_WIDTH , SVGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 800 x 600 SVGA */
564
+ OV2640_VIDEO_FORMAT_CAP (XGA_WIDTH , XGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 1024 x 768 XVGA */
565
+ OV2640_VIDEO_FORMAT_CAP (SXGA_WIDTH , SXGA_HEIGHT ,
566
+ VIDEO_PIX_FMT_RGB565 ), /* 1280 x 1024 SXGA */
567
+ OV2640_VIDEO_FORMAT_CAP (UXGA_WIDTH , UXGA_HEIGHT ,
568
+ VIDEO_PIX_FMT_RGB565 ), /* 1600 x 1200 UXGA */
569
+ OV2640_VIDEO_FORMAT_CAP (QQVGA_WIDTH , QQVGA_HEIGHT ,
570
+ VIDEO_PIX_FMT_JPEG ), /* 160 x 120 QQVGA */
571
+ OV2640_VIDEO_FORMAT_CAP (QCIF_WIDTH , QCIF_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 176 x 144 QCIF */
572
+ OV2640_VIDEO_FORMAT_CAP (CIF_WIDTH , CIF_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 352 x 288 CIF */
573
+ OV2640_VIDEO_FORMAT_CAP (240 , 240 , VIDEO_PIX_FMT_JPEG ),
574
+ OV2640_VIDEO_FORMAT_CAP (QVGA_WIDTH , QVGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 320 x 240 QVGA */
575
+ OV2640_VIDEO_FORMAT_CAP (VGA_WIDTH , VGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 640 x 480 VGA */
576
+ OV2640_VIDEO_FORMAT_CAP (SVGA_WIDTH , SVGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 800 x 600 SVGA */
577
+ OV2640_VIDEO_FORMAT_CAP (XGA_WIDTH , XGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 1024 x 768 XVGA */
578
+ OV2640_VIDEO_FORMAT_CAP (SXGA_WIDTH , SXGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 1280 x 1024 SXGA */
579
+ OV2640_VIDEO_FORMAT_CAP (UXGA_WIDTH , UXGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 1600 x 1200 UXGA */
580
+ {0 }};
498
581
499
582
static int ov2640_write_reg (const struct i2c_dt_spec * spec , uint8_t reg_addr ,
500
583
uint8_t value )
@@ -775,6 +858,17 @@ static int ov2640_set_vertical_flip(const struct device *dev, int enable)
775
858
return ret ;
776
859
}
777
860
861
+ static const struct ov2640_win_size * ov2640_select_win (uint32_t width , uint32_t height )
862
+ {
863
+ for (int i = 0 ; i < ARRAY_SIZE (ov2640_supported_win_sizes ); i ++ ) {
864
+ if (ov2640_supported_win_sizes [i ].width >= width &&
865
+ ov2640_supported_win_sizes [i ].height >= height ) {
866
+ return & ov2640_supported_win_sizes [i ];
867
+ }
868
+ }
869
+ return NULL ;
870
+ }
871
+
778
872
static int ov2640_set_resolution (const struct device * dev ,
779
873
uint16_t img_width , uint16_t img_height )
780
874
{
@@ -784,23 +878,30 @@ static int ov2640_set_resolution(const struct device *dev,
784
878
uint16_t w = img_width ;
785
879
uint16_t h = img_height ;
786
880
881
+ const struct ov2640_win_size * win = ov2640_select_win (w , h );
882
+
883
+ if (win == NULL ) {
884
+ LOG_ERR ("Couldn't find window size for desired resolution setting" );
885
+ return - EINVAL ;
886
+ }
887
+ LOG_INF ("Selected resolution %ux%u" , win -> width , win -> height );
888
+
889
+ /* Write DSP input registers */
890
+ ret = ov2640_write_all (dev , uxga_regs , ARRAY_SIZE (uxga_regs ));
891
+ if (ret < 0 ) {
892
+ return ret ;
893
+ }
894
+
787
895
/* Disable DSP */
788
896
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_DSP );
789
897
ret |= ov2640_write_reg (& cfg -> i2c , R_BYPASS , R_BYPASS_DSP_BYPAS );
790
898
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] */
899
+ ret |= ov2640_write_all (dev , win -> regs , win -> regs_size );
796
900
797
901
/* Set CLKRC */
798
902
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_SENSOR );
799
903
ret |= ov2640_write_reg (& cfg -> i2c , CLKRC , cfg -> clock_rate_control );
800
904
801
- /* Write DSP input registers */
802
- ov2640_write_all (dev , uxga_regs , ARRAY_SIZE (uxga_regs ));
803
-
804
905
/* Enable DSP */
805
906
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_DSP );
806
907
ret |= ov2640_write_reg (& cfg -> i2c , R_BYPASS , R_BYPASS_DSP_EN );
@@ -1004,8 +1105,8 @@ static int ov2640_init(const struct device *dev)
1004
1105
/* set default/init format SVGA RGB565 */
1005
1106
struct video_format fmt = {
1006
1107
.pixelformat = VIDEO_PIX_FMT_RGB565 ,
1007
- .width = SVGA_HSIZE ,
1008
- .height = SVGA_VSIZE ,
1108
+ .width = SVGA_WIDTH ,
1109
+ .height = SVGA_HEIGHT ,
1009
1110
};
1010
1111
1011
1112
#if DT_INST_NODE_HAS_PROP (0 , reset_gpios )
0 commit comments