xref: /OK3568_Linux_fs/kernel/drivers/video/rockchip/vehicle/vehicle_ad_max96714.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * vehicle sensor max96714
4  *
5  * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
6  * Authors:
7  *	Jianwei Fan <jianwei.fan@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_max96714.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_SVGAP30,
41 	CVSTD_SD,
42 	CVSTD_NTSC,
43 	CVSTD_PAL
44 };
45 
46 enum {
47 	FORCE_PAL_WIDTH = 960,
48 	FORCE_PAL_HEIGHT = 576,
49 	FORCE_NTSC_WIDTH = 960,
50 	FORCE_NTSC_HEIGHT = 480,
51 	FORCE_SVGA_WIDTH = 800,
52 	FORCE_SVGA_HEIGHT = 600,
53 	FORCE_720P_WIDTH = 1280,
54 	FORCE_720P_HEIGHT = 720,
55 	FORCE_1080P_WIDTH = 1920,
56 	FORCE_1080P_HEIGHT = 1080,
57 	FORCE_CIF_OUTPUT_FORMAT = CIF_OUTPUT_FORMAT_420,
58 };
59 
60 enum {
61 	VIDEO_UNPLUG,
62 	VIDEO_IN,
63 	VIDEO_LOCKED,
64 	VIDEO_UNLOCK
65 };
66 
67 #define FLAG_LOCKED			(0x1 << 3)
68 #define MAX96714_LINK_FREQ_150M		150000000UL
69 
70 static struct vehicle_ad_dev *max96714_g_addev;
71 static int cvstd_mode = CVSTD_1080P30;
72 //static int cvstd_old = CVSTD_720P25;
73 static int cvstd_old = CVSTD_NTSC;
74 
75 //static int cvstd_sd = CVSTD_NTSC;
76 static int cvstd_state = VIDEO_UNPLUG;
77 static int cvstd_old_state = VIDEO_UNLOCK;
78 
79 static bool g_max96714_streaming;
80 
81 #define SENSOR_VALUE_LEN	1	/* sensor register value bytes*/
82 #define MAX96714_CHIP_ID	0xC9
83 #define MAX96714_CHIP_ID_REG	0x0D
84 #define MAX96714_GMSL_STATE	0x0013
85 #define MAX96714_STREAM_CTL	0x0313
86 #define MAX96714_MODE_SW_STANDBY	0x0
87 #define MAX96714_MODE_STREAMING		BIT(1)
88 
89 struct regval {
90 	u16 reg;
91 	u8 val;
92 };
93 #define REG_NULL  0xFFFF
94 
95 /* 1080p Preview resolution setting*/
96 static struct regval sensor_preview_data_1080p_30hz[] = {
97 	{0x0313, 0x00},
98 	{0x0001, 0x01},
99 	{0x0010, 0x21},
100 	{0x0320, 0x23},
101 	{0x0325, 0x80},
102 	{0x0313, 0x00},
103 	{REG_NULL, 0x00},
104 };
105 
106 static struct rkmodule_csi_dphy_param max96714_dcphy_param = {
107 	.vendor = PHY_VENDOR_SAMSUNG,
108 	.lp_vol_ref = 3,
109 	.lp_hys_sw = {3, 0, 0, 0},
110 	.lp_escclk_pol_sel = {1, 0, 0, 0},
111 	.skew_data_cal_clk = {0, 3, 3, 3},
112 	.clk_hs_term_sel = 2,
113 	.data_hs_term_sel = {2, 2, 2, 2},
114 	.reserved = {0},
115 };
116 
max96714_read_reg(struct vehicle_ad_dev * ad,u16 reg,unsigned int len,u32 * val)117 static int max96714_read_reg(struct vehicle_ad_dev *ad, u16 reg,
118 			    unsigned int len, u32 *val)
119 {
120 	struct i2c_msg msgs[2];
121 	u8 *data_be_p;
122 	__be32 data_be = 0;
123 	__be16 reg_addr_be = cpu_to_be16(reg);
124 	int ret;
125 
126 	if (len > 4 || !len)
127 		return -EINVAL;
128 
129 	data_be_p = (u8 *)&data_be;
130 	/* Write register address */
131 	msgs[0].addr = ad->i2c_add;
132 	msgs[0].flags = 0;
133 	msgs[0].len = 2;
134 	msgs[0].buf = (u8 *)&reg_addr_be;
135 
136 	/* Read data from register */
137 	msgs[1].addr = ad->i2c_add;
138 	msgs[1].flags = I2C_M_RD;
139 	msgs[1].len = len;
140 	msgs[1].buf = &data_be_p[4 - len];
141 
142 	ret = i2c_transfer(ad->adapter, msgs, ARRAY_SIZE(msgs));
143 	if (ret != ARRAY_SIZE(msgs))
144 		return -EIO;
145 
146 	*val = be32_to_cpu(data_be);
147 
148 	return 0;
149 }
150 
max96714_write_reg(struct vehicle_ad_dev * ad,u16 reg,u8 val)151 static int max96714_write_reg(struct vehicle_ad_dev *ad, u16 reg, u8 val)
152 {
153 	struct i2c_msg msg;
154 	u8 buf[3];
155 	int ret;
156 
157 	buf[0] = reg >> 8;
158 	buf[1] = reg & 0xff;
159 	buf[2] = val;
160 
161 	msg.addr = ad->i2c_add;
162 	msg.flags = 0;
163 	msg.buf = buf;
164 	msg.len = sizeof(buf);
165 
166 	ret = i2c_transfer(ad->adapter, &msg, 1);
167 	if (ret >= 0)
168 		return 0;
169 
170 	VEHICLE_DGERR(
171 		"max96714 write reg(0x%x val:0x%x) failed !\n", reg, val);
172 
173 	return ret;
174 }
175 
max96714_write_array(struct vehicle_ad_dev * ad,const struct regval * regs)176 static int max96714_write_array(struct vehicle_ad_dev *ad,
177 				const struct regval *regs)
178 {
179 	u32 i = 0;
180 	int ret = 0;
181 
182 	for (i = 0; ret == 0 && regs[i].reg != REG_NULL; i++)
183 		ret = max96714_write_reg(ad, regs[i].reg, regs[i].val);
184 
185 	return ret;
186 }
187 
max96714_reinit_parameter(struct vehicle_ad_dev * ad,unsigned char cvstd)188 static void max96714_reinit_parameter(struct vehicle_ad_dev *ad, unsigned char cvstd)
189 {
190 	int i = 0;
191 
192 	switch (cvstd) {
193 	case CVSTD_1080P30:
194 		ad->cfg.width = 1920;
195 		ad->cfg.height = 1080;
196 		ad->cfg.start_x = 0;
197 		ad->cfg.start_y = 0;
198 		ad->cfg.input_format = CIF_INPUT_FORMAT_YUV;
199 		ad->cfg.output_format = FORCE_CIF_OUTPUT_FORMAT;
200 		ad->cfg.field_order = 0;
201 		ad->cfg.yuv_order = 0;/*00 - UYVY*/
202 		ad->cfg.href = 0;
203 		ad->cfg.vsync = 0;
204 		ad->cfg.frame_rate = 30;
205 		ad->cfg.mipi_freq = MAX96714_LINK_FREQ_150M;
206 		break;
207 
208 	default:
209 		ad->cfg.width = 1920;
210 		ad->cfg.height = 1080;
211 		ad->cfg.start_x = 0;
212 		ad->cfg.start_y = 0;
213 		ad->cfg.input_format = CIF_INPUT_FORMAT_YUV;
214 		ad->cfg.output_format = FORCE_CIF_OUTPUT_FORMAT;
215 		ad->cfg.field_order = 0;
216 		ad->cfg.yuv_order = 0;/*00 - UYVY*/
217 		ad->cfg.href = 0;
218 		ad->cfg.vsync = 0;
219 		ad->cfg.frame_rate = 30;
220 		ad->cfg.mipi_freq = MAX96714_LINK_FREQ_150M;
221 		break;
222 	}
223 	ad->cfg.type = V4L2_MBUS_CSI2_DPHY;
224 	ad->cfg.mbus_flags = V4L2_MBUS_CSI2_4_LANE | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK |
225 			 V4L2_MBUS_CSI2_CHANNEL_0;
226 	ad->cfg.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8;
227 	ad->cfg.dphy_param = &max96714_dcphy_param;
228 
229 	switch (ad->cfg.mbus_flags & V4L2_MBUS_CSI2_LANES) {
230 	case V4L2_MBUS_CSI2_1_LANE:
231 		ad->cfg.lanes = 1;
232 		break;
233 	case V4L2_MBUS_CSI2_2_LANE:
234 		ad->cfg.lanes = 2;
235 		break;
236 	case V4L2_MBUS_CSI2_3_LANE:
237 		ad->cfg.lanes = 3;
238 		break;
239 	case V4L2_MBUS_CSI2_4_LANE:
240 		ad->cfg.lanes = 4;
241 		break;
242 	default:
243 		ad->cfg.lanes = 1;
244 		break;
245 	}
246 
247 	/* fix crop info from dts config */
248 	for (i = 0; i < 4; i++) {
249 		if ((ad->defrects[i].width == ad->cfg.width) &&
250 		    (ad->defrects[i].height == ad->cfg.height)) {
251 			ad->cfg.start_x = ad->defrects[i].crop_x;
252 			ad->cfg.start_y = ad->defrects[i].crop_y;
253 			ad->cfg.width = ad->defrects[i].crop_width;
254 			ad->cfg.height = ad->defrects[i].crop_height;
255 		}
256 	}
257 
258 	VEHICLE_DG("crop(%d,%d)", ad->cfg.start_x, ad->cfg.start_y);
259 }
260 
max96714_reg_init(struct vehicle_ad_dev * ad,unsigned char cvstd)261 static void max96714_reg_init(struct vehicle_ad_dev *ad, unsigned char cvstd)
262 {
263 	struct regval *sensor;
264 	int ret = 0;
265 
266 	switch (cvstd) {
267 	case CVSTD_1080P30:
268 		VEHICLE_INFO("%s, init CVSTD_1080P30 mode", __func__);
269 		sensor = sensor_preview_data_1080p_30hz;
270 		break;
271 	default:
272 		VEHICLE_INFO("%s, init CVSTD_1080P30 mode", __func__);
273 		sensor = sensor_preview_data_1080p_30hz;
274 		break;
275 	}
276 
277 	ret = max96714_write_array(ad, sensor);
278 	if (ret)
279 		VEHICLE_DGERR("%s, init sensor fail", __func__);
280 }
281 
max96714_channel_set(struct vehicle_ad_dev * ad,int channel)282 void max96714_channel_set(struct vehicle_ad_dev *ad, int channel)
283 {
284 }
285 
max96714_ad_get_cfg(struct vehicle_cfg ** cfg)286 int max96714_ad_get_cfg(struct vehicle_cfg **cfg)
287 {
288 	if (!max96714_g_addev)
289 		return -1;
290 
291 	switch (cvstd_state) {
292 	case VIDEO_UNPLUG:
293 		max96714_g_addev->cfg.ad_ready = false;
294 		break;
295 	case VIDEO_LOCKED:
296 		max96714_g_addev->cfg.ad_ready = true;
297 		break;
298 	case VIDEO_IN:
299 		max96714_g_addev->cfg.ad_ready = false;
300 		break;
301 	}
302 
303 	max96714_g_addev->cfg.ad_ready = true;
304 
305 	*cfg = &max96714_g_addev->cfg;
306 
307 	return 0;
308 }
309 
max96714_ad_check_cif_error(struct vehicle_ad_dev * ad,int last_line)310 void max96714_ad_check_cif_error(struct vehicle_ad_dev *ad, int last_line)
311 {
312 	VEHICLE_DG("last_line %d\n", last_line);
313 
314 	if (last_line < 1)
315 		return;
316 
317 	ad->cif_error_last_line = last_line;
318 	if (cvstd_mode == CVSTD_PAL) {
319 		if (last_line == FORCE_NTSC_HEIGHT) {
320 			if (ad->state_check_work.state_check_wq)
321 				queue_delayed_work(
322 					ad->state_check_work.state_check_wq,
323 					&ad->state_check_work.work,
324 					msecs_to_jiffies(0));
325 		}
326 	} else if (cvstd_mode == CVSTD_NTSC) {
327 		if (last_line == FORCE_PAL_HEIGHT) {
328 			if (ad->state_check_work.state_check_wq)
329 				queue_delayed_work(
330 					ad->state_check_work.state_check_wq,
331 					&ad->state_check_work.work,
332 					msecs_to_jiffies(0));
333 		}
334 	} else if (cvstd_mode == CVSTD_1080P30) {
335 		if (last_line == FORCE_1080P_HEIGHT) {
336 			if (ad->state_check_work.state_check_wq)
337 				queue_delayed_work(
338 					ad->state_check_work.state_check_wq,
339 					&ad->state_check_work.work,
340 					msecs_to_jiffies(0));
341 		}
342 	}
343 }
344 
max96714_check_id(struct vehicle_ad_dev * ad)345 int max96714_check_id(struct vehicle_ad_dev *ad)
346 {
347 	int ret = 0;
348 	u32 pid = 0;
349 
350 	ret = max96714_read_reg(ad, MAX96714_CHIP_ID_REG, SENSOR_VALUE_LEN, &pid);
351 	if (pid != MAX96714_CHIP_ID) {
352 		VEHICLE_DGERR("%s: expected 0xC9, detected: 0x%02x !",
353 		    ad->ad_name, pid);
354 		ret = -EINVAL;
355 	} else {
356 		VEHICLE_INFO("Found MAX96714 sensor: id(0x%2x) !\n", pid);
357 	}
358 
359 	return ret;
360 }
361 
max96714_check_cvstd(struct vehicle_ad_dev * ad,bool activate_check)362 static int max96714_check_cvstd(struct vehicle_ad_dev *ad, bool activate_check)
363 {
364 	static int state = VIDEO_UNPLUG;
365 	int ret = 0;
366 
367 	ret = max96714_read_reg(ad, MAX96714_GMSL_STATE, SENSOR_VALUE_LEN, &state);
368 	if (ret)
369 		VEHICLE_DGERR("read GMSL2 link lock failed!\n");
370 
371 	if (state & FLAG_LOCKED) {
372 		state = VIDEO_LOCKED;
373 		VEHICLE_DG("GMSL2 link locked!\n");
374 		cvstd_mode = CVSTD_1080P30;
375 	} else {
376 		state = VIDEO_UNPLUG;
377 		VEHICLE_DG("GMSL2 link not locked!\n");
378 		cvstd_mode = cvstd_old;
379 	}
380 
381 	return 0;
382 }
383 
max96714_stream(struct vehicle_ad_dev * ad,int enable)384 int max96714_stream(struct vehicle_ad_dev *ad, int enable)
385 {
386 	VEHICLE_INFO("%s on(%d)\n", __func__, enable);
387 
388 	g_max96714_streaming = (enable != 0);
389 	if (g_max96714_streaming) {
390 		max96714_write_reg(ad, MAX96714_STREAM_CTL, MAX96714_MODE_STREAMING);
391 		if (ad->state_check_work.state_check_wq)
392 			queue_delayed_work(ad->state_check_work.state_check_wq,
393 				&ad->state_check_work.work, msecs_to_jiffies(200));
394 	} else {
395 		max96714_write_reg(ad, MAX96714_STREAM_CTL, MAX96714_MODE_SW_STANDBY);
396 		if (ad->state_check_work.state_check_wq)
397 			cancel_delayed_work_sync(&ad->state_check_work.work);
398 	}
399 
400 	return 0;
401 }
402 
max96714_power_on(struct vehicle_ad_dev * ad)403 static void max96714_power_on(struct vehicle_ad_dev *ad)
404 {
405 	/* gpio_direction_output(ad->power, ad->pwr_active); */
406 	if (gpio_is_valid(ad->power)) {
407 		gpio_request(ad->power, "max96714_power");
408 		gpio_direction_output(ad->power, ad->pwr_active);
409 		/* gpio_set_value(ad->power, ad->pwr_active); */
410 	}
411 
412 	if (gpio_is_valid(ad->powerdown)) {
413 		gpio_request(ad->powerdown, "max96714_pwd");
414 		gpio_direction_output(ad->powerdown, 1);
415 		/* gpio_set_value(ad->powerdown, !ad->pwdn_active); */
416 	}
417 
418 	if (gpio_is_valid(ad->reset)) {
419 		gpio_request(ad->reset, "max96714_rst");
420 		gpio_direction_output(ad->reset, 0);
421 		usleep_range(1500, 2000);
422 		gpio_direction_output(ad->reset, 1);
423 	}
424 }
425 
max96714_power_deinit(struct vehicle_ad_dev * ad)426 static void max96714_power_deinit(struct vehicle_ad_dev *ad)
427 {
428 	if (gpio_is_valid(ad->reset))
429 		gpio_free(ad->reset);
430 	if (gpio_is_valid(ad->power))
431 		gpio_free(ad->power);
432 	if (gpio_is_valid(ad->powerdown))
433 		gpio_free(ad->powerdown);
434 }
435 
max96714_check_state_work(struct work_struct * work)436 static void max96714_check_state_work(struct work_struct *work)
437 {
438 	struct vehicle_ad_dev *ad;
439 
440 	ad = max96714_g_addev;
441 
442 	if (ad->cif_error_last_line > 0) {
443 		max96714_check_cvstd(ad, true);
444 		ad->cif_error_last_line = 0;
445 	} else {
446 		max96714_check_cvstd(ad, false);
447 	}
448 
449 	VEHICLE_DG("%s:cvstd_old(%d), cvstd_mode(%d)\n", __func__, cvstd_old, cvstd_mode);
450 	if (cvstd_old != cvstd_mode || cvstd_old_state != cvstd_state) {
451 		VEHICLE_INFO("%s:ad sensor std mode change, cvstd_old(%d), cvstd_mode(%d)\n",
452 				 __func__, cvstd_old, cvstd_mode);
453 		cvstd_old = cvstd_mode;
454 		cvstd_old_state = cvstd_state;
455 		max96714_reinit_parameter(ad, cvstd_mode);
456 		max96714_reg_init(ad, cvstd_mode);
457 		vehicle_ad_stat_change_notify();
458 	}
459 	if (g_max96714_streaming) {
460 		queue_delayed_work(ad->state_check_work.state_check_wq,
461 			&ad->state_check_work.work, msecs_to_jiffies(100));
462 	}
463 }
464 
max96714_ad_deinit(void)465 int max96714_ad_deinit(void)
466 {
467 	struct vehicle_ad_dev *ad;
468 
469 	ad = max96714_g_addev;
470 
471 	if (!ad)
472 		return -ENODEV;
473 
474 	if (ad->state_check_work.state_check_wq) {
475 		cancel_delayed_work_sync(&ad->state_check_work.work);
476 		flush_delayed_work(&ad->state_check_work.work);
477 		flush_workqueue(ad->state_check_work.state_check_wq);
478 		destroy_workqueue(ad->state_check_work.state_check_wq);
479 	}
480 	if (ad->irq)
481 		free_irq(ad->irq, ad);
482 	max96714_power_deinit(ad);
483 
484 	return 0;
485 }
486 
get_ad_mode_from_fix_format(int fix_format)487 static __maybe_unused int get_ad_mode_from_fix_format(int fix_format)
488 {
489 	int mode = -1;
490 
491 	switch (fix_format) {
492 	case AD_FIX_FORMAT_PAL:
493 	case AD_FIX_FORMAT_NTSC:
494 	case AD_FIX_FORMAT_720P_50FPS:
495 	case AD_FIX_FORMAT_720P_30FPS:
496 	case AD_FIX_FORMAT_720P_25FPS:
497 		mode = CVSTD_720P25;
498 		break;
499 	case AD_FIX_FORMAT_1080P_30FPS:
500 	case AD_FIX_FORMAT_1080P_25FPS:
501 
502 	default:
503 		mode = CVSTD_1080P30;
504 		break;
505 	}
506 
507 	return mode;
508 }
509 
max96714_ad_init(struct vehicle_ad_dev * ad)510 int max96714_ad_init(struct vehicle_ad_dev *ad)
511 {
512 	max96714_g_addev = ad;
513 
514 	/*  1. i2c init */
515 	while (ad->adapter == NULL) {
516 		ad->adapter = i2c_get_adapter(ad->i2c_chl);
517 		usleep_range(10000, 12000);
518 	}
519 	if (ad->adapter == NULL)
520 		return -ENODEV;
521 
522 	if (!i2c_check_functionality(ad->adapter, I2C_FUNC_I2C))
523 		return -EIO;
524 
525 	max96714_power_on(ad);
526 
527 	max96714_reg_init(ad, cvstd_mode);
528 
529 	max96714_reinit_parameter(ad, cvstd_mode);
530 
531 	INIT_DELAYED_WORK(&ad->state_check_work.work, max96714_check_state_work);
532 	ad->state_check_work.state_check_wq =
533 		create_singlethread_workqueue("vehicle-ad-max96714");
534 
535 	queue_delayed_work(ad->state_check_work.state_check_wq,
536 			   &ad->state_check_work.work, msecs_to_jiffies(100));
537 
538 	return 0;
539 }
540