1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * vehicle sensor tp2825
4 *
5 * Copyright (C) 2020 Rockchip Electronics Co.Ltd
6 * Authors:
7 * Zhiqin Wei <wzq@rock-chips.com>
8 *
9 */
10
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/delay.h>
15 #include <linux/sched.h>
16 #include <linux/errno.h>
17 #include <linux/sysctl.h>
18 #include <linux/interrupt.h>
19 #include <linux/platform_device.h>
20 #include <linux/proc_fs.h>
21 #include <linux/suspend.h>
22 #include <linux/delay.h>
23 #include <linux/io.h>
24 #include <linux/irq.h>
25 #include <linux/uaccess.h>
26 #include <linux/of_gpio.h>
27 #include <linux/of_irq.h>
28 #include "vehicle_cfg.h"
29 #include "vehicle_main.h"
30 #include "vehicle_ad.h"
31 #include "vehicle_ad_tp2825.h"
32
33 enum {
34 CVSTD_720P60 = 0,
35 CVSTD_720P50,
36 CVSTD_1080P30,
37 CVSTD_1080P25,
38 CVSTD_720P30,
39 CVSTD_720P25,
40 CVSTD_SD,
41 CVSTD_NTSC,
42 CVSTD_PAL
43 };
44
45 enum {
46 FORCE_PAL_WIDTH = 960,
47 FORCE_PAL_HEIGHT = 576,
48 FORCE_NTSC_WIDTH = 960,
49 FORCE_NTSC_HEIGHT = 480,
50 FORCE_CIF_OUTPUT_FORMAT = CIF_OUTPUT_FORMAT_420,
51 };
52
53 enum {
54 VIDEO_UNPLUG,
55 VIDEO_IN,
56 VIDEO_LOCKED,
57 VIDEO_UNLOCK
58 };
59 #define FLAG_LOSS (0x1 << 7)
60 #define FLAG_V_LOCKED (0x1 << 6)
61 #define FLAG_H_LOCKED (0x1 << 5)
62 #define FLAG_CARRIER_PLL_LOCKED (0x1 << 4)
63 #define FLAG_VIDEO_DETECTED (0x1 << 3)
64 #define FLAG_EQ_SD_DETECTED (0x1 << 2)
65 #define FLAG_PROGRESSIVE (0x1 << 1)
66 #define FLAG_NO_CARRIER (0x1 << 0)
67 #define FLAG_LOCKED (FLAG_V_LOCKED | FLAG_H_LOCKED)
68
69 static struct vehicle_ad_dev *tp2825_g_addev;
70 static int cvstd_mode = CVSTD_720P50;
71 static int cvstd_old = CVSTD_720P50;
72 static int cvstd_sd = CVSTD_NTSC;
73 static int cvstd_state = VIDEO_UNPLUG;
74 static int cvstd_old_state = VIDEO_UNPLUG;
75
76 #define SENSOR_REGISTER_LEN 1 /* sensor register address bytes*/
77 #define SENSOR_VALUE_LEN 1 /* sensor register value bytes*/
78
79 struct rk_sensor_reg {
80 unsigned int reg;
81 unsigned int val;
82 };
83
84 #define SENSOR_CHANNEL_REG 0x41
85
86 #define SEQCMD_END 0xFF000000
87 #define SensorEnd {SEQCMD_END, 0x00}
88
89 #define SENSOR_DG VEHICLE_DG
90
91 /* Preview resolution setting*/
92 static struct rk_sensor_reg sensor_preview_data_ntsc[] = {
93 {0x02, 0xCF},
94 {0x06, 0x32},
95 {0x07, 0xC0},
96 {0x08, 0x00},
97 {0x09, 0x24},
98 {0x0A, 0x48},
99 {0x0B, 0xC0},
100 {0x0C, 0x53},
101 {0x0D, 0x10},
102 {0x0E, 0x00},
103 {0x0F, 0x00},
104 {0x10, 0x5e},
105 {0x11, 0x40},
106 {0x12, 0x44},
107 {0x13, 0x00},
108 {0x14, 0x00},
109 {0x15, 0x13},
110 {0x16, 0x4E},
111 {0x17, 0xBC},
112 {0x18, 0x15},
113 {0x19, 0xF0},
114 {0x1A, 0x07},
115 {0x1B, 0x00},
116 {0x1C, 0x09},
117 {0x1D, 0x38},
118 {0x1E, 0x80},
119 {0x1F, 0x80},
120 {0x20, 0xA0},
121 {0x21, 0x86},
122 {0x22, 0x38},
123 {0x23, 0x3C},
124 {0x24, 0x56},
125 {0x25, 0xFF},
126 {0x26, 0x12},
127 {0x27, 0x2D},
128 {0x28, 0x00},
129 {0x29, 0x48},
130 {0x2A, 0x30},
131 {0x2B, 0x70},
132 {0x2C, 0x1A},
133 {0x2D, 0x68},
134 {0x2E, 0x5E},
135 {0x2F, 0x00},
136 {0x30, 0x62},
137 {0x31, 0xBB},
138 {0x32, 0x96},
139 {0x33, 0xC0},
140 {0x34, 0x00},
141 {0x35, 0x65},
142 {0x36, 0xDC},
143 {0x37, 0x00},
144 {0x38, 0x40},
145 {0x39, 0x84},
146 {0x3A, 0x00},
147 {0x3B, 0x03},
148 {0x3C, 0x00},
149 {0x3D, 0x60},
150 {0x3E, 0x00},
151 {0x3F, 0x00},
152 {0x40, 0x00},
153 {0x41, 0x00},
154 {0x42, 0x00},
155 {0x43, 0x12},
156 {0x44, 0x07},
157 {0x45, 0x49},
158 {0x46, 0x00},
159 {0x47, 0x00},
160 {0x48, 0x00},
161 {0x49, 0x00},
162 {0x4A, 0x00},
163 {0x4B, 0x00},
164 {0x4C, 0x03},
165 {0x4D, 0x00},
166 {0x4E, 0x37},
167 {0x4F, 0x01},
168 {0xB5, 0x01},
169 {0xB8, 0x00},
170 {0xBA, 0x00},
171 {0xF3, 0x00},
172 {0xF4, 0x00},
173 {0xF5, 0x00},
174 {0xF6, 0x00},
175 {0xF7, 0x00},
176 {0xF8, 0x00},
177 {0xF9, 0x00},
178 {0xFA, 0x00},
179 {0xFB, 0x00},
180 {0xFC, 0xC0},
181 {0xFD, 0x00},
182 SensorEnd
183 };
184
185 static struct rk_sensor_reg sensor_preview_data_pal[] = {
186 {0x02, 0xCE},
187 {0x06, 0x32},
188 {0x07, 0xC0},
189 {0x08, 0x00},
190 {0x09, 0x24},
191 {0x0A, 0x48},
192 {0x0B, 0xC0},
193 {0x0C, 0x53},
194 {0x0D, 0x11},
195 {0x0E, 0x00},
196 {0x0F, 0x00},
197 {0x10, 0x70},
198 {0x11, 0x4D},
199 {0x12, 0x40},
200 {0x13, 0x00},
201 {0x14, 0x00},
202 {0x15, 0x13},
203 {0x16, 0x67},
204 {0x17, 0xBC},
205 {0x18, 0x16},
206 {0x19, 0x20},
207 {0x1A, 0x17},
208 {0x1B, 0x00},
209 {0x1C, 0x09},
210 {0x1D, 0x48},
211 {0x1E, 0x80},
212 {0x1F, 0x80},
213 {0x20, 0xB0},
214 {0x21, 0x86},
215 {0x22, 0x38},
216 {0x23, 0x3C},
217 {0x24, 0x56},
218 {0x25, 0xFF},
219 {0x26, 0x02},
220 {0x27, 0x2D},
221 {0x28, 0x00},
222 {0x29, 0x48},
223 {0x2A, 0x30},
224 {0x2B, 0x70},
225 {0x2C, 0x1A},
226 {0x2D, 0x60},
227 {0x2E, 0x5E},
228 {0x2F, 0x00},
229 {0x30, 0x7A},
230 {0x31, 0x4A},
231 {0x32, 0x4D},
232 {0x33, 0xF0},
233 {0x34, 0x00},
234 {0x35, 0x65},
235 {0x36, 0xDC},
236 {0x37, 0x00},
237 {0x38, 0x40},
238 {0x39, 0x84},
239 {0x3A, 0x00},
240 {0x3B, 0x03},
241 {0x3C, 0x00},
242 {0x3D, 0x60},
243 {0x3E, 0x00},
244 {0x3F, 0x00},
245 {0x40, 0x00},
246 {0x41, 0x00},
247 {0x42, 0x00},
248 {0x43, 0x12},
249 {0x44, 0x07},
250 {0x45, 0x49},
251 {0x46, 0x00},
252 {0x47, 0x00},
253 {0x48, 0x00},
254 {0x49, 0x00},
255 {0x4A, 0x00},
256 {0x4B, 0x00},
257 {0x4C, 0x03},
258 {0x4D, 0x00},
259 {0x4E, 0x37},
260 {0x4F, 0x00},
261 {0xB5, 0x01},
262 {0xB8, 0x00},
263 {0xBA, 0x00},
264 {0xF3, 0x00},
265 {0xF4, 0x00},
266 {0xF5, 0x00},
267 {0xF6, 0x00},
268 {0xF7, 0x00},
269 {0xF8, 0x00},
270 {0xF9, 0x00},
271 {0xFA, 0x00},
272 {0xFB, 0x00},
273 {0xFC, 0xC0},
274 {0xFD, 0x00},
275 SensorEnd
276 };
277
278 static struct rk_sensor_reg sensor_preview_data_720p_50hz[] = {
279 {0x02, 0xCA},
280 {0x06, 0x32},
281 {0x07, 0xC0},
282 {0x08, 0x00},
283 {0x09, 0x24},
284 {0x0A, 0x48},
285 {0x0B, 0xC0},
286 {0x0C, 0x43},
287 {0x0D, 0x10},
288 {0x0E, 0x00},
289 {0x0F, 0x00},
290 {0x10, 0xf0},
291 {0x11, 0x50},
292 {0x12, 0x60},
293 {0x13, 0x00},
294 {0x14, 0x08},
295 {0x15, 0x13},
296 {0x16, 0x16},
297 {0x17, 0x00},
298 {0x18, 0x18},
299 {0x19, 0xD0},
300 {0x1A, 0x25},
301 {0x1B, 0x00},
302 {0x1C, 0x07},
303 {0x1D, 0xBC},
304 {0x1E, 0x80},
305 {0x1F, 0x80},
306 {0x20, 0x60},
307 {0x21, 0x86},
308 {0x22, 0x38},
309 {0x23, 0x3C},
310 {0x24, 0x56},
311 {0x25, 0xFF},
312 {0x26, 0x02},
313 {0x27, 0x2D},
314 {0x28, 0x00},
315 {0x29, 0x48},
316 {0x2A, 0x30},
317 {0x2B, 0x4A},
318 {0x2C, 0x1A},
319 {0x2D, 0x30},
320 {0x2E, 0x70},
321 {0x2F, 0x00},
322 {0x30, 0x48},
323 {0x31, 0xBB},
324 {0x32, 0x2E},
325 {0x33, 0x90},
326 {0x34, 0x00},
327 {0x35, 0x05},
328 {0x36, 0xDC},
329 {0x37, 0x00},
330 {0x38, 0x40},
331 {0x39, 0x8C},
332 {0x3A, 0x00},
333 {0x3B, 0x03},
334 {0x3C, 0x00},
335 {0x3D, 0x60},
336 {0x3E, 0x00},
337 {0x3F, 0x00},
338 {0x40, 0x00},
339 {0x41, 0x00},
340 {0x42, 0x00},
341 {0x43, 0x12},
342 {0x44, 0x07},
343 {0x45, 0x49},
344 {0x46, 0x00},
345 {0x47, 0x00},
346 {0x48, 0x00},
347 {0x49, 0x00},
348 {0x4A, 0x00},
349 {0x4B, 0x00},
350 {0x4C, 0x03},
351 {0x4D, 0x00},
352 {0x4E, 0x03},
353 {0x4F, 0x01},
354 {0xB5, 0x01},
355 {0xB8, 0x00},
356 {0xBA, 0x00},
357 {0xF3, 0x00},
358 {0xF4, 0x00},
359 {0xF5, 0x00},
360 {0xF6, 0x00},
361 {0xF7, 0x00},
362 {0xF8, 0x00},
363 {0xF9, 0x00},
364 {0xFA, 0x00},
365 {0xFB, 0x00},
366 {0xFC, 0xC0},
367 {0xFD, 0x00},
368 SensorEnd
369 };
370
371 static struct rk_sensor_reg sensor_preview_data_720p_30hz[] = {
372 {0x02, 0xDA},
373 {0x06, 0x32},
374 {0x07, 0xC0},
375 {0x08, 0x00},
376 {0x09, 0x24},
377 {0x0A, 0x48},
378 {0x0B, 0xC0},
379 {0x0C, 0x53},
380 {0x0D, 0x10},
381 {0x0E, 0x00},
382 {0x0F, 0x00},
383 {0x10, 0xf0},
384 {0x11, 0x50},
385 {0x12, 0x60},
386 {0x13, 0x00},
387 {0x14, 0x08},
388 {0x15, 0x13},
389 {0x16, 0x16},
390 {0x17, 0x00},
391 {0x18, 0x19},
392 {0x19, 0xD0},
393 {0x1A, 0x25},
394 {0x1B, 0x00},
395 {0x1C, 0x06},
396 {0x1D, 0x72},
397 {0x1E, 0x80},
398 {0x1F, 0x80},
399 {0x20, 0x60},
400 {0x21, 0x86},
401 {0x22, 0x38},
402 {0x23, 0x3C},
403 {0x24, 0x56},
404 {0x25, 0xFF},
405 {0x26, 0x02},
406 {0x27, 0x2D},
407 {0x28, 0x00},
408 {0x29, 0x48},
409 {0x2A, 0x30},
410 {0x2B, 0x4A},
411 {0x2C, 0x1A},
412 {0x2D, 0x30},
413 {0x2E, 0x70},
414 {0x2F, 0x00},
415 {0x30, 0x48},
416 {0x31, 0xBB},
417 {0x32, 0x2E},
418 {0x33, 0x90},
419 {0x34, 0x00},
420 {0x35, 0x25},
421 {0x36, 0xDC},
422 {0x37, 0x00},
423 {0x38, 0x40},
424 {0x39, 0x88},
425 {0x3A, 0x00},
426 {0x3B, 0x03},
427 {0x3C, 0x00},
428 {0x3D, 0x60},
429 {0x3E, 0x00},
430 {0x3F, 0x00},
431 {0x40, 0x03},
432 {0x41, 0x00},
433 {0x42, 0x00},
434 {0x43, 0x12},
435 {0x44, 0x07},
436 {0x45, 0x49},
437 {0x46, 0x00},
438 {0x47, 0x00},
439 {0x48, 0x00},
440 {0x49, 0x00},
441 {0x4A, 0x00},
442 {0x4B, 0x00},
443 {0x4C, 0x03},
444 {0x4D, 0x00},
445 {0x4E, 0x17},
446 {0x4F, 0x01},
447 {0x85, 0x00},
448 {0x88, 0x00},
449 {0x8A, 0x00},
450 {0xF3, 0x00},
451 {0xF4, 0x00},
452 {0xF5, 0x00},
453 {0xF6, 0x00},
454 {0xF7, 0x00},
455 {0xF8, 0x00},
456 {0xF9, 0x00},
457 {0xFA, 0x00},
458 {0xFB, 0x00},
459 {0xFC, 0xC0},
460 {0xFD, 0x00},
461 SensorEnd
462 };
463
464 static struct rk_sensor_reg sensor_preview_data_720p_25hz[] = {
465 {0x02, 0xCA},
466 {0x06, 0x32},
467 {0x07, 0xC0},
468 {0x08, 0x00},
469 {0x09, 0x24},
470 {0x0A, 0x48},
471 {0x0B, 0xC0},
472 {0x0C, 0x53},
473 {0x0D, 0x10},
474 {0x0E, 0x00},
475 {0x0F, 0x00},
476 {0x10, 0xf0},
477 {0x11, 0x50},
478 {0x12, 0x60},
479 {0x13, 0x00},
480 {0x14, 0x08},
481 {0x15, 0x13},
482 {0x16, 0x16},
483 {0x17, 0x00},
484 {0x18, 0x19},
485 {0x19, 0xD0},
486 {0x1A, 0x25},
487 {0x1B, 0x00},
488 {0x1C, 0x07},
489 {0x1D, 0xBC},
490 {0x1E, 0x80},
491 {0x1F, 0x80},
492 {0x20, 0x60},
493 {0x21, 0x86},
494 {0x22, 0x38},
495 {0x23, 0x3C},
496 {0x24, 0x56},
497 {0x25, 0xFF},
498 {0x26, 0x02},
499 {0x27, 0x2D},
500 {0x28, 0x00},
501 {0x29, 0x48},
502 {0x2A, 0x30},
503 {0x2B, 0x70},
504 {0x2C, 0x1A},
505 {0x2D, 0x30},
506 {0x2E, 0x70},
507 {0x2F, 0x00},
508 {0x30, 0x48},
509 {0x31, 0xBB},
510 {0x32, 0x2E},
511 {0x33, 0x90},
512 {0x34, 0x00},
513 {0x35, 0x25},
514 {0x36, 0xDC},
515 {0x37, 0x00},
516 {0x38, 0x40},
517 {0x39, 0x88},
518 {0x3A, 0x00},
519 {0x3B, 0x03},
520 {0x3C, 0x00},
521 {0x3D, 0x60},
522 {0x3E, 0x00},
523 {0x3F, 0x00},
524 {0x40, 0x00},
525 {0x41, 0x00},
526 {0x42, 0x00},
527 {0x43, 0x12},
528 {0x44, 0x07},
529 {0x45, 0x49},
530 {0x46, 0x00},
531 {0x47, 0x00},
532 {0x48, 0x00},
533 {0x49, 0x00},
534 {0x4A, 0x00},
535 {0x4B, 0x00},
536 {0x4C, 0x03},
537 {0x4D, 0x00},
538 {0x4E, 0x17},
539 {0x4F, 0x01},
540 {0xB5, 0x01},
541 {0xB8, 0x00},
542 {0xBA, 0x00},
543 {0xF3, 0x00},
544 {0xF4, 0x00},
545 {0xF5, 0x00},
546 {0xF6, 0x00},
547 {0xF7, 0x00},
548 {0xF8, 0x00},
549 {0xF9, 0x00},
550 {0xFA, 0x00},
551 {0xFB, 0x00},
552 {0xFC, 0xC0},
553 {0xFD, 0x00},
554 SensorEnd
555 };
556
tp2825_reinit_parameter(struct vehicle_ad_dev * ad,unsigned char cvstd)557 static void tp2825_reinit_parameter(struct vehicle_ad_dev *ad, unsigned char cvstd)
558 {
559 int i = 0, defrect_index = 0;
560
561 switch (cvstd) {
562 case CVSTD_PAL:
563 ad->cfg.width = FORCE_PAL_WIDTH;
564 ad->cfg.height = FORCE_PAL_HEIGHT;
565 ad->cfg.start_x = 0;
566 ad->cfg.start_y = 0;
567 ad->cfg.input_format = CIF_INPUT_FORMAT_PAL;
568 ad->cfg.output_format = FORCE_CIF_OUTPUT_FORMAT;
569 ad->cfg.field_order = 0;
570 ad->cfg.yuv_order = 0;
571 ad->cfg.href = 0;
572 ad->cfg.vsync = 0;
573 ad->cfg.frame_rate = 25;
574 ad->cfg.type = V4L2_MBUS_PARALLEL;
575 ad->cfg.mbus_flags = V4L2_MBUS_HSYNC_ACTIVE_LOW |
576 V4L2_MBUS_VSYNC_ACTIVE_LOW |
577 V4L2_MBUS_PCLK_SAMPLE_RISING;
578 break;
579 case CVSTD_NTSC:
580 ad->cfg.width = FORCE_NTSC_WIDTH;
581 ad->cfg.height = FORCE_NTSC_HEIGHT;
582 ad->cfg.start_x = 0;
583 ad->cfg.start_y = 0;
584 ad->cfg.input_format = CIF_INPUT_FORMAT_NTSC;
585 ad->cfg.output_format = FORCE_CIF_OUTPUT_FORMAT;
586 ad->cfg.field_order = 0;
587 ad->cfg.yuv_order = 0;
588 ad->cfg.href = 0;
589 ad->cfg.vsync = 0;
590 ad->cfg.frame_rate = 30;
591 ad->cfg.type = V4L2_MBUS_PARALLEL;
592 ad->cfg.mbus_flags = V4L2_MBUS_HSYNC_ACTIVE_LOW |
593 V4L2_MBUS_VSYNC_ACTIVE_LOW |
594 V4L2_MBUS_PCLK_SAMPLE_RISING;
595 break;
596 default:
597 ad->cfg.width = 1280;
598 ad->cfg.height = 720;
599 ad->cfg.start_x = 8;
600 ad->cfg.start_y = 20;
601 ad->cfg.input_format = CIF_INPUT_FORMAT_YUV;
602 ad->cfg.output_format = FORCE_CIF_OUTPUT_FORMAT;
603 ad->cfg.field_order = 0;
604 ad->cfg.yuv_order = 0;/*00 - UYVY*/
605 ad->cfg.href = 0;
606 ad->cfg.vsync = 1;
607 ad->cfg.frame_rate = 50;
608 ad->cfg.type = V4L2_MBUS_PARALLEL;
609 ad->cfg.mbus_flags = V4L2_MBUS_HSYNC_ACTIVE_LOW |
610 V4L2_MBUS_VSYNC_ACTIVE_HIGH |
611 V4L2_MBUS_PCLK_SAMPLE_RISING;
612 break;
613 }
614
615 /* fix crop info from dts config */
616 for (i = 0; i < 4; i++) {
617 if ((ad->defrects[i].width == ad->cfg.width) &&
618 (ad->defrects[i].height == ad->cfg.height)) {
619 ad->cfg.start_x = ad->defrects[i].crop_x;
620 ad->cfg.start_y = ad->defrects[i].crop_y;
621 ad->cfg.width = ad->defrects[i].crop_width;
622 ad->cfg.height = ad->defrects[i].crop_height;
623 defrect_index = i;
624 }
625 }
626
627 #ifdef CVBS_DOUBLE_FPS_MODE
628 switch (cvstd) {
629 case CVSTD_PAL:
630 if (!strstr(ad->defrects[defrect_index].interface, "pal")) {
631 ad->cfg.height /= 2;
632 ad->cfg.input_format =
633 CIF_INPUT_FORMAT_PAL_SW_COMPOSITE;
634 ad->cfg.href = 0;
635 ad->cfg.vsync = 1;
636 ad->cfg.frame_rate = 50;
637 }
638 break;
639 case CVSTD_NTSC:
640 if (!strstr(ad->defrects[defrect_index].interface, "ntsc")) {
641 ad->cfg.height /= 2;
642 ad->cfg.input_format =
643 CIF_INPUT_FORMAT_NTSC_SW_COMPOSITE;
644 ad->cfg.href = 0;
645 ad->cfg.vsync = 1;
646 ad->cfg.frame_rate = 60;
647 }
648 break;
649 }
650 #endif
651 SENSOR_DG("%s,crop(%d,%d)", __func__, ad->cfg.start_x, ad->cfg.start_y);
652 }
653
tp2825_reg_init(struct vehicle_ad_dev * ad,unsigned char cvstd)654 static void tp2825_reg_init(struct vehicle_ad_dev *ad, unsigned char cvstd)
655 {
656 struct rk_sensor_reg *sensor;
657 int i;
658 unsigned char val[2];
659
660 switch (cvstd) {
661 case CVSTD_720P50:
662 sensor = sensor_preview_data_720p_50hz;
663 break;
664 case CVSTD_720P30:
665 sensor = sensor_preview_data_720p_30hz;
666 break;
667 case CVSTD_720P25:
668 sensor = sensor_preview_data_720p_25hz;
669 break;
670 case CVSTD_PAL:
671 sensor = sensor_preview_data_pal;
672 break;
673 case CVSTD_NTSC:
674 sensor = sensor_preview_data_ntsc;
675 break;
676 default:
677 sensor = sensor_preview_data_720p_50hz;
678 break;
679 }
680 i = 0;
681 while ((sensor[i].reg != SEQCMD_END) && (sensor[i].reg != 0xFC000000)) {
682 if (sensor[i].reg == SENSOR_CHANNEL_REG)
683 sensor[i].val = ad->ad_chl;
684
685 val[0] = sensor[i].val;
686 vehicle_generic_sensor_write(ad, sensor[i].reg, val);
687 i++;
688 }
689 }
690
tp2825_channel_set(struct vehicle_ad_dev * ad,int channel)691 void tp2825_channel_set(struct vehicle_ad_dev *ad, int channel)
692 {
693 unsigned int reg = 0x41;
694 unsigned char val[0];
695
696 val[0] = channel;
697 ad->ad_chl = channel;
698
699 vehicle_generic_sensor_write(ad, reg, val);
700 }
701
tp2825_ad_get_cfg(struct vehicle_cfg ** cfg)702 int tp2825_ad_get_cfg(struct vehicle_cfg **cfg)
703 {
704 if (!tp2825_g_addev)
705 return -1;
706
707 switch (cvstd_state) {
708 case VIDEO_UNPLUG:
709 tp2825_g_addev->cfg.ad_ready = false;
710 break;
711 case VIDEO_LOCKED:
712 tp2825_g_addev->cfg.ad_ready = true;
713 break;
714 case VIDEO_IN:
715 tp2825_g_addev->cfg.ad_ready = false;
716 break;
717 }
718
719 *cfg = &tp2825_g_addev->cfg;
720
721 return 0;
722 }
723
tp2825_ad_check_cif_error(struct vehicle_ad_dev * ad,int last_line)724 void tp2825_ad_check_cif_error(struct vehicle_ad_dev *ad, int last_line)
725 {
726 SENSOR_DG("%s, last_line %d\n", __func__, last_line);
727 if (last_line < 1)
728 return;
729
730 ad->cif_error_last_line = last_line;
731 if (cvstd_mode == CVSTD_PAL) {
732 if (last_line == FORCE_NTSC_HEIGHT) {
733 if (ad->state_check_work.state_check_wq)
734 queue_delayed_work(
735 ad->state_check_work.state_check_wq,
736 &ad->state_check_work.work,
737 msecs_to_jiffies(0));
738 }
739 } else if (cvstd_mode == CVSTD_NTSC) {
740 if (last_line == FORCE_PAL_HEIGHT) {
741 if (ad->state_check_work.state_check_wq)
742 queue_delayed_work(
743 ad->state_check_work.state_check_wq,
744 &ad->state_check_work.work,
745 msecs_to_jiffies(0));
746 }
747 }
748 }
749
tp2825_check_id(struct vehicle_ad_dev * ad)750 int tp2825_check_id(struct vehicle_ad_dev *ad)
751 {
752 int ret = 0;
753 int pidh, pidl;
754
755 pidh = vehicle_generic_sensor_read(ad, 0xfe);
756 pidl = vehicle_generic_sensor_read(ad, 0xff);
757 if (pidh != 0x28 || pidl != 0x25) {
758 SENSOR_DG("%s: expected 0x2825, detected 0x%02x 0x%02x\n",
759 ad->ad_name, pidh, pidl);
760 ret = -EINVAL;
761 }
762
763 return ret;
764 }
765
tp2825_check_cvstd(struct vehicle_ad_dev * ad,bool activate_check)766 static int tp2825_check_cvstd(struct vehicle_ad_dev *ad, bool activate_check)
767 {
768 unsigned char cvstd = 0;
769 unsigned char status = 0;
770 static bool is_first = true;
771 static int state = VIDEO_UNPLUG;
772 int check_count = 20;
773 unsigned char v[2];
774
775 check_continue:
776 status = vehicle_generic_sensor_read(ad, 0x01);
777
778 if (status & FLAG_LOSS) {
779 state = VIDEO_UNPLUG;
780 v[0] = 0x01;
781 vehicle_generic_sensor_write(ad, 0x26, v);
782 } else if (FLAG_LOCKED == (status & FLAG_LOCKED)) {
783 /* video locked */
784 state = VIDEO_LOCKED;
785 v[0] = 0x02;
786 vehicle_generic_sensor_write(ad, 0x26, v);
787 } else {
788 /* video in but unlocked */
789 state = VIDEO_IN;
790 v[0] = 0x02;
791 vehicle_generic_sensor_write(ad, 0x26, v);
792 }
793
794 if (state == VIDEO_IN) {
795 cvstd = vehicle_generic_sensor_read(ad, 0x03);
796 SENSOR_DG("%s(%d): cvstd_old %d, read 0x03 return 0x%x",
797 __func__, __LINE__, cvstd_old, cvstd);
798
799 cvstd &= 0x07;
800 if (cvstd == cvstd_old)
801 goto check_end;
802
803 if (cvstd == CVSTD_720P30) {
804 cvstd_mode = CVSTD_720P30;
805 SENSOR_DG("%s(%d): 720P30\n", __func__, __LINE__);
806 } else if (cvstd == CVSTD_720P25) {
807 cvstd_mode = CVSTD_720P25;
808 SENSOR_DG("%s(%d): 720P25\n", __func__, __LINE__);
809 } else if (cvstd == CVSTD_720P60) {
810 SENSOR_DG("%s(%d): 720P60", __func__, __LINE__);
811 } else if (cvstd == CVSTD_720P50) {
812 cvstd_mode = CVSTD_720P50;
813 SENSOR_DG("%s(%d): 720P50\n", __func__, __LINE__);
814 } else if (cvstd == CVSTD_1080P30) {
815 SENSOR_DG("%s(%d): 1080P30", __func__, __LINE__);
816 } else if (cvstd == CVSTD_1080P25) {
817 SENSOR_DG("%s(%d): 1080P25", __func__, __LINE__);
818 } else if (cvstd == CVSTD_SD) {
819 msleep(80);
820 status = vehicle_generic_sensor_read(ad, 0x01);
821 SENSOR_DG("%s(%d): read 0x01 return 0x%x\n",
822 __func__, __LINE__, status);
823
824 /*
825 * 1: pal 0: ntsc
826 */
827 if ((status >> 2) & 0x01)
828 cvstd_sd = CVSTD_PAL;
829 else
830 cvstd_sd = CVSTD_NTSC;
831
832 SENSOR_DG("%s(%d): cvstd_sd is %s\n",
833 __func__, __LINE__,
834 (cvstd_sd == CVSTD_PAL) ? "PAL" : "NTSC");
835 cvstd_mode = cvstd_sd;
836 }
837 tp2825_reinit_parameter(ad, cvstd_mode);
838 } else if (state == VIDEO_LOCKED) {
839 goto check_end;
840 } else {
841 SENSOR_DG("%s: check sensor statue failed!\n", __func__);
842 goto check_end;
843 }
844
845 tp2825_reg_init(ad, cvstd_mode);
846 check_end:
847 if (check_count && is_first && (state != VIDEO_LOCKED)) {
848 check_count--;
849 if (cvstd == CVSTD_SD)
850 mdelay(100);
851 else
852 mdelay(100);
853 goto check_continue;
854 }
855 is_first = false;
856 cvstd_state = state;
857
858 return 0;
859 }
tp2825_stream(struct vehicle_ad_dev * ad,int enable)860 int tp2825_stream(struct vehicle_ad_dev *ad, int enable)
861 {
862 char val;
863
864 if (enable)
865 val = 0x03; //stream on
866 else
867 val = 0x00; //stream off
868 SENSOR_DG("stream write 0x%x to reg 0x4D\n", val);
869 vehicle_generic_sensor_write(ad, 0x4D, &val);
870
871 return 0;
872 }
power_on(struct vehicle_ad_dev * ad)873 static void power_on(struct vehicle_ad_dev *ad)
874 {
875 /* gpio_direction_output(ad->power, ad->pwr_active); */
876
877 if (gpio_is_valid(ad->powerdown)) {
878 gpio_request(ad->powerdown, "ad_powerdown");
879 gpio_direction_output(ad->powerdown, !ad->pwdn_active);
880 /* gpio_set_value(ad->powerdown, !ad->pwdn_active); */
881 }
882
883 if (gpio_is_valid(ad->power)) {
884 gpio_request(ad->power, "ad_power");
885 gpio_direction_output(ad->power, ad->pwr_active);
886 /* gpio_set_value(ad->power, ad->pwr_active); */
887 }
888 }
889
power_off(struct vehicle_ad_dev * ad)890 static void power_off(struct vehicle_ad_dev *ad)
891 {
892 if (gpio_is_valid(ad->power))
893 gpio_free(ad->power);
894 if (gpio_is_valid(ad->powerdown))
895 gpio_free(ad->powerdown);
896 }
897
tp2825_check_state_work(struct work_struct * work)898 static void tp2825_check_state_work(struct work_struct *work)
899 {
900 struct vehicle_ad_dev *ad;
901
902 ad = tp2825_g_addev;
903
904 if (ad->cif_error_last_line > 0) {
905 tp2825_check_cvstd(ad, true);
906 ad->cif_error_last_line = 0;
907 } else {
908 tp2825_check_cvstd(ad, false);
909 }
910
911 if (cvstd_old != cvstd_mode || cvstd_old_state != cvstd_state) {
912 cvstd_old = cvstd_mode;
913 cvstd_old_state = cvstd_state;
914 SENSOR_DG("ad signal change notify\n");
915 vehicle_ad_stat_change_notify();
916 }
917
918 queue_delayed_work(ad->state_check_work.state_check_wq,
919 &ad->state_check_work.work, msecs_to_jiffies(100));
920 }
921
tp2825_ad_deinit(void)922 int tp2825_ad_deinit(void)
923 {
924 struct vehicle_ad_dev *ad;
925
926 ad = tp2825_g_addev;
927
928 if (!ad)
929 return -1;
930
931 if (ad->state_check_work.state_check_wq) {
932 cancel_delayed_work_sync(&ad->state_check_work.work);
933 flush_delayed_work(&ad->state_check_work.work);
934 flush_workqueue(ad->state_check_work.state_check_wq);
935 destroy_workqueue(ad->state_check_work.state_check_wq);
936 }
937 if (ad->irq)
938 free_irq(ad->irq, ad);
939 power_off(ad);
940
941 return 0;
942 }
943
get_ad_mode_from_fix_format(int fix_format)944 static int get_ad_mode_from_fix_format(int fix_format)
945 {
946 int mode = -1;
947
948 switch (fix_format) {
949 case AD_FIX_FORMAT_PAL:
950 mode = CVSTD_PAL;
951 break;
952 case AD_FIX_FORMAT_NTSC:
953 mode = CVSTD_NTSC;
954 break;
955 case AD_FIX_FORMAT_720P_50FPS:
956 mode = CVSTD_720P50;
957 break;
958 case AD_FIX_FORMAT_720P_30FPS:
959 mode = CVSTD_720P30;
960 break;
961 case AD_FIX_FORMAT_720P_25FPS:
962 mode = CVSTD_720P25;
963 break;
964 default:
965 mode = -1;
966 break;
967 }
968
969 return mode;
970 }
971
tp2825_ad_init(struct vehicle_ad_dev * ad)972 int tp2825_ad_init(struct vehicle_ad_dev *ad)
973 {
974 int val = 0;
975 int i = 0;
976 int mode;
977
978 tp2825_g_addev = ad;
979
980 /* 1. i2c init */
981 while (ad->adapter == NULL) {
982 ad->adapter = i2c_get_adapter(ad->i2c_chl);
983 usleep_range(10000, 12000);
984 }
985 if (ad->adapter == NULL)
986 return -ENODEV;
987
988 if (!i2c_check_functionality(ad->adapter, I2C_FUNC_I2C))
989 return -EIO;
990
991 /* 2. ad power on sequence */
992 power_on(ad);
993
994 while (++i < 5) {
995 usleep_range(1000, 1200);
996 val = vehicle_generic_sensor_read(ad, 0x12);
997 if (val != 0xff)
998 break;
999 SENSOR_DG("tp2825_init i2c_reg_read fail\n");
1000 }
1001
1002 /* fix mode */
1003 mode = get_ad_mode_from_fix_format(ad->fix_format);
1004 if (mode > 0) {
1005 SENSOR_DG("fix format %d, fix cvxtd mode %d\n", ad->fix_format, mode);
1006 tp2825_reg_init(ad, mode);
1007 tp2825_reinit_parameter(ad, mode);
1008 SENSOR_DG("%s after init\n", __func__);
1009 /* wait for signal locked; */
1010 i = 0;
1011 while (++i < 10) {
1012 msleep(100);
1013 val = vehicle_generic_sensor_read(ad, 0x01);
1014 if ((FLAG_LOCKED == (val & FLAG_LOCKED)))
1015 break;
1016 }
1017 cvstd_state = VIDEO_LOCKED;
1018 return 0;
1019 }
1020
1021 /* 3 .init default format params */
1022 tp2825_reg_init(ad, cvstd_mode);
1023 tp2825_reinit_parameter(ad, cvstd_mode);
1024 SENSOR_DG("%s after reinit init\n", __func__);
1025
1026 /* 5. create workqueue to detect signal change */
1027 INIT_DELAYED_WORK(&ad->state_check_work.work, tp2825_check_state_work);
1028 ad->state_check_work.state_check_wq =
1029 create_singlethread_workqueue("vehicle-ad-tp2825");
1030
1031 /* tp2825_check_cvstd(ad, true); */
1032
1033 queue_delayed_work(ad->state_check_work.state_check_wq,
1034 &ad->state_check_work.work, msecs_to_jiffies(100));
1035
1036 return 0;
1037 }
1038
1039
1040