1 /*
2 * Copyright (c) 2020, FrankLi Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ovti_ov7725
8 #include <zephyr.h>
9 #include <device.h>
10
11 #include <sys/byteorder.h>
12
13 #include <drivers/video.h>
14 #include <drivers/i2c.h>
15 #include <drivers/gpio.h>
16
17 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
18 #include <logging/log.h>
19 LOG_MODULE_REGISTER(ov7725);
20
21 #define OV7725_REVISION 0x7721U
22
23 #define OV7725_GAIN 0x00U
24 #define OV7725_BLUE 0x01U
25 #define OV7725_RED 0x02U
26 #define OV7725_GREEN 0x03U
27 #define OV7725_BAVG 0x05U
28 #define OV7725_GAVG 0x06U
29 #define OV7725_RAVG 0x07U
30 #define OV7725_AECH 0x08U
31 #define OV7725_COM2 0x09U
32 #define OV7725_PID 0x0AU
33 #define OV7725_VER 0x0BU
34 #define OV7725_COM3 0x0CU
35 #define OV7725_COM4 0x0DU
36 #define OV7725_COM5 0x0EU
37 #define OV7725_COM6 0x0FU
38 #define OV7725_AEC 0x10U
39 #define OV7725_CLKRC 0x11U
40 #define OV7725_COM7 0x12U
41 #define OV7725_COM8 0x13U
42 #define OV7725_COM9 0x14U
43 #define OV7725_COM10 0x15U
44 #define OV7725_REG16 0x16U
45 #define OV7725_HSTART 0x17U
46 #define OV7725_HSIZE 0x18U
47 #define OV7725_VSTART 0x19U
48 #define OV7725_VSIZE 0x1AU
49 #define OV7725_PSHFT 0x1BU
50 #define OV7725_MIDH 0x1CU
51 #define OV7725_MIDL 0x1DU
52 #define OV7725_LAEC 0x1FU
53 #define OV7725_COM11 0x20U
54 #define OV7725_BDBASE 0x22U
55 #define OV7725_BDMSTEP 0x23U
56 #define OV7725_AEW 0x24U
57 #define OV7725_AEB 0x25U
58 #define OV7725_VPT 0x26U
59 #define OV7725_REG28 0x28U
60 #define OV7725_HOUTSIZE 0x29U
61 #define OV7725_EXHCH 0x2AU
62 #define OV7725_EXHCL 0x2BU
63 #define OV7725_VOUTSIZE 0x2CU
64 #define OV7725_ADVFL 0x2DU
65 #define OV7725_ADVFH 0x2EU
66 #define OV7725_YAVE 0x2FU
67 #define OV7725_LUMHTH 0x30U
68 #define OV7725_LUMLTH 0x31U
69 #define OV7725_HREF 0x32U
70 #define OV7725_DM_LNL 0x33U
71 #define OV7725_DM_LNH 0x34U
72 #define OV7725_ADOFF_B 0x35U
73 #define OV7725_ADOFF_R 0x36U
74 #define OV7725_ADOFF_GB 0x37U
75 #define OV7725_ADOFF_GR 0x38U
76 #define OV7725_OFF_B 0x39U
77 #define OV7725_OFF_R 0x3AU
78 #define OV7725_OFF_GB 0x3BU
79 #define OV7725_OFF_GR 0x3CU
80 #define OV7725_COM12 0x3DU
81 #define OV7725_COM13 0x3EU
82 #define OV7725_COM14 0x3FU
83 #define OV7725_COM16 0x41U
84 #define OV7725_TGT_B 0x42U
85 #define OV7725_TGT_R 0x43U
86 #define OV7725_TGT_GB 0x44U
87 #define OV7725_TGT_GR 0x45U
88 #define OV7725_LC_CTR 0x46U
89 #define OV7725_LC_XC 0x47U
90 #define OV7725_LC_YC 0x48U
91 #define OV7725_LC_COEF 0x49U
92 #define OV7725_LC_RADI 0x4AU
93 #define OV7725_LC_COEFB 0x4BU
94 #define OV7725_LC_COEFR 0x4CU
95 #define OV7725_FIXGAIN 0x4DU
96 #define OV7725_AREF1 0x4FU
97 #define OV7725_AREF6 0x54U
98 #define OV7725_UFIX 0x60U
99 #define OV7725_VFIX 0x61U
100 #define OV7725_AWBB_BLK 0x62U
101 #define OV7725_AWB_CTRL0 0x63U
102 #define OV7725_DSP_CTRL1 0x64U
103 #define OV7725_DSP_CTRL2 0x65U
104 #define OV7725_DSP_CTRL3 0x66U
105 #define OV7725_DSP_CTRL4 0x67U
106 #define OV7725_AWB_BIAS 0x68U
107 #define OV7725_AWB_CTRL1 0x69U
108 #define OV7725_AWB_CTRL2 0x6AU
109 #define OV7725_AWB_CTRL3 0x6BU
110 #define OV7725_AWB_CTRL4 0x6CU
111 #define OV7725_AWB_CTRL5 0x6DU
112 #define OV7725_AWB_CTRL6 0x6EU
113 #define OV7725_AWB_CTRL7 0x6FU
114 #define OV7725_AWB_CTRL8 0x70U
115 #define OV7725_AWB_CTRL9 0x71U
116 #define OV7725_AWB_CTRL10 0x72U
117 #define OV7725_AWB_CTRL11 0x73U
118 #define OV7725_AWB_CTRL12 0x74U
119 #define OV7725_AWB_CTRL13 0x75U
120 #define OV7725_AWB_CTRL14 0x76U
121 #define OV7725_AWB_CTRL15 0x77U
122 #define OV7725_AWB_CTRL16 0x78U
123 #define OV7725_AWB_CTRL17 0x79U
124 #define OV7725_AWB_CTRL18 0x7AU
125 #define OV7725_AWB_CTRL19 0x7BU
126 #define OV7725_AWB_CTRL20 0x7CU
127 #define OV7725_AWB_CTRL21 0x7DU
128 #define OV7725_GAM1 0x7EU
129 #define OV7725_GAM2 0x7FU
130 #define OV7725_GAM3 0x80U
131 #define OV7725_GAM4 0x81U
132 #define OV7725_GAM5 0x82U
133 #define OV7725_GAM6 0x83U
134 #define OV7725_GAM7 0x84U
135 #define OV7725_GAM8 0x85U
136 #define OV7725_GAM9 0x86U
137 #define OV7725_GAM10 0x87U
138 #define OV7725_GAM11 0x88U
139 #define OV7725_GAM12 0x89U
140 #define OV7725_GAM13 0x8AU
141 #define OV7725_GAM14 0x8BU
142 #define OV7725_GAM15 0x8CU
143 #define OV7725_SLOP 0x8DU
144 #define OV7725_DNSTH 0x8EU
145 #define OV7725_EDGE0 0x8FU
146 #define OV7725_EDGE1 0x90U
147 #define OV7725_DNSOFF 0x91U
148 #define OV7725_EDGE2 0x92U
149 #define OV7725_EDGE3 0x93U
150 #define OV7725_MTX1 0x94U
151 #define OV7725_MTX2 0x95U
152 #define OV7725_MTX3 0x96U
153 #define OV7725_MTX4 0x97U
154 #define OV7725_MTX5 0x98U
155 #define OV7725_MTX6 0x99U
156 #define OV7725_MTX_CTRL 0x9AU
157 #define OV7725_BRIGHT 0x9BU
158 #define OV7725_CNST 0x9CU
159 #define OV7725_UVADJ0 0x9EU
160 #define OV7725_UVADJ1 0x9FU
161 #define OV7725_SCAL0 0xA0U
162 #define OV7725_SCAL1 0xA1U
163 #define OV7725_SCAL2 0xA2U
164 #define OV7725_SDE 0xA6U
165 #define OV7725_USAT 0xA7U
166 #define OV7725_VSAT 0xA8U
167 #define OV7725_HUECOS 0xA9U
168 #define OV7725_HUESIN 0xAAU
169 #define OV7725_SIGN 0xABU
170 #define OV7725_DSPAUTO 0xACU
171
172 #define OV7725_COM10_VSYNC_NEG_MASK BIT(1)
173 #define OV7725_COM10_HREF_REVERSE_MASK BIT(3)
174 #define OV7725_COM10_PCLK_REVERSE_MASK BIT(4)
175 #define OV7725_COM10_PCLK_OUT_MASK BIT(5)
176 #define OV7725_COM10_DATA_NEG_MASK BIT(7)
177
178 struct ov7725_data {
179 const struct device *i2c;
180 const struct device *reset_gpio;
181 uint8_t reset_pin;
182 gpio_dt_flags_t reset_flags;
183 struct video_format fmt;
184 uint8_t i2c_addr;
185 };
186
187 struct ov7725_clock {
188 uint32_t input_clk;
189 uint32_t framerate;
190 uint8_t clkrc; /*!< Register CLKRC. */
191 uint8_t com4; /*!< Register COM4. */
192 uint8_t dm_lnl; /*!< Register DM_LNL. */
193 };
194
195 struct ov7725_pixel_format {
196 uint32_t pixel_format;
197 uint8_t com7;
198 };
199
200 struct ov7725_reg {
201 uint8_t addr;
202 uint8_t value;
203 };
204
205 static const struct ov7725_clock ov7725_clock_configs[] = {
206 { .input_clk = 24000000, .framerate = 30,
207 .clkrc = 0x01, .com4 = 0x41, .dm_lnl = 0x00 },
208 { .input_clk = 24000000, .framerate = 15,
209 .clkrc = 0x03, .com4 = 0x41, .dm_lnl = 0x00 },
210 { .input_clk = 24000000, .framerate = 25,
211 .clkrc = 0x01, .com4 = 0x41, .dm_lnl = 0x66 },
212 { .input_clk = 24000000, .framerate = 14,
213 .clkrc = 0x03, .com4 = 0x41, .dm_lnl = 0x1a },
214 { .input_clk = 26000000, .framerate = 30,
215 .clkrc = 0x01, .com4 = 0x41, .dm_lnl = 0x2b },
216 { .input_clk = 26000000, .framerate = 15,
217 .clkrc = 0x03, .com4 = 0x41, .dm_lnl = 0x2b },
218 { .input_clk = 26000000, .framerate = 25,
219 .clkrc = 0x01, .com4 = 0x41, .dm_lnl = 0x99 },
220 { .input_clk = 26000000, .framerate = 14,
221 .clkrc = 0x03, .com4 = 0x41, .dm_lnl = 0x46 },
222 { .input_clk = 13000000, .framerate = 30,
223 .clkrc = 0x00, .com4 = 0x41, .dm_lnl = 0x2b },
224 { .input_clk = 13000000, .framerate = 15,
225 .clkrc = 0x01, .com4 = 0x41, .dm_lnl = 0x2b },
226 { .input_clk = 13000000, .framerate = 25,
227 .clkrc = 0x00, .com4 = 0x41, .dm_lnl = 0x99 },
228 { .input_clk = 13000000, .framerate = 14,
229 .clkrc = 0x01, .com4 = 0x41, .dm_lnl = 0x46 },
230 };
231
232
233 static const struct ov7725_pixel_format ov7725_pf_configs[] = {
234 { .pixel_format = VIDEO_PIX_FMT_RGB565, .com7 = (1 << 2) | (2) }
235 };
236
237 static const struct ov7725_reg ov7725_init_reg_tb[] = {
238 /*Output config*/
239 { OV7725_CLKRC, 0x00 },
240 { OV7725_COM7, 0x06 },
241 { OV7725_HSTART, 0x3f },
242 { OV7725_HSIZE, 0x50 },
243 { OV7725_VSTART, 0x03 },
244 { OV7725_VSIZE, 0x78 },
245 { OV7725_HREF, 0x00 },
246 { OV7725_HOUTSIZE, 0x50 },
247 { OV7725_VOUTSIZE, 0x78 },
248
249 /*DSP control*/
250 { OV7725_TGT_B, 0x7f },
251 { OV7725_FIXGAIN, 0x09 },
252 { OV7725_AWB_CTRL0, 0xe0 },
253 { OV7725_DSP_CTRL1, 0xff },
254 { OV7725_DSP_CTRL2, 0x00 },
255 { OV7725_DSP_CTRL3, 0x00 },
256 { OV7725_DSP_CTRL4, 0x00 },
257
258 /*AGC AEC AWB*/
259 { OV7725_COM8, 0xf0 },
260 { OV7725_COM4, 0x81 },
261 { OV7725_COM6, 0xc5 },
262 { OV7725_COM9, 0x11 },
263 { OV7725_BDBASE, 0x7F },
264 { OV7725_BDMSTEP, 0x03 },
265 { OV7725_AEW, 0x40 },
266 { OV7725_AEB, 0x30 },
267 { OV7725_VPT, 0xa1 },
268 { OV7725_EXHCL, 0x9e },
269 { OV7725_AWB_CTRL3, 0xaa },
270 { OV7725_COM8, 0xff },
271
272 /*matrix shapness brightness contrast*/
273 { OV7725_EDGE1, 0x08 },
274 { OV7725_DNSOFF, 0x01 },
275 { OV7725_EDGE2, 0x03 },
276 { OV7725_EDGE3, 0x00 },
277 { OV7725_MTX1, 0xb0 },
278 { OV7725_MTX2, 0x9d },
279 { OV7725_MTX3, 0x13 },
280 { OV7725_MTX4, 0x16 },
281 { OV7725_MTX5, 0x7b },
282 { OV7725_MTX6, 0x91 },
283 { OV7725_MTX_CTRL, 0x1e },
284 { OV7725_BRIGHT, 0x08 },
285 { OV7725_CNST, 0x20 },
286 { OV7725_UVADJ0, 0x81 },
287 { OV7725_SDE, 0X06 },
288 { OV7725_USAT, 0x65 },
289 { OV7725_VSAT, 0x65 },
290 { OV7725_HUECOS, 0X80 },
291 { OV7725_HUESIN, 0X80 },
292
293 /*GAMMA config*/
294 { OV7725_GAM1, 0x0c },
295 { OV7725_GAM2, 0x16 },
296 { OV7725_GAM3, 0x2a },
297 { OV7725_GAM4, 0x4e },
298 { OV7725_GAM5, 0x61 },
299 { OV7725_GAM6, 0x6f },
300 { OV7725_GAM7, 0x7b },
301 { OV7725_GAM8, 0x86 },
302 { OV7725_GAM9, 0x8e },
303 { OV7725_GAM10, 0x97 },
304 { OV7725_GAM11, 0xa4 },
305 { OV7725_GAM12, 0xaf },
306 { OV7725_GAM13, 0xc5 },
307 { OV7725_GAM14, 0xd7 },
308 { OV7725_GAM15, 0xe8 },
309 { OV7725_SLOP, 0x20 },
310
311 { OV7725_COM3, 0x40 },
312 { OV7725_COM5, 0xf5 },
313 { OV7725_COM10, 0x02 },
314 { OV7725_COM2, 0x01 }
315 };
316
ov7725_write_reg(const struct device * dev,uint8_t reg_addr,uint8_t value)317 static int ov7725_write_reg(const struct device *dev, uint8_t reg_addr,
318 uint8_t value)
319 {
320 struct ov7725_data *drv_data = dev->data;
321 struct i2c_msg msgs[2];
322
323 msgs[0].buf = (uint8_t *)®_addr;
324 msgs[0].len = 1;
325 msgs[0].flags = I2C_MSG_WRITE;
326
327 msgs[1].buf = (uint8_t *)&value;
328 msgs[1].len = 1;
329 msgs[1].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
330
331 return i2c_transfer(drv_data->i2c, msgs, 2, drv_data->i2c_addr);
332 }
333
ov7725_read_reg(const struct device * dev,uint8_t reg_addr,uint8_t * value)334 static int ov7725_read_reg(const struct device *dev, uint8_t reg_addr,
335 uint8_t *value)
336 {
337 struct ov7725_data *drv_data = dev->data;
338 struct i2c_msg msgs[2];
339
340 msgs[0].buf = (uint8_t *)®_addr;
341 msgs[0].len = 1;
342 /*
343 * When using I2C to read the registers of the SCCB device,
344 * a stop bit is required after writing the register address
345 */
346 msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
347
348 msgs[1].buf = (uint8_t *)value;
349 msgs[1].len = 1;
350 msgs[1].flags = I2C_MSG_READ | I2C_MSG_STOP | I2C_MSG_RESTART;
351
352 return i2c_transfer(drv_data->i2c, msgs, 2, drv_data->i2c_addr);
353 }
354
ov7725_modify_reg(const struct device * dev,uint8_t reg_addr,uint8_t clear_mask,uint8_t value)355 int ov7725_modify_reg(const struct device *dev,
356 uint8_t reg_addr,
357 uint8_t clear_mask,
358 uint8_t value)
359 {
360 int ret;
361 uint8_t set_value;
362
363 ret = ov7725_read_reg(dev, reg_addr, &set_value);
364
365 if (ret == 0) {
366 set_value = (set_value & (~clear_mask)) |
367 (set_value & clear_mask);
368 ret = ov7725_write_reg(dev, reg_addr, set_value);
369 }
370
371
372 return ret;
373 }
374
ov7725_write_all(const struct device * dev,const struct ov7725_reg * regs,uint16_t reg_num)375 static int ov7725_write_all(const struct device *dev,
376 const struct ov7725_reg *regs,
377 uint16_t reg_num)
378 {
379 uint16_t i = 0;
380
381 for (i = 0; i < reg_num; i++) {
382 int err;
383
384 err = ov7725_write_reg(dev, regs[i].addr, regs[i].value);
385 if (err) {
386 return err;
387 }
388 }
389
390 return 0;
391 }
392
ov7725_set_clock(const struct device * dev,unsigned int framerate,unsigned int input_clk)393 static int ov7725_set_clock(const struct device *dev,
394 unsigned int framerate,
395 unsigned int input_clk)
396 {
397 for (unsigned int i = 0; i < ARRAY_SIZE(ov7725_clock_configs); i++) {
398 if ((ov7725_clock_configs[i].framerate == framerate) &&
399 (ov7725_clock_configs[i].input_clk == input_clk)) {
400 ov7725_write_reg(dev, OV7725_CLKRC,
401 ov7725_clock_configs[i].clkrc);
402 ov7725_modify_reg(dev, OV7725_COM4, 0xc0,
403 ov7725_clock_configs[i].com4);
404 ov7725_write_reg(dev, OV7725_EXHCL, 0x00);
405 ov7725_write_reg(dev, OV7725_DM_LNL,
406 ov7725_clock_configs[i].dm_lnl);
407 ov7725_write_reg(dev, OV7725_DM_LNH, 0x00);
408 ov7725_write_reg(dev, OV7725_ADVFL, 0x00);
409 ov7725_write_reg(dev, OV7725_ADVFH, 0x00);
410 return ov7725_write_reg(dev, OV7725_COM5, 0x65);
411 }
412 }
413
414 return -1;
415 }
416
ov7725_set_fmt(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)417 static int ov7725_set_fmt(const struct device *dev,
418 enum video_endpoint_id ep,
419 struct video_format *fmt)
420 {
421 struct ov7725_data *drv_data = dev->data;
422 uint8_t com10 = 0;
423 uint16_t width, height;
424 uint16_t hstart, vstart, hsize;
425 int ret;
426
427 /* we only support one format for now (VGA RGB565) */
428 if (fmt->pixelformat != VIDEO_PIX_FMT_RGB565 || fmt->height != 480 ||
429 fmt->width != 640) {
430 return -ENOTSUP;
431 }
432
433 width = fmt->width;
434 height = fmt->height;
435
436 if (!memcmp(&drv_data->fmt, fmt, sizeof(drv_data->fmt))) {
437 /* nothing to do */
438 return 0;
439 }
440
441 drv_data->fmt = *fmt;
442
443 /* Configure Sensor */
444 ret = ov7725_write_all(dev, ov7725_init_reg_tb,
445 ARRAY_SIZE(ov7725_init_reg_tb));
446 if (ret) {
447 LOG_ERR("Unable to write ov7725 config");
448 return ret;
449 }
450
451 /* Set clock : framerate 30fps, input clock 24M*/
452 ov7725_set_clock(dev, 30, 24000000);
453
454 /* Set output format */
455 for (uint8_t i = 0; i < ARRAY_SIZE(ov7725_pf_configs); i++) {
456 if (ov7725_pf_configs[i].pixel_format == fmt->pixelformat) {
457 ret = ov7725_modify_reg(dev,
458 OV7725_COM7,
459 0x1FU,
460 ov7725_pf_configs[i].com7);
461 if (ret) {
462 LOG_ERR("Unable to write ov7725 pixel format");
463 return ret;
464 }
465 }
466 }
467
468 ov7725_modify_reg(dev, OV7725_COM7, (1 << 5), (0 << 5));
469
470 com10 |= OV7725_COM10_VSYNC_NEG_MASK;
471 ov7725_write_reg(dev, OV7725_COM10, com10);
472
473 /* Don't swap output MSB/LSB. */
474 ov7725_write_reg(dev, OV7725_COM3, 0x00);
475
476 /*
477 * Output drive capability
478 * 0: 1X
479 * 1: 2X
480 * 2: 3X
481 * 3: 4X
482 */
483 ov7725_modify_reg(dev, OV7725_COM2, 0x03, 0x03);
484
485 /* Resolution and timing. */
486 hstart = 0x22U << 2U;
487 vstart = 0x07U << 1U;
488 hsize = width + 16U;
489
490 /* Set the window size. */
491 ov7725_write_reg(dev, OV7725_HSTART, hstart >> 2U);
492 ov7725_write_reg(dev, OV7725_HSIZE, hsize >> 2U);
493 ov7725_write_reg(dev, OV7725_VSTART, vstart >> 1U);
494 ov7725_write_reg(dev, OV7725_VSIZE, height >> 1U);
495 ov7725_write_reg(dev, OV7725_HOUTSIZE, width >> 2U);
496 ov7725_write_reg(dev, OV7725_VOUTSIZE, height >> 1U);
497 ov7725_write_reg(dev, OV7725_HREF,
498 ((vstart & 1U) << 6U) |
499 ((hstart & 3U) << 4U) |
500 ((height & 1U) << 2U) |
501 ((hsize & 3U) << 0U));
502 return ov7725_write_reg(dev, OV7725_EXHCH,
503 ((height & 1U) << 2U) |
504 ((width & 3U) << 0U));
505 }
506
ov7725_get_fmt(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)507 static int ov7725_get_fmt(const struct device *dev,
508 enum video_endpoint_id ep,
509 struct video_format *fmt)
510 {
511 struct ov7725_data *drv_data = dev->data;
512
513 *fmt = drv_data->fmt;
514
515 return 0;
516 }
517
ov7725_stream_start(const struct device * dev)518 static int ov7725_stream_start(const struct device *dev)
519 {
520 return 0;
521 }
522
ov7725_stream_stop(const struct device * dev)523 static int ov7725_stream_stop(const struct device *dev)
524 {
525 return 0;
526 }
527
528 static const struct video_format_cap fmts[] = {
529 {
530 .pixelformat = VIDEO_PIX_FMT_RGB565,
531 .width_min = 640,
532 .width_max = 640,
533 .height_min = 480,
534 .height_max = 480,
535 .width_step = 0,
536 .height_step = 0,
537 },
538 { 0 }
539 };
540
ov7725_get_caps(const struct device * dev,enum video_endpoint_id ep,struct video_caps * caps)541 static int ov7725_get_caps(const struct device *dev,
542 enum video_endpoint_id ep,
543 struct video_caps *caps)
544 {
545 caps->format_caps = fmts;
546 return 0;
547 }
548
549 static const struct video_driver_api ov7725_driver_api = {
550 .set_format = ov7725_set_fmt,
551 .get_format = ov7725_get_fmt,
552 .get_caps = ov7725_get_caps,
553 .stream_start = ov7725_stream_start,
554 .stream_stop = ov7725_stream_stop,
555 };
556
ov7725_init(const struct device * dev)557 static int ov7725_init(const struct device *dev)
558 {
559 struct ov7725_data *drv_data = dev->data;
560 struct video_format fmt;
561 uint8_t pid, ver;
562 int ret;
563
564
565 if (drv_data->reset_gpio) {
566 ret = gpio_pin_configure(drv_data->reset_gpio,
567 drv_data->reset_pin,
568 GPIO_OUTPUT_ACTIVE |
569 drv_data->reset_flags);
570 if (ret) {
571 return ret;
572 }
573
574 gpio_pin_set(drv_data->reset_gpio,
575 drv_data->reset_pin,
576 0);
577 k_sleep(K_MSEC(1));
578 gpio_pin_set(drv_data->reset_gpio,
579 drv_data->reset_pin,
580 1);
581 k_sleep(K_MSEC(1));
582 }
583
584 /* Identify the device. */
585 ret = ov7725_read_reg(dev, OV7725_PID, &pid);
586 if (ret) {
587 LOG_ERR("Unable to read PID");
588 return -ENODEV;
589 }
590
591 ret = ov7725_read_reg(dev, OV7725_VER, &ver);
592 if (ret) {
593 LOG_ERR("Unable to read VER");
594 return -ENODEV;
595 }
596
597 if (OV7725_REVISION != (((uint32_t)pid << 8U) | (uint32_t)ver)) {
598 LOG_ERR("OV7725 Get Vision fail\n");
599 return -ENODEV;
600 }
601
602 /* Device identify OK, perform software reset. */
603 ov7725_write_reg(dev, OV7725_COM7, 0x80);
604
605 k_sleep(K_MSEC(2));
606
607 /* set default/init format VGA RGB565 */
608 fmt.pixelformat = VIDEO_PIX_FMT_RGB565;
609 fmt.width = 640;
610 fmt.height = 480;
611 fmt.pitch = 640 * 2;
612 ret = ov7725_set_fmt(dev, VIDEO_EP_OUT, &fmt);
613 if (ret) {
614 LOG_ERR("Unable to configure default format");
615 return -EIO;
616 }
617
618 return 0;
619 }
620
621 /* Unique Instance */
622 static struct ov7725_data ov7725_data_0;
623
ov7725_init_0(const struct device * dev)624 static int ov7725_init_0(const struct device *dev)
625 {
626 struct ov7725_data *drv_data = dev->data;
627 char *gpio_name = DT_INST_GPIO_LABEL(0, reset_gpios);
628
629 drv_data->reset_pin = DT_INST_GPIO_PIN(0, reset_gpios),
630 drv_data->reset_flags = DT_INST_GPIO_FLAGS(0, reset_gpios),
631
632 drv_data->i2c = device_get_binding(DT_INST_BUS_LABEL(0));
633 if (drv_data->i2c == NULL) {
634 LOG_ERR("Failed to get pointer to %s device!",
635 DT_INST_LABEL(0));
636 return -EINVAL;
637 }
638
639 if (gpio_name) {
640 drv_data->reset_gpio = device_get_binding(gpio_name);
641 if (drv_data->reset_gpio == NULL) {
642 LOG_ERR("Failed to get pointer to %s device!",
643 gpio_name);
644 }
645 }
646
647 drv_data->i2c_addr = DT_INST_REG_ADDR(0);
648
649 return ov7725_init(dev);
650 }
651
652 DEVICE_DT_INST_DEFINE(0, &ov7725_init_0, NULL,
653 &ov7725_data_0, NULL,
654 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
655 &ov7725_driver_api);
656