@@ -152,17 +152,114 @@ LOG_MODULE_REGISTER(video_ov2640, CONFIG_VIDEO_LOG_LEVEL);
152
152
#define REG32_UXGA 0x36
153
153
154
154
/* Configuration arrays */
155
- #define SVGA_HSIZE (800)
156
- #define SVGA_VSIZE (600)
157
-
158
- #define UXGA_HSIZE (1600)
159
- #define UXGA_VSIZE (1200)
155
+ #define SVGA_HSIZE (800UL)
156
+ #define SVGA_VSIZE (600UL)
157
+
158
+ #define UXGA_HSIZE (1600UL)
159
+ #define UXGA_VSIZE (1200UL)
160
+
161
+ #define VAL_SET (x , mask , rshift , lshift ) ((((x) >> rshift) & mask) << lshift)
162
+
163
+ #define CTRLI_V_DIV_SET (x ) VAL_SET(x, 0x3, 0, 3)
164
+ #define CTRLI_H_DIV_SET (x ) VAL_SET(x, 0x3, 0, 0)
165
+ #define ZMOW_OUTW_SET (x ) VAL_SET(x, 0xFF, 2, 0)
166
+ #define ZMOH_OUTH_SET (x ) VAL_SET(x, 0xFF, 2, 0)
167
+
168
+ #define ZMHH_ZSPEED_SET (x ) VAL_SET(x, 0x0F, 0, 4)
169
+ #define ZMHH_OUTH_SET (x ) VAL_SET(x, 0x1, (8 + 2), 2)
170
+ #define ZMHH_OUTW_SET (x ) VAL_SET(x, 0x3, (8 + 2), 0)
171
+
172
+ #define CIF_WIDTH 352
173
+ #define CIF_HEIGHT 288
174
+ #define HD_720_WIDTH 1280
175
+ #define HD_720_HEIGHT 720
176
+ #define HD_1080_WIDTH 1920
177
+ #define HD_1080_HEIGHT 1080
178
+ #define QCIF_WIDTH 176
179
+ #define QCIF_HEIGHT 144
180
+ #define QQCIF_WIDTH 88
181
+ #define QQCIF_HEIGHT 72
182
+ #define QQVGA_WIDTH 160
183
+ #define QQVGA_HEIGHT 120
184
+ #define QVGA_WIDTH 320
185
+ #define QVGA_HEIGHT 240
186
+ #define SVGA_WIDTH 800
187
+ #define SVGA_HEIGHT 600
188
+ #define SXGA_WIDTH 1280
189
+ #define SXGA_HEIGHT 1024
190
+ #define VGA_WIDTH 640
191
+ #define VGA_HEIGHT 480
192
+ #define UXGA_WIDTH 1600
193
+ #define UXGA_HEIGHT 1200
194
+ #define XGA_WIDTH 1024
195
+ #define XGA_HEIGHT 768
160
196
161
197
struct ov2640_reg {
162
198
uint8_t addr ;
163
199
uint8_t value ;
164
200
};
165
201
202
+ struct ov2640_win_size {
203
+ char * name ;
204
+ uint32_t width ;
205
+ uint32_t height ;
206
+ const struct ov2640_reg * regs ;
207
+ uint32_t regs_size ;
208
+ };
209
+
210
+ #define PER_SIZE_REG_SEQ (x , y , v_div , h_div , pclk_div ) \
211
+ {CTRLI, CTRLI_LP_DP | CTRLI_V_DIV_SET(v_div) | CTRLI_H_DIV_SET(h_div)}, \
212
+ {ZMOW, ZMOW_OUTW_SET(x)}, {ZMOH, ZMOH_OUTH_SET(y)}, \
213
+ {ZMHH, ZMHH_OUTW_SET(x) | ZMHH_OUTH_SET(y)}, {R_DVP_SP, pclk_div}, {RESET, 0x00}
214
+
215
+ static const struct ov2640_reg ov2640_qqvga_regs [] = {
216
+ PER_SIZE_REG_SEQ (QQVGA_WIDTH , QQVGA_HEIGHT , 3 , 3 , 8 ),
217
+ };
218
+ static const struct ov2640_reg ov2640_qcif_regs [] = {
219
+ PER_SIZE_REG_SEQ (QCIF_WIDTH , QCIF_HEIGHT , 3 , 3 , 4 ),
220
+ };
221
+ static const struct ov2640_reg ov2640_qvga_regs [] = {
222
+ PER_SIZE_REG_SEQ (QVGA_WIDTH , QVGA_HEIGHT , 2 , 2 , 4 ),
223
+ };
224
+ static const struct ov2640_reg ov2640_cif_regs [] = {
225
+ PER_SIZE_REG_SEQ (CIF_WIDTH , CIF_HEIGHT , 2 , 2 , 8 ),
226
+ };
227
+ static const struct ov2640_reg ov2640_vga_regs [] = {
228
+ PER_SIZE_REG_SEQ (VGA_WIDTH , VGA_HEIGHT , 0 , 0 , 2 ),
229
+ };
230
+ static const struct ov2640_reg ov2640_svga_regs [] = {
231
+ PER_SIZE_REG_SEQ (SVGA_WIDTH , SVGA_HEIGHT , 1 , 1 , 2 ),
232
+ };
233
+ static const struct ov2640_reg ov2640_xga_regs [] = {
234
+ PER_SIZE_REG_SEQ (XGA_WIDTH , XGA_HEIGHT , 0 , 0 , 2 ),
235
+ {CTRLI , 0x00 },
236
+ };
237
+ static const struct ov2640_reg ov2640_sxga_regs [] = {
238
+ PER_SIZE_REG_SEQ (SXGA_WIDTH , SXGA_HEIGHT , 0 , 0 , 2 ),
239
+ {CTRLI , 0x00 },
240
+ {R_DVP_SP , 2 | R_DVP_SP_AUTO_MODE },
241
+ };
242
+ static const struct ov2640_reg ov2640_uxga_regs [] = {
243
+ PER_SIZE_REG_SEQ (UXGA_WIDTH , UXGA_HEIGHT , 0 , 0 , 0 ),
244
+ {CTRLI , 0x00 },
245
+ {R_DVP_SP , 0 | R_DVP_SP_AUTO_MODE },
246
+ };
247
+
248
+ #define OV2640_SIZE (n , w , h , r ) \
249
+ {.name = n, .width = w, .height = h, .regs = r, .regs_size = ARRAY_SIZE(r)}
250
+
251
+ static const struct ov2640_win_size ov2640_supported_win_sizes [] = {
252
+ OV2640_SIZE ("QQVGA" , QQVGA_WIDTH , QQVGA_HEIGHT , ov2640_qqvga_regs ),
253
+ OV2640_SIZE ("QCIF" , QCIF_WIDTH , QCIF_HEIGHT , ov2640_qcif_regs ),
254
+ OV2640_SIZE ("QVGA" , QVGA_WIDTH , QVGA_HEIGHT , ov2640_qvga_regs ),
255
+ OV2640_SIZE ("CIF" , CIF_WIDTH , CIF_HEIGHT , ov2640_cif_regs ),
256
+ OV2640_SIZE ("VGA" , VGA_WIDTH , VGA_HEIGHT , ov2640_vga_regs ),
257
+ OV2640_SIZE ("SVGA" , SVGA_WIDTH , SVGA_HEIGHT , ov2640_svga_regs ),
258
+ OV2640_SIZE ("XGA" , XGA_WIDTH , XGA_HEIGHT , ov2640_xga_regs ),
259
+ OV2640_SIZE ("SXGA" , SXGA_WIDTH , SXGA_HEIGHT , ov2640_sxga_regs ),
260
+ OV2640_SIZE ("UXGA" , UXGA_WIDTH , UXGA_HEIGHT , ov2640_uxga_regs ),
261
+ };
262
+
166
263
static const struct ov2640_reg default_regs [] = {
167
264
{ BANK_SEL , BANK_SEL_DSP },
168
265
{ 0x2c , 0xff },
@@ -346,61 +443,60 @@ static const struct ov2640_reg default_regs[] = {
346
443
};
347
444
348
445
static const struct ov2640_reg uxga_regs [] = {
349
- { BANK_SEL , BANK_SEL_SENSOR },
446
+ {BANK_SEL , BANK_SEL_SENSOR },
350
447
/* DSP input image resolution and window size control */
351
- { COM7 , COM7_RES_UXGA },
352
- { COM1 , 0x0F }, /* UXGA=0x0F, SVGA=0x0A, CIF=0x06 */
353
- { REG32 , REG32_UXGA }, /* UXGA=0x36, SVGA/CIF=0x09 */
354
-
355
- { HSTART , 0x11 }, /* UXGA=0x11, SVGA/CIF=0x11 */
356
- { HSTOP , 0x75 }, /* UXGA=0x75, SVGA/CIF=0x43 */
357
-
358
- { VSTART , 0x01 }, /* UXGA=0x01, SVGA/CIF=0x00 */
359
- { VSTOP , 0x97 }, /* UXGA=0x97, SVGA/CIF=0x4b */
360
- { 0x3d , 0x34 }, /* UXGA=0x34, SVGA/CIF=0x38 */
361
-
362
- { 0x35 , 0x88 },
363
- { 0x22 , 0x0a },
364
- { 0x37 , 0x40 },
365
- { 0x34 , 0xa0 },
366
- { 0x06 , 0x02 },
367
- { 0x0d , 0xb7 },
368
- { 0x0e , 0x01 },
369
- { 0x42 , 0x83 },
448
+ {COM7 , COM7_RES_UXGA },
449
+ {COM1 , 0x0F }, /* UXGA=0x0F, SVGA=0x0A, CIF=0x06 */
450
+ {REG32 , REG32_UXGA }, /* UXGA=0x36, SVGA/CIF=0x09 */
451
+
452
+ {HSTART , 0x11 }, /* UXGA=0x11, SVGA/CIF=0x11 */
453
+ {HSTOP , 0x75 }, /* UXGA=0x75, SVGA/CIF=0x43 */
454
+
455
+ {VSTART , 0x01 }, /* UXGA=0x01, SVGA/CIF=0x00 */
456
+ {VSTOP , 0x97 }, /* UXGA=0x97, SVGA/CIF=0x4b */
457
+ {0x3d , 0x34 }, /* UXGA=0x34, SVGA/CIF=0x38 */
458
+
459
+ {0x35 , 0x88 },
460
+ {0x22 , 0x0a },
461
+ {0x37 , 0x40 },
462
+ {0x34 , 0xa0 },
463
+ {0x06 , 0x02 },
464
+ {0x0d , 0xb7 },
465
+ {0x0e , 0x01 },
466
+ {0x42 , 0x83 },
370
467
371
468
/*
372
469
* Set DSP input image size and offset.
373
470
* The sensor output image can be scaled with OUTW/OUTH
374
471
*/
375
- { BANK_SEL , BANK_SEL_DSP },
376
- { R_BYPASS , R_BYPASS_DSP_BYPAS },
472
+ {BANK_SEL , BANK_SEL_DSP },
473
+ {R_BYPASS , R_BYPASS_DSP_BYPAS },
377
474
378
- { 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] */
475
+ {RESET , RESET_DVP },
476
+ {HSIZE8 , (UXGA_HSIZE >> 3 )}, /* Image Horizontal Size HSIZE[10:3] */
477
+ {VSIZE8 , (UXGA_VSIZE >> 3 )}, /* Image Vertical Size VSIZE[10:3] */
381
478
382
479
/* {HSIZE[11], HSIZE[2:0], VSIZE[2:0]} */
383
- { SIZEL , ((UXGA_HSIZE >> 6 ) & 0x40 ) | ((UXGA_HSIZE & 0x7 )<< 3 ) | (UXGA_VSIZE & 0x7 )},
480
+ {SIZEL , ((UXGA_HSIZE >> 6 ) & 0x40 ) | ((UXGA_HSIZE & 0x7 ) << 3 ) | (UXGA_VSIZE & 0x7 )},
384
481
385
- { XOFFL , 0x00 }, /* OFFSET_X[7:0] */
386
- { 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 */
482
+ {XOFFL , 0x00 }, /* OFFSET_X[7:0] */
483
+ {YOFFL , 0x00 }, /* OFFSET_Y[7:0] */
484
+ {HSIZE , ((UXGA_HSIZE >> 2 ) & 0xFF )}, /* H_SIZE[7:0] real/4 */
485
+ {VSIZE , ((UXGA_VSIZE >> 2 ) & 0xFF )}, /* V_SIZE[7:0] real/4 */
389
486
390
487
/* 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] */
488
+ {VHYX , ((UXGA_VSIZE >> 3 ) & 0x80 ) | ((UXGA_HSIZE >> 7 ) & 0x08 )},
489
+ {TEST , (UXGA_HSIZE >> 4 ) & 0x80 }, /* H_SIZE[9] */
393
490
394
- { CTRL2 , CTRL2_DCW_EN | CTRL2_SDE_EN |
395
- CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
491
+ {CTRL2 , CTRL2_DCW_EN | CTRL2_SDE_EN | CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
396
492
397
493
/* H_DIVIDER/V_DIVIDER */
398
- { CTRLI , CTRLI_LP_DP | 0x00 },
494
+ {CTRLI , CTRLI_LP_DP | 0x00 },
399
495
/* DVP prescaler */
400
- { R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x04 },
496
+ {R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x04 },
401
497
402
- { R_BYPASS , R_BYPASS_DSP_EN },
403
- { RESET , 0x00 },
498
+ {R_BYPASS , R_BYPASS_DSP_EN },
499
+ /* { RESET, 0x00 }, */
404
500
{0 , 0 },
405
501
};
406
502
@@ -472,29 +568,23 @@ struct ov2640_data {
472
568
}
473
569
474
570
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
- };
571
+ OV2640_VIDEO_FORMAT_CAP (QQVGA_WIDTH , QQVGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* QQVGA */
572
+ OV2640_VIDEO_FORMAT_CAP (QCIF_WIDTH , QCIF_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* QCIF */
573
+ OV2640_VIDEO_FORMAT_CAP (CIF_WIDTH , CIF_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* CIF */
574
+ OV2640_VIDEO_FORMAT_CAP (VGA_WIDTH , VGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* VGA */
575
+ OV2640_VIDEO_FORMAT_CAP (SVGA_WIDTH , SVGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* SVGA */
576
+ OV2640_VIDEO_FORMAT_CAP (XGA_WIDTH , XGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* XVGA */
577
+ OV2640_VIDEO_FORMAT_CAP (SXGA_WIDTH , SXGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* SXGA */
578
+ OV2640_VIDEO_FORMAT_CAP (UXGA_WIDTH , UXGA_HEIGHT , VIDEO_PIX_FMT_RGB565 ), /* UXGA */
579
+ OV2640_VIDEO_FORMAT_CAP (QQVGA_WIDTH , QQVGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* QQVGA */
580
+ OV2640_VIDEO_FORMAT_CAP (QCIF_WIDTH , QCIF_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* QCIF */
581
+ OV2640_VIDEO_FORMAT_CAP (CIF_WIDTH , CIF_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* CIF */
582
+ OV2640_VIDEO_FORMAT_CAP (VGA_WIDTH , VGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* VGA */
583
+ OV2640_VIDEO_FORMAT_CAP (SVGA_WIDTH , SVGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* SVGA */
584
+ OV2640_VIDEO_FORMAT_CAP (XGA_WIDTH , XGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* XVGA */
585
+ OV2640_VIDEO_FORMAT_CAP (SXGA_WIDTH , SXGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* SXGA */
586
+ OV2640_VIDEO_FORMAT_CAP (UXGA_WIDTH , UXGA_HEIGHT , VIDEO_PIX_FMT_JPEG ), /* UXGA */
587
+ {0 }};
498
588
499
589
static int ov2640_write_reg (const struct i2c_dt_spec * spec , uint8_t reg_addr ,
500
590
uint8_t value )
@@ -775,6 +865,19 @@ static int ov2640_set_vertical_flip(const struct device *dev, int enable)
775
865
return ret ;
776
866
}
777
867
868
+ static const struct ov2640_win_size * ov2640_select_win (uint32_t width , uint32_t height )
869
+ {
870
+ int i , default_size = ARRAY_SIZE (ov2640_supported_win_sizes ) - 1 ;
871
+
872
+ for (i = 0 ; i < ARRAY_SIZE (ov2640_supported_win_sizes ); i ++ ) {
873
+ if (ov2640_supported_win_sizes [i ].width >= width &&
874
+ ov2640_supported_win_sizes [i ].height >= height ) {
875
+ return & ov2640_supported_win_sizes [i ];
876
+ }
877
+ }
878
+ return & ov2640_supported_win_sizes [default_size ];
879
+ }
880
+
778
881
static int ov2640_set_resolution (const struct device * dev ,
779
882
uint16_t img_width , uint16_t img_height )
780
883
{
@@ -784,23 +887,23 @@ static int ov2640_set_resolution(const struct device *dev,
784
887
uint16_t w = img_width ;
785
888
uint16_t h = img_height ;
786
889
890
+ const struct ov2640_win_size * win = ov2640_select_win (w , h );
891
+
892
+ LOG_INF ("Selected resolution %s" , win -> name );
893
+
894
+ /* Write DSP input registers */
895
+ ret |= ov2640_write_all (dev , uxga_regs , ARRAY_SIZE (uxga_regs ));
896
+
787
897
/* Disable DSP */
788
898
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_DSP );
789
899
ret |= ov2640_write_reg (& cfg -> i2c , R_BYPASS , R_BYPASS_DSP_BYPAS );
790
900
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] */
901
+ ret |= ov2640_write_all (dev , win -> regs , win -> regs_size );
796
902
797
903
/* Set CLKRC */
798
904
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_SENSOR );
799
905
ret |= ov2640_write_reg (& cfg -> i2c , CLKRC , cfg -> clock_rate_control );
800
906
801
- /* Write DSP input registers */
802
- ov2640_write_all (dev , uxga_regs , ARRAY_SIZE (uxga_regs ));
803
-
804
907
/* Enable DSP */
805
908
ret |= ov2640_write_reg (& cfg -> i2c , BANK_SEL , BANK_SEL_DSP );
806
909
ret |= ov2640_write_reg (& cfg -> i2c , R_BYPASS , R_BYPASS_DSP_EN );
0 commit comments