Skip to content

Commit 4a441e4

Browse files
committed
drivers: video: ov7670 driver changes in prep for adding OV7675
drivers: video: ov7670 driver changes in prep for adding OV7675 Updates ov7670.c in prep for incorporation of OV7675. See previous PR. Signed-off-by: Michael Smorto <[email protected]>
1 parent 0e3cd5b commit 4a441e4

File tree

1 file changed

+113
-164
lines changed

1 file changed

+113
-164
lines changed

drivers/video/ov7670.c

Lines changed: 113 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,22 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
#define DT_DRV_COMPAT ovti_ov7670
8-
97
#include <zephyr/drivers/gpio.h>
108
#include <zephyr/drivers/i2c.h>
119
#include <zephyr/drivers/video.h>
1210
#include <zephyr/drivers/video-controls.h>
1311
#include <zephyr/logging/log.h>
1412

13+
#include "video_common.h"
1514
#include "video_ctrls.h"
1615
#include "video_device.h"
1716

1817
LOG_MODULE_REGISTER(video_ov7670, CONFIG_VIDEO_LOG_LEVEL);
1918

20-
/* Initialization register structure */
21-
struct ov7670_reg {
22-
uint8_t reg;
23-
uint8_t cmd;
24-
};
25-
2619
struct ov7670_config {
2720
struct i2c_dt_spec bus;
28-
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios)
29-
struct gpio_dt_spec reset;
30-
#endif
31-
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(pwdn_gpios)
32-
struct gpio_dt_spec pwdn;
33-
#endif
21+
const struct gpio_dt_spec reset;
22+
const struct gpio_dt_spec pwdn;
3423
};
3524

