From 518132acec2372353c87203a48ef466c2f72071c Mon Sep 17 00:00:00 2001 From: Mike S Date: Sat, 20 Sep 2025 10:04:29 -0400 Subject: [PATCH] drivers: video: ov7670 driver changes in prep for adding OV7675 drivers: video: Restructure OV760.c driver before adding OV7675 support Modifications for use of video cci helpers in video_common.h. Signed-off-by: Mike S --- drivers/video/ov7670.c | 218 +++++++++++++++++------------------------ 1 file changed, 90 insertions(+), 128 deletions(-) diff --git a/drivers/video/ov7670.c b/drivers/video/ov7670.c index 448b0e659bcf3..13688de840f57 100644 --- a/drivers/video/ov7670.c +++ b/drivers/video/ov7670.c @@ -12,17 +12,12 @@ #include #include +#include "video_common.h" #include "video_ctrls.h" #include "video_device.h" LOG_MODULE_REGISTER(video_ov7670, CONFIG_VIDEO_LOG_LEVEL); -/* Initialization register structure */ -struct ov7670_reg { - uint8_t reg; - uint8_t cmd; -}; - struct ov7670_config { struct i2c_dt_spec bus; #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) @@ -43,63 +38,7 @@ struct ov7670_data { struct video_format fmt; }; -struct ov7670_resolution_cfg { - uint8_t com7; - uint8_t com3; - uint8_t com14; - uint8_t scaling_xsc; - uint8_t scaling_ysc; - uint8_t dcwctr; - uint8_t pclk_div; - uint8_t pclk_delay; -}; - -/* Resolution settings for camera, based on those present in MCUX SDK */ -const struct ov7670_resolution_cfg OV7670_RESOLUTION_QCIF = { - .com7 = 0x2c, - .com3 = 0x00, - .com14 = 0x11, - .scaling_xsc = 0x3a, - .scaling_ysc = 0x35, - .dcwctr = 0x11, - .pclk_div = 0xf1, - .pclk_delay = 0x52 -}; - -const struct ov7670_resolution_cfg OV7670_RESOLUTION_QVGA = { - .com7 = 0x14, - .com3 = 0x04, - .com14 = 0x19, - .scaling_xsc = 0x3a, - .scaling_ysc = 0x35, - .dcwctr = 0x11, - .pclk_div = 0xf1, - .pclk_delay = 0x02 -}; - -const struct ov7670_resolution_cfg OV7670_RESOLUTION_CIF = { - .com7 = 0x24, - .com3 = 0x08, - .com14 = 0x11, - .scaling_xsc = 0x3a, - .scaling_ysc = 0x35, - .dcwctr = 0x11, - .pclk_div = 0xf1, - .pclk_delay = 0x02 -}; - -const struct ov7670_resolution_cfg OV7670_RESOLUTION_VGA = { - .com7 = 0x04, - .com3 = 0x00, - .com14 = 0x00, - .scaling_xsc = 0x3a, - .scaling_ysc = 0x35, - .dcwctr = 0x11, - .pclk_div = 0xf0, - .pclk_delay = 0x02 -}; - - +#define OV7670_REG8(addr) ((addr) | VIDEO_REG_ADDR8_DATA8) /* OV7670 registers */ #define OV7670_PID 0x0A #define OV7670_COM7 0x12 @@ -209,13 +148,14 @@ static const struct video_format_cap fmts[] = { OV7670_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_YUYV), /* QVGA */ OV7670_VIDEO_FORMAT_CAP(352, 288, VIDEO_PIX_FMT_YUYV), /* CIF */ OV7670_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_YUYV), /* VGA */ - {0}}; + {0} +}; /* * This initialization table is based on the MCUX SDK driver for the OV7670. * Note that this table assumes the camera is fed a 6MHz XCLK signal */ -static const struct ov7670_reg ov7670_init_regtbl[] = { +static const struct video_reg8 ov7670_init_regtbl[] = { {OV7670_MVFP, 0x00}, /* MVFP: Mirror/VFlip,Normal image */ /* configure the output timing */ @@ -369,6 +309,51 @@ static const struct ov7670_reg ov7670_init_regtbl[] = { {0xb8, 0x0a}, }; +/* Resolution settings for camera, based on those present in MCUX SDK */ +static const struct video_reg8 ov7670_regs_qcif[] = { + {OV7670_COM7, 0x2c}, + {OV7670_COM3, 0x00}, + {OV7670_COM14, 0x11}, + {OV7670_SCALING_XSC, 0x3a}, + {OV7670_SCALING_YSC, 0x35}, + {OV7670_SCALING_DCWCTR, 0x11}, + {OV7670_SCALING_PCLK_DIV, 0xf1}, + {OV7670_SCALING_PCLK_DELAY, 0x52}, +}; + +static const struct video_reg8 ov7670_regs_qvga[] = { + {OV7670_COM7, 0x14}, + {OV7670_COM3, 0x04}, + {OV7670_COM14, 0x19}, + {OV7670_SCALING_XSC, 0x3a}, + {OV7670_SCALING_YSC, 0x35}, + {OV7670_SCALING_DCWCTR, 0x11}, + {OV7670_SCALING_PCLK_DIV, 0xf1}, + {OV7670_SCALING_PCLK_DELAY, 0x02}, +}; + +static const struct video_reg8 ov7670_regs_cif[] = { + {OV7670_COM7, 0x24}, + {OV7670_COM3, 0x08}, + {OV7670_COM14, 0x11}, + {OV7670_SCALING_XSC, 0x3a}, + {OV7670_SCALING_YSC, 0x35}, + {OV7670_SCALING_DCWCTR, 0x11}, + {OV7670_SCALING_PCLK_DIV, 0xf1}, + {OV7670_SCALING_PCLK_DELAY, 0x02}, +}; + +static const struct video_reg8 ov7670_regs_vga[] = { + {OV7670_COM7, 0x04}, + {OV7670_COM3, 0x00}, + {OV7670_COM14, 0x00}, + {OV7670_SCALING_XSC, 0x3a}, + {OV7670_SCALING_YSC, 0x35}, + {OV7670_SCALING_DCWCTR, 0x11}, + {OV7670_SCALING_PCLK_DIV, 0xf0}, + {OV7670_SCALING_PCLK_DELAY, 0x02}, +}; + static int ov7670_get_caps(const struct device *dev, struct video_caps *caps) { caps->format_caps = fmts; @@ -379,8 +364,7 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt) { const struct ov7670_config *config = dev->config; struct ov7670_data *data = dev->data; - const struct ov7670_resolution_cfg *resolution; - int ret; + int ret = -ENOTSUP; uint8_t i = 0U; if (fmt->pixelformat != VIDEO_PIX_FMT_RGB565 && fmt->pixelformat != VIDEO_PIX_FMT_YUYV) { @@ -397,67 +381,46 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt) /* Set output resolution */ while (fmts[i].pixelformat) { - if (fmts[i].width_min == fmt->width && fmts[i].height_min == fmt->height && - fmts[i].pixelformat == fmt->pixelformat) { + if (fmts[i].width_min == fmt->width && + fmts[i].height_min == fmt->height && + fmts[i].pixelformat == fmt->pixelformat){ /* Set output format */ switch (fmts[i].width_min) { case 176: /* QCIF */ - resolution = &OV7670_RESOLUTION_QCIF; + ret = video_write_cci_multiregs8(&config->bus, ov7670_regs_qcif, + ARRAY_SIZE(ov7670_regs_qcif)); + break; + case 352: /* QCIF */ + ret = video_write_cci_multiregs8(&config->bus, ov7670_regs_cif, + ARRAY_SIZE(ov7670_regs_cif)); break; case 320: /* QVGA */ - resolution = &OV7670_RESOLUTION_QVGA; + ret = video_write_cci_multiregs8(&config->bus, ov7670_regs_qvga, + ARRAY_SIZE(ov7670_regs_qvga)); break; - case 352: /* CIF */ - resolution = &OV7670_RESOLUTION_CIF; + case 640: /* VGA */ + ret = video_write_cci_multiregs8(&config->bus, ov7670_regs_vga, + ARRAY_SIZE(ov7670_regs_vga)); break; - default: /* VGA */ - resolution = &OV7670_RESOLUTION_VGA; + default: /* QVGA */ + ret = video_write_cci_multiregs8(&config->bus, ov7670_regs_qvga, + ARRAY_SIZE(ov7670_regs_vga)); break; } - /* Program resolution bytes settings */ - ret = i2c_reg_write_byte_dt(&config->bus, OV7670_COM7, - resolution->com7); - if (ret < 0) { - return ret; - } - ret = i2c_reg_write_byte_dt(&config->bus, OV7670_COM3, - resolution->com3); - if (ret < 0) { - return ret; - } - ret = i2c_reg_write_byte_dt(&config->bus, OV7670_COM14, - resolution->com14); - if (ret < 0) { - return ret; - } - ret = i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_XSC, - resolution->scaling_xsc); - if (ret < 0) { - return ret; - } - ret = i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_YSC, - resolution->scaling_ysc); if (ret < 0) { + LOG_ERR("Resolution not set!"); return ret; } - ret = i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_DCWCTR, - resolution->dcwctr); - if (ret < 0) { - return ret; - } - ret = i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_PCLK_DIV, - resolution->pclk_div); - if (ret < 0) { - return ret; - } - return i2c_reg_write_byte_dt(&config->bus, OV7670_SCALING_PCLK_DELAY, - resolution->pclk_delay); } i++; } - LOG_ERR("Unsupported format"); - return -ENOTSUP; + if (ret < 0) { + LOG_ERR("Resolution not supported!"); + return ret; + } + + return 0; } static int ov7670_get_fmt(const struct device *dev, struct video_format *fmt) @@ -487,14 +450,13 @@ static int ov7670_init_controls(const struct device *dev) static int ov7670_init(const struct device *dev) { const struct ov7670_config *config = dev->config; - int ret, i; + int ret; uint8_t pid; struct video_format fmt = { .pixelformat = VIDEO_PIX_FMT_RGB565, .width = 320, .height = 240, }; - const struct ov7670_reg *reg; if (!i2c_is_ready_dt(&config->bus)) { /* I2C device is not ready, return */ @@ -559,7 +521,7 @@ static int ov7670_init(const struct device *dev) } /* Reset camera registers */ - ret = i2c_reg_write_byte_dt(&config->bus, OV7670_COM7, 0x80); + ret = video_write_cci_reg(&config->bus, OV7670_REG8(OV7670_COM7), 0x80); if (ret < 0) { LOG_ERR("Could not reset camera: %d", ret); return ret; @@ -573,12 +535,10 @@ static int ov7670_init(const struct device *dev) } /* Write initialization values to OV7670 */ - for (i = 0; i < ARRAY_SIZE(ov7670_init_regtbl); i++) { - reg = &ov7670_init_regtbl[i]; - ret = i2c_reg_write_byte_dt(&config->bus, reg->reg, reg->cmd); - if (ret < 0) { - return ret; - } + ret = video_write_cci_multiregs8(&config->bus, ov7670_init_regtbl, + ARRAY_SIZE(ov7670_init_regtbl)); + if (ret < 0) { + return ret; } /* Initialize controls */ @@ -628,15 +588,17 @@ static DEVICE_API(video, ov7670_api) = { #define OV7670_PWDN_GPIO(inst) #endif -#define OV7670_INIT(inst) \ - const struct ov7670_config ov7670_config_##inst = {.bus = I2C_DT_SPEC_INST_GET(inst), \ - OV7670_RESET_GPIO(inst) \ - OV7670_PWDN_GPIO(inst)}; \ - struct ov7670_data ov7670_data_##inst; \ - \ +#define OV7670_INIT(inst) \ + const struct ov7670_config ov7670_config_##inst = { \ + .bus = I2C_DT_SPEC_INST_GET(inst), \ + OV7670_RESET_GPIO(inst) \ + OV7670_PWDN_GPIO(inst)}; \ + \ + struct ov7670_data ov7670_data_##inst; \ + \ DEVICE_DT_INST_DEFINE(inst, ov7670_init, NULL, &ov7670_data_##inst, &ov7670_config_##inst, \ POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &ov7670_api); \ - \ + \ VIDEO_DEVICE_DEFINE(ov7670_##inst, DEVICE_DT_INST_GET(inst), NULL); DT_INST_FOREACH_STATUS_OKAY(OV7670_INIT)