@@ -151,18 +151,101 @@ 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
+ char * name ;
186
+ uint32_t width ;
187
+ uint32_t height ;
188
+ const struct ov2640_reg * regs ;
189
+ uint32_t regs_size ;
190
+ };
191
+
192
+ #define PER_SIZE_REG_SEQ (x , y , v_div , h_div , pclk_div ) \
193
+ { CTRLI, CTRLI_LP_DP | FIELD_PREP(GENMASK(5, 3), v_div) | \
194
+ FIELD_PREP(GENMASK(2, 0), h_div)}, \
195
+ { ZMOW, FIELD_PREP(GENMASK(7, 0), (x) >> 2) }, \
196
+ { ZMOH, FIELD_PREP(GENMASK(7, 0), (y) >> 2) }, \
197
+ { ZMHH, FIELD_PREP(GENMASK(1, 0), (x) >> (8+2)) | FIELD_PREP(GENMASK(2, 2), (y) >> (8+2)) }, \
198
+ { R_DVP_SP, pclk_div }, \
199
+ { RESET, 0x00}
200
+
201
+ static const struct ov2640_reg ov2640_qqvga_regs [] = {
202
+ PER_SIZE_REG_SEQ (QQVGA_WIDTH , QQVGA_HEIGHT , 3 , 3 , 8 ),
203
+ };
204
+ static const struct ov2640_reg ov2640_qcif_regs [] = {
205
+ PER_SIZE_REG_SEQ (QCIF_WIDTH , QCIF_HEIGHT , 3 , 3 , 4 ),
206
+ };
207
+ static const struct ov2640_reg ov2640_qvga_regs [] = {
208
+ PER_SIZE_REG_SEQ (QVGA_WIDTH , QVGA_HEIGHT , 2 , 2 , 4 ),
209
+ };
210
+ static const struct ov2640_reg ov2640_cif_regs [] = {
211
+ PER_SIZE_REG_SEQ (CIF_WIDTH , CIF_HEIGHT , 2 , 2 , 8 ),
212
+ };
213
+ static const struct ov2640_reg ov2640_vga_regs [] = {
214
+ PER_SIZE_REG_SEQ (VGA_WIDTH , VGA_HEIGHT , 0 , 0 , 2 ),
215
+ };
216
+ static const struct ov2640_reg ov2640_svga_regs [] = {
217
+ PER_SIZE_REG_SEQ (SVGA_WIDTH , SVGA_HEIGHT , 1 , 1 , 2 ),
218
+ };
219
+ static const struct ov2640_reg ov2640_xga_regs [] = {
220
+ PER_SIZE_REG_SEQ (XGA_WIDTH , XGA_HEIGHT , 0 , 0 , 2 ),
221
+ { CTRLI , 0x00 },
222
+ };
223
+ static const struct ov2640_reg ov2640_sxga_regs [] = {
224
+ PER_SIZE_REG_SEQ (SXGA_WIDTH , SXGA_HEIGHT , 0 , 0 , 2 ),
225
+ { CTRLI , 0x00 },
226
+ { R_DVP_SP , 2 | R_DVP_SP_AUTO_MODE },
227
+ };
228
+ static const struct ov2640_reg ov2640_uxga_regs [] = {
229
+ PER_SIZE_REG_SEQ (UXGA_WIDTH , UXGA_HEIGHT , 0 , 0 , 0 ),
230
+ { CTRLI , 0x00 },
231
+ { R_DVP_SP , 0 | R_DVP_SP_AUTO_MODE },
232
+ };
233
+
234
+ #define OV2640_SIZE (n , w , h , r ) \
235
+ {.name = n, .width = w , .height = h, .regs = r, .regs_size = ARRAY_SIZE(r) }
236
+
237
+ static const struct ov2640_win_size ov2640_supported_win_sizes [] = {
238
+ OV2640_SIZE ("QQVGA" , QQVGA_WIDTH , QQVGA_HEIGHT , ov2640_qqvga_regs ),
239
+ OV2640_SIZE ("QCIF" , QCIF_WIDTH , QCIF_HEIGHT , ov2640_qcif_regs ),
240
+ OV2640_SIZE ("QVGA" , QVGA_WIDTH , QVGA_HEIGHT , ov2640_qvga_regs ),
241
+ OV2640_SIZE ("CIF" , CIF_WIDTH , CIF_HEIGHT , ov2640_cif_regs ),
242
+ OV2640_SIZE ("VGA" , VGA_WIDTH , VGA_HEIGHT , ov2640_vga_regs ),
243
+ OV2640_SIZE ("SVGA" , SVGA_WIDTH , SVGA_HEIGHT , ov2640_svga_regs ),
244
+ OV2640_SIZE ("XGA" , XGA_WIDTH , XGA_HEIGHT , ov2640_xga_regs ),
245
+ OV2640_SIZE ("SXGA" , SXGA_WIDTH , SXGA_HEIGHT , ov2640_sxga_regs ),
246
+ OV2640_SIZE ("UXGA" , UXGA_WIDTH , UXGA_HEIGHT , ov2640_uxga_regs ),
247
+ };
248
+
166
249
static const struct ov2640_reg default_regs [] = {
167
250
{ BANK_SEL , BANK_SEL_DSP },
168
251
{ 0x2c , 0xff },
@@ -376,20 +459,20 @@ static const struct ov2640_reg uxga_regs[] = {
376
459
{ R_BYPASS , R_BYPASS_DSP_BYPAS },
377
460
378
461
{ 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] */
462
+ { HSIZE8 , (UXGA_WIDTH >>3 )}, /* Image Horizontal Size HSIZE[10:3] */
463
+ { VSIZE8 , (UXGA_HEIGHT >>3 )}, /* Image Vertical Size VSIZE[10:3] */
381
464
382
465
/* {HSIZE[11], HSIZE[2:0], VSIZE[2:0]} */
383
- { SIZEL , ((UXGA_HSIZE >>6 )& 0x40 ) | ((UXGA_HSIZE & 0x7 )<<3 ) | (UXGA_VSIZE & 0x7 )},
466
+ { SIZEL , ((UXGA_WIDTH >>6 )& 0x40 ) | ((UXGA_WIDTH & 0x7 )<<3 ) | (UXGA_HEIGHT & 0x7 )},
384
467
385
468
{ XOFFL , 0x00 }, /* OFFSET_X[7:0] */
386
469
{ 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 */
470
+ { HSIZE , ((UXGA_WIDTH >>2 )& 0xFF ) }, /* H_SIZE[7:0] real/4 */
471
+ { VSIZE , ((UXGA_HEIGHT >>2 )& 0xFF ) }, /* V_SIZE[7:0] real/4 */
389
472
390
473
/* 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] */
474
+ { VHYX , ((UXGA_HEIGHT >>3 )& 0x80 ) | ((UXGA_WIDTH >>7 )& 0x08 ) },
475
+ { TEST , (UXGA_WIDTH >>4 )& 0x80 }, /* H_SIZE[9] */
393
476
394
477
{ CTRL2 , CTRL2_DCW_EN | CTRL2_SDE_EN |
395
478
CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
@@ -400,7 +483,8 @@ static const struct ov2640_reg uxga_regs[] = {
400
483
{ R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x04 },
401
484
402
485
{ R_BYPASS , R_BYPASS_DSP_EN },
403
- { RESET , 0x00 },
486
+ /* Keep reset asserted as zoom config is coming next */
487
+ /* { RESET, 0x00 }, */
404
488
{0 , 0 },
405
489
};
406
490
@@ -472,27 +556,22 @@ 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 */
559
+ OV2640_VIDEO_FORMAT_CAP (QQVGA_WIDTH , QQVGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 160 x 120 QQVGA */
560
+ OV2640_VIDEO_FORMAT_CAP (QCIF_WIDTH , QCIF_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 176 x 144 QCIF */
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 , VIDEO_PIX_FMT_RGB565 ), /* 1280 x 1024 SXGA */
566
+ OV2640_VIDEO_FORMAT_CAP (UXGA_WIDTH , UXGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* 1600 x 1200 UXGA */
567
+ OV2640_VIDEO_FORMAT_CAP (QQVGA_WIDTH , QQVGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 160 x 120 QQVGA */
568
+ OV2640_VIDEO_FORMAT_CAP (QCIF_WIDTH , QCIF_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 176 x 144 QCIF */
569
+ OV2640_VIDEO_FORMAT_CAP (CIF_WIDTH , CIF_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 352 x 288 CIF */
570
+ OV2640_VIDEO_FORMAT_CAP (VGA_WIDTH , VGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 640 x 480 VGA */
571
+ OV2640_VIDEO_FORMAT_CAP (SVGA_WIDTH , SVGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 800 x 600 SVGA */
572
+ OV2640_VIDEO_FORMAT_CAP (XGA_WIDTH , XGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 1024 x 768 XVGA */
573
+ OV2640_VIDEO_FORMAT_CAP (SXGA_WIDTH , SXGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 1280 x 1024 SXGA */
574
+ OV2640_VIDEO_FORMAT_CAP (UXGA_WIDTH , UXGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* 1600 x 1200 UXGA */
496
575
{ 0 }
497
576
};
498
577
@@ -775,6 +854,17 @@ static int ov2640_set_vertical_flip(const struct device *dev, int enable)
775
854
return ret ;
776
855
}
777
856
857
+ static const struct ov2640_win_size * ov2640_select_win (uint32_t width , uint32_t height )
858
+ {
859
+ int i ;
860
+ for (i = 0 ; i < ARRAY_SIZE (ov2640_supported_win_sizes ); i ++ ) {
861
+ if (ov2640_supported_win_sizes [i ].width >= width &&
862
+ ov2640_supported_win_sizes [i ].height >= height )
863
+ return & ov2640_supported_win_sizes [i ];
864
+ }
865
+ return NULL ;
866
+ }
867
+
778
868
static int ov2640_set_resolution (const struct device * dev ,
779
869
uint16_t img_width , uint16_t img_height )
780
870
{
@@ -784,23 +874,29 @@ static int ov2640_set_resolution(const struct device *dev,
784
874
uint16_t w = img_width ;
785
875
uint16_t h = img_height ;
786
876
877
+ const struct ov2640_win_size * win = ov2640_select_win (w , h );
878
+ if (NULL == win ) {
879
+ LOG_ERR ("Couldn't find window size for desired resolution setting" );
880
+ return - EINVAL ;
881
+ }
882
+ LOG_INF ("Selected resolution %s" , win -> name );
883
+
884
+ /* Write DSP input registers */
885
+ ret |= ov2640_write_all (dev , uxga_regs , ARRAY_SIZE (uxga_regs ));
886
+ if (ret < 0 ) {
887
+ return ret ;
888
+ }
889
+
787
890
/* Disable DSP */
788
891
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_DSP );
789
892
ret |= ov2640_write_reg (& cfg -> i2c , R_BYPASS , R_BYPASS_DSP_BYPAS );
790
893
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] */
894
+ ret |= ov2640_write_all (dev , win -> regs , win -> regs_size );
796
895
797
896
/* Set CLKRC */
798
897
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_SENSOR );
799
898
ret |= ov2640_write_reg (& cfg -> i2c , CLKRC , cfg -> clock_rate_control );
800
899
801
- /* Write DSP input registers */
802
- ov2640_write_all (dev , uxga_regs , ARRAY_SIZE (uxga_regs ));
803
-
804
900
/* Enable DSP */
805
901
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_DSP );
806
902
ret |= ov2640_write_reg (& cfg -> i2c , R_BYPASS , R_BYPASS_DSP_EN );
@@ -1004,8 +1100,8 @@ static int ov2640_init(const struct device *dev)
1004
1100
/* set default/init format SVGA RGB565 */
1005
1101
struct video_format fmt = {
1006
1102
.pixelformat = VIDEO_PIX_FMT_RGB565 ,
1007
- .width = SVGA_HSIZE ,
1008
- .height = SVGA_VSIZE ,
1103
+ .width = SVGA_WIDTH ,
1104
+ .height = SVGA_HEIGHT ,
1009
1105
};
1010
1106
1011
1107
#if DT_INST_NODE_HAS_PROP (0 , reset_gpios )
0 commit comments