3625
struct ov7670_ctrls {
@@ -43,63 +32,7 @@ struct ov7670_data {
4332
struct video_format fmt;
4433
};
4534

46-
struct ov7670_resolution_cfg {
47-
uint8_t com7;
48-
uint8_t com3;
49-
uint8_t com14;
50-
uint8_t scaling_xsc;
51-
uint8_t scaling_ysc;
52-
uint8_t dcwctr;
53-
uint8_t pclk_div;
54-
uint8_t pclk_delay;
55-
};
56-
57-
/* Resolution settings for camera, based on those present in MCUX SDK */
58-
const struct ov7670_resolution_cfg OV7670_RESOLUTION_QCIF = {
59-
.com7 = 0x2c,
60-
.com3 = 0x00,
61-
.com14 = 0x11,
62-
.scaling_xsc = 0x3a,
63-
.scaling_ysc = 0x35,
64-
.dcwctr = 0x11,
65-
.pclk_div = 0xf1,
66-
.pclk_delay = 0x52
67-
};
68-
69-
const struct ov7670_resolution_cfg OV7670_RESOLUTION_QVGA = {
70-
.com7 = 0x14,
71-
.com3 = 0x04,
72-
.com14 = 0x19,
73-
.scaling_xsc = 0x3a,
74-
.scaling_ysc = 0x35,
75-
.dcwctr = 0x11,
76-
.pclk_div = 0xf1,
77-
.pclk_delay = 0x02
78-
};
79-
80-
const struct ov7670_resolution_cfg OV7670_RESOLUTION_CIF = {
81-
.com7 = 0x24,
82-
.com3 = 0x08,
83-
.com14 = 0x11,
84-
.scaling_xsc = 0x3a,
85-
.scaling_ysc = 0x35,
86-
.dcwctr = 0x11,
87-
.pclk_div = 0xf1,
88-
.pclk_delay = 0x02
89-
};
90-
91-
const struct ov7670_resolution_cfg OV7670_RESOLUTION_VGA = {
92-
.com7 = 0x04,
93-
.com3 = 0x00,
94-
.com14 = 0x00,
95-
.scaling_xsc = 0x3a,
96-
.scaling_ysc = 0x35,
97-
.dcwctr = 0x11,
98-
.pclk_div = 0xf0,
99-
.pclk_delay = 0x02
100-
};
101-
102-
35+
#define OV7670_REG8(addr) ((addr) | VIDEO_REG_ADDR8_DATA8)
10336
/* OV7670 registers */
10437
#define OV7670_PID 0x0A
10538
#define OV7670_COM7 0x12
@@ -190,37 +123,26 @@ const struct ov7670_resolution_cfg OV7670_RESOLUTION_VGA = {
190123
#define OV7670_HAECC6 0xA9
191124

192125
/* OV7670 definitions */
193-
#define OV7670_PROD_ID 0x76
126+
#define OV7670_PROD_ID 0x76
194127
#define OV7670_MVFP_HFLIP 0x20
195128
#define OV7670_MVFP_VFLIP 0x10
196129

197-
#define OV7670_VIDEO_FORMAT_CAP(width, height, format) \
130+
#define OV767X_VIDEO_FORMAT_CAP(width, height, format) \
198131
{ \
199132
.pixelformat = (format), .width_min = (width), .width_max = (width), \
200133
.height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \
201134
}
202135

203-
static const struct video_format_cap fmts[] = {
204-
OV7670_VIDEO_FORMAT_CAP(176, 144, VIDEO_PIX_FMT_RGB565), /* QCIF */
205-
OV7670_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_RGB565), /* QVGA */
206-
OV7670_VIDEO_FORMAT_CAP(352, 288, VIDEO_PIX_FMT_RGB565), /* CIF */
207-
OV7670_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_RGB565), /* VGA */
208-
OV7670_VIDEO_FORMAT_CAP(176, 144, VIDEO_PIX_FMT_YUYV), /* QCIF */
209-
OV7670_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_YUYV), /* QVGA */
210-
OV7670_VIDEO_FORMAT_CAP(352, 288, VIDEO_PIX_FMT_YUYV), /* CIF */
211-
OV7670_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_YUYV), /* VGA */
212-
{0}};
213-
214136
/*
215137
* This initialization table is based on the MCUX SDK driver for the OV7670.
216138
* Note that this table assumes the camera is fed a 6MHz XCLK signal
217139
*/
218-
static const struct ov7670_reg ov7670_init_regtbl[] = {
140+
static const struct video_reg8 ov7670_init_regtbl[] = {
219141
{OV7670_MVFP, 0x00}, /* MVFP: Mirror/VFlip,Normal image */
220142

221143
/* configure the output timing */
222144
/* PCLK does not toggle during horizontal blank, one PCLK, one pixel */
223-
{OV7670_COM10, 0x20}, /* COM10 */
145+
{OV7670_COM10, 0x03}, /* COM10 */
224146
{OV7670_COM12, 0x00}, /* COM12,No HREF when VSYNC is low */
225147
/* Brightness Control, with signal -128 to +128, 0x00 is middle value */
226148
{OV7670_BRIGHT, 0x2f},
@@ -369,8 +291,67 @@ static const struct ov7670_reg ov7670_init_regtbl[] = {
369291
{0xb8, 0x0a},
370292
};
371293

294+
#if DT_HAS_COMPAT_STATUS_OKAY(ovti_ov7670)
295+
/* Resolution settings for camera, based on those present in MCUX SDK */
296+
static const struct video_reg8 ov7670_regs_qcif[] = {
297+
{OV7670_COM7, 0x2c},
298+
{OV7670_COM3, 0x00},
299+
{OV7670_COM14, 0x11},
300+
{OV7670_SCALING_XSC, 0x3a},
301+
{OV7670_SCALING_YSC, 0x35},
302+
{OV7670_SCALING_DCWCTR, 0x11},
303+
{OV7670_SCALING_PCLK_DIV, 0xf1},
304+
{OV7670_SCALING_PCLK_DELAY, 0x52},
305+
};
306+
307+
static const struct video_reg8 ov7670_regs_qvga[] = {
308+
{OV7670_COM7, 0x14},
309+
{OV7670_COM3, 0x04},
310+
{OV7670_COM14, 0x19},
311+
{OV7670_SCALING_XSC, 0x3a},
312+
{OV7670_SCALING_YSC, 0x35},
313+
{OV7670_SCALING_DCWCTR, 0x11},
314+
{OV7670_SCALING_PCLK_DIV, 0xf1},
315+
{OV7670_SCALING_PCLK_DELAY, 0x02},
316+
};
317+
318+
static const struct video_reg8 ov7670_regs_cif[] = {
319+
{OV7670_COM7, 0x24},
320+
{OV7670_COM3, 0x08},
321+
{OV7670_COM14, 0x11},
322+
{OV7670_SCALING_XSC, 0x3a},
323+
{OV7670_SCALING_YSC, 0x35},
324+
{OV7670_SCALING_DCWCTR, 0x11},
325+
{OV7670_SCALING_PCLK_DIV, 0xf1},
326+
{OV7670_SCALING_PCLK_DELAY, 0x02},
327+
};
328+
329+
static const struct video_reg8 ov7670_regs_vga[] = {
330+
{OV7670_COM7, 0x04},
331+
{OV7670_COM3, 0x00},
332+
{OV7670_COM14, 0x00},
333+
{OV7670_SCALING_XSC, 0x3a},
334+
{OV7670_SCALING_YSC, 0x35},
335+
{OV7670_SCALING_DCWCTR, 0x11},
336+
{OV7670_SCALING_PCLK_DIV, 0xf0},
337+
{OV7670_SCALING_PCLK_DELAY, 0x02},
338+
};
339+
340+
static const struct video_format_cap fmts[] = {
341+
OV767X_VIDEO_FORMAT_CAP(176, 144, VIDEO_PIX_FMT_RGB565), /* QCIF */
342+
OV767X_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_RGB565), /* QVGA */
343+
OV767X_VIDEO_FORMAT_CAP(352, 288, VIDEO_PIX_FMT_RGB565), /* CIF */
344+
OV767X_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_RGB565), /* VGA */
345+
OV767X_VIDEO_FORMAT_CAP(176, 144, VIDEO_PIX_FMT_YUYV), /* QCIF */
346+
OV767X_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_YUYV), /* QVGA */
347+
OV767X_VIDEO_FORMAT_CAP(352, 288, VIDEO_PIX_FMT_YUYV), /* CIF */
348+
OV767X_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_YUYV), /* VGA */
349+
{0}};
350+
#endif
351+
372352
static int ov7670_get_caps(const struct device *dev, struct video_caps *caps)
373353
{
354+
374355
caps->format_caps = fmts;
375356
return 0;
376357
}
@@ -379,7 +360,6 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
379360
{
380361
const struct ov7670_config *config = dev->config;
381362
struct ov7670_data *data = dev->data;
382-
const struct ov7670_resolution_cfg *resolution;
383363
int ret;
384364
uint8_t i = 0U;
385365

@@ -397,67 +377,38 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
397377

398378
/* Set output resolution */
399379
while (fmts[i].pixelformat) {
400-
if (fmts[i].width_min == fmt->width && fmts[i].height_min == fmt->height &&
380+
if (fmts[i].width_min == fmt->width &&
381+
fmts[i].height_min == fmt->height &&
401382
fmts[i].pixelformat == fmt->pixelformat) {
402383
/* Set output format */
403384
switch (fmts[i].width_min) {
404385
case 176: /* QCIF */
405-
resolution = &OV7670_RESOLUTION_QCIF;
406-
break;
407-
case 320: /* QVGA */
408-
resolution = &OV7670_RESOLUTION_QVGA;
386+
ret = video_write_cci_multiregs8(&config->bus, ov7670_regs_qcif,
387+
ARRAY_SIZE(ov7670_regs_qcif));
409388
break;
410389
case 352: /* CIF */
411-
resolution = &OV7670_RESOLUTION_CIF;
390+
ret = video_write_cci_multiregs8(&config->bus, ov7670_regs_cif,
391+
ARRAY_SIZE(ov7670_regs_cif));
412392
break;
393+
case 320: /* QVGA */
394+
ret = video_write_cci_multiregs8(&config->bus, ov7670_regs_qvga,
395+
ARRAY_SIZE(ov7670_regs_qvga));
396+
break;
397+
413398
default: /* VGA */
414-
resolution = &OV7670_RESOLUTION_VGA;
399+
ret = video_write_cci_multiregs8(&config->bus, ov7670_regs_vga,
400+
ARRAY_SIZE(ov7670_regs_vga));
415401
break;
416402
}
417-
/* Program resolution bytes settings */
418-
ret = i2c_reg_write_byte_dt(&config->bus, OV7670_COM7,
419-
resolution->com7);
420403
if (ret < 0) {
404+
LOG_ERR("Resolution not set or not supported!");
421405
return ret;
422406
}
423-
ret = i2c_reg_write_byte_dt(&config->bus, OV7670_COM3,
424-
resolution->com3);
425-
if (ret < 0) {
426-
return ret;
427-
}
428-
ret = i2c_reg_write_byte_dt(&config->bus, OV7670_COM14,
429-
resolution->com14);
430-
if (ret < 0) {
431-
return ret;
432-
}
433-
ret = i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_XSC,
434-
resolution->scaling_xsc);
435-
if (ret < 0) {
436-
return ret;
437-
}
438-
ret = i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_YSC,
439-
resolution->scaling_ysc);
440-
if (ret < 0) {
441-
return ret;
442-
}
443-
ret = i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_DCWCTR,
444-
resolution->dcwctr);
445-
if (ret < 0) {
446-
return ret;
447-
}
448-
ret = i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_PCLK_DIV,
449-
resolution->pclk_div);
450-
if (ret < 0) {
451-
return ret;
452-
}
453-
return i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_PCLK_DELAY,
454-
resolution->pclk_delay);
455407
}
456408
i++;
457409
}
458410

