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(®_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(®_sem);
173 techpoint->do_reset = 0;
174 }
175
176 while (!kthread_should_stop()) {
177 mutex_lock(®_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(®_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(®_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(®_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(®_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(®_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(®_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(®_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(®_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(®_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(®_sem);
399 if (techpoint->chip_id == CHIP_TP9930)
400 tp9930_pll_reset(techpoint->client);
401 mutex_unlock(®_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(®_sem);
414 if (techpoint->chip_id == CHIP_TP9930)
415 tp9930_do_reset_pll(techpoint->client);
416 mutex_unlock(®_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