xref: /OK3568_Linux_fs/kernel/drivers/media/i2c/techpoint/techpoint_dev.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * techpoint dev driver
4  *
5  * Copyright (C) 2023 Rockchip Electronics Co., Ltd.
6  *
7  * V0.0X01.0X00 first version.
8  */
9 
10 #include "techpoint_dev.h"
11 #include "techpoint_tp9930.h"
12 #include "techpoint_tp9950.h"
13 #include "techpoint_tp2855.h"
14 #include "techpoint_tp2815.h"
15 
16 static DEFINE_MUTEX(reg_sem);
17 
techpoint_write_reg(struct i2c_client * client,u8 reg,u8 val)18 int techpoint_write_reg(struct i2c_client *client, u8 reg, u8 val)
19 {
20 	struct i2c_msg msg;
21 	u8 buf[2];
22 	int ret;
23 
24 	buf[0] = reg & 0xFF;
25 	buf[1] = val;
26 
27 	msg.addr = client->addr;
28 	msg.flags = client->flags;
29 	msg.buf = buf;
30 	msg.len = sizeof(buf);
31 
32 	ret = i2c_transfer(client->adapter, &msg, 1);
33 	if (ret >= 0) {
34 		usleep_range(300, 400);
35 		return 0;
36 	}
37 
38 	dev_err(&client->dev,
39 		"techpoint write reg(0x%x val:0x%x) failed !\n", reg, val);
40 
41 	return ret;
42 }
43 
techpoint_write_array(struct i2c_client * client,const struct regval * regs,int size)44 int techpoint_write_array(struct i2c_client *client,
45 			  const struct regval *regs, int size)
46 {
47 	int i, ret = 0;
48 
49 	i = 0;
50 
51 	while (i < size) {
52 		ret = techpoint_write_reg(client, regs[i].addr, regs[i].val);
53 		if (ret) {
54 			dev_err(&client->dev, "%s failed !\n", __func__);
55 			break;
56 		}
57 		i++;
58 	}
59 
60 	return ret;
61 }
62 
techpoint_read_reg(struct i2c_client * client,u8 reg,u8 * val)63 int techpoint_read_reg(struct i2c_client *client, u8 reg, u8 *val)
64 {
65 	struct i2c_msg msg[2];
66 	u8 buf[1];
67 	int ret;
68 
69 	buf[0] = reg & 0xFF;
70 
71 	msg[0].addr = client->addr;
72 	msg[0].flags = client->flags;
73 	msg[0].buf = buf;
74 	msg[0].len = sizeof(buf);
75 
76 	msg[1].addr = client->addr;
77 	msg[1].flags = client->flags | I2C_M_RD;
78 	msg[1].buf = buf;
79 	msg[1].len = 1;
80 
81 	ret = i2c_transfer(client->adapter, msg, 2);
82 	if (ret >= 0) {
83 		*val = buf[0];
84 		return 0;
85 	}
86 
87 	dev_err(&client->dev, "techpoint read reg(0x%x) failed !\n", reg);
88 
89 	return ret;
90 }
91 
check_chip_id(struct techpoint * techpoint)92 static int check_chip_id(struct techpoint *techpoint)
93 {
94 	struct i2c_client *client = techpoint->client;
95 	struct device *dev = &client->dev;
96 	unsigned char chip_id_h = 0xFF, chip_id_l = 0xFF;
97 
98 	techpoint_read_reg(client, CHIP_ID_H_REG, &chip_id_h);
99 	techpoint_read_reg(client, CHIP_ID_L_REG, &chip_id_l);
100 	dev_err(dev, "chip_id_h:0x%2x chip_id_l:0x%2x\n", chip_id_h, chip_id_l);
101 	if (chip_id_h == TP9930_CHIP_ID_H_VALUE &&
102 	    chip_id_l == TP9930_CHIP_ID_L_VALUE) {
103 		dev_info(&client->dev,
104 			 "techpoint check chip id CHIP_TP9930 !\n");
105 		techpoint->chip_id = CHIP_TP9930;
106 		techpoint->input_type = TECHPOINT_DVP_BT1120;
107 		return 0;
108 	} else if (chip_id_h == TP2855_CHIP_ID_H_VALUE &&
109 		   chip_id_l == TP2855_CHIP_ID_L_VALUE) {
110 		dev_info(&client->dev,
111 			 "techpoint check chip id CHIP_TP2855 !\n");
112 		techpoint->chip_id = CHIP_TP2855;
113 		techpoint->input_type = TECHPOINT_MIPI;
114 		return 0;
115 	} else if (chip_id_h == TP2815_CHIP_ID_H_VALUE &&
116 		   chip_id_l == TP2815_CHIP_ID_L_VALUE) {
117 		dev_info(&client->dev,
118 			 "techpoint check chip id CHIP_TP2815 !\n");
119 		techpoint->chip_id = CHIP_TP2855;
120 		techpoint->input_type = TECHPOINT_MIPI;
121 		return 0;
122 	} else if (chip_id_h == TP9950_CHIP_ID_H_VALUE &&
123 		   chip_id_l == TP9950_CHIP_ID_L_VALUE) {
124 		dev_info(&client->dev,
125 			 "techpoint check chip id CHIP_TP9950 !\n");
126 		techpoint->chip_id = CHIP_TP9950;
127 		techpoint->input_type = TECHPOINT_MIPI;
128 		return 0;
129 	}
130 
131 	dev_info(&client->dev, "techpoint check chip id failed !\n");
132 	return -1;
133 }
134 
techpoint_initialize_devices(struct techpoint * techpoint)135 int techpoint_initialize_devices(struct techpoint *techpoint)
136 {
137 	if (check_chip_id(techpoint))
138 		return -1;
139 
140 	if (techpoint->chip_id == CHIP_TP9930)
141 		tp9930_initialize(techpoint);
142 	else if (techpoint->chip_id == CHIP_TP2855)
143 		tp2855_initialize(techpoint);
144 	else if (techpoint->chip_id == CHIP_TP9950)
145 		tp9950_initialize(techpoint);
146 
147 	return 0;
148 }
149 
detect_thread_function(void * data)150 static int detect_thread_function(void *data)
151 {
152 	struct techpoint *techpoint = (struct techpoint *)data;
153 	struct i2c_client *client = techpoint->client;
154 	u8 detect_status = 0, i;
155 	int need_reset_wait = -1;
156 
157 	if (techpoint->power_on) {
158 		mutex_lock(&reg_sem);
159 		if (techpoint->chip_id == CHIP_TP9930) {
160 			tp9930_get_all_input_status(techpoint,
161 						    techpoint->detect_status);
162 			for (i = 0; i < PAD_MAX; i++)
163 				tp9930_set_decoder_mode(client, i,
164 							techpoint->detect_status[i]);
165 		} else if (techpoint->chip_id == CHIP_TP2855) {
166 			tp2855_get_all_input_status(techpoint,
167 						    techpoint->detect_status);
168 			for (i = 0; i < PAD_MAX; i++)
169 				tp2855_set_decoder_mode(client, i,
170 							techpoint->detect_status[i]);
171 		}
172 		mutex_unlock(&reg_sem);
173 		techpoint->do_reset = 0;
174 	}
175 
176 	while (!kthread_should_stop()) {
177 		mutex_lock(&reg_sem);
178 		if (techpoint->power_on) {
179 			for (i = 0; i < PAD_MAX; i++) {
180 				if (techpoint->chip_id == CHIP_TP9930)
181 					detect_status =
182 					    tp9930_get_channel_input_status
183 					    (techpoint, i);
184 				else if (techpoint->chip_id == CHIP_TP2855)
185 					detect_status =
186 					    tp2855_get_channel_input_status
187 					    (techpoint, i);
188 
189 				if (techpoint->detect_status[i] !=
190 				    detect_status) {
191 					if (!detect_status)
192 						dev_info(&client->dev,
193 							"detect channel %d video plug out\n",
194 							i);
195 					else
196 						dev_info(&client->dev,
197 							"detect channel %d video plug in\n",
198 							i);
199 
200 					if (techpoint->chip_id == CHIP_TP9930)
201 						tp9930_set_decoder_mode(client, i, detect_status);
202 					else if (techpoint->chip_id == CHIP_TP2855)
203 						tp2855_set_decoder_mode(client, i, detect_status);
204 
205 					techpoint->detect_status[i] =
206 					    detect_status;
207 					need_reset_wait = 5;
208 				}
209 			}
210 			if (need_reset_wait > 0) {
211 				need_reset_wait--;
212 			} else if (need_reset_wait == 0) {
213 				need_reset_wait = -1;
214 				techpoint->do_reset = 1;
215 				dev_info(&client->dev,
216 					"trigger reset time up\n");
217 			}
218 		}
219 		mutex_unlock(&reg_sem);
220 		set_current_state(TASK_INTERRUPTIBLE);
221 		schedule_timeout(msecs_to_jiffies(200));
222 	}
223 	return 0;
224 }
225 
detect_thread_start(struct techpoint * techpoint)226 static int __maybe_unused detect_thread_start(struct techpoint *techpoint)
227 {
228 	int ret = 0;
229 	struct i2c_client *client = techpoint->client;
230 
231 	techpoint->detect_thread = kthread_create(detect_thread_function,
232 						  techpoint,
233 						  "techpoint_kthread");
234 	if (IS_ERR(techpoint->detect_thread)) {
235 		dev_err(&client->dev,
236 			"kthread_create techpoint_kthread failed\n");
237 		ret = PTR_ERR(techpoint->detect_thread);
238 		techpoint->detect_thread = NULL;
239 		return ret;
240 	}
241 	wake_up_process(techpoint->detect_thread);
242 	return ret;
243 }
244 
detect_thread_stop(struct techpoint * techpoint)245 static int __maybe_unused detect_thread_stop(struct techpoint *techpoint)
246 {
247 	if (techpoint->detect_thread)
248 		kthread_stop(techpoint->detect_thread);
249 	techpoint->detect_thread = NULL;
250 	return 0;
251 }
252 
auto_detect_channel_fmt(struct techpoint * techpoint)253 static __maybe_unused int auto_detect_channel_fmt(struct techpoint *techpoint)
254 {
255 	int ch = 0;
256 	enum techpoint_support_reso reso = 0xff;
257 	struct i2c_client *client = techpoint->client;
258 
259 	mutex_lock(&reg_sem);
260 
261 	for (ch = 0; ch < PAD_MAX; ch++) {
262 		if (techpoint->chip_id == CHIP_TP9930) {
263 			reso = tp9930_get_channel_reso(client, ch);
264 			tp9930_set_channel_reso(client, ch, reso);
265 		} else if (techpoint->chip_id == CHIP_TP2855) {
266 			reso = tp2855_get_channel_reso(client, ch);
267 			tp2855_set_channel_reso(client, ch, reso);
268 		}
269 	}
270 
271 	if (techpoint->chip_id == CHIP_TP9950) {
272 		reso = tp9950_get_channel_reso(client, 0);
273 		tp9950_set_channel_reso(client, 0, reso);
274 	}
275 
276 	mutex_unlock(&reg_sem);
277 
278 	return 0;
279 }
280 
__techpoint_get_vc_fmt_inf(struct techpoint * techpoint,struct rkmodule_vc_fmt_info * inf)281 void __techpoint_get_vc_fmt_inf(struct techpoint *techpoint,
282 				struct rkmodule_vc_fmt_info *inf)
283 {
284 	int ch = 0;
285 	int val = 0;
286 	enum techpoint_support_reso reso = 0xff;
287 	struct i2c_client *client = techpoint->client;
288 
289 	mutex_lock(&reg_sem);
290 
291 	for (ch = 0; ch < PAD_MAX; ch++) {
292 		if (techpoint->chip_id == CHIP_TP9930) {
293 			reso = tp9930_get_channel_reso(client, ch);
294 			techpoint->cur_video_mode->channel_reso[ch] = reso;
295 		} else if (techpoint->chip_id == CHIP_TP2855) {
296 			reso = tp2855_get_channel_reso(client, ch);
297 			techpoint->cur_video_mode->channel_reso[ch] = reso;
298 		}
299 		val = reso;
300 		switch (val) {
301 		case TECHPOINT_S_RESO_1080P_30:
302 			inf->width[ch] = 1920;
303 			inf->height[ch] = 1080;
304 			inf->fps[ch] = 30;
305 			break;
306 		case TECHPOINT_S_RESO_1080P_25:
307 			inf->width[ch] = 1920;
308 			inf->height[ch] = 1080;
309 			inf->fps[ch] = 25;
310 			break;
311 		case TECHPOINT_S_RESO_720P_30:
312 			inf->width[ch] = 1280;
313 			inf->height[ch] = 720;
314 			inf->fps[ch] = 30;
315 			break;
316 		case TECHPOINT_S_RESO_720P_25:
317 			inf->width[ch] = 1280;
318 			inf->height[ch] = 720;
319 			inf->fps[ch] = 25;
320 			break;
321 		case TECHPOINT_S_RESO_SD:
322 			inf->width[ch] = 720;
323 			inf->height[ch] = 560;
324 			inf->fps[ch] = 25;
325 			break;
326 		default:
327 #if DEF_1080P
328 			inf->width[ch] = 1920;
329 			inf->height[ch] = 1080;
330 			inf->fps[ch] = 25;
331 #else
332 			inf->width[ch] = 1280;
333 			inf->height[ch] = 720;
334 			inf->fps[ch] = 25;
335 #endif
336 			break;
337 		}
338 	}
339 
340 	mutex_unlock(&reg_sem);
341 }
342 
techpoint_get_vc_fmt_inf(struct techpoint * techpoint,struct rkmodule_vc_fmt_info * inf)343 void techpoint_get_vc_fmt_inf(struct techpoint *techpoint,
344 			      struct rkmodule_vc_fmt_info *inf)
345 {
346 	mutex_lock(&reg_sem);
347 
348 	if (techpoint->chip_id == CHIP_TP9930)
349 		tp9930_pll_reset(techpoint->client);
350 
351 	techpoint_write_array(techpoint->client,
352 			      techpoint->cur_video_mode->common_reg_list,
353 			      techpoint->cur_video_mode->common_reg_size);
354 
355 	if (techpoint->chip_id == CHIP_TP9930)
356 		tp9930_do_reset_pll(techpoint->client);
357 
358 	mutex_unlock(&reg_sem);
359 
360 	__techpoint_get_vc_fmt_inf(techpoint, inf);
361 }
362 
techpoint_get_vc_hotplug_inf(struct techpoint * techpoint,struct rkmodule_vc_hotplug_info * inf)363 void techpoint_get_vc_hotplug_inf(struct techpoint *techpoint,
364 				  struct rkmodule_vc_hotplug_info *inf)
365 {
366 	int ch = 0;
367 	int detect_status = 0;
368 
369 	memset(inf, 0, sizeof(*inf));
370 
371 	mutex_lock(&reg_sem);
372 
373 	for (ch = 0; ch < 4; ch++) {
374 		if (techpoint->chip_id == CHIP_TP9930)
375 			detect_status =
376 			    tp9930_get_channel_input_status(techpoint, ch);
377 		else if (techpoint->chip_id == CHIP_TP2855)
378 			detect_status =
379 			    tp2855_get_channel_input_status(techpoint, ch);
380 
381 		inf->detect_status |= detect_status << ch;
382 	}
383 
384 	mutex_unlock(&reg_sem);
385 }
386 
techpoint_set_quick_stream(struct techpoint * techpoint,u32 stream)387 void techpoint_set_quick_stream(struct techpoint *techpoint, u32 stream)
388 {
389 	if (techpoint->chip_id == CHIP_TP2855)
390 		tp2855_set_quick_stream(techpoint, stream);
391 }
392 
techpoint_start_video_stream(struct techpoint * techpoint)393 int techpoint_start_video_stream(struct techpoint *techpoint)
394 {
395 	int ret = 0;
396 	struct i2c_client *client = techpoint->client;
397 
398 	mutex_lock(&reg_sem);
399 	if (techpoint->chip_id == CHIP_TP9930)
400 		tp9930_pll_reset(techpoint->client);
401 	mutex_unlock(&reg_sem);
402 
403 	auto_detect_channel_fmt(techpoint);
404 	ret = techpoint_write_array(techpoint->client,
405 				    techpoint->cur_video_mode->common_reg_list,
406 				    techpoint->cur_video_mode->common_reg_size);
407 	if (ret) {
408 		dev_err(&client->dev,
409 			"%s common_reg_list failed", __func__);
410 		return ret;
411 	}
412 
413 	mutex_lock(&reg_sem);
414 	if (techpoint->chip_id == CHIP_TP9930)
415 		tp9930_do_reset_pll(techpoint->client);
416 	mutex_unlock(&reg_sem);
417 
418 	usleep_range(500 * 1000, 1000 * 1000);
419 
420 	detect_thread_start(techpoint);
421 
422 	return 0;
423 }
424 
techpoint_stop_video_stream(struct techpoint * techpoint)425 int techpoint_stop_video_stream(struct techpoint *techpoint)
426 {
427 	detect_thread_stop(techpoint);
428 	return 0;
429 }
430