459-
LOG_ERR("Unsupported format");
460-
return -ENOTSUP;
411+
return 0;
461412
}
462413

463414
static int ov7670_get_fmt(const struct device *dev, struct video_format *fmt)
@@ -487,14 +438,13 @@ static int ov7670_init_controls(const struct device *dev)
487438
static int ov7670_init(const struct device *dev)
488439
{
489440
const struct ov7670_config *config = dev->config;
490-
int ret, i;
441+
int ret;
491442
uint8_t pid;
492443
struct video_format fmt = {
493444
.pixelformat = VIDEO_PIX_FMT_RGB565,
494445
.width = 320,
495446
.height = 240,
496447
};
497-
const struct ov7670_reg *reg;
498448

499449
if (!i2c_is_ready_dt(&config->bus)) {
500450
/* I2C device is not ready, return */
@@ -559,7 +509,7 @@ static int ov7670_init(const struct device *dev)
559509
}
560510

561511
/* Reset camera registers */
562-
ret = i2c_reg_write_byte_dt(&config->bus, OV7670_COM7, 0x80);
512+
ret = video_write_cci_reg(&config->bus, OV7670_REG8(OV7670_COM7), 0x80);
563513
if (ret < 0) {
564514
LOG_ERR("Could not reset camera: %d", ret);
565515
return ret;
@@ -573,12 +523,10 @@ static int ov7670_init(const struct device *dev)
573523
}
574524

575525
/* Write initialization values to OV7670 */
576-
for (i = 0; i < ARRAY_SIZE(ov7670_init_regtbl); i++) {
577-
reg = &ov7670_init_regtbl[i];
578-
ret = i2c_reg_write_byte_dt(&config->bus, reg->reg, reg->cmd);
579-
if (ret < 0) {
580-
return ret;
581-
}
526+
ret = video_write_cci_multiregs8(&config->bus, ov7670_init_regtbl,
527+
ARRAY_SIZE(ov7670_init_regtbl));
528+
if (ret < 0) {
529+
return ret;
582530
}
583531

584532
/* Initialize controls */
@@ -616,27 +564,28 @@ static DEVICE_API(video, ov7670_api) = {
616564
.set_ctrl = ov7670_set_ctrl,
617565
};
618566

619-
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios)
620-
#define OV7670_RESET_GPIO(inst) .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}),
621-
#else
622-
#define OV7670_RESET_GPIO(inst)
623-
#endif
624-
625-
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(pwdn_gpios)
626-
#define OV7670_PWDN_GPIO(inst) .pwdn = GPIO_DT_SPEC_INST_GET_OR(inst, pwdn_gpios, {}),
627-
#else
628-
#define OV7670_PWDN_GPIO(inst)
629-
#endif
630-
631-
#define OV7670_INIT(inst) \
632-
const struct ov7670_config ov7670_config_##inst = {.bus = I2C_DT_SPEC_INST_GET(inst), \
633-
OV7670_RESET_GPIO(inst) \
634-
OV7670_PWDN_GPIO(inst)}; \
635-
struct ov7670_data ov7670_data_##inst; \
636-
\
637-
DEVICE_DT_INST_DEFINE(inst, ov7670_init, NULL, &ov7670_data_##inst, &ov7670_config_##inst, \
638-
POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &ov7670_api); \
639-
\
640-
VIDEO_DEVICE_DEFINE(ov7670_##inst, DEVICE_DT_INST_GET(inst), NULL);
641-
642-
DT_INST_FOREACH_STATUS_OKAY(OV7670_INIT)
567+
#define OV7670_INIT(n, id) \
568+
static const struct ov7670_config ov7670_config_##n = { \
569+
.bus = I2C_DT_SPEC_INST_GET(n), \
570+
.reset = \
571+
GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {}), \
572+
.pwdn = \
573+
GPIO_DT_SPEC_INST_GET_OR(n, pwdn_gpios, {}), \
574+
}; \
575+
\
576+
static struct ov7670_data ov7670_data_##n; \
577+
\
578+
DEVICE_DT_INST_DEFINE(n, \
579+
ov7670_init, \
580+
NULL, \
581+
&ov7670##_data_##n, \
582+
&ov7670##_config_##n, \
583+
POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
584+
&ov7670_api); \
585+
\
586+
VIDEO_DEVICE_DEFINE(ov7670_##n, DEVICE_DT_INST_GET(n), NULL); \
587+
588+
589+
#undef DT_DRV_COMPAT
590+
#define DT_DRV_COMPAT ovti_ov7670
591+
DT_INST_FOREACH_STATUS_OKAY_VARGS(OV7670_INIT, 7670)

0 commit comments

Comments
 (0)