1 /*
2  * Copyright (c) 2024 Felipe Neves
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT galaxycore_gc2145
8 #include <zephyr/kernel.h>
9 #include <zephyr/device.h>
10 
11 #include <zephyr/drivers/video.h>
12 #include <zephyr/drivers/video-controls.h>
13 #include <zephyr/drivers/i2c.h>
14 #include <zephyr/drivers/gpio.h>
15 
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(video_gc2145, CONFIG_VIDEO_LOG_LEVEL);
18 
19 #define GC2145_REG_AMODE1               0x17
20 #define GC2145_AMODE1_WINDOW_MASK       0xFC
21 #define GC2145_REG_AMODE1_DEF           0x14
22 #define GC2145_REG_OUTPUT_FMT           0x84
23 #define GC2145_REG_OUTPUT_FMT_MASK      0x1F
24 #define GC2145_REG_OUTPUT_FMT_RGB565    0x06
25 #define GC2145_REG_OUTPUT_FMT_YCBYCR    0x02
26 #define GC2145_REG_SYNC_MODE            0x86
27 #define GC2145_REG_SYNC_MODE_DEF        0x23
28 #define GC2145_REG_SYNC_MODE_COL_SWITCH 0x10
29 #define GC2145_REG_SYNC_MODE_ROW_SWITCH 0x20
30 #define GC2145_REG_RESET                0xFE
31 #define GC2145_REG_SW_RESET             0x80
32 #define GC2145_PID_VAL                  0x21
33 #define GC2145_REV_VAL                  0x55
34 #define GC2145_SET_P0_REGS              0x00
35 #define GC2145_REG_CROP_ENABLE          0x90
36 #define GC2145_CROP_SET_ENABLE          0x01
37 #define GC2145_REG_BLANK_WINDOW_BASE    0x09
38 #define GC2145_REG_WINDOW_BASE          0x91
39 #define GC2145_REG_SUBSAMPLE            0x99
40 #define GC2145_REG_SUBSAMPLE_MODE       0x9A
41 #define GC2145_SUBSAMPLE_MODE_SMOOTH    0x0E
42 
43 #define UXGA_HSIZE 1600
44 #define UXGA_VSIZE 1200
45 
46 struct gc2145_reg {
47 	uint8_t addr;
48 	uint8_t value;
49 };
50 
51 static const struct gc2145_reg default_regs[] = {
52 	{0xfe, 0xf0},
53 	{0xfe, 0xf0},
54 	{0xfe, 0xf0},
55 	{0xfc, 0x06},
56 	{0xf6, 0x00},
57 	{0xf7, 0x1d},
58 	{0xf8, 0x85},
59 	{0xfa, 0x00},
60 	{0xf9, 0xfe},
61 	{0xf2, 0x00},
62 
63 	/* ISP settings */
64 	{0xfe, 0x00},
65 	{0x03, 0x04},
66 	{0x04, 0xe2},
67 
68 	{0x09, 0x00},
69 	{0x0a, 0x00},
70 
71 	{0x0b, 0x00},
72 	{0x0c, 0x00},
73 
74 	{0x0d, 0x04}, /* Window height */
75 	{0x0e, 0xc0},
76 
77 	{0x0f, 0x06}, /* Window width */
78 	{0x10, 0x52},
79 
80 	{0x99, 0x11}, /* Subsample */
81 	{0x9a, 0x0E}, /* Subsample mode */
82 
83 	{0x12, 0x2e},
84 	{0x17, 0x14}, /* Analog Mode 1 (vflip/mirror[1:0]) */
85 	{0x18, 0x22}, /* Analog Mode 2 */
86 	{0x19, 0x0e},
87 	{0x1a, 0x01},
88 	{0x1b, 0x4b},
89 	{0x1c, 0x07},
90 	{0x1d, 0x10},
91 	{0x1e, 0x88},
92 	{0x1f, 0x78},
93 	{0x20, 0x03},
94 	{0x21, 0x40},
95 	{0x22, 0xa0},
96 	{0x24, 0x16},
97 	{0x25, 0x01},
98 	{0x26, 0x10},
99 	{0x2d, 0x60},
100 	{0x30, 0x01},
101 	{0x31, 0x90},
102 	{0x33, 0x06},
103 	{0x34, 0x01},
104 	{0x80, 0x7f},
105 	{0x81, 0x26},
106 	{0x82, 0xfa},
107 	{0x83, 0x00},
108 	{GC2145_REG_OUTPUT_FMT, 0x06},
109 	{GC2145_REG_SYNC_MODE, 0x23},
110 	{0x88, 0x03},
111 	{0x89, 0x03},
112 	{0x85, 0x08},
113 	{0x8a, 0x00},
114 	{0x8b, 0x00},
115 	{0xb0, 0x55},
116 	{0xc3, 0x00},
117 	{0xc4, 0x80},
118 	{0xc5, 0x90},
119 	{0xc6, 0x3b},
120 	{0xc7, 0x46},
121 	{0xec, 0x06},
122 	{0xed, 0x04},
123 	{0xee, 0x60},
124 	{0xef, 0x90},
125 	{0xb6, 0x01},
126 
127 	{0x90, 0x01},
128 	{0x91, 0x00},
129 	{0x92, 0x00},
130 	{0x93, 0x00},
131 	{0x94, 0x00},
132 	{0x95, 0x02},
133 	{0x96, 0x58},
134 	{0x97, 0x03},
135 	{0x98, 0x20},
136 	{0x99, 0x22},
137 	{0x9a, 0x0E},
138 
139 	{0x9b, 0x00},
140 	{0x9c, 0x00},
141 	{0x9d, 0x00},
142 	{0x9e, 0x00},
143 	{0x9f, 0x00},
144 	{0xa0, 0x00},
145 	{0xa1, 0x00},
146 	{0xa2, 0x00},
147 
148 	/* BLK Settings */
149 	{0xfe, 0x00},
150 	{0x40, 0x42},
151 	{0x41, 0x00},
152 	{0x43, 0x5b},
153 	{0x5e, 0x00},
154 	{0x5f, 0x00},
155 	{0x60, 0x00},
156 	{0x61, 0x00},
157 	{0x62, 0x00},
158 	{0x63, 0x00},
159 	{0x64, 0x00},
160 	{0x65, 0x00},
161 	{0x66, 0x20},
162 	{0x67, 0x20},
163 	{0x68, 0x20},
164 	{0x69, 0x20},
165 	{0x76, 0x00},
166 	{0x6a, 0x08},
167 	{0x6b, 0x08},
168 	{0x6c, 0x08},
169 	{0x6d, 0x08},
170 	{0x6e, 0x08},
171 	{0x6f, 0x08},
172 	{0x70, 0x08},
173 	{0x71, 0x08},
174 	{0x76, 0x00},
175 	{0x72, 0xf0},
176 	{0x7e, 0x3c},
177 	{0x7f, 0x00},
178 	{0xfe, 0x02},
179 	{0x48, 0x15},
180 	{0x49, 0x00},
181 	{0x4b, 0x0b},
182 	{0xfe, 0x00},
183 
184 	/* AEC Settings */
185 	{0xfe, 0x01},
186 	{0x01, 0x04},
187 	{0x02, 0xc0},
188 	{0x03, 0x04},
189 	{0x04, 0x90},
190 	{0x05, 0x30},
191 	{0x06, 0x90},
192 	{0x07, 0x30},
193 	{0x08, 0x80},
194 	{0x09, 0x00},
195 	{0x0a, 0x82},
196 	{0x0b, 0x11},
197 	{0x0c, 0x10},
198 	{0x11, 0x10},
199 	{0x13, 0x68},
200 	{GC2145_REG_OUTPUT_FMT, 0x00},
201 	{0x1c, 0x11},
202 	{0x1e, 0x61},
203 	{0x1f, 0x35},
204 	{0x20, 0x40},
205 	{0x22, 0x40},
206 	{0x23, 0x20},
207 	{0xfe, 0x02},
208 	{0x0f, 0x04},
209 	{0xfe, 0x01},
210 	{0x12, 0x30},
211 	{0x15, 0xb0},
212 	{0x10, 0x31},
213 	{0x3e, 0x28},
214 	{0x3f, 0xb0},
215 	{0x40, 0x90},
216 	{0x41, 0x0f},
217 	{0xfe, 0x02},
218 	{0x90, 0x6c},
219 	{0x91, 0x03},
220 	{0x92, 0xcb},
221 	{0x94, 0x33},
222 	{0x95, 0x84},
223 	{0x97, 0x65},
224 	{0xa2, 0x11},
225 	{0xfe, 0x00},
226 	{0xfe, 0x02},
227 	{0x80, 0xc1},
228 	{0x81, 0x08},
229 	{0x82, 0x05},
230 	{0x83, 0x08},
231 	{GC2145_REG_OUTPUT_FMT, 0x0a},
232 	{GC2145_REG_SYNC_MODE, 0xf0},
233 	{0x87, 0x50},
234 	{0x88, 0x15},
235 	{0x89, 0xb0},
236 	{0x8a, 0x30},
237 	{0x8b, 0x10},
238 	{0xfe, 0x01},
239 	{0x21, 0x04},
240 	{0xfe, 0x02},
241 	{0xa3, 0x50},
242 	{0xa4, 0x20},
243 	{0xa5, 0x40},
244 	{0xa6, 0x80},
245 	{0xab, 0x40},
246 	{0xae, 0x0c},
247 	{0xb3, 0x46},
248 	{0xb4, 0x64},
249 	{0xb6, 0x38},
250 	{0xb7, 0x01},
251 	{0xb9, 0x2b},
252 	{0x3c, 0x04},
253 	{0x3d, 0x15},
254 	{0x4b, 0x06},
255 	{0x4c, 0x20},
256 	{0xfe, 0x00},
257 
258 	/* Gamma Control */
259 	{0xfe, 0x02},
260 	{0x10, 0x09},
261 	{0x11, 0x0d},
262 	{0x12, 0x13},
263 	{0x13, 0x19},
264 	{0x14, 0x27},
265 	{0x15, 0x37},
266 	{0x16, 0x45},
267 	{GC2145_REG_OUTPUT_FMT, 0x53},
268 	{0x18, 0x69},
269 	{0x19, 0x7d},
270 	{0x1a, 0x8f},
271 	{0x1b, 0x9d},
272 	{0x1c, 0xa9},
273 	{0x1d, 0xbd},
274 	{0x1e, 0xcd},
275 	{0x1f, 0xd9},
276 	{0x20, 0xe3},
277 	{0x21, 0xea},
278 	{0x22, 0xef},
279 	{0x23, 0xf5},
280 	{0x24, 0xf9},
281 	{0x25, 0xff},
282 	{0xfe, 0x00},
283 	{0xc6, 0x20},
284 	{0xc7, 0x2b},
285 	{0xfe, 0x02},
286 	{0x26, 0x0f},
287 	{0x27, 0x14},
288 	{0x28, 0x19},
289 	{0x29, 0x1e},
290 	{0x2a, 0x27},
291 	{0x2b, 0x33},
292 	{0x2c, 0x3b},
293 	{0x2d, 0x45},
294 	{0x2e, 0x59},
295 	{0x2f, 0x69},
296 	{0x30, 0x7c},
297 	{0x31, 0x89},
298 	{0x32, 0x98},
299 	{0x33, 0xae},
300 	{0x34, 0xc0},
301 	{0x35, 0xcf},
302 	{0x36, 0xda},
303 	{0x37, 0xe2},
304 	{0x38, 0xe9},
305 	{0x39, 0xf3},
306 	{0x3a, 0xf9},
307 	{0x3b, 0xff},
308 	{0xfe, 0x02},
309 	{0xd1, 0x32},
310 	{0xd2, 0x32},
311 	{0xd3, 0x40},
312 	{0xd6, 0xf0},
313 	{0xd7, 0x10},
314 	{0xd8, 0xda},
315 	{0xdd, 0x14},
316 	{0xde, 0x86},
317 	{0xed, 0x80},
318 	{0xee, 0x00},
319 	{0xef, 0x3f},
320 	{0xd8, 0xd8},
321 	{0xfe, 0x01},
322 	{0x9f, 0x40},
323 	{0xfe, 0x01},
324 	{0xc2, 0x14},
325 	{0xc3, 0x0d},
326 	{0xc4, 0x0c},
327 	{0xc8, 0x15},
328 	{0xc9, 0x0d},
329 	{0xca, 0x0a},
330 	{0xbc, 0x24},
331 	{0xbd, 0x10},
332 	{0xbe, 0x0b},
333 	{0xb6, 0x25},
334 	{0xb7, 0x16},
335 	{0xb8, 0x15},
336 	{0xc5, 0x00},
337 	{0xc6, 0x00},
338 	{0xc7, 0x00},
339 	{0xcb, 0x00},
340 	{0xcc, 0x00},
341 	{0xcd, 0x00},
342 	{0xbf, 0x07},
343 	{0xc0, 0x00},
344 	{0xc1, 0x00},
345 	{0xb9, 0x00},
346 	{0xba, 0x00},
347 	{0xbb, 0x00},
348 	{0xaa, 0x01},
349 	{0xab, 0x01},
350 	{0xac, 0x00},
351 	{0xad, 0x05},
352 	{0xae, 0x06},
353 	{0xaf, 0x0e},
354 	{0xb0, 0x0b},
355 	{0xb1, 0x07},
356 	{0xb2, 0x06},
357 	{0xb3, 0x17},
358 	{0xb4, 0x0e},
359 	{0xb5, 0x0e},
360 	{0xd0, 0x09},
361 	{0xd1, 0x00},
362 	{0xd2, 0x00},
363 	{0xd6, 0x08},
364 	{0xd7, 0x00},
365 	{0xd8, 0x00},
366 	{0xd9, 0x00},
367 	{0xda, 0x00},
368 	{0xdb, 0x00},
369 	{0xd3, 0x0a},
370 	{0xd4, 0x00},
371 	{0xd5, 0x00},
372 	{0xa4, 0x00},
373 	{0xa5, 0x00},
374 	{0xa6, 0x77},
375 	{0xa7, 0x77},
376 	{0xa8, 0x77},
377 	{0xa9, 0x77},
378 	{0xa1, 0x80},
379 	{0xa2, 0x80},
380 
381 	{0xfe, 0x01},
382 	{0xdf, 0x0d},
383 	{0xdc, 0x25},
384 	{0xdd, 0x30},
385 	{0xe0, 0x77},
386 	{0xe1, 0x80},
387 	{0xe2, 0x77},
388 	{0xe3, 0x90},
389 	{0xe6, 0x90},
390 	{0xe7, 0xa0},
391 	{0xe8, 0x90},
392 	{0xe9, 0xa0},
393 	{0xfe, 0x00},
394 	{0xfe, 0x01},
395 	{0x4f, 0x00},
396 	{0x4f, 0x00},
397 	{0x4b, 0x01},
398 	{0x4f, 0x00},
399 
400 	{0x4c, 0x01},
401 	{0x4d, 0x71},
402 	{0x4e, 0x01},
403 	{0x4c, 0x01},
404 	{0x4d, 0x91},
405 	{0x4e, 0x01},
406 	{0x4c, 0x01},
407 	{0x4d, 0x70},
408 	{0x4e, 0x01},
409 	{0x4c, 0x01},
410 	{0x4d, 0x90},
411 	{0x4e, 0x02},
412 	{0x4c, 0x01},
413 	{0x4d, 0xb0},
414 	{0x4e, 0x02},
415 	{0x4c, 0x01},
416 	{0x4d, 0x8f},
417 	{0x4e, 0x02},
418 	{0x4c, 0x01},
419 	{0x4d, 0x6f},
420 	{0x4e, 0x02},
421 	{0x4c, 0x01},
422 	{0x4d, 0xaf},
423 	{0x4e, 0x02},
424 	{0x4c, 0x01},
425 	{0x4d, 0xd0},
426 	{0x4e, 0x02},
427 	{0x4c, 0x01},
428 	{0x4d, 0xf0},
429 	{0x4e, 0x02},
430 	{0x4c, 0x01},
431 	{0x4d, 0xcf},
432 	{0x4e, 0x02},
433 	{0x4c, 0x01},
434 	{0x4d, 0xef},
435 	{0x4e, 0x02},
436 	{0x4c, 0x01},
437 	{0x4d, 0x6e},
438 	{0x4e, 0x03},
439 	{0x4c, 0x01},
440 	{0x4d, 0x8e},
441 	{0x4e, 0x03},
442 	{0x4c, 0x01},
443 	{0x4d, 0xae},
444 	{0x4e, 0x03},
445 	{0x4c, 0x01},
446 	{0x4d, 0xce},
447 	{0x4e, 0x03},
448 	{0x4c, 0x01},
449 	{0x4d, 0x4d},
450 	{0x4e, 0x03},
451 	{0x4c, 0x01},
452 	{0x4d, 0x6d},
453 	{0x4e, 0x03},
454 	{0x4c, 0x01},
455 	{0x4d, 0x8d},
456 	{0x4e, 0x03},
457 	{0x4c, 0x01},
458 	{0x4d, 0xad},
459 	{0x4e, 0x03},
460 	{0x4c, 0x01},
461 	{0x4d, 0xcd},
462 	{0x4e, 0x03},
463 	{0x4c, 0x01},
464 	{0x4d, 0x4c},
465 	{0x4e, 0x03},
466 	{0x4c, 0x01},
467 	{0x4d, 0x6c},
468 	{0x4e, 0x03},
469 	{0x4c, 0x01},
470 	{0x4d, 0x8c},
471 	{0x4e, 0x03},
472 	{0x4c, 0x01},
473 	{0x4d, 0xac},
474 	{0x4e, 0x03},
475 	{0x4c, 0x01},
476 	{0x4d, 0xcc},
477 	{0x4e, 0x03},
478 	{0x4c, 0x01},
479 	{0x4d, 0xcb},
480 	{0x4e, 0x03},
481 	{0x4c, 0x01},
482 	{0x4d, 0x4b},
483 	{0x4e, 0x03},
484 	{0x4c, 0x01},
485 	{0x4d, 0x6b},
486 	{0x4e, 0x03},
487 	{0x4c, 0x01},
488 	{0x4d, 0x8b},
489 	{0x4e, 0x03},
490 	{0x4c, 0x01},
491 	{0x4d, 0xab},
492 	{0x4e, 0x03},
493 	{0x4c, 0x01},
494 	{0x4d, 0x8a},
495 	{0x4e, 0x04},
496 	{0x4c, 0x01},
497 	{0x4d, 0xaa},
498 	{0x4e, 0x04},
499 	{0x4c, 0x01},
500 	{0x4d, 0xca},
501 	{0x4e, 0x04},
502 	{0x4c, 0x01},
503 	{0x4d, 0xca},
504 	{0x4e, 0x04},
505 	{0x4c, 0x01},
506 	{0x4d, 0xc9},
507 	{0x4e, 0x04},
508 	{0x4c, 0x01},
509 	{0x4d, 0x8a},
510 	{0x4e, 0x04},
511 	{0x4c, 0x01},
512 	{0x4d, 0x89},
513 	{0x4e, 0x04},
514 	{0x4c, 0x01},
515 	{0x4d, 0xa9},
516 	{0x4e, 0x04},
517 	{0x4c, 0x02},
518 	{0x4d, 0x0b},
519 	{0x4e, 0x05},
520 	{0x4c, 0x02},
521 	{0x4d, 0x0a},
522 	{0x4e, 0x05},
523 	{0x4c, 0x01},
524 	{0x4d, 0xeb},
525 	{0x4e, 0x05},
526 	{0x4c, 0x01},
527 	{0x4d, 0xea},
528 	{0x4e, 0x05},
529 	{0x4c, 0x02},
530 	{0x4d, 0x09},
531 	{0x4e, 0x05},
532 	{0x4c, 0x02},
533 	{0x4d, 0x29},
534 	{0x4e, 0x05},
535 	{0x4c, 0x02},
536 	{0x4d, 0x2a},
537 	{0x4e, 0x05},
538 	{0x4c, 0x02},
539 	{0x4d, 0x4a},
540 	{0x4e, 0x05},
541 	{0x4c, 0x02},
542 	{0x4d, 0x8a},
543 	{0x4e, 0x06},
544 	{0x4c, 0x02},
545 	{0x4d, 0x49},
546 	{0x4e, 0x06},
547 	{0x4c, 0x02},
548 	{0x4d, 0x69},
549 	{0x4e, 0x06},
550 	{0x4c, 0x02},
551 	{0x4d, 0x89},
552 	{0x4e, 0x06},
553 	{0x4c, 0x02},
554 	{0x4d, 0xa9},
555 	{0x4e, 0x06},
556 	{0x4c, 0x02},
557 	{0x4d, 0x48},
558 	{0x4e, 0x06},
559 	{0x4c, 0x02},
560 	{0x4d, 0x68},
561 	{0x4e, 0x06},
562 	{0x4c, 0x02},
563 	{0x4d, 0x69},
564 	{0x4e, 0x06},
565 	{0x4c, 0x02},
566 	{0x4d, 0xca},
567 	{0x4e, 0x07},
568 	{0x4c, 0x02},
569 	{0x4d, 0xc9},
570 	{0x4e, 0x07},
571 	{0x4c, 0x02},
572 	{0x4d, 0xe9},
573 	{0x4e, 0x07},
574 	{0x4c, 0x03},
575 	{0x4d, 0x09},
576 	{0x4e, 0x07},
577 	{0x4c, 0x02},
578 	{0x4d, 0xc8},
579 	{0x4e, 0x07},
580 	{0x4c, 0x02},
581 	{0x4d, 0xe8},
582 	{0x4e, 0x07},
583 	{0x4c, 0x02},
584 	{0x4d, 0xa7},
585 	{0x4e, 0x07},
586 	{0x4c, 0x02},
587 	{0x4d, 0xc7},
588 	{0x4e, 0x07},
589 	{0x4c, 0x02},
590 	{0x4d, 0xe7},
591 	{0x4e, 0x07},
592 	{0x4c, 0x03},
593 	{0x4d, 0x07},
594 	{0x4e, 0x07},
595 
596 	{0x4f, 0x01},
597 	{0x50, 0x80},
598 	{0x51, 0xa8},
599 	{0x52, 0x47},
600 	{0x53, 0x38},
601 	{0x54, 0xc7},
602 	{0x56, 0x0e},
603 	{0x58, 0x08},
604 	{0x5b, 0x00},
605 	{0x5c, 0x74},
606 	{0x5d, 0x8b},
607 	{0x61, 0xdb},
608 	{0x62, 0xb8},
609 	{0x63, 0x86},
610 	{0x64, 0xc0},
611 	{0x65, 0x04},
612 	{0x67, 0xa8},
613 	{0x68, 0xb0},
614 	{0x69, 0x00},
615 	{0x6a, 0xa8},
616 	{0x6b, 0xb0},
617 	{0x6c, 0xaf},
618 	{0x6d, 0x8b},
619 	{0x6e, 0x50},
620 	{0x6f, 0x18},
621 	{0x73, 0xf0},
622 	{0x70, 0x0d},
623 	{0x71, 0x60},
624 	{0x72, 0x80},
625 	{0x74, 0x01},
626 	{0x75, 0x01},
627 	{0x7f, 0x0c},
628 	{0x76, 0x70},
629 	{0x77, 0x58},
630 	{0x78, 0xa0},
631 	{0x79, 0x5e},
632 	{0x7a, 0x54},
633 	{0x7b, 0x58},
634 	{0xfe, 0x00},
635 	{0xfe, 0x02},
636 	{0xc0, 0x01},
637 	{0xc1, 0x44},
638 	{0xc2, 0xfd},
639 	{0xc3, 0x04},
640 	{0xc4, 0xF0},
641 	{0xc5, 0x48},
642 	{0xc6, 0xfd},
643 	{0xc7, 0x46},
644 	{0xc8, 0xfd},
645 	{0xc9, 0x02},
646 	{0xca, 0xe0},
647 	{0xcb, 0x45},
648 	{0xcc, 0xec},
649 	{0xcd, 0x48},
650 	{0xce, 0xf0},
651 	{0xcf, 0xf0},
652 	{0xe3, 0x0c},
653 	{0xe4, 0x4b},
654 	{0xe5, 0xe0},
655 	{0xfe, 0x01},
656 	{0x9f, 0x40},
657 	{0xfe, 0x00},
658 
659 	/* Output Control  */
660 	{0xfe, 0x00},
661 	{0xf2, 0x0f},
662 	{0xfe, 0x02},
663 	{0x40, 0xbf},
664 	{0x46, 0xcf},
665 	{0xfe, 0x00},
666 
667 	{0xfe, 0x00},
668 	{0x05, 0x01},
669 	{0x06, 0x1C},
670 	{0x07, 0x00},
671 	{0x08, 0x32},
672 	{0x11, 0x00},
673 	{0x12, 0x1D},
674 	{0x13, 0x00},
675 	{0x14, 0x00},
676 
677 	{0xfe, 0x01},
678 	{0x3c, 0x00},
679 	{0x3d, 0x04},
680 	{0xfe, 0x00},
681 	{0x00, 0x00},
682 };
683 
684 struct gc2145_config {
685 	struct i2c_dt_spec i2c;
686 #if DT_INST_NODE_HAS_PROP(0, pwdn_gpios)
687 	struct gpio_dt_spec pwdn_gpio;
688 #endif
689 #if DT_INST_NODE_HAS_PROP(0, reset_gpios)
690 	struct gpio_dt_spec reset_gpio;
691 #endif
692 };
693 
694 struct gc2145_data {
695 	struct video_format fmt;
696 };
697 
698 #define GC2145_VIDEO_FORMAT_CAP(width, height, format)                                             \
699 	{                                                                                          \
700 		.pixelformat = format, .width_min = width, .width_max = width,                     \
701 		.height_min = height, .height_max = height, .width_step = 0, .height_step = 0,     \
702 	}
703 
704 #define RESOLUTION_QVGA_W	320
705 #define RESOLUTION_QVGA_H	240
706 
707 #define RESOLUTION_VGA_W	640
708 #define RESOLUTION_VGA_H	480
709 
710 #define RESOLUTION_UXGA_W	1600
711 #define RESOLUTION_UXGA_H	1200
712 
713 static const struct video_format_cap fmts[] = {
714 	GC2145_VIDEO_FORMAT_CAP(RESOLUTION_QVGA_W, RESOLUTION_QVGA_H, VIDEO_PIX_FMT_RGB565),
715 	GC2145_VIDEO_FORMAT_CAP(RESOLUTION_VGA_W, RESOLUTION_VGA_H, VIDEO_PIX_FMT_RGB565),
716 	GC2145_VIDEO_FORMAT_CAP(RESOLUTION_UXGA_W, RESOLUTION_UXGA_H, VIDEO_PIX_FMT_RGB565),
717 	GC2145_VIDEO_FORMAT_CAP(RESOLUTION_QVGA_W, RESOLUTION_QVGA_H, VIDEO_PIX_FMT_YUYV),
718 	GC2145_VIDEO_FORMAT_CAP(RESOLUTION_VGA_W, RESOLUTION_VGA_H, VIDEO_PIX_FMT_YUYV),
719 	GC2145_VIDEO_FORMAT_CAP(RESOLUTION_UXGA_W, RESOLUTION_UXGA_H, VIDEO_PIX_FMT_YUYV),
720 	{0},
721 };
722 
gc2145_write_reg(const struct i2c_dt_spec * spec,uint8_t reg_addr,uint8_t value)723 static int gc2145_write_reg(const struct i2c_dt_spec *spec, uint8_t reg_addr, uint8_t value)
724 {
725 	int ret;
726 	uint8_t tries = 3;
727 
728 	/*
729 	 * It rarely happens that the camera does not respond with ACK signal.
730 	 * In that case it usually responds on 2nd try but there is a 3rd one
731 	 * just to be sure that the connection error is not caused by driver
732 	 * itself.
733 	 */
734 	do {
735 		ret = i2c_reg_write_byte_dt(spec, reg_addr, value);
736 		if (!ret) {
737 			return 0;
738 		}
739 		/* If writing failed wait 5ms before next attempt */
740 		k_msleep(5);
741 	} while (tries-- > 0);
742 
743 	LOG_ERR("failed to write 0x%x to 0x%x,", value, reg_addr);
744 	return ret;
745 }
746 
gc2145_read_reg(const struct i2c_dt_spec * spec,uint8_t reg_addr,uint8_t * value)747 static int gc2145_read_reg(const struct i2c_dt_spec *spec, uint8_t reg_addr, uint8_t *value)
748 {
749 	int ret;
750 	uint8_t tries = 3;
751 
752 	/*
753 	 * It rarely happens that the camera does not respond with ACK signal.
754 	 * In that case it usually responds on 2nd try but there is a 3rd one
755 	 * just to be sure that the connection error is not caused by driver
756 	 * itself.
757 	 */
758 	do {
759 		ret = i2c_reg_read_byte_dt(spec, reg_addr, value);
760 		if (!ret) {
761 			return 0;
762 		}
763 		/* If writing failed wait 5ms before next attempt */
764 		k_msleep(5);
765 	} while (tries-- > 0);
766 
767 	LOG_ERR("failed to read 0x%x register", reg_addr);
768 	return ret;
769 }
770 
gc2145_write_all(const struct device * dev,const struct gc2145_reg * regs,uint16_t reg_num)771 static int gc2145_write_all(const struct device *dev, const struct gc2145_reg *regs,
772 			    uint16_t reg_num)
773 {
774 	const struct gc2145_config *cfg = dev->config;
775 
776 	for (uint16_t i = 0; i < reg_num; i++) {
777 		int ret;
778 
779 		ret = gc2145_write_reg(&cfg->i2c, regs[i].addr, regs[i].value);
780 		if (ret < 0) {
781 			return ret;
782 		}
783 	}
784 
785 	return 0;
786 }
787 
gc2145_soft_reset(const struct device * dev)788 static int gc2145_soft_reset(const struct device *dev)
789 {
790 	int ret;
791 	const struct gc2145_config *cfg = dev->config;
792 
793 	/* Initiate system reset */
794 	ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_REG_SW_RESET);
795 
796 	k_msleep(300);
797 
798 	return ret;
799 }
800 
gc2145_set_ctrl_vflip(const struct device * dev,bool enable)801 static int gc2145_set_ctrl_vflip(const struct device *dev, bool enable)
802 {
803 	int ret;
804 	const struct gc2145_config *cfg = dev->config;
805 	uint8_t old_value;
806 
807 	ret = gc2145_read_reg(&cfg->i2c, GC2145_REG_AMODE1, &old_value);
808 	if (ret < 0) {
809 		return ret;
810 	}
811 
812 	/* Set the vertical flip state */
813 	return gc2145_write_reg(&cfg->i2c, GC2145_REG_AMODE1,
814 				(old_value & GC2145_AMODE1_WINDOW_MASK) | (enable << 1));
815 }
816 
gc2145_set_ctrl_hmirror(const struct device * dev,bool enable)817 static int gc2145_set_ctrl_hmirror(const struct device *dev, bool enable)
818 {
819 	int ret;
820 	const struct gc2145_config *cfg = dev->config;
821 	uint8_t old_value;
822 
823 	ret = gc2145_read_reg(&cfg->i2c, GC2145_REG_AMODE1, &old_value);
824 	if (ret < 0) {
825 		return ret;
826 	}
827 
828 	/* Set the horizontal mirror state */
829 	return gc2145_write_reg(&cfg->i2c, GC2145_REG_AMODE1,
830 				(old_value & GC2145_AMODE1_WINDOW_MASK) | enable);
831 }
832 
gc2145_set_window(const struct device * dev,uint16_t reg,uint16_t x,uint16_t y,uint16_t w,uint16_t h)833 static int gc2145_set_window(const struct device *dev, uint16_t reg, uint16_t x, uint16_t y,
834 			     uint16_t w, uint16_t h)
835 {
836 	int ret;
837 	const struct gc2145_config *cfg = dev->config;
838 
839 	ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
840 	if (ret < 0) {
841 		return ret;
842 	}
843 
844 	/* Y/row offset */
845 	ret = gc2145_write_reg(&cfg->i2c, reg++, y >> 8);
846 	if (ret < 0) {
847 		return ret;
848 	}
849 
850 	ret = gc2145_write_reg(&cfg->i2c, reg++, y & 0xff);
851 	if (ret < 0) {
852 		return ret;
853 	}
854 
855 	/* X/col offset */
856 	ret = gc2145_write_reg(&cfg->i2c, reg++, x >> 8);
857 	if (ret < 0) {
858 		return ret;
859 	}
860 
861 	ret = gc2145_write_reg(&cfg->i2c, reg++, x & 0xff);
862 	if (ret < 0) {
863 		return ret;
864 	}
865 
866 	/* Window height */
867 	ret = gc2145_write_reg(&cfg->i2c, reg++, h >> 8);
868 	if (ret < 0) {
869 		return ret;
870 	}
871 
872 	ret = gc2145_write_reg(&cfg->i2c, reg++, h & 0xff);
873 	if (ret < 0) {
874 		return ret;
875 	}
876 
877 	/* Window width */
878 	ret = gc2145_write_reg(&cfg->i2c, reg++, w >> 8);
879 	if (ret < 0) {
880 		return ret;
881 	}
882 
883 	ret = gc2145_write_reg(&cfg->i2c, reg++, w & 0xff);
884 	if (ret < 0) {
885 		return ret;
886 	}
887 
888 	return 0;
889 }
890 
gc2145_set_output_format(const struct device * dev,int output_format)891 static int gc2145_set_output_format(const struct device *dev, int output_format)
892 {
893 	int ret;
894 	uint8_t old_value;
895 	const struct gc2145_config *cfg = dev->config;
896 
897 	ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_RESET, GC2145_SET_P0_REGS);
898 	if (ret < 0) {
899 		return ret;
900 	}
901 
902 	/* Map format to sensor format */
903 	if (output_format == VIDEO_PIX_FMT_RGB565) {
904 		output_format = GC2145_REG_OUTPUT_FMT_RGB565;
905 	} else if (output_format == VIDEO_PIX_FMT_YUYV) {
906 		output_format = GC2145_REG_OUTPUT_FMT_YCBYCR;
907 	} else {
908 		LOG_ERR("Image format not supported");
909 		return -ENOTSUP;
910 	}
911 
912 	ret = gc2145_read_reg(&cfg->i2c, GC2145_REG_OUTPUT_FMT, &old_value);
913 	if (ret < 0) {
914 		return ret;
915 	}
916 
917 	ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_OUTPUT_FMT,
918 			(old_value & ~GC2145_REG_OUTPUT_FMT_MASK) | output_format);
919 	if (ret < 0) {
920 		return ret;
921 	}
922 
923 	k_sleep(K_MSEC(30));
924 
925 	return 0;
926 }
927 
gc2145_set_resolution(const struct device * dev,uint32_t w,uint32_t h)928 static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t h)
929 {
930 	int ret;
931 	const struct gc2145_config *cfg = dev->config;
932 
933 	uint16_t win_w;
934 	uint16_t win_h;
935 	uint16_t c_ratio;
936 	uint16_t r_ratio;
937 	uint16_t x;
938 	uint16_t y;
939 	uint16_t win_x;
940 	uint16_t win_y;
941 
942 	/* Add the subsampling factor depending on resolution */
943 	switch (w) {
944 	case RESOLUTION_QVGA_W:
945 		c_ratio = 3;
946 		r_ratio = 3;
947 		break;
948 	case RESOLUTION_VGA_W:
949 		c_ratio = 2;
950 		r_ratio = 2;
951 		break;
952 	case RESOLUTION_UXGA_W:
953 		c_ratio = 1;
954 		r_ratio = 1;
955 		break;
956 	default:
957 		LOG_ERR("Unsupported resolution %d %d", w, h);
958 		return -EIO;
959 	};
960 
961 	/* Calculates the window boundaries to obtain the desired resolution */
962 	win_w = w * c_ratio;
963 	win_h = h * r_ratio;
964 	x = (((win_w / c_ratio) - w) / 2);
965 	y = (((win_h / r_ratio) - h) / 2);
966 	win_x = ((UXGA_HSIZE - win_w) / 2);
967 	win_y = ((UXGA_VSIZE - win_h) / 2);
968 
969 	/* Set readout window first. */
970 	ret = gc2145_set_window(dev, GC2145_REG_BLANK_WINDOW_BASE, win_x, win_y, win_w + 16,
971 				win_h + 8);
972 	if (ret < 0) {
973 		return ret;
974 	}
975 
976 	/* Set cropping window next. */
977 	ret = gc2145_set_window(dev, GC2145_REG_WINDOW_BASE, x, y, w, h);
978 	if (ret < 0) {
979 		return ret;
980 	}
981 
982 	/* Enable crop */
983 	ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_CROP_ENABLE, GC2145_CROP_SET_ENABLE);
984 	if (ret < 0) {
985 		return ret;
986 	}
987 
988 	/* Set Sub-sampling ratio and mode */
989 	ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE, ((r_ratio << 4) | c_ratio));
990 	if (ret < 0) {
991 		return ret;
992 	}
993 
994 	ret = gc2145_write_reg(&cfg->i2c, GC2145_REG_SUBSAMPLE_MODE, GC2145_SUBSAMPLE_MODE_SMOOTH);
995 	if (ret < 0) {
996 		return ret;
997 	}
998 	/*
999 	 * Galaxy Core datasheet does not document the reason behind of this
1000 	 * and other short delay requirements, but the reason exposed by them
1001 	 * is to give enough time for the sensor DSP to handle the I2C transaction
1002 	 * give some time time to apply the changes before the next instruction.
1003 	 */
1004 	k_sleep(K_MSEC(30));
1005 
1006 	return 0;
1007 }
1008 
gc2145_check_connection(const struct device * dev)1009 static uint8_t gc2145_check_connection(const struct device *dev)
1010 {
1011 	int ret;
1012 	const struct gc2145_config *cfg = dev->config;
1013 	uint8_t reg_pid_val;
1014 	uint8_t reg_ver_val;
1015 
1016 	ret = gc2145_read_reg(&cfg->i2c, 0xf0, &reg_pid_val);
1017 	if (ret < 0) {
1018 		return ret;
1019 	}
1020 
1021 	ret = gc2145_read_reg(&cfg->i2c, 0xf1, &reg_ver_val);
1022 	if (ret < 0) {
1023 		return ret;
1024 	}
1025 
1026 	if ((reg_ver_val != GC2145_REV_VAL) || (reg_pid_val != GC2145_PID_VAL)) {
1027 		LOG_WRN("Unexpected GC2145 pid: 0x%x or rev: 0x%x", reg_pid_val, reg_ver_val);
1028 	}
1029 
1030 	return 0;
1031 }
1032 
gc2145_set_fmt(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)1033 static int gc2145_set_fmt(const struct device *dev, enum video_endpoint_id ep,
1034 			  struct video_format *fmt)
1035 {
1036 	struct gc2145_data *drv_data = dev->data;
1037 	size_t res = ARRAY_SIZE(fmts);
1038 	int ret;
1039 
1040 	if (memcmp(&drv_data->fmt, fmt, sizeof(drv_data->fmt)) == 0) {
1041 		/* nothing to do */
1042 		return 0;
1043 	}
1044 
1045 	/* Check if camera is capable of handling given format */
1046 	for (int i = 0; i < ARRAY_SIZE(fmts) - 1; i++) {
1047 		if (fmts[i].width_min == fmt->width && fmts[i].height_min == fmt->height &&
1048 		    fmts[i].pixelformat == fmt->pixelformat) {
1049 			res = i;
1050 			break;
1051 		}
1052 	}
1053 	if (res == ARRAY_SIZE(fmts)) {
1054 		LOG_ERR("Image format not supported");
1055 		return -ENOTSUP;
1056 	}
1057 
1058 	drv_data->fmt = *fmt;
1059 
1060 	/* Set output format */
1061 	ret = gc2145_set_output_format(dev, fmt->pixelformat);
1062 	if (ret < 0) {
1063 		LOG_ERR("Failed to set the output format");
1064 		return ret;
1065 	}
1066 
1067 	/* Set window size */
1068 	ret = gc2145_set_resolution(dev, fmt->width, fmt->height);
1069 
1070 	if (ret < 0) {
1071 		LOG_ERR("Failed to set the resolution");
1072 		return ret;
1073 	}
1074 
1075 	return 0;
1076 }
1077 
gc2145_get_fmt(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)1078 static int gc2145_get_fmt(const struct device *dev, enum video_endpoint_id ep,
1079 			  struct video_format *fmt)
1080 {
1081 	struct gc2145_data *drv_data = dev->data;
1082 
1083 	*fmt = drv_data->fmt;
1084 
1085 	return 0;
1086 }
1087 
gc2145_set_stream(const struct device * dev,bool enable)1088 static int gc2145_set_stream(const struct device *dev, bool enable)
1089 {
1090 	const struct gc2145_config *cfg = dev->config;
1091 
1092 	return enable ? gc2145_write_reg(&cfg->i2c, 0xf2, 0x0f)
1093 		      : gc2145_write_reg(&cfg->i2c, 0xf2, 0x00);
1094 }
1095 
gc2145_get_caps(const struct device * dev,enum video_endpoint_id ep,struct video_caps * caps)1096 static int gc2145_get_caps(const struct device *dev, enum video_endpoint_id ep,
1097 			   struct video_caps *caps)
1098 {
1099 	caps->format_caps = fmts;
1100 	return 0;
1101 }
1102 
gc2145_set_ctrl(const struct device * dev,unsigned int cid,void * value)1103 static int gc2145_set_ctrl(const struct device *dev, unsigned int cid, void *value)
1104 {
1105 	switch (cid) {
1106 	case VIDEO_CID_HFLIP:
1107 		return gc2145_set_ctrl_hmirror(dev, (int)value);
1108 	case VIDEO_CID_VFLIP:
1109 		return gc2145_set_ctrl_vflip(dev, (int)value);
1110 	default:
1111 		return -ENOTSUP;
1112 	}
1113 }
1114 
1115 static DEVICE_API(video, gc2145_driver_api) = {
1116 	.set_format = gc2145_set_fmt,
1117 	.get_format = gc2145_get_fmt,
1118 	.get_caps = gc2145_get_caps,
1119 	.set_stream = gc2145_set_stream,
1120 	.set_ctrl = gc2145_set_ctrl,
1121 };
1122 
gc2145_init(const struct device * dev)1123 static int gc2145_init(const struct device *dev)
1124 {
1125 	struct video_format fmt;
1126 	int ret;
1127 	const struct gc2145_config *cfg = dev->config;
1128 	(void) cfg;
1129 
1130 #if DT_INST_NODE_HAS_PROP(0, pwdn_gpios)
1131 	ret = gpio_pin_configure_dt(&cfg->pwdn_gpio, GPIO_OUTPUT_INACTIVE);
1132 	if (ret) {
1133 		return ret;
1134 	}
1135 
1136 	k_sleep(K_MSEC(10));
1137 #endif
1138 #if DT_INST_NODE_HAS_PROP(0, reset_gpios)
1139 	ret = gpio_pin_configure_dt(&cfg->reset_gpio, GPIO_OUTPUT_ACTIVE);
1140 	if (ret) {
1141 		return ret;
1142 	}
1143 
1144 	k_sleep(K_MSEC(1));
1145 	gpio_pin_set_dt(&cfg->reset_gpio, 0);
1146 	k_sleep(K_MSEC(1));
1147 #endif
1148 
1149 	ret = gc2145_check_connection(dev);
1150 	if (ret) {
1151 		return ret;
1152 	}
1153 
1154 	gc2145_soft_reset(dev);
1155 	gc2145_write_all(dev, default_regs, ARRAY_SIZE(default_regs));
1156 
1157 	/* set default/init format QVGA RGB565 */
1158 	fmt.pixelformat = VIDEO_PIX_FMT_RGB565;
1159 	fmt.width = RESOLUTION_QVGA_W;
1160 	fmt.height = RESOLUTION_QVGA_H;
1161 	fmt.pitch = RESOLUTION_QVGA_W * 2;
1162 
1163 	ret = gc2145_set_fmt(dev, VIDEO_EP_OUT, &fmt);
1164 	if (ret) {
1165 		LOG_ERR("Unable to configure default format");
1166 		return ret;
1167 	}
1168 
1169 	return 0;
1170 }
1171 
1172 /* Unique Instance */
1173 static const struct gc2145_config gc2145_cfg_0 = {
1174 	.i2c = I2C_DT_SPEC_INST_GET(0),
1175 #if DT_INST_NODE_HAS_PROP(0, pwdn_gpios)
1176 	.pwdn_gpio = GPIO_DT_SPEC_INST_GET(0, pwdn_gpios),
1177 #endif
1178 #if DT_INST_NODE_HAS_PROP(0, reset_gpios)
1179 	.reset_gpio = GPIO_DT_SPEC_INST_GET(0, reset_gpios),
1180 #endif
1181 };
1182 static struct gc2145_data gc2145_data_0;
1183 
gc2145_init_0(const struct device * dev)1184 static int gc2145_init_0(const struct device *dev)
1185 {
1186 	const struct gc2145_config *cfg = dev->config;
1187 
1188 	if (!i2c_is_ready_dt(&cfg->i2c)) {
1189 		LOG_ERR("Bus device is not ready");
1190 		return -ENODEV;
1191 	}
1192 
1193 #if DT_INST_NODE_HAS_PROP(0, pwdn_gpios)
1194 	if (!gpio_is_ready_dt(&cfg->pwdn_gpio)) {
1195 		LOG_ERR("%s: device %s is not ready", dev->name, cfg->pwdn_gpio.port->name);
1196 		return -ENODEV;
1197 	}
1198 #endif
1199 #if DT_INST_NODE_HAS_PROP(0, reset_gpios)
1200 	if (!gpio_is_ready_dt(&cfg->reset_gpio)) {
1201 		LOG_ERR("%s: device %s is not ready", dev->name, cfg->reset_gpio.port->name);
1202 		return -ENODEV;
1203 	}
1204 #endif
1205 
1206 	return gc2145_init(dev);
1207 }
1208 
1209 DEVICE_DT_INST_DEFINE(0, &gc2145_init_0, NULL, &gc2145_data_0, &gc2145_cfg_0, POST_KERNEL,
1210 		      CONFIG_VIDEO_INIT_PRIORITY, &gc2145_driver_api);
1211