xref: /OK3568_Linux_fs/kernel/drivers/media/i2c/it66353/it66353.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2022 Rockchip Electronics Co. Ltd.
4  *
5  * it66353 HDMI 3 in 1 out driver.
6  *
7  * Author: Kenneth.Hung@ite.com.tw
8  * 	   Wangqiang Guo<kay.guo@rock-chips.com>
9  * Version: IT66353_SAMPLE_1.08
10  *
11  */
12 #define _SHOW_PRAGMA_MSG
13 #include "config.h"
14 // #include "platform.h"
15 #include "debug.h"
16 #include "it66353_drv.h"
17 #include "it66353_EQ.h"
18 #include "it66353.h"
19 
20 /*
21  * RK kernel follow
22  */
23 #include <linux/miscdevice.h>
24 #include <linux/cdev.h>
25 #include <linux/delay.h>
26 #include <linux/device.h>
27 #include <linux/fs.h>
28 #include <linux/i2c-dev.h>
29 #include <linux/i2c.h>
30 #include <linux/init.h>
31 #include <linux/kernel.h>
32 #include <linux/module.h>
33 #include <linux/notifier.h>
34 #include <linux/slab.h>
35 #include <linux/uaccess.h>
36 #include <linux/compat.h>
37 #include <linux/printk.h>
38 #include <linux/kobject.h>
39 #include <linux/version.h>
40 #include <linux/time.h>
41 #include <linux/timer.h>
42 #include <linux/workqueue.h>
43 
44 //#define DEBUG_EN
45 #define DRIVER_VERSION	KERNEL_VERSION(0, 0x01, 0x00)
46 #define DRIVER_NAME		"IT66353"
47 #define DEBUG(...)\
48 		do {\
49 			if (debug_on)\
50 				printk(__VA_ARGS__);\
51 		} while (0)
52 /*
53  * ********* compile options ***********
54  * CHECK_DEV_PRESENT:
55  * 1: FW will restart when device ID check failed.
56  */
57 #define CHECK_DEV_PRESENT 0
58 #define PR_IO(x)  { if (g_enable_io_log)  dev_dbg(g_it66353->dev, x); }
59 
60 // ********* compile options end *******
61 
62 #if DEBUG_FSM_CHANGE
63 #define __init_str_SYS_FSM_STATE
64 #include "IT66353_drv_h_str.h"
65 #endif
66 
67 /*
68  * for CEC
69  * #if EN_CEC
70  * #include "it66353_cec.h"
71  * #include "..\Customer\IT6635_CecSys.h"
72  * #endif
73  * for CEC
74  */
75 
76 struct it66353_dev {
77 	struct		device *dev;
78 	struct		miscdevice miscdev;
79 	struct		i2c_client *client;
80 	struct		timer_list timer;
81 	struct		delayed_work work_i2c_poll;
82 	struct		mutex poll_lock;
83 	struct		mutex port_lock;
84 	struct		task_struct *poll_task;
85 	bool		auto_switch_en;
86 	bool		is_chip_ready;
87 	bool		cec_switch_en;
88 	bool		nosignal;
89 	u8			tx_current_5v;
90 	u32			hdmi_rx_sel;
91 };
92 static struct it66353_dev *g_it66353;
93 static struct it66353_dev *it66353;
94 
95 static u8 dev_state = DEV_FW_VAR_INIT;
96 IT6635_DEVICE_DATA it66353_gdev;
97 static int debug_on;
98 static void it66353_dev_loop(void);
99 static void _rx_set_hpd(u8 port, u8 hpd_value, u8 term_value);
100 
101 /*
102  * RK kernel
103  */
i2c_wr(struct it66353_dev * it66353,u16 reg,u8 * val,u32 n)104 static void i2c_wr(struct it66353_dev *it66353, u16 reg, u8 *val, u32 n)
105 {
106 	struct i2c_msg msg;
107 	struct i2c_client *client = it66353->client;
108 	int err;
109 	u8 data[128];
110 
111 	data[0] = reg;
112 	memcpy(&data[1], val, n);
113 	msg.addr = client->addr;
114 	msg.flags = 0;
115 	msg.buf = data;
116 	msg.len = n + 1;
117 	err = i2c_transfer(client->adapter, &msg, 1);
118 	if (err != 1) {
119 		dev_err(it66353->dev, "writing register 0x%x from 0x%x failed\n",
120 			reg, client->addr);
121 	} else {
122 		switch (n) {
123 		case 1:
124 			dev_dbg(it66353->dev, "I2C write 0x%02x = 0x%02x\n",
125 				reg, data[1]);
126 			break;
127 		case 2:
128 			dev_dbg(it66353->dev,
129 				"I2C write 0x%02x = 0x%02x%02x\n",
130 				reg, data[2], data[1]);
131 			break;
132 		case 4:
133 			dev_dbg(it66353->dev,
134 				"I2C write 0x%02x = 0x%02x%02x%02x%02x\n",
135 				reg, data[4], data[3], data[2], data[1]);
136 			break;
137 		default:
138 			dev_dbg(it66353->dev,
139 				"I2C write %d bytes from address 0x%02x\n",
140 				n, reg);
141 		}
142 	}
143 }
144 
i2c_rd(struct it66353_dev * it66353,u16 reg,u8 * val,u32 n)145 static void i2c_rd(struct it66353_dev *it66353, u16 reg, u8 *val, u32 n)
146 {
147 	struct i2c_msg msg[2];
148 	struct i2c_client *client = it66353->client;
149 	int err;
150 	u8 buf[1] = { reg };
151 	// msg[0] addr to read
152 	msg[0].addr = client->addr;
153 	msg[0].flags = 0;
154 	msg[0].buf = buf;
155 	msg[0].len = 1;
156 	// msg[1] read data
157 	msg[1].addr = client->addr;
158 	msg[1].flags = I2C_M_RD;
159 	msg[1].buf = val;
160 	msg[1].len = n;
161 	err = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
162 	if (err != ARRAY_SIZE(msg)) {
163 		dev_err(it66353->dev, "reading register 0x%x from 0x%x failed\n",
164 			reg, client->addr);
165 	}
166 }
167 
i2c_rd8(u8 i2c_addr,u16 reg,u8 * val)168 static void i2c_rd8(u8 i2c_addr, u16 reg, u8 *val)
169 {
170 	struct it66353_dev *it66353 = g_it66353;
171 
172 	it66353->client->addr = (i2c_addr >> 1);
173 	i2c_rd(it66353, reg, val, 1);
174 }
175 
it66353_i2c_read(u8 i2c_addr,u16 reg,u8 n,u8 * val)176 static void it66353_i2c_read(u8 i2c_addr, u16 reg, u8 n, u8 *val)
177 {
178 	struct it66353_dev *it66353 = g_it66353;
179 
180 	it66353->client->addr = (i2c_addr >> 1);
181 	i2c_rd(it66353, reg, val, n);
182 }
183 
i2c_wr8(u8 i2c_addr,u16 reg,u8 buf)184 static void i2c_wr8(u8 i2c_addr, u16 reg, u8 buf)
185 {
186 	struct it66353_dev *it66353 = g_it66353;
187 
188 	it66353->client->addr = (i2c_addr >> 1);
189 	i2c_wr(it66353, reg, &buf, 1);
190 }
191 
rx_rd8(u8 offset)192 static u8 rx_rd8(u8 offset)
193 {
194 	u8 rd_data;
195 
196 	i2c_rd8(it66353_gdev.opts.dev_opt->RxAddr, offset, &rd_data);
197 	return rd_data;
198 }
199 
200 #if EN_CEC
cec_rd8(u8 offset)201 static u8 cec_rd8(u8 offset)
202 {
203 	u8 rd_data;
204 
205 	i2c_rd8(it66353_gdev.opts.dev_opt->CecAddr, offset, &rd_data);
206 	return rd_data;
207 }
208 #endif
209 
sw_rd8(u8 offset)210 static u8 sw_rd8(u8 offset)
211 {
212 	u8 rd_data;
213 
214 	i2c_rd8(it66353_gdev.opts.dev_opt->SwAddr, offset, &rd_data);
215 	return rd_data;
216 }
217 
swAddr_updata_bit(u16 reg,u32 mask,u32 val)218 static void swAddr_updata_bit(u16 reg, u32 mask, u32 val)
219 {
220 	u8 val_p;
221 
222 	i2c_rd8(it66353_gdev.opts.dev_opt->SwAddr, reg, &val_p);
223 	val_p = (val_p & ((~mask) & 0xFF)) | (mask & val);
224 	i2c_wr8(it66353_gdev.opts.dev_opt->SwAddr, reg, val_p);
225 }
226 
rxAddr_updata_bit(u16 reg,u32 mask,u32 val)227 static void rxAddr_updata_bit(u16 reg, u32 mask, u32 val)
228 {
229 	u8 val_p;
230 
231 	i2c_rd8(it66353_gdev.opts.dev_opt->RxAddr, reg, &val_p);
232 	val_p = (val_p & ((~mask) & 0xFF)) | (mask & val);
233 	i2c_wr8(it66353_gdev.opts.dev_opt->RxAddr, reg, val_p);
234 }
235 
cecAddr_updata_bit(u16 reg,u32 mask,u32 val)236 static void cecAddr_updata_bit(u16 reg, u32 mask, u32 val)
237 {
238 	u8 val_p;
239 
240 	i2c_rd8(it66353_gdev.opts.dev_opt->CecAddr, reg, &val_p);
241 	val_p = (val_p & ((~mask) & 0xFF)) | (mask & val);
242 	i2c_wr8(it66353_gdev.opts.dev_opt->CecAddr, reg, val_p);
243 }
244 
it66353_ioctl(struct file * file,uint32_t cmd,unsigned long arg)245 static long it66353_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
246 {
247 	return 0;
248 }
249 
it66353_write(struct file * file,const char __user * buf,size_t size,loff_t * ppos)250 static ssize_t it66353_write(struct file *file, const char __user *buf,
251 				 size_t size, loff_t *ppos)
252 {
253 	return 1;
254 }
255 
it66353_read(struct file * file,char __user * buf,size_t size,loff_t * ppos)256 static ssize_t it66353_read(struct file *file, char __user *buf, size_t size,
257 				loff_t *ppos)
258 {
259 	return 1;
260 }
261 
it66353_work_i2c_poll(struct work_struct * work)262 static void it66353_work_i2c_poll(struct work_struct *work)
263 {
264 	struct delayed_work *dwork = to_delayed_work(work);
265 	struct it66353_dev *it66353 =
266 		container_of(dwork, struct it66353_dev, work_i2c_poll);
267 
268 	mutex_lock(&it66353->poll_lock);
269 	it66353_dev_loop();
270 	mutex_unlock(&it66353->poll_lock);
271 	schedule_delayed_work(&it66353->work_i2c_poll, msecs_to_jiffies(50));
272 }
273 
it66353_hdmirxsel_show(struct device * dev,struct device_attribute * attr,char * buf)274 static ssize_t it66353_hdmirxsel_show(struct device *dev,
275 					  struct device_attribute *attr, char *buf)
276 {
277 	struct it66353_dev *it66353 = g_it66353;
278 
279 	dev_info(it66353->dev, "%s: hdmi rx select state: %d\n",
280 		 __func__, g_it66353->hdmi_rx_sel);
281 
282 	return sprintf(buf, "%d\n", g_it66353->hdmi_rx_sel);
283 }
284 
it66353_hdmirxsel_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)285 static ssize_t it66353_hdmirxsel_store(struct device *dev,
286 					   struct device_attribute *attr,
287 					   const char *buf, size_t count)
288 {
289 	struct it66353_dev *it66353 = g_it66353;
290 	u32 hdmirxstate = 0;
291 	int ret;
292 
293 	mutex_lock(&it66353->port_lock);
294 	ret = kstrtouint(buf, 10, &hdmirxstate);
295 	if (!ret && hdmirxstate >= 0 && hdmirxstate <= RX_PORT_COUNT) {
296 		it66353->hdmi_rx_sel = hdmirxstate;
297 		dev_info(it66353->dev, "%s: state: %d\n", __func__, hdmirxstate);
298 		/*
299 		 * _rx_set_hpd(hdmirxstate, 0, TERM_FOLLOW_HPD);
300 		 * msleep(200);
301 		 * _rx_set_hpd(hdmirxstate, 1, TERM_FOLLOW_HPD);
302 		 */
303 		it66353_set_active_port(hdmirxstate);
304 	} else {
305 		dev_info(it66353->dev, "%s: write hdmi_rx_sel failed!!!, hdmirxstate:%d \n",
306 						__func__, hdmirxstate);
307 	}
308 	mutex_unlock(&it66353->port_lock);
309 
310 	return count;
311 }
312 static DEVICE_ATTR_RW(it66353_hdmirxsel);
313 
314 static const struct file_operations it66353_fops = {
315 	.owner = THIS_MODULE,
316 	.read = it66353_read,
317 	.write = it66353_write,
318 	.unlocked_ioctl = it66353_ioctl,
319 };
320 
321 static struct miscdevice it66353_miscdev = {
322 	.minor = MISC_DYNAMIC_MINOR,
323 	.name = "it66353_dev",
324 	.fops = &it66353_fops,
325 };
326 
it66353_probe(struct i2c_client * client,const struct i2c_device_id * id)327 static int it66353_probe(struct i2c_client *client,
328 			 const struct i2c_device_id *id)
329 {
330 	struct it66353_dev *it66353;
331 	struct device *dev = &client->dev;
332 	int ret;
333 
334 	dev_info(dev, "driver version: %02x.%02x.%02x",
335 		DRIVER_VERSION >> 16,
336 		(DRIVER_VERSION & 0xff00) >> 8,
337 		DRIVER_VERSION & 0x00ff);
338 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
339 		return -EIO;
340 	dev_info(dev, "chip found @ 0x%x (%s)\n", client->addr << 1,
341 		client->adapter->name);
342 	it66353 = devm_kzalloc(dev, sizeof(struct it66353_dev), GFP_KERNEL);
343 	if (!it66353)
344 		return -ENOMEM;
345 
346 	it66353->client = client;
347 	it66353->dev = dev;
348 	client->flags |= I2C_CLIENT_SCCB;
349 
350 	mutex_init(&it66353->poll_lock);
351 	mutex_init(&it66353->port_lock);
352 
353 	ret = misc_register(&it66353_miscdev);
354 	if (ret) {
355 		dev_err(it66353->dev,
356 			"it66353 ERROR: could not register it66353 device\n");
357 		return ret;
358 	}
359 	INIT_DELAYED_WORK(&it66353->work_i2c_poll, it66353_work_i2c_poll);
360 
361 	g_it66353 = it66353;
362 
363 	ret = device_create_file(it66353_miscdev.this_device,
364 				&dev_attr_it66353_hdmirxsel);
365 	if (ret) {
366 		dev_err(it66353->dev, "failed to create attr hdmirxsel!\n");
367 		goto err0;
368 	}
369 	it66353_options_init();
370 	schedule_delayed_work(&it66353->work_i2c_poll, msecs_to_jiffies(10));
371 	dev_info(it66353->dev, "%s found @ 0x%x (%s)\n",
372 				client->name, client->addr << 1,
373 				client->adapter->name);
374 	return 0;
375 err0:
376 	misc_deregister(&it66353_miscdev);
377 	return ret;
378 }
379 
it66353_remove(struct i2c_client * client)380 static int it66353_remove(struct i2c_client *client)
381 {
382 	cancel_delayed_work_sync(&it66353->work_i2c_poll);
383 
384 	device_remove_file(it66353_miscdev.this_device,
385 			   &dev_attr_it66353_hdmirxsel);
386 	misc_deregister(&it66353_miscdev);
387 	mutex_destroy(&it66353->poll_lock);
388 	mutex_destroy(&it66353->port_lock);
389 
390 	return 0;
391 }
392 
393 static const struct of_device_id it66353_of_match[] = {
394 	{ .compatible = "ite,it66353" },
395 	{}
396 };
397 MODULE_DEVICE_TABLE(of, it66353_of_match);
398 
399 static struct i2c_driver it66353_driver = {
400 	.probe = it66353_probe,
401 	.remove = it66353_remove,
402 	.driver = {
403 		.owner = THIS_MODULE,
404 		.name = DRIVER_NAME,
405 		.of_match_table = of_match_ptr(it66353_of_match),
406 	},
407 };
408 
it66353_driver_init(void)409 static int __init it66353_driver_init(void)
410 {
411 	return i2c_add_driver(&it66353_driver);
412 }
413 
it66353_driver_exit(void)414 static void __exit it66353_driver_exit(void)
415 {
416 	i2c_del_driver(&it66353_driver);
417 }
418 
419 device_initcall_sync(it66353_driver_init);
420 module_exit(it66353_driver_exit);
421 MODULE_DESCRIPTION("ITE IT66353 3 HDMI in switch driver");
422 MODULE_AUTHOR("Wangqiang Guo <kay.guo@rock-chips.com>");
423 MODULE_LICENSE("GPL v2");
424 /*
425  * end rk kernel
426  */
427 
_pr_buf(void * buffer,int length)428 static void _pr_buf(void *buffer, int length)
429 {
430 	u8 *buf = (u8 *)buffer;
431 
432 	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf,
433 			length, false);
434 }
435 
it66353_h2swwr(u8 offset,u8 wdata)436 u8 it66353_h2swwr(u8 offset, u8 wdata)
437 {
438 	swAddr_updata_bit(offset, 0xFF, wdata);
439 	return 0;
440 }
441 
it66353_h2swrd(u8 offset)442 u8 it66353_h2swrd(u8 offset)
443 {
444 	u8 rddata;
445 
446 	rddata = sw_rd8(offset);
447 	return rddata;
448 }
449 
it66353_h2swset(u8 offset,u8 mask,u8 wdata)450 u8 it66353_h2swset(u8 offset, u8 mask, u8 wdata)
451 {
452 	swAddr_updata_bit(offset, mask, wdata);
453 	return 0;
454 }
455 
it66353_h2swbrd(u8 offset,u8 length,u8 * rddata)456 void it66353_h2swbrd(u8 offset, u8 length, u8 *rddata)
457 {
458 	if (length > 0) {
459 		g_it66353->client->addr = (SWAddr >> 1);
460 		i2c_rd(g_it66353, offset, rddata, length);
461 	}
462 }
463 
it66353_h2swbwr(u8 offset,u8 length,u8 * rddata)464 void it66353_h2swbwr(u8 offset, u8 length, u8 *rddata)
465 {
466 	if (length > 0) {
467 		g_it66353->client->addr = (SWAddr >> 1);
468 		i2c_wr(g_it66353, offset, rddata, length);
469 	}
470 }
471 
it66353_h2rxedidwr(u8 offset,u8 * wrdata,u8 length)472 u8 it66353_h2rxedidwr(u8 offset, u8 *wrdata, u8 length)
473 {
474 	#if 0
475 	u8 i;
476 	for (i = 0; i < length; i++) {
477 		PR_IO("w %02x %02x %02x\r\n", offset+i, wrdata[i], RXEDIDAddr);
478 	}
479 	#endif
480 	g_it66353->client->addr = (RXEDIDAddr >> 1);
481 	i2c_wr(g_it66353, offset, wrdata, length);
482 	return 0;
483 }
484 
it66353_h2rxedidrd(u8 offset,u8 * wrdata,u8 length)485 static u8 it66353_h2rxedidrd(u8 offset, u8 *wrdata, u8 length)
486 {
487 	g_it66353->client->addr = (RXEDIDAddr >> 1);
488 	i2c_wr(g_it66353, offset, wrdata, length);
489 	return 0;
490 }
491 
it66353_h2rxwr(u8 offset,u8 rdata)492 u8 it66353_h2rxwr(u8 offset, u8 rdata)
493 {
494 	rxAddr_updata_bit(offset, 0xFF, rdata);
495 	return 0;
496 }
497 
it66353_h2rxrd(u8 offset)498 u8 it66353_h2rxrd(u8 offset)
499 {
500 	u8 rddata;
501 
502 	rddata = rx_rd8(offset);
503 
504 	return rddata;
505 }
506 
it66353_h2rxset(u8 offset,u8 mask,u8 wdata)507 u8 it66353_h2rxset(u8 offset, u8 mask, u8 wdata)
508 {
509 	rxAddr_updata_bit(offset, mask, wdata);
510 	return 0;
511 }
512 
it66353_h2rxbrd(u8 offset,u8 length,u8 * rddata)513 void it66353_h2rxbrd(u8 offset, u8 length, u8 *rddata)
514 {
515 	if (length > 0) {
516 		g_it66353->client->addr = (RXAddr >> 1);
517 		i2c_rd(g_it66353, offset, rddata, length);
518 	}
519 }
520 
it66353_h2rxbwr(u8 offset,u8 length,u8 * rddata)521 void it66353_h2rxbwr(u8 offset, u8 length, u8 *rddata)
522 {
523 	if (length > 0) {
524 		g_it66353->client->addr = (RXAddr >> 1);
525 		i2c_wr(g_it66353, offset, rddata, length);
526 	}
527 }
528 
529 #if EN_CEC
530 
it66353_cecwr(u8 offset,u8 wdata)531 u8 it66353_cecwr(u8 offset, u8 wdata)
532 {
533 	return cecAddr_updata_bit(g_it66353, offset, 0xFF, wdata);
534 }
535 
cecrd(u8 offset)536 u8 cecrd(u8 offset)
537 {
538 	u8 rddata;
539 
540 	rddata = cec_rd8(offset);
541 
542 	return rddata;
543 }
544 
it66353_cecset(u8 offset,u8 mask,u8 rdata)545 u8 it66353_cecset(u8 offset, u8 mask, u8 rdata)
546 {
547 	return cecAddr_updata_bit(offset, mask, rddata);
548 }
549 
it66353_cecbrd(u8 offset,u8 length,u8 * rddata)550 void it66353_cecbrd(u8 offset, u8 length, u8 *rddata)
551 {
552 	if (length > 0) {
553 		g_it66353->client->addr = (CecAddr >> 1);
554 		i2c_rd(g_it66353, offset, rddata, length);
555 	}
556 }
557 
it66353_cecbwr(u8 offset,u8 length,u8 * rddata)558 void it66353_cecbwr(u8 offset, u8 length, u8 *rddata)
559 {
560 	if (length > 0) {
561 		g_it66353->client->addr = (CecAddr >> 1);
562 		i2c_wr(g_it66353, offset, rddata, length);
563 	}
564 }
565 
566 #endif
567 
it66353_chgrxbank(u8 bankno)568 void it66353_chgrxbank(u8 bankno)
569 {
570 	it66353_h2rxset(0x0f, 0x07, bankno & 0x07);
571 }
572 
_tx_is_sink_hpd_high(void)573 static bool _tx_is_sink_hpd_high(void)
574 {
575 	if (it66353_h2swrd(0x11) & 0x20)
576 		return TRUE;
577 	else
578 		return FALSE;
579 }
580 
_tx_ddcwait(void)581 static bool _tx_ddcwait(void)
582 {
583 	u8 ddcwaitcnt, ddc_status;
584 
585 	ddcwaitcnt = 0;
586 	do {
587 		ddcwaitcnt++;
588 		msleep(DDCWAITTIME);
589 	} while ((it66353_h2swrd(0x1B) & 0x80) == 0x00 && ddcwaitcnt < DDCWAITNUM);
590 
591 	if (ddcwaitcnt == DDCWAITNUM) {
592 		ddc_status = it66353_h2swrd(0x1B) & 0xFE;
593 		dev_err(g_it66353->dev, "** TX DDC Bus Sta=%02x\r\n", ddc_status);
594 		dev_err(g_it66353->dev, "** TX DDC Bus Wait TimeOut => ");
595 
596 		if (it66353_h2swrd(0x27) & 0x80) {
597 			dev_err(g_it66353->dev, "** DDC Bus Hang\r\n");
598 			// Do not handle the DDC Bus Hang here
599 			// h2txwr(port, 0x2E, 0x0F);  // Abort DDC Command
600 			// h2txwr(port, 0x16, 0x08);  // Clear Interrupt
601 		} else if (ddc_status & 0x20) {
602 			dev_err(g_it66353->dev, "** DDC NoACK\r\n");
603 		} else if (ddc_status & 0x10) {
604 			dev_err(g_it66353->dev, "** DDC WaitBus\r\n");
605 		} else if (ddc_status & 0x08) {
606 			dev_err(g_it66353->dev, "** DDC ArbiLose\r\n");
607 		} else {
608 			dev_err(g_it66353->dev, "** UnKnown Issue\r\n");
609 		}
610 
611 		return FALSE;
612 	} else {
613 		return TRUE;
614 	}
615 }
616 
_tx_scdc_write(u8 offset,u8 wdata)617 static u8 _tx_scdc_write(u8 offset, u8 wdata)
618 {
619 	int ddcwaitsts;
620 	u8 reg3C;
621 
622 	if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass) {
623 		dev_err(g_it66353->dev, "** EnRxDDCBypass:Abort SCDC write\r\n");
624 		return FALSE;
625 	}
626 
627 	if ((it66353_h2swrd(0x11) & 0x20) == 0x00) {
628 		dev_err(g_it66353->dev, "** HPD-Low:Abort SCDC write\r\n");
629 		return FALSE;
630 	}
631 
632 	reg3C = it66353_h2swrd(0x3C);
633 	it66353_h2swset(0x3C, 0x01, 0x01);		// Enable PC DDC Mode
634 	it66353_h2swwr(0x3D, 0x09);			// DDC FIFO Clear
635 	it66353_h2swwr(0x3E, 0xA8);			// EDID Address
636 	it66353_h2swwr(0x3F, offset);			// EDID Offset
637 	it66353_h2swwr(0x40, 0x01);			// ByteNum[7:0]
638 	it66353_h2swwr(0x42, wdata);			// WrData
639 	it66353_h2swwr(0x3D, 0x01);			// Sequential Burst Write
640 	ddcwaitsts = _tx_ddcwait();
641 	it66353_h2swwr(0x3C, reg3C);			// Disable PC DDC Mode
642 
643 	if (ddcwaitsts == 0) {
644 		DEBUG("SCDC wr %02x %02x, ddcwaitsts = %d\r\n",
645 		      offset, wdata, ddcwaitsts);
646 	}
647 
648 	return ddcwaitsts;
649 }
650 
_tx_scdc_read(u8 offset,u8 * data_buf)651 static u8 __maybe_unused _tx_scdc_read(u8 offset, u8 *data_buf)
652 {
653 	int ddcwaitsts;
654 	u8 reg3C;
655 
656 	if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass) {
657 		dev_err(g_it66353->dev, "EnRxDDCBypass:Abort SCDC read\r\n");
658 		return FALSE;
659 	}
660 
661 	if ((it66353_h2swrd(0x11) & 0x20) == 0x00) {
662 		dev_err(g_it66353->dev, "HPD-Low:Abort SCDC read\r\n");
663 		return FALSE;
664 	}
665 
666 	reg3C = it66353_h2swrd(0x3C);
667 	it66353_h2swset(0x3C, 0x01, 0x01);		// Enable PC DDC Mode
668 	it66353_h2swwr(0x3D, 0x09);			// DDC FIFO Clear
669 	it66353_h2swwr(0x3E, 0xA8);			// EDID Address
670 	it66353_h2swwr(0x3F, offset);			// EDID Offset
671 	it66353_h2swwr(0x40, 0x01);			// ByteNum[7:0]
672 	//it66353_h2swwr(0x42, data);			// WrData
673 	it66353_h2swwr(0x3D, 0x00);			// Sequential Burst Write
674 	ddcwaitsts = _tx_ddcwait();
675 	it66353_h2swwr(0x3C, reg3C);			// Disable PC DDC Mode
676 
677 	if (ddcwaitsts == 0) {
678 		dev_err(g_it66353->dev, "SCDC rd %02x ddcwaitsts = %d\r\n",
679 			offset, ddcwaitsts);
680 	} else {
681 		*data_buf = it66353_h2swrd(0x42);
682 	}
683 
684 	return ddcwaitsts;
685 }
686 
_tx_hdcp_write(u8 offset,u8 data)687 static u8 __maybe_unused _tx_hdcp_write(u8 offset, u8 data)
688 {
689 	int ddcwaitsts;
690 
691 	if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass) {
692 		dev_err(g_it66353->dev, "EnRxDDCBypass:Abort HDCP write\r\n");
693 		return FALSE;
694 	}
695 
696 	if ((it66353_h2swrd(0x11) & 0x20) == 0x00) {
697 		dev_err(g_it66353->dev, "HPD-Low:Abort HDCP write\r\n");
698 		return FALSE;
699 	}
700 
701 	it66353_h2swset(0x3C, 0x01, 0x01);		// Enable PC DDC Mode
702 	it66353_h2swwr(0x3D, 0x09);			// DDC FIFO Clear
703 	it66353_h2swwr(0x3E, 0x74);			// EDID Address
704 	it66353_h2swwr(0x3F, offset);			// EDID Offset
705 	it66353_h2swwr(0x40, 0x01);			// ByteNum[7:0]
706 	it66353_h2swwr(0x42, data);			// WrData
707 	it66353_h2swwr(0x3D, 0x01);			// Sequential Burst Write
708 	ddcwaitsts = _tx_ddcwait();
709 	it66353_h2swset(0x3C, 0x01, 0x00);		// Disable PC DDC Mode
710 
711 	if (ddcwaitsts == 0) {
712 		DEBUG("SCDC wr %02x %02x, ddcwaitsts = %d\r\n", offset, data, ddcwaitsts);
713 	}
714 
715 	return ddcwaitsts;
716 }
717 
_tx_hdcp_read(u8 offset,u8 * data_buf,u8 len)718 static u8 __maybe_unused _tx_hdcp_read(u8 offset, u8 *data_buf, u8 len)
719 {
720 	int ddcwaitsts;
721 
722 	if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass) {
723 		dev_err(g_it66353->dev, "EnRxDDCBypass:Abort HDCP read\r\n");
724 		return FALSE;
725 	}
726 
727 
728 	if ((it66353_h2swrd(0x11) & 0x20) == 0x00) {
729 		dev_err(g_it66353->dev, "HPD-Low:Abort HDCP read\r\n");
730 		return FALSE;
731 	}
732 
733 	it66353_h2swset(0x3C, 0x01, 0x01);		// Enable PC DDC Mode
734 	it66353_h2swwr(0x3D, 0x09);			// DDC FIFO Clear
735 	it66353_h2swwr(0x3E, 0x74);			// EDID Address
736 	it66353_h2swwr(0x3F, offset);			// EDID Offset
737 	it66353_h2swwr(0x40, len);			// ByteNum[7:0]
738 	// it66353_h2swwr(0x42, data);			// WrData
739 	it66353_h2swwr(0x3D, 0x00);			// Sequential Burst Write
740 	ddcwaitsts = _tx_ddcwait();
741 	it66353_h2swset(0x3C, 0x01, 0x00);		// Disable PC DDC Mode
742 
743 	if (ddcwaitsts == 0) {
744 		dev_err(g_it66353->dev, "SCDC rd %02x ddcwaitsts = %d\r\n",
745 			offset, ddcwaitsts);
746 	} else {
747 		u8 i;
748 
749 		DEBUG("HDCP read - %02X : ", offset);
750 		for (i = 0; i < len; i++) {
751 			data_buf[i] = it66353_h2swrd(0x42);
752 			DEBUG("%02X ", data_buf[i]);
753 		}
754 
755 		DEBUG("\r\n");
756 	}
757 
758 	return ddcwaitsts;
759 }
760 
_tx_scdc_read_ced(u8 * data_buf)761 static u8 __maybe_unused _tx_scdc_read_ced(u8 *data_buf)
762 {
763 	int ddcwaitsts;
764 	u8 i;
765 
766 	if ((it66353_h2swrd(0x11) & 0x20) == 0x00) {
767 		dev_err(g_it66353->dev, "HPD-Low:Abort SCDC read\r\n");
768 		return FALSE;
769 	}
770 
771 	it66353_h2swset(0x3C, 0x01, 0x01);		// Enable PC DDC Mode
772 	it66353_h2swwr(0x3D, 0x09);			// DDC FIFO Clear
773 	it66353_h2swwr(0x3E, 0xA8);			// EDID Address
774 	it66353_h2swwr(0x3F, 0x50);			// EDID Offset
775 	it66353_h2swwr(0x40, 0x06);			// ByteNum[7:0]
776 	// it66353_h2swwr(0x42, data);			// WrData
777 	it66353_h2swwr(0x3D, 0x00);			// Sequential Burst Write
778 	ddcwaitsts = _tx_ddcwait();
779 	it66353_h2swset(0x3C, 0x01, 0x00);		// Disable PC DDC Mode
780 
781 	if (ddcwaitsts == 0) {
782 		dev_err(g_it66353->dev, "SCDC rd ced ddcwaitsts = %d\r\n", ddcwaitsts);
783 	} else {
784 		for (i = 0; i < 6; i++) {
785 			data_buf[i] = it66353_h2swrd(0x42);
786 		}
787 	}
788 
789 	return ddcwaitsts;
790 }
791 
_tx_power_down(void)792 static void _tx_power_down(void)
793 {
794 	if (it66353_gdev.opts.dev_opt->DoTxPowerDown) {
795 		it66353_h2swset(0xD3, 0x80, 0x00);
796 		it66353_h2swset(0xD1, 0x60, 0x60);
797 	}
798 }
799 
_tx_power_on(void)800 static void _tx_power_on(void)
801 {
802 	it66353_h2swset(0xD3, 0x80, 0x80);	// Reg_XP_ALPWDB=1
803 	it66353_h2swset(0xD1, 0x60, 0x00);	// Reg_XP_PWDi = 0, Reg_XP_PWDPLL=0
804 }
805 
_tx_show_sink_ced(void)806 static void __maybe_unused _tx_show_sink_ced(void)
807 {
808 	u8 ced_valid;
809 	u8 i;
810 	u8 pr_ced = 0;
811 	u8 ced_value[6];
812 	// static u8 read_from_scdc;
813 
814 	ced_valid = it66353_h2swrd(0xB0);
815 	if (ced_valid) {
816 		DEBUG("Begin READ CED:\r\n");
817 		pr_ced = 1;
818 		for (i = 0; i < 6; i++) {
819 			if (ced_valid & (0x01 << i)) {	// 0x5? error status is valid
820 				it66353_h2swset(0xAC, 0xE0, (i<<5));	// offset select
821 				ced_value[i] = it66353_h2swrd(0xB1);
822 			}
823 		}
824 		it66353_h2swwr(0xAD, 0xFF); // clear CED valid on 0xB0
825 	} else {
826 		#if 0
827 		if (read_from_scdc > 10) {
828 			#if 0
829 			for (i = 0; i < 6; i++) {
830 				_tx_scdc_read(0x50 + i, &ced_value[i]);
831 
832 			}
833 			#else
834 			_tx_scdc_read_ced(&ced_value[0]);
835 			#endif
836 
837 			dev_info("SCDC: ");
838 			pr_ced = 1;
839 			read_from_scdc = 0;
840 		} else {
841 			read_from_scdc++;
842 		}
843 		#else
844 		// read_from_scdc = read_from_scdc;	// suppress warning
845 		#endif
846 	}
847 
848 	if (pr_ced) {
849 		for (i = 0; i < 3; i++) {
850 			DEBUG("ced_valid = %02X, ch%d V=%d err=%04X\r\n",
851 				ced_valid, i, (ced_value[2*i+1]>>7)&0x01,
852 				((ced_value[2*i+1]&0xEF)<<8) + ced_value[2*i]);
853 		}
854 		DEBUG("\r\n");
855 	}
856 }
857 
_tx_ovwr_hdmi_clk(u8 ratio)858 static void __maybe_unused _tx_ovwr_hdmi_clk(u8 ratio)
859 {
860 	switch (ratio) {
861 	case HDMI_MODE_AUTO:
862 		it66353_h2swset(0xB2, 0x03, 0x00);
863 		break;
864 	case HDMI_MODE_14:
865 		it66353_h2swset(0xB2, 0x03, 0x01);
866 		break;
867 	case HDMI_MODE_20:
868 		it66353_h2swset(0xB2, 0x03, 0x03);
869 		break;
870 	default:
871 		break;
872 	}
873 }
874 
_tx_ovwr_h20_scrb(u8 scrb)875 static void __maybe_unused _tx_ovwr_h20_scrb(u8 scrb)
876 {
877 	switch (scrb) {
878 	case HDMI_MODE_AUTO:
879 		it66353_h2swset(0xB2, 0x0C, 0x00);
880 		break;
881 	case HDMI_MODE_14:
882 		it66353_h2swset(0xB2, 0x0C, 0x08);
883 		break;
884 	case HDMI_MODE_20:
885 		it66353_h2swset(0xB2, 0x0C, 0x0c);
886 		break;
887 	default:
888 		break;
889 	}
890 }
891 
892 
it66353_rx_is_ch_symlock(u8 ch)893 u8 it66353_rx_is_ch_symlock(u8 ch)
894 {
895 	if ((it66353_h2rxrd(0x14) & (0x08 << ch))) {
896 		return 1;
897 	}
898 	return 0;
899 }
900 
901 
it66353it66353_rx_ovwr_hdmi_clk(u8 port,u8 ratio)902 static void __maybe_unused it66353it66353_rx_ovwr_hdmi_clk(u8 port, u8 ratio)
903 {
904 	switch (ratio) {
905 	case HDMI_MODE_AUTO:
906 		it66353_h2swset(0x51 + port, 0x28, 0x00);
907 		break;
908 	case HDMI_MODE_14:
909 		it66353_h2swset(0x51 + port, 0x28, 0x20);
910 		break;
911 	case HDMI_MODE_20:
912 		it66353_h2swset(0x51 + port, 0x28, 0x28);
913 		break;
914 	default:
915 		break;
916 	}
917 }
918 
it66353it66353_rx_ovwr_h20_scrb(u8 port,u8 scrb)919 static void __maybe_unused it66353it66353_rx_ovwr_h20_scrb(u8 port, u8 scrb)
920 {
921 	switch (scrb) {
922 	case HDMI_MODE_AUTO:
923 		it66353_h2swset(0x51 + port, 0x30, 0x00);
924 		break;
925 	case HDMI_MODE_14:
926 		it66353_h2swset(0x51 + port, 0x30, 0x20);
927 		break;
928 	case HDMI_MODE_20:
929 		it66353_h2swset(0x51 + port, 0x30, 0x30);
930 		break;
931 	default:
932 		break;
933 	}
934 }
935 
936 
it66353_sw_config_timer0(u8 count)937 static void it66353_sw_config_timer0(u8 count)
938 {
939 	// init timer = count[6:0] * 10 ms
940 	it66353_h2swwr(0x1C, count);
941 }
942 
it66353it66353_sw_enable_timer0(void)943 static void it66353it66353_sw_enable_timer0(void)
944 {
945 	it66353_h2swset(0x38, 0x02, 0x02);
946 }
947 
_sw_clear_timer0_interrupt(void)948 static void _sw_clear_timer0_interrupt(void)
949 {
950 	it66353_h2swset(0x28, 0x02, 0x02);
951 }
952 
_sw_enable_txoe_timer_check(void)953 static void __maybe_unused _sw_enable_txoe_timer_check(void)
954 {
955 	it66353_sw_disable_timer0();
956 	it66353_sw_config_timer0(45);		// 450ms time out
957 	_sw_clear_timer0_interrupt();
958 	it66353it66353_sw_enable_timer0();
959 }
960 
_sw_disable_txoe_timer_check(void)961 static void __maybe_unused _sw_disable_txoe_timer_check(void)
962 {
963 	it66353_sw_disable_timer0();
964 }
965 
_sw_show_hdcp_status(void)966 static void __maybe_unused _sw_show_hdcp_status(void)
967 {
968 	u8 hdcp_sts;
969 	if (it66353_gdev.vars.Rev >= 0xC0) {
970 		hdcp_sts = it66353_h2swrd(0xB3);
971 		if (hdcp_sts & BIT(5)) {
972 			DEBUG("HDCP 2 done\r\n");
973 			it66353_sw_clear_hdcp_status();
974 		}
975 		if (hdcp_sts & BIT(6)) {
976 			DEBUG("HDCP 1 done\r\n");
977 			it66353_sw_clear_hdcp_status();
978 		}
979 	}
980 }
981 
it66353_get_port_info1(u8 port,u8 info)982 u8 it66353_get_port_info1(u8 port, u8 info)
983 {
984 	u8 tmp;
985 	tmp = it66353_h2swrd(0x61 + port * 3);
986 
987 	if ((tmp & info) == info) {
988 		return 1;
989 	} else {
990 		return 0;
991 	}
992 }
993 
_tx_ovwr_hdmi_mode(u8 mode)994 static void _tx_ovwr_hdmi_mode(u8 mode)
995 {
996 	switch (mode) {
997 	case HDMI_MODE_AUTO:
998 		it66353_h2swset(0xB2, 0x0F, 0x00);
999 		break;
1000 	case HDMI_MODE_14:
1001 		it66353_h2swset(0xB2, 0x0F, 0x05);
1002 		break;
1003 	case HDMI_MODE_20:
1004 		it66353_h2swset(0xB2, 0x0F, 0x0F);
1005 		break;
1006 	default:
1007 		break;
1008 	}
1009 }
1010 
_tx_setup_afe(u32 vclk)1011 static void _tx_setup_afe(u32 vclk)
1012 {
1013 	u8 H2ON_PLL, DRV_TERMON, DRV_RTERM, DRV_ISW, DRV_ISWC, DRV_TPRE, DRV_NOPE, H2ClkRatio;
1014 	u8 DRV_PISW, DRV_PISWC, DRV_HS;
1015 
1016 	// vclk = 340000UL;
1017 	DEBUG("_tx_setup_afe %u\r\n", vclk);
1018 	// it66353_h2rxset(0x23, 0x04, 0x04);
1019 
1020 	if (vclk > 100000UL)  {			// IP_VCLK05 > 50MHz
1021 		it66353_h2swset(0xD1, 0x07, 0x04);
1022 	} else {
1023 		it66353_h2swset(0xD1, 0x07, 0x03);
1024 	}
1025 
1026 	if (vclk > 162000UL) {			// IP_VCLK05 > 81MHz
1027 		// it66353_h2swset(0xD4, 0x04, 0x04);
1028 		DRV_HS = 1;
1029 	} else {
1030 		DRV_HS = 0;
1031 	}
1032 
1033 	it66353_h2swset(0xd8, 0xf0, 0x00);
1034 	if (vclk > 300000UL) {			// single-end swing = 520mV
1035 		DRV_TERMON = 1;
1036 		DRV_RTERM = 0x5;
1037 		DRV_ISW = 0x0E;
1038 		DRV_ISWC = 0x0B;
1039 		DRV_TPRE = 0x0;
1040 		DRV_NOPE = 0;
1041 		H2ON_PLL = 1;
1042 		DRV_PISW = 1;
1043 		DRV_PISWC = 1;
1044 		it66353_h2swset(0xd8, 0xf0, 0x30);
1045 	} else if (vclk > 100000UL) {	// single-end swing = 450mV
1046 		DRV_TERMON = 1;
1047 		DRV_RTERM = 0x1;
1048 		DRV_ISW = 0x9;
1049 		DRV_ISWC = 0x9;
1050 		DRV_TPRE = 0;
1051 		DRV_NOPE = 1;
1052 		H2ON_PLL = 0;
1053 		DRV_PISW = 1;
1054 		DRV_PISWC = 1;
1055 	} else {			// single-end swing = 500mV
1056 		DRV_TERMON = 0;
1057 		DRV_RTERM = 0x0;
1058 		DRV_ISW = 0x3;
1059 		DRV_ISWC = 0x3;
1060 		DRV_TPRE = 0;
1061 		DRV_NOPE = 1;
1062 		H2ON_PLL = 0;
1063 		DRV_PISW = 1;
1064 		DRV_PISWC = 1;
1065 	}
1066 
1067 	it66353_h2swset(0xD0, 0x08, (H2ON_PLL << 3));
1068 	it66353_h2swset(0xD3, 0x1F, DRV_ISW);
1069 	it66353_h2swset(0xD4, 0xF4, (DRV_PISWC << 6)+(DRV_PISW << 4)+(DRV_HS << 2));
1070 	it66353_h2swset(0xD5, 0xBF, (DRV_NOPE << 7) + (DRV_TERMON << 5) + DRV_RTERM);
1071 	it66353_h2swset(0xD7, 0x1F, DRV_ISWC);
1072 	it66353_h2swset(0xD6, 0x0F, DRV_TPRE);
1073 
1074 	H2ClkRatio = (it66353_h2swrd(0xb2) & 0x02) >> 1;// RegH2ClkRatio from TX
1075 
1076 	DEBUG("TX Output H2ClkRatio=%d ...\r\n", H2ClkRatio);
1077 
1078 	// msleep(10);
1079 	// it66353_h2rxset(0x23, 0x04, 0x00);
1080 }
1081 
_rx_calc_edid_sum(u8 * edid)1082 static u8 _rx_calc_edid_sum(u8 *edid)
1083 {
1084 	u8 i;
1085 	u16 sum = 0x100;
1086 
1087 	for (i = 0; i < 127; i++) {
1088 		sum = sum - edid[i];
1089 	}
1090 	return (sum & 0xFF);
1091 }
1092 
it66353_rx_caof_init(u8 port)1093 void it66353_rx_caof_init(u8 port)
1094 {
1095 	u8 reg08;
1096 	u8 failcnt;
1097 
1098 	it66353_h2swset(0x05, 0x01, 0x01);
1099 	it66353_h2swset(0x59 + port, 0x20, 0x20);	// new at IT6635B0
1100 	it66353_h2swset(0x05 + port, 0x01, 0x01);	// IPLL RST, it6635
1101 	it66353_rx_auto_power_down_enable(port, 0);
1102 	it66353_rx_term_power_down(port, 0x00);		// disable PWD CHx termination
1103 
1104 	msleep(1);
1105 	it66353_chgrxbank(3);
1106 	it66353_h2rxset(0x3A, 0x80, 0x00);		// Reg_CAOFTrg low
1107 	it66353_h2rxset(0xA0, 0x80, 0x80);
1108 	it66353_h2rxset(0xA1, 0x80, 0x80);
1109 	it66353_h2rxset(0xA2, 0x80, 0x80);
1110 	it66353_chgrxbank(0);
1111 
1112 	it66353_h2rxset(0x2A, 0x41, 0x41);		// CAOF RST and CAOFCLK inversion
1113 	msleep(1);
1114 	it66353_h2rxset(0x2A, 0x40, 0x00);		// deassert CAOF RST
1115 	it66353_h2rxwr(0x25, 0x00);			// Disable AFE PWD
1116 	it66353_h2rxset(0x3C, 0x10, 0x00);		// disable PLLBufRst
1117 
1118 	it66353_chgrxbank(3);
1119 	it66353_h2rxset(0x3B, 0xC0, 0x00);		// Reg_ENSOF, Reg_ENCAOF
1120 	it66353_h2rxset(0x48, 0x80, 0x80);		// for read back sof value registers
1121 	msleep(10);
1122 	it66353_h2rxset(0x3A, 0x80, 0x80);		// Reg_CAOFTrg high
1123 
1124 	// wait for INT Done
1125 	it66353_chgrxbank(0);
1126 	reg08 = 0;
1127 	failcnt = 0;
1128 
1129 	while (reg08 == 0x00) {
1130 		reg08 = it66353_h2rxrd(0x08) & 0x10;
1131 
1132 		if (reg08 == 0) {
1133 			failcnt++;
1134 			if (failcnt >= 10) {
1135 				dev_err(g_it66353->dev, "ERROR: CAOF fail !!!\r\n");
1136 
1137 				it66353_chgrxbank(3);
1138 				it66353_h2rxset(0x3A, 0x80, 0x00);// disable CAOF_Trig
1139 				it66353_chgrxbank(0);
1140 				it66353_h2rxset(0x2A, 0x40, 0x40);// reset CAOF when caof fail
1141 				it66353_h2rxset(0x2A, 0x40, 0x00);
1142 				break;
1143 			}
1144 		}
1145 
1146 		msleep(2);
1147 	}
1148 
1149 
1150 	it66353_chgrxbank(3);
1151 	it66353_h2rxset(0x48, 0x80, 0x80);
1152 
1153 	DEBUG("CAOF_Int=%02x, Status=%02x\r\n\r\n",
1154 		   (it66353_h2rxrd(0x59) & 0xC0),
1155 		   ((it66353_h2rxrd(0x5A) << 4) + (it66353_h2rxrd(0x59) & 0x0F)));
1156 	it66353_chgrxbank(0);
1157 
1158 	it66353_h2swset(0x59+port, 0x20, 0x00);
1159 	it66353_h2swset(0x05+port, 0x01, 0x00);
1160 	it66353_h2swset(0x05, 0x01, 0x00);
1161 
1162 	it66353_h2rxset(0x08, 0x30, 0x30);
1163 	it66353_h2rxset(0x3C, 0x10, 0x10);
1164 
1165 	it66353_chgrxbank(3);
1166 	it66353_h2rxset(0x3A, 0x80, 0x00);	// Reg_CAOFTrg low
1167 	it66353_h2rxset(0xA0, 0x80, 0x00);
1168 	it66353_h2rxset(0xA1, 0x80, 0x00);
1169 	it66353_h2rxset(0xA2, 0x80, 0x00);
1170 	it66353_chgrxbank(0);
1171 
1172 	it66353_rx_auto_power_down_enable(port, it66353_gdev.opts.dev_opt->RxAutoPowerDown);
1173 }
1174 
_rx_show_ced_info(void)1175 static void _rx_show_ced_info(void)
1176 {
1177 	u8 symlock = (it66353_h2rxrd(0x14) & 0x38) >> 3;
1178 	u8 ch;
1179 
1180 	if (0x38 != symlock) {
1181 		DEBUG("symlock = %02x\r\n", symlock);
1182 	} else {
1183 		for (ch = 0; ch < 3; ch++) {
1184 			if (it66353_gdev.vars.RxCEDErrValid & (0x01 << ch)) {
1185 				DEBUG("ch_%d CED=0x%04x\r\n", ch, it66353_gdev.vars.RxCEDErr[ch]);
1186 			} else {
1187 				DEBUG("ch_%d CED=invalid\r\n", ch);
1188 			}
1189 		}
1190 	}
1191 }
1192 
_rx_setup_afe(u32 vclk)1193 static void _rx_setup_afe(u32 vclk)
1194 {
1195 	it66353_chgrxbank(3);
1196 
1197 	if (vclk >= (1024UL * 102UL)) {
1198 		it66353_h2rxset(0xA7, 0x40, 0x40);
1199 	} else {
1200 		it66353_h2rxset(0xA7, 0x40, 0x00);
1201 	}
1202 	it66353_chgrxbank(0);
1203 }
1204 
_rx_is_any_ch_symlock(void)1205 static u8 _rx_is_any_ch_symlock(void)
1206 {
1207 	if ((it66353_h2rxrd(0x14) & 0x38)) {
1208 		return 1;
1209 	}
1210 	return 0;
1211 }
1212 
it66353_rx_is_all_ch_symlock(void)1213 u8 it66353_rx_is_all_ch_symlock(void)
1214 {
1215 	if ((it66353_h2rxrd(0x14) & 0x38) == 0x38) {
1216 		DBG_SYMLOCK_1();
1217 		// it66353_txoe(1);
1218 		return 1;
1219 	}
1220 	DBG_SYMLOCK_0();
1221 	return 0;
1222 }
1223 
_rx_is_5v_active(void)1224 static bool _rx_is_5v_active(void)
1225 {
1226 	return (it66353_h2rxrd(0x13) & 0x01);
1227 }
1228 
it66353_rx_is_clock_stable(void)1229 u8 it66353_rx_is_clock_stable(void)
1230 {
1231 	if (it66353_get_port_info0(it66353_gdev.vars.Rx_active_port,
1232 				  (PI_CLK_STABLE | PI_CLK_VALID | PI_5V))) {
1233 		DBG_CLKSTABLE_1();
1234 		return 1;
1235 	} else {
1236 		DBG_CLKSTABLE_0();
1237 		return 0;
1238 	}
1239 }
1240 
1241 #if EN_AUTO_RS
_rx_need_hpd_toggle(void)1242 static u8 _rx_need_hpd_toggle(void)
1243 {
1244 	u8 hdcp_sts;
1245 	if (it66353_gdev.vars.Rev >= 0xC0) {
1246 		hdcp_sts = it66353_h2swrd(0xB3);
1247 		if (hdcp_sts & BIT(5)) {
1248 			dev_info(g_it66353->dev, "HDCP 2 done\r\n");
1249 			return 1;
1250 		}
1251 		if (hdcp_sts & BIT(6)) {
1252 			dev_info(g_it66353->dev, "HDCP 1 done\r\n");
1253 			return 1;
1254 		}
1255 		if (hdcp_sts & BIT(7)) {
1256 			dev_info(g_it66353->dev, "HDCP acc\r\n");
1257 			// return 0;
1258 		}
1259 	} else {
1260 		if (it66353_sw_get_timer0_interrupt()) {
1261 			dev_info(g_it66353->dev, "TXOE timeout 2\r\n");
1262 			return 1;
1263 		}
1264 	}
1265 
1266 	return 0;
1267 
1268 	#if 0
1269 	// todo: need more information
1270 	return 1;
1271 	#endif
1272 }
1273 #endif
1274 
_rx_int_enable(void)1275 static void _rx_int_enable(void)
1276 {
1277 /*
1278  * Set RX Interrupt Enable
1279  */
1280 	it66353_h2rxwr(0x53, 0xFF);		// Enable RxIntEn[7:0]
1281 	it66353_h2rxwr(0x54, 0xFF);		// Enable RxIntEn[15:8]
1282 	it66353_h2rxwr(0x55, 0xFF);		// Enable RxIntEn[23:16]
1283 	it66353_h2rxwr(0x56, 0xFF);		// Enable RxIntEn[31:24]
1284 	it66353_h2rxwr(0x57, 0xFF);		// Enable RxIntEn[39:32]
1285 	it66353_h2rxwr(0x5D, 0xF7);		// Enable BKIntEn[7:0], but timer int
1286 	it66353_h2rxwr(0x5E, 0xFF);		// Enable BKIntEn[15:8]
1287 	it66353_h2rxwr(0x5F, 0xFF);		// Enable BKIntEn[23:16]
1288 	it66353_h2rxset(0x60, 0x20, 0x20);	// RegEnIntOut=1
1289 }
1290 
_rx_wdog_rst(u8 port)1291 static void _rx_wdog_rst(u8 port)
1292 {
1293 	#if 0
1294 	u8 mask;
1295 	mask = (0x10 << port) | (1 << port);
1296 	it66353_h2swset(0x16, mask, mask);
1297 	msleep(1);
1298 	it66353_h2swset(0x16, mask, 0x00);
1299 	#else
1300 	it66353_h2swset(0x2b, 0x01, 0x00);
1301 	msleep(2);
1302 	// it66353_h2swwr(0x20 + port * 2, 0x7C);// clear clock related interrupt
1303 	it66353_h2swset(0x2b, 0x01, 0x01);
1304 	// it66353_h2swwr(0x20 + port * 2, 0x04);
1305 	#endif
1306 }
1307 
_rx_ovwr_hdmi_mode(u8 port,u8 mode)1308 static void _rx_ovwr_hdmi_mode(u8 port, u8 mode)
1309 {
1310 	switch (mode) {
1311 	case HDMI_MODE_AUTO:
1312 		it66353_h2swset(0x51 + port, 0x38, 0x00);
1313 		it66353_h2swset(0x98 + port, 0xC0, 0x00);
1314 		break;
1315 	case HDMI_MODE_14:
1316 		it66353_h2swset(0x51 + port, 0x38, 0x20);
1317 		it66353_h2swset(0x98 + port, 0xC0, 0x00);
1318 		break;
1319 	case HDMI_MODE_20:
1320 		it66353_h2swset(0x51 + port, 0x38, 0x38);
1321 		it66353_h2swset(0x98 + port, 0xC0, 0xC0);
1322 		break;
1323 	}
1324 }
1325 
1326 
_rx_set_hpd(u8 port,u8 hpd_value,u8 term_value)1327 static void _rx_set_hpd(u8 port, u8 hpd_value, u8 term_value)
1328 {
1329 	if (port < RX_PORT_COUNT) {
1330 		switch (term_value) {
1331 		case TERM_LOW:
1332 			term_value = 0xFF;
1333 			break;
1334 		case TERM_HIGH:
1335 			term_value = 0x00;
1336 			break;
1337 		case TERM_FOLLOW_TX:
1338 			if (it66353_h2swrd(0x11) & 0x40)
1339 				term_value = 0x00;
1340 			else
1341 				term_value = 0xFF;
1342 			break;
1343 		case TERM_FOLLOW_HPD:
1344 		default:
1345 			if (hpd_value) {
1346 				term_value = 0x00;
1347 			} else {
1348 				term_value = 0xFF;
1349 			}
1350 			break;
1351 		}
1352 
1353 		// if (it66353_gdev.vars.RxHPDFlag[port] != value)
1354 		// {
1355 			it66353_gdev.vars.RxHPDFlag[port] = hpd_value;
1356 			if (hpd_value) {
1357 				if (it66353_gdev.vars.Rx_active_port == port) {
1358 					DBG_TM(RX_HPD_HIGH);
1359 
1360 					if (it66353_gdev.opts.rx_opt[port]->EnRxDDCBypass == 0) {
1361 						it66353_h2swset(0x3C, 0x01, 0x01);
1362 						msleep(1);
1363 						it66353_h2swset(0x3C, 0x01, 0x00);
1364 					}
1365 				}
1366 
1367 				if (it66353_gdev.opts.rx_opt[port]->DisableEdidRam == 0) {
1368 					_rx_edid_ram_enable(port);
1369 				}
1370 
1371 				if (it66353_gdev.opts.rx_opt[port]->HPDOutputInverse) {
1372 					it66353_h2swset(0x4C + port, 0xC0, 0x40);// RXHPD=0
1373 				} else {
1374 					it66353_h2swset(0x4C + port, 0xC0, 0xC0);// RXHPD=1
1375 				}
1376 
1377 
1378 				#if 0
1379 				if (it66353_gdev.vars.Rx_active_port == port) {
1380 					// term power down = 0
1381 					it66353_rx_term_power_down(port, 0x7e);
1382 				} else {
1383 					#if NON_ACTIVE_PORT_DETECT_CLOCK
1384 					// term power down = 0
1385 					it66353_rx_term_power_down(port, 0x7e);
1386 					#else
1387 					// term power down = 0
1388 					it66353_rx_term_power_down(port, 0xFF);
1389 					#endif
1390 				}
1391 				#else
1392 				it66353_rx_term_power_down(port, term_value);
1393 				#endif
1394 			} else {
1395 				if (it66353_gdev.vars.Rx_active_port == port) {
1396 					DBG_TM(RX_HPD_LOW);
1397 				}
1398 
1399 				_rx_edid_ram_disable(port);
1400 
1401 				it66353_rx_term_power_down(port, term_value);
1402 
1403 				if (it66353_gdev.opts.rx_opt[port]->HPDOutputInverse) {
1404 					it66353_h2swset(0x4C + port, 0xC0, 0xC0);// RXHPD=1
1405 				} else {
1406 					it66353_h2swset(0x4C + port, 0xC0, 0x40);// RXHPD=0
1407 				}
1408 
1409 				if (port == it66353_gdev.vars.Rx_active_port) {
1410 					it66353_h2swset(0xB2, 0x0A, 0x0A); // clear H2Mode
1411 				}
1412 			}
1413 			dev_info(g_it66353->dev, "Set RxP%d HPD = %d %02x\r\n",
1414 				 (int)port, (int)hpd_value, (int)term_value);
1415 		// }
1416 	} else {
1417 		dev_err(g_it66353->dev, "Invaild port %d\r\n", port);
1418 	}
1419 }
1420 
_rx_set_hpd_all(u8 value)1421 static void _rx_set_hpd_all(u8 value)
1422 {
1423 	u8 i;
1424 
1425 	for (i = 0; i < RX_PORT_COUNT; i++) {
1426 		_rx_set_hpd(i, value, TERM_FOLLOW_HPD);
1427 	}
1428 }
1429 
_rx_set_hpd_with_5v_all(u8 non_active_port_only)1430 static void _rx_set_hpd_with_5v_all(u8 non_active_port_only)
1431 {
1432 	u8 i;
1433 	for (i = 0; i < RX_PORT_COUNT; i++) {
1434 		if (non_active_port_only) {
1435 			if (it66353_gdev.vars.Rx_active_port == i) {
1436 				continue;
1437 			}
1438 		}
1439 
1440 		if (it66353_gdev.opts.rx_opt[i]->NonActivePortReplyHPD) {
1441 			if (it66353_get_port_info0(i, PI_5V)) {
1442 				_rx_set_hpd(i, 1, TERM_FOLLOW_HPD);
1443 			} else {
1444 				_rx_set_hpd(i, 0, TERM_FOLLOW_HPD);
1445 			}
1446 		}
1447 	}
1448 }
1449 
_rx_get_all_port_5v(void)1450 static u8 _rx_get_all_port_5v(void)
1451 {
1452 	u8 i;
1453 	u8 ret = 0;
1454 	for (i = 0; i < RX_PORT_COUNT; i++) {
1455 		if (it66353_get_port_info0(i, PI_5V)) {
1456 			ret |= (1 << i);
1457 		}
1458 	}
1459 
1460 	return ret;
1461 }
1462 
it66353it66353_rx_handle_output_err(void)1463 static void __maybe_unused it66353it66353_rx_handle_output_err(void)
1464 {
1465 #if EN_AUTO_RS
1466 	if (it66353_gdev.opts.active_rx_opt->EnableAutoEQ) {
1467 		if (it66353_gdev.vars.try_fixed_EQ) {
1468 			dev_info(g_it66353->dev, "*** fixed EQ fail\r\n");
1469 			it66353_gdev.vars.try_fixed_EQ = 0;
1470 			it66353_eq_reset_txoe_ready();
1471 			it66353_eq_reset_state();
1472 			it66353_fsm_chg(RX_CHECK_EQ);
1473 		} else {
1474 			it66353_auto_eq_adjust();
1475 		}
1476 	}
1477 #endif
1478 }
1479 
it66353_rx_auto_power_down_enable(u8 port,u8 enable)1480 void it66353_rx_auto_power_down_enable(u8 port, u8 enable)
1481 {
1482 	if (enable) {
1483 		/*
1484 		 * //will auto power down D0~D2 3.3V
1485 		 * it66353_h2swset(0x90 + port, 0x3D, 0x3D);
1486 		 * // will not power down D0~D2 3.3V
1487 		 * it66353_h2swset(0x90 + port, 0x3D, 0x1D);
1488 		 */
1489 		it66353_h2swset(0x90 + port, 0x3D, 0x1D);
1490 	} else {
1491 		it66353_h2swset(0x90 + port, 0x3D, 0x00);
1492 	}
1493 }
1494 
it66353_rx_auto_power_down_enable_all(u8 enable)1495 static void it66353_rx_auto_power_down_enable_all(u8 enable)
1496 {
1497 	u8 i;
1498 	for (i = 0; i < RX_PORT_COUNT; i++) {
1499 		it66353_rx_auto_power_down_enable(i, enable);
1500 	}
1501 }
1502 
it66353_rx_term_power_down(u8 port,u8 channel)1503 void it66353_rx_term_power_down(u8 port, u8 channel)
1504 {
1505 	// to detect clock,
1506 	// 0x88[7][0] must be '0','0';
1507 	it66353_h2swset(0x88 + port, 0xFF, channel);
1508 }
1509 
1510 
_sw_int_enable(u8 port,u8 enable)1511 static void _sw_int_enable(u8 port, u8 enable)
1512 {
1513 	if (enable) {
1514 		// Enable Switch RX Port Interrupt
1515 		it66353_h2swwr(0x30 + port * 2, 0xff);
1516 		it66353_h2swset(0x31 + port * 2, 0x01, 0x01);
1517 	} else {
1518 		// Disable Switch RX Port Interrupt
1519 		it66353_h2swwr(0x30 + port * 2, 0x00);
1520 		it66353_h2swset(0x31 + port * 2, 0x01, 0x00);
1521 		it66353_h2swwr(0x20 + port * 2, 0xff);
1522 		it66353_h2swwr(0x21 + port * 2, 0xff);
1523 	}
1524 
1525 }
1526 
_sw_int_enable_all(u8 enable)1527 static void _sw_int_enable_all(u8 enable)
1528 {
1529 	u8 i;
1530 	for (i = 0; i < RX_PORT_COUNT; i++) {
1531 		_sw_int_enable(i, enable);
1532 	}
1533 }
1534 
it66353_sw_disable_timer0(void)1535 void it66353_sw_disable_timer0(void)
1536 {
1537 	// disable timer will also clear timer interrupt flag
1538 	it66353_h2swset(0x38, 0x02, 0x00);
1539 }
1540 
1541 #if EN_AUTO_RS
it66353_sw_get_timer0_interrupt(void)1542 u8 it66353_sw_get_timer0_interrupt(void)
1543 {
1544 	return ((it66353_h2swrd(0x28)&0x02));
1545 }
1546 #endif
1547 
1548 
_sw_config_timer1(u8 count)1549 static void _sw_config_timer1(u8 count)
1550 {
1551 	// init timer = count[6:0] * 10 ms
1552 	// init timer = BIT7|count[6:0] * 100 ms
1553 	it66353_h2swwr(0x1D, count);
1554 }
1555 
_sw_enable_timer1(void)1556 static void _sw_enable_timer1(void)
1557 {
1558 	it66353_h2swset(0x38, 0x04, 0x04);
1559 }
1560 
_sw_disable_timer1(void)1561 static void _sw_disable_timer1(void)
1562 {
1563 	it66353_h2swset(0x38, 0x04, 0x00);
1564 }
1565 
_sw_get_timer1_interrupt(void)1566 static u8 _sw_get_timer1_interrupt(void)
1567 {
1568 	return ((it66353_h2swrd(0x28)&0x04));
1569 }
1570 
_sw_clear_timer1_interrupt(void)1571 static void _sw_clear_timer1_interrupt(void)
1572 {
1573 	it66353_h2swset(0x28, 0x04, 0x04);
1574 }
1575 
_sw_enable_hpd_toggle_timer(u8 timeout)1576 static void _sw_enable_hpd_toggle_timer(u8 timeout)
1577 {
1578 	// init timer = count[6:0] * 10 ms
1579 	// init timer = BIT7|count[6:0] * 100 ms
1580 	_sw_config_timer1(timeout);		// HPT toggle time out
1581 
1582 	_sw_clear_timer1_interrupt();
1583 	_sw_enable_timer1();
1584 }
1585 
_sw_disable_hpd_toggle_timer(void)1586 static void _sw_disable_hpd_toggle_timer(void)
1587 {
1588 	_sw_disable_timer1();
1589 }
1590 
_sw_check_hpd_toggle_timer(void)1591 static u8 _sw_check_hpd_toggle_timer(void)
1592 {
1593 	return _sw_get_timer1_interrupt();
1594 }
1595 
_sw_reset_scdc_monitor(void)1596 static void _sw_reset_scdc_monitor(void)
1597 {
1598 	it66353_h2swwr(0xAD, 0xFF);
1599 }
1600 
_sw_monitor_and_fix_scdc_write(void)1601 static void _sw_monitor_and_fix_scdc_write(void)
1602 {
1603 	u8 reg;
1604 
1605 	reg = it66353_h2swrd(0xAD);
1606 	if (reg & 0x10) {		// P0SCDCWrReg20hVld
1607 		dev_info(g_it66353->dev, "## src SCDC wr %02x\r\n", reg);
1608 		if (it66353_gdev.vars.current_hdmi_mode == HDMI_MODE_20) {
1609 			if ((reg&0x03) != 0x03) {
1610 				_tx_scdc_write(0x20, 0x03);
1611 			}
1612 		} else if (it66353_gdev.vars.current_hdmi_mode == HDMI_MODE_14) {
1613 			if ((reg&0x03) != 0x00) {
1614 				_tx_scdc_write(0x20, 0x00);
1615 			}
1616 		}
1617 		_sw_reset_scdc_monitor();
1618 	}
1619 }
1620 
it66353_sw_clear_hdcp_status(void)1621 void it66353_sw_clear_hdcp_status(void)
1622 {
1623 	it66353_h2swwr(0xB0, 0xC0);
1624 }
1625 
_sw_sdi_check(void)1626 static void _sw_sdi_check(void)
1627 {
1628 	u8 port;
1629 	u8 reg6C, reg70;
1630 	port = it66353_gdev.vars.Rx_active_port;
1631 
1632 	if (it66353_gdev.vars.sdi_stable_count < 8) {
1633 		if (it66353_get_port_info0(port, PI_CLK_STABLE)) {
1634 			it66353_gdev.vars.sdi_stable_count++;
1635 		} else {
1636 			it66353_gdev.vars.sdi_stable_count = 0;
1637 		}
1638 	} else {
1639 		// perform check
1640 		it66353_gdev.vars.sdi_stable_count = 0;
1641 		reg6C = it66353_h2swrd(0x6c + port);
1642 		reg70 = it66353_h2swrd(0x70 + port);
1643 
1644 		if (reg70 & BIT(3)) {
1645 			reg6C = reg6C/8;
1646 		} else if (reg70 & BIT(2)) {
1647 			reg6C = reg6C/4;
1648 		} else if (reg70 & BIT(1)) {
1649 			reg6C = reg6C/2;
1650 		} else {
1651 			// reg6C = reg6C/1;
1652 		}
1653 
1654 		if (reg6C < 22) {
1655 			reg70 = it66353_h2swrd(0x61 + port * 3);
1656 			if (0 == (reg70 & BIT(1))) {
1657 				// need re-calculate RDetIPLL_HS1P48G
1658 				reg70 = 1 << port;
1659 				it66353_h2swset(0x2A, reg70, reg70);
1660 				DEBUG("check_for_sdi recheck ...\r\n");
1661 			} else {
1662 				it66353_gdev.vars.check_for_sdi = 0;
1663 				DEBUG("check_for_sdi disabled ...%02x\r\n",
1664 				      it66353_h2rxrd(0x13));
1665 			}
1666 		} else {
1667 			it66353_gdev.vars.check_for_sdi = 0;
1668 		}
1669 	}
1670 }
1671 
_sw_hdcp_access_enable(u8 enable)1672 static void _sw_hdcp_access_enable(u8 enable)
1673 {
1674 	if (it66353_gdev.vars.spmon == 2) {
1675 		DEBUG("  >> skip HDCP acc %d\r\n", enable);
1676 		return;
1677 	}
1678 
1679 	DEBUG("  >> HDCP acc %d\r\n", enable);
1680 
1681 	if (enable) {
1682 		it66353_h2swwr(0xAB, 0x60);
1683 		// it66353_h2swset(0x3C, 0x01, 0x00);
1684 	} else {
1685 		it66353_h2swwr(0xAB, 0x74);
1686 		// it66353_h2swset(0x3C, 0x01, 0x01);
1687 	}
1688 }
1689 
_tx_init(void)1690 static void _tx_init(void)
1691 {
1692 	if (it66353_gdev.opts.dev_opt->ForceRxOn) {
1693 		// for ATC electrical test
1694 		it66353_h2swwr(0xFF, 0xC3);
1695 		it66353_h2swwr(0xFF, 0xA5);
1696 		it66353_h2swset(0xF4, 0x80, it66353_gdev.opts.dev_opt->ForceRxOn << 7);
1697 		it66353_h2swwr(0xFF, 0xFF);
1698 	}
1699 
1700 	it66353_h2swset(0x50, 0x0B, 0x08);
1701 
1702 	it66353_h2swset(0x3A, 0xC0, (1 << 7) + (0 << 6));
1703 	it66353_h2swset(0x3B, 0x03, 0);			// DDC 75K
1704 	it66353_h2swset(0x43, 0xFC, (0 << 7) + (0 << 5) + (0 << 4) + (2 << 2));
1705 	it66353_h2swset(0xA9, 0xC0, (it66353_gdev.opts.tx_opt->EnTxChSwap << 7) +
1706 			(it66353_gdev.opts.tx_opt->EnTxPNSwap << 6));
1707 
1708 	// Enable HPD and RxSen Interrupt
1709 	it66353_h2swwr(0x27, 0xff);
1710 	it66353_h2swset(0x37, 0x78, 0x78);
1711 
1712 	_tx_power_down();
1713 
1714 	it66353_h2swset(0xBD, 0x01, it66353_gdev.opts.tx_opt->EnTxVCLKInv);
1715 	it66353_h2swset(0xA9, 0x20, it66353_gdev.opts.tx_opt->EnTxOutD1t << 5);
1716 
1717 	it66353_h2swset(0x50, 0x03, it66353_gdev.vars.Rx_active_port);
1718 	it66353_enable_tx_port(1);
1719 }
1720 
_tx_reset(void)1721 static void _tx_reset(void)
1722 {
1723 	DEBUG("TX Reset\r\n");
1724 
1725 	it66353_h2swset(0x09, 0x01, 0x01);		// RegSoftTxVRst=1
1726 	it66353_h2swset(0x09, 0x01, 0x00);		// RegSoftTxVRst=0
1727 
1728 	// Enable TX DDC Master Reset
1729 	it66353_h2swset(0x3B, 0x10, 0x10);		// DDC Master Reset
1730 	it66353_h2swset(0x3B, 0x10, 0x00);
1731 
1732 	_tx_init();
1733 }
1734 
_rx_init(void)1735 static void _rx_init(void)
1736 {
1737 	// Add RX initial option setting here
1738 	it66353_h2rxset(0x34, 0x01, 0x01);	// Reg_AutoRCLK=1 (default)
1739 	it66353_h2rxset(0x21, 0x40, 0x40);	// Reg_AutoEDIDRst=1
1740 	it66353_h2rxwr(0x3A, 0xCB);		// to reduce RxDeskew Err and Chx LagErr
1741 	it66353_h2rxset(0x3B, 0x20, 0x20);	// CED_Opt
1742 	it66353_h2swset(0x44, 0x08, 0x00);
1743 	it66353_h2rxset(0x29, 0x40, 0x00);
1744 	it66353_h2rxset(0x3C, 0x01, 0x00);
1745 
1746 	// it66353_h2rxset(0x3d, 0x02, 0x02);	// Reg_deskewdown = 1
1747 }
1748 
it66353_rx_reset(void)1749 void it66353_rx_reset(void)
1750 {
1751 	DEBUG("RX Reset\r\n");
1752 
1753 	it66353_h2rxset(0x29, 0x40, 0x00);
1754 	it66353_h2swset(0x44, 0x08, 0x08);
1755 	it66353_h2rxwr(0x23, 0x01);		// SWRst=1
1756 	// it66353_h2rxwr(0x22, 0x08);		// RegRst=1
1757 
1758 	it66353_h2rxwr(0x23, 0xAF);
1759 	msleep(1);
1760 	it66353_h2rxwr(0x23, 0xA0);
1761 
1762 	_rx_init();
1763 }
1764 
_sw_init(void)1765 static void _sw_init(void)
1766 {
1767 	u8 port;
1768 	// H2SW Initial Setting
1769 	it66353_h2swset(0x44, 0x03, RCLKFreqSel);
1770 	msleep(1);
1771 
1772 	it66353_init_rclk();
1773 
1774 	// Enable Slave Address
1775 	it66353_h2swwr(0xEF, it66353_gdev.opts.dev_opt->RxAddr | 0x01);
1776 
1777 	#if EN_CEC
1778 	if (it66353_gdev.opts.EnCEC) {
1779 		// if CEC is enabled, we should have a accurate RCLK.
1780 		u16 cec_timer_unit;
1781 
1782 		it66353_h2swwr(0xEE, (it66353_gdev.opts.dev_opt->CecAddr | 0x01));
1783 		it66353_cecset(0x08, 0x01, 0x01);
1784 
1785 		cec_timer_unit = it66353_gdev.vars.RCLK / (16*10);
1786 		Cec_Init(0xff & cec_timer_unit);
1787 	} else
1788 	#endif
1789 	{
1790 		u8 tmp;
1791 		it66353_h2swwr(0xEE, (it66353_gdev.opts.dev_opt->CecAddr | 0x01));
1792 		// it66353_cecset(0x0d, 0x10, 0x00);		// Disable CEC_IOPU
1793 		tmp = 0x40;
1794 		cecAddr_updata_bit(0x10, 0xff, tmp);		// Disable CEC_IOPU
1795 		it66353_h2swwr(0xEE, (it66353_gdev.opts.dev_opt->CecAddr & 0xFE));
1796 	}
1797 
1798 	it66353_h2swset(0x44, 0x40, 0x00);			// EnRxPort2Pwd=0
1799 	msleep(10);
1800 
1801 	it66353_rx_caof_init(it66353_gdev.vars.Rx_active_port);
1802 
1803 	// Setup INT Pin: Active Low & Open-Drain
1804 	it66353_h2swset(0x11, 0x07, 0x03);
1805 
1806 	// Enable SW Interrupt
1807 	it66353_h2swset(0x37, 0xE0, 0xE0);
1808 	it66353_h2swset(0x38, 0xF9, 0xF9);
1809 
1810 	// enable non main port to power down
1811 	it66353_h2swset(0x15, 0x08, 0 << 3);
1812 
1813 	it66353_h2swset(0x2B, 0x02, 0x00);
1814 	it66353_h2swset(0x2C, 0xC0, 0xC0);
1815 
1816 	it66353_h2swset(0x50, 0xf0, 0x00);
1817 
1818 	it66353_h2swset(0xC4, 0x08, 0x08);
1819 	it66353_h2swset(0xC5, 0x08, 0x08);
1820 	it66353_h2swset(0xC6, 0x08, 0x08);
1821 
1822 	// P0~P3 auto power downs
1823 #if 0
1824 	it66353_rx_auto_power_down_enable_all(1);
1825 #else
1826 	it66353_rx_auto_power_down_enable_all(it66353_gdev.opts.dev_opt->RxAutoPowerDown);
1827 
1828 	it66353_rx_term_power_down(RX_PORT_0, 0);
1829 	it66353_rx_term_power_down(RX_PORT_1, 0);
1830 	it66353_rx_term_power_down(RX_PORT_2, 0);
1831 	it66353_rx_term_power_down(RX_PORT_3, 0);
1832 
1833 #endif
1834 
1835 	it66353_h2swset(0xF5, 0xE0,
1836 			(it66353_gdev.opts.active_rx_opt->EnRxDDCBypass << 7)+
1837 			(it66353_gdev.opts.active_rx_opt->EnRxPWR5VBypass << 6)+
1838 			(it66353_gdev.opts.active_rx_opt->EnRxHPDBypass << 5));
1839 	if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == 1) {
1840 		it66353_h2swset(0x3C, 0x01, 0x01);// disable DDCRegen by set RegTxMastersel=1
1841 		it66353_h2swset(0xb3, 0x20, 0x20);
1842 		_rx_edid_ram_disable(RX_PORT_0);
1843 		_rx_edid_ram_disable(RX_PORT_1);
1844 		_rx_edid_ram_disable(RX_PORT_2);
1845 		_rx_edid_ram_disable(RX_PORT_3);
1846 	} else {
1847 		// config EDID RAM
1848 		for (port = 0; port < RX_PORT_COUNT; port++) {
1849 			if (it66353_gdev.opts.rx_opt[port]->DisableEdidRam) {
1850 				_rx_edid_ram_disable(port);
1851 				_rx_edid_address_disable(port);
1852 			} else {
1853 				_rx_edid_ram_enable(port);
1854 				_rx_edid_address_enable(port);
1855 			}
1856 		}
1857 	}
1858 
1859 	if (it66353_gdev.opts.active_rx_opt->EnRxHPDBypass) {
1860 		it66353_h2swset(0x4c, 0x40, 0x00);
1861 		it66353_h2swset(0x4d, 0x40, 0x00);
1862 		it66353_h2swset(0x4e, 0x40, 0x00);
1863 	}
1864 
1865 	// disable EDID read/write to clear P0AutoH2Mode and AutoScrbEn
1866 	it66353_h2swset(0xB2, 0x60, 0x00);
1867 	// it66353_h2swset(0xB2, 0x40, 0x00);
1868 
1869 	// enable TX port latch ERROR count
1870 	it66353_h2swset(0xAC, 0x11, 0x11);
1871 
1872 	// ddc monitor
1873 	it66353_h2swwr(0xB0, 0x80);
1874 
1875 }
1876 
_sw_reset(void)1877 static void _sw_reset(void)
1878 {
1879 	DEBUG("Switch Reset\r\n");
1880 
1881 	it66353_h2swwr(0xEF, it66353_gdev.opts.dev_opt->RxAddr | 0x01);
1882 	it66353_h2swset(0x0A, 0x01, 0x01);	// SoftRstAll=1
1883 	if (it66353_h2swrd(0xEF) == (it66353_gdev.opts.dev_opt->RxAddr | 0x01)) {
1884 		it66353_h2swset(0x44, 0xA0, 0x80);// ForceWrUpd = 1 and SWGateRCLK = 0
1885 	}
1886 	// it66353_h2swset(0x0A, 0x02, 0x02);	// SoftSWRRst=1
1887 
1888 	_sw_init();
1889 }
1890 
1891 // To have accurate RCLK,
1892 // we should use "it66353_cal_rclk" instead of "it66353_init_rclk"
1893 #if EN_CEC
it66353_cal_rclk(void)1894 static void it66353_cal_rclk(void)
1895 {
1896 	u8 i;
1897 	u8 timer_int, timer_flt, wclk_high_ext;
1898 	u32 wclk_valid_num, wclk_high_num, wclk_high_num_b, wclk_high_num_c;
1899 	u32 sum, rclk_tmp, rclk, rddata;
1900 
1901 	sum = 0;
1902 	for (i = 0; i < 5; i++) {
1903 		it66353_h2swset(0x11, 0x80, 0x80);
1904 		msleep(99);
1905 		it66353_h2swset(0x11, 0x80, 0x00);
1906 
1907 		rddata = it66353_h2swrd(0x12);
1908 		rddata += (it66353_h2swrd(0x13) << 8);
1909 		rddata += (it66353_h2swrd(0x14) << 16);
1910 
1911 		sum += rddata;
1912 	}
1913 	sum /= 5;
1914 	rclk = sum / 100;
1915 
1916 	DEBUG("RCLK=%d kHz\r\n\r\n", rclk);
1917 
1918 	timer_int = rclk / 1000;
1919 	timer_flt = (rclk - timer_int * 1000) * 256 / 1000;
1920 
1921 	it66353_h2swwr(0x1E, timer_int);
1922 	it66353_h2swwr(0x1F, timer_flt);
1923 
1924 	rclk_tmp = (rclk) * (1 << RCLKFreqSel);
1925 
1926 	wclk_valid_num = (8UL * rclk_tmp + 625) / 1250UL;
1927 	wclk_high_num = (8 * rclk_tmp + 3125) / 6250UL;
1928 	it66353_h2swset(0x2C, 0x3F, (u8)wclk_high_num & 0xFF);
1929 	it66353_h2swwr(0x2D, (u8)wclk_valid_num & 0xFF);
1930 
1931 	wclk_high_num_b = 32UL * rclk_tmp / (37125UL);
1932 	wclk_high_num = 32UL * rclk_tmp - (wclk_high_num_b * 37125UL);
1933 	wclk_high_ext = wclk_high_num * 2 / 37125UL;
1934 	it66353_h2swwr(0x2E, (wclk_high_ext << 6) + ((u8)wclk_high_num_b));
1935 
1936 	wclk_high_num_c = 4UL * rclk_tmp / 10625UL;
1937 	wclk_high_num = 4UL * rclk_tmp - (wclk_high_num_c * 10625UL);
1938 	wclk_high_ext = wclk_high_num * 4 / 10625UL;
1939 	it66353_h2swwr(0x2F, (wclk_high_ext << 6) + ((u8)wclk_high_num_c));
1940 
1941 	it66353_gdev.vars.RCLK = rclk;
1942 }
1943 #endif
1944 
1945 
it66353_init_rclk(void)1946 void it66353_init_rclk(void)
1947 {
1948 #if EN_CEC
1949 	if (it66353_gdev.opts.EnCEC) {
1950 		it66353_cal_rclk();
1951 	} else
1952 #endif
1953 	{
1954 		#if 0
1955 			// RCLK=20000 kHz
1956 			it66353_h2swwr(0x1e, 0x14);
1957 			it66353_h2swwr(0x1f, 0x00);
1958 			it66353_h2swset(0x2c, 0x3f, 0x1a);
1959 			it66353_h2swwr(0x2d, 0x80);
1960 			it66353_h2swwr(0x2e, 0x11);
1961 			it66353_h2swwr(0x2f, 0x87);
1962 			it66353_gdev.vars.RCLK = 20000;
1963 		#else
1964 			#if 0
1965 			// RCLK=19569 kHz
1966 			it66353_h2swwr(0x1e, 0x13);
1967 			it66353_h2swwr(0x1f, 0x91);
1968 			it66353_h2swset(0x2c, 0x3f, 0x19);
1969 			it66353_h2swwr(0x2d, 0x7d);
1970 			it66353_h2swwr(0x2e, 0x50);
1971 			it66353_h2swwr(0x2f, 0x47);
1972 			it66353_gdev.vars.RCLK = 19569;
1973 			#endif
1974 
1975 			// RCLK=18562 kHz
1976 			it66353_h2swwr(0x1e, 0x12);
1977 			it66353_h2swwr(0x1f, 0x90);
1978 			it66353_h2swset(0x2c, 0x3f, 0x18);
1979 			it66353_h2swwr(0x2d, 0x77);
1980 			it66353_h2swwr(0x2e, 0x10);
1981 			it66353_h2swwr(0x2f, 0xc6);
1982 			it66353_gdev.vars.RCLK = 18562;
1983 
1984 		#endif
1985 	}
1986 }
1987 
1988 
1989 
it66353_get_port_info0(u8 port,u8 info)1990 u8 it66353_get_port_info0(u8 port, u8 info)
1991 {
1992 	u8 tmp;
1993 	tmp = it66353_h2swrd(0x60 + port * 3);
1994 
1995 	if ((tmp & info) == info)
1996 		return 1;
1997 	else
1998 		return 0;
1999 }
2000 
it66353_enable_tx_port(u8 enable)2001 void it66353_enable_tx_port(u8 enable)
2002 {
2003 	it66353_h2swset(0x50, 0x08, (enable << 3));
2004 }
2005 
it66353_txoe(u8 enable)2006 void it66353_txoe(u8 enable)
2007 {
2008 	if (it66353_gdev.vars.current_txoe == enable) {
2009 		DEBUG("  >> it66353_txoe return %d \r\n", enable);
2010 		return;
2011 	}
2012 
2013 	DEBUG("TXOE=%d align=%d\r\n", enable, it66353_gdev.opts.active_rx_opt->TxOEAlignment);
2014 
2015 	if (enable) {
2016 		if (it66353_gdev.vars.current_hdmi_mode == HDMI_MODE_20) {
2017 			_tx_ovwr_hdmi_mode(HDMI_MODE_20);
2018 			_tx_scdc_write(0x20, 0x03);
2019 		} else if (it66353_gdev.vars.current_hdmi_mode == HDMI_MODE_14) {
2020 			_tx_ovwr_hdmi_mode(HDMI_MODE_14);
2021 			_tx_scdc_write(0x20, 0x00); // todo: ? check if safe to send this?
2022 		}
2023 
2024 		it66353_h2swset(0xD4, 0x03, 0x01);	// Set DRV_RST='0'
2025 		it66353_h2swset(0xD4, 0x03, 0x00);	// Set DRV_RST='0'
2026 
2027 		// REPORT_TXOE_1();
2028 	} else {
2029 		// REPORT_TXOE_0();
2030 
2031 		it66353_h2swset(0xD4, 0x07, 0x03);	// Set DRV_RST='1'
2032 	}
2033 
2034 	it66353_gdev.vars.current_txoe = enable;
2035 }
2036 
it66353_auto_txoe(u8 enable)2037 static void it66353_auto_txoe(u8 enable)
2038 {
2039 	DEBUG("A_TXOE=%d align=%d\r\n", enable, it66353_gdev.opts.active_rx_opt->TxOEAlignment);
2040 
2041 	if (enable) {
2042 		it66353_h2swset(0xEB, 0x07, 0x02);	// output when data ready
2043 		// it66353_h2swset(0xEB, 0x07, 0x07);	// output when clock ready
2044 		//[7]Reg_GateTxOut, [5]Disoutdeskew, [1]Reg_EnTxDly
2045 		it66353_h2swset(0xEA, 0xA2, 0x00);
2046 		it66353_h2swset(0xEB, 0x10, 0x00); //[4]RegEnTxDODeskew_doneDly
2047 	} else {
2048 		it66353_h2swset(0xEB, 0x03, 0x01);
2049 	}
2050 }
2051 
it66353_set_tx_5v(u8 output_value)2052 void it66353_set_tx_5v(u8 output_value)
2053 {
2054 	if (it66353_gdev.vars.Tx_current_5v != output_value) {
2055 		it66353_gdev.vars.Tx_current_5v = output_value;
2056 		DEBUG("TX 5V output=%d\r\n", output_value);
2057 	}
2058 
2059 	if (output_value) {
2060 		it66353_h2swset(0xF4, 0x0C, 0x0C);		// TXPWR5V=1
2061 	} else {
2062 		it66353_h2swset(0xF4, 0x0C, 0x08);		// TXPWR5V=0
2063 	}
2064 }
2065 
2066 
it66353_get_rx_vclk(u8 port)2067 static u32 it66353_get_rx_vclk(u8 port)
2068 {
2069 	u32 tmds_clk;
2070 	#if USING_WDOG
2071 	u16 tmds_clk_speed;
2072 	u8  wdog_clk_div;
2073 	u8  sw_reg20;
2074 
2075 	if (port >= RX_PORT_COUNT) {
2076 		dev_err(g_it66353->dev, "it66353_get_rx_vclk p=%u\r\n", port);
2077 		return 0;
2078 	}
2079 
2080 	_rx_wdog_rst(it66353_gdev.vars.Rx_active_port);
2081 
2082 __RETRY_VCLK:
2083 
2084 	wdog_clk_div = it66353_h2swrd(0x70 + port) & 0x07;
2085 
2086 	if (wdog_clk_div & 0x04)
2087 		wdog_clk_div = 8;
2088 	else if (wdog_clk_div & 0x02)
2089 		wdog_clk_div = 4;
2090 	else if (wdog_clk_div & 0x01)
2091 		wdog_clk_div = 2;
2092 	else
2093 		wdog_clk_div = 1;
2094 
2095 	tmds_clk_speed = it66353_h2swrd(0x6C + port);
2096 
2097 	sw_reg20 = it66353_h2swrd(0x20 + port * 2);
2098 	if (sw_reg20 & 0x7C) {
2099 		dev_err(g_it66353->dev, "it66353_get_rx_vclk sw_reg20=%02x\r\n",
2100 			sw_reg20);
2101 		tmds_clk_speed = ((tmds_clk_speed * 2) >> (RCLKFreqSel));
2102 		tmds_clk = it66353_gdev.vars.RCLK * 256 * wdog_clk_div / tmds_clk_speed;
2103 
2104 		dev_err(g_it66353->dev,
2105 			"RXP%d WatchDog detect TMDSCLK = %lu kHz (div=%d, 6C=%02x)\r\n",
2106 			port, tmds_clk, wdog_clk_div, tmds_clk_speed);
2107 
2108 		tmds_clk_speed = 0;
2109 
2110 		it66353_h2swwr(0x20 + port * 2, sw_reg20);
2111 
2112 		goto __RETRY_VCLK;
2113 	}
2114 
2115 	if (tmds_clk_speed) {
2116 		tmds_clk_speed = ((tmds_clk_speed * 2) >> (RCLKFreqSel));
2117 		tmds_clk = it66353_gdev.vars.RCLK * 256 * wdog_clk_div / tmds_clk_speed;
2118 
2119 		DEBUG("RXP%d WatchDog detect TMDSCLK = %lu kHz (div=%d, 6C=%02x)\r\n",
2120 		      port, tmds_clk, wdog_clk_div, tmds_clk_speed);
2121 	} else {
2122 		dev_err(g_it66353->dev, "TMDSCLKSpeed == 0 p=%u\r\n", port);
2123 		tmds_clk = 0;
2124 	}
2125 	#else
2126 
2127 	u8 clk;
2128 
2129 	if (port >= RX_PORT_COUNT) {
2130 		dev_err(g_it66353->dev, "it66353_get_rx_vclk p=%u\r\n", port);
2131 		return 0;
2132 	}
2133 
2134 	clk = it66353_h2swrd(0x61 + port*3);
2135 
2136 	// the assigned tmds_clk value should refer to _tx_setup_afe()
2137 	if (clk & 0x04) {
2138 		DEBUG("RXP%d clock > 340M\r\n", port);
2139 		tmds_clk = 340000UL;
2140 	} else if (clk & 0x02) {
2141 		DEBUG("RXP%d clock > 148M\r\n", port);
2142 		tmds_clk = 163000UL;
2143 	} else if (clk & 0x01) {
2144 		DEBUG("RXP%d clock > 100M\r\n", port);
2145 		tmds_clk = 148500UL;
2146 	} else {
2147 		DEBUG("RXP%d clock < 100M\r\n", port);
2148 		tmds_clk = 74000UL;
2149 	}
2150 	#endif
2151 
2152 	return tmds_clk;
2153 }
2154 
it66353_detect_port(u8 port)2155 static void it66353_detect_port(u8 port)
2156 {
2157 	u8 sw_reg20;
2158 	u8 sw_reg21;
2159 	u8 rddata;
2160 	u8 sts_off0;
2161 
2162 	sw_reg20 = it66353_h2swrd(0x20 + port * 2);
2163 	sw_reg21 = it66353_h2swrd(0x21 + port * 2) & 0x01;
2164 
2165 	if (sw_reg20) {
2166 		sts_off0 = 0x60 + port * 3;
2167 		rddata = it66353_h2swrd(sts_off0);
2168 
2169 		if (sw_reg20 & 0x01) {
2170 			DEBUG("--RXP-%d 5V Chg => 5V = %d\r\n", port, (rddata & 0x01));
2171 			if (it66353_gdev.vars.Rx_active_port != port) {
2172 				if ((rddata & 0x01)) {
2173 					// 5V presents
2174 					if (it66353_gdev.opts.rx_opt[port]->NonActivePortReplyHPD) {
2175 						_rx_set_hpd(port, 1, TERM_FOLLOW_HPD);
2176 						sw_reg20 &= 0x01;
2177 					} else {
2178 						_rx_set_hpd(port, 0, TERM_FOLLOW_HPD);
2179 					}
2180 				} else {
2181 					_rx_set_hpd(port, 0, TERM_FOLLOW_HPD);
2182 				}
2183 			}
2184 		}
2185 
2186 		if (sw_reg20 & 0x02) {
2187 			DEBUG("--RXP-%d RX Clock Valid Chg => RxCLK_Valid = %d\r\n",
2188 				   port, (rddata & 0x08) >> 3);
2189 		}
2190 
2191 		if (sw_reg20 & 0x04) {
2192 			DEBUG("--RXP-%d RX Clock Stable Chg => RxCLK_Stb = %d\r\n\r\n",
2193 				   port, (rddata & 0x10) >> 4);
2194 		}
2195 
2196 		if (sw_reg20 & 0x08) {
2197 			DEBUG("--RXP-%d RX Clock Frequency Change ...\r\n", port);
2198 		}
2199 
2200 		sts_off0 = 0x61 + port * 3;
2201 		rddata = it66353_h2swrd(sts_off0);
2202 
2203 		if (sw_reg20 & 0x10) {
2204 			DEBUG("--RXP-%d RX Clock Ratio Chg => Clk_Ratio = %d \r\n",
2205 				   port, (rddata & 0x40) >> 6);
2206 		}
2207 
2208 		if (sw_reg20 & 0x20) {
2209 			DEBUG("--RXP%d RX Scrambling Enable Chg => Scr_En = %d \r\n",
2210 				   port, (rddata & 0x80) >> 7);
2211 		}
2212 
2213 		sts_off0 = 0x62 + port * 3;
2214 		rddata = it66353_h2swrd(sts_off0);
2215 
2216 		if (sw_reg20 & 0x40) {
2217 			DEBUG("--RXP%d RX Scrambling Status Chg => ScrbSts = %d \r\n",
2218 					port, (rddata & 0x02) >> 1);
2219 		}
2220 
2221 		if (sw_reg20 & 0x80) {
2222 			DEBUG("--RXP%d RX HDMI2 Detected Interrupt => HDMI2DetSts = %d \r\n",
2223 					port, (rddata & 0x3C) >> 2);
2224 		}
2225 
2226 		it66353_h2swwr(0x20 + port * 2, sw_reg20);
2227 	}
2228 
2229 	if (sw_reg21) {
2230 		it66353_h2swwr(0x21 + port * 2, sw_reg21);
2231 #if 1
2232 		if (sw_reg21 & 0x01) {
2233 			DEBUG("--RXP%d EDID Bus Hang\r\n", port);
2234 		}
2235 #endif
2236 	}
2237 }
2238 
it66353_detect_ports(void)2239 static void it66353_detect_ports(void)
2240 {
2241 	u8 i;
2242 
2243 	for (i = 0; i < 4; i++) {
2244 		if (it66353_gdev.vars.Rx_active_port != i) {
2245 			it66353_detect_port(i);
2246 		}
2247 	}
2248 }
2249 
it66353_rx_irq(void)2250 static void it66353_rx_irq(void)
2251 {
2252 	u8 rddata, hdmi_int;
2253 	u8 rx_reg05, rx_reg06, rx_reg10;
2254 
2255 	rddata = it66353_h2rxrd(0x96);
2256 	hdmi_int = (rddata & 0x40) >> 6;
2257 
2258 	if (hdmi_int) {
2259 		rx_reg05 = it66353_h2rxrd(0x05);
2260 		rx_reg06 = it66353_h2rxrd(0x06);
2261 		rx_reg10 = it66353_h2rxrd(0x10);
2262 		it66353_h2rxwr(0x05, rx_reg05);
2263 		it66353_h2rxwr(0x06, rx_reg06);
2264 
2265 		if (rx_reg05 & 0x01) {
2266 			DEBUG("..RX5V change\r\n");
2267 
2268 			it66353_eq_reset_txoe_ready();
2269 			it66353_eq_reset_state();
2270 			it66353_auto_detect_hdmi_encoding();
2271 
2272 			if (it66353_gdev.opts.active_rx_opt->TryFixedEQFirst) {
2273 				it66353_gdev.vars.try_fixed_EQ = 1;
2274 			}
2275 
2276 			if (0 == _rx_is_5v_active()) {
2277 				it66353_fsm_chg_delayed(RX_UNPLUG);
2278 			}
2279 		}
2280 
2281 		if (rx_reg05 & 0x10) {
2282 			DEBUG("..RX HDMIMode chg => HDMIMode = %d\r\n",
2283 			      (it66353_h2rxrd(0x13) & 0x02) >> 1);
2284 		}
2285 
2286 		if (rx_reg05 & 0x40) {
2287 			DEBUG("..RX DeSkew Err\r\n");
2288 			it66353_gdev.vars.rx_deskew_err++;
2289 			if (it66353_gdev.vars.rx_deskew_err > 50) {
2290 				it66353_gdev.vars.rx_deskew_err = 0;
2291 				it66353_toggle_hpd(1000);
2292 			}
2293 		}
2294 
2295 		if (rx_reg05 & 0x80) {
2296 			DEBUG("..RXP H2V FIFO Skew Fail\r\n");
2297 		}
2298 
2299 		if (rx_reg06 & 0x01) {
2300 			u8 symlock = ((it66353_h2rxrd(0x13) & 0x80) >> 7);
2301 			DEBUG("..RX CHx SymLock Chg => RxSymLock = %d\r\n", symlock);
2302 			if (symlock) {
2303 				// it66353_gdev.vars.count_fsm_err = 0;
2304 			}
2305 		}
2306 
2307 		if (rx_reg06 & 0x02) {
2308 			DEBUG("..RX CH0 SymFIFORst\r\n");
2309 		}
2310 
2311 		if (rx_reg06 & 0x04) {
2312 			DEBUG("..RX CH1 SymFIFORst\r\n");
2313 		}
2314 
2315 		if (rx_reg06 & 0x08) {
2316 			DEBUG("..RX CH2 SymFIFORst\r\n");
2317 		}
2318 
2319 		if (rx_reg06 & 0x10) {
2320 			DEBUG("..RX CH0 SymLockRst\r\n");
2321 		}
2322 
2323 		if (rx_reg06 & 0x20) {
2324 			DEBUG("..RX CH1 SymLockRst\r\n");
2325 		}
2326 
2327 		if (rx_reg06 & 0x40) {
2328 			DEBUG("..RX CH2 SymLockRst\r\n");
2329 		}
2330 
2331 		if (rx_reg06 & 0x80) {
2332 			DEBUG("..RX FSM Fail\r\n");
2333 			it66353_gdev.vars.count_fsm_err++;
2334 			if (it66353_gdev.vars.count_fsm_err > 20) {
2335 				if (it66353_gdev.opts.active_rx_opt->FixIncorrectHdmiEnc) {
2336 					it66353_fix_incorrect_hdmi_encoding();
2337 				}
2338 				it66353_eq_reset_txoe_ready();
2339 				it66353_eq_reset_state();
2340 				it66353_fsm_chg(RX_WAIT_CLOCK);
2341 				it66353_gdev.vars.count_fsm_err = 0;
2342 			}
2343 		} else {
2344 			if (it66353_gdev.vars.count_fsm_err > 0) {
2345 				it66353_gdev.vars.count_fsm_err--;
2346 			}
2347 		}
2348 
2349 		#if EN_H14_SKEW
2350 		{
2351 			u8 rx_reg07;
2352 			rx_reg07 = it66353_h2rxrd(0x07);
2353 			it66353_h2rxwr(0x07, rx_reg07);
2354 
2355 			if (rx_reg07 & 0x01) {
2356 				DEBUG("..RX CH0 Lag Err\r\n");
2357 				it66353_rx_skew_adj(0);
2358 			}
2359 			if (rx_reg07 & 0x02) {
2360 				DEBUG("..RX CH1 Lag Err\r\n");
2361 				it66353_rx_skew_adj(1);
2362 			}
2363 			if (rx_reg07 & 0x04) {
2364 				DEBUG("..RX CH2 Lag Err\r\n");
2365 				it66353_rx_skew_adj(2);
2366 			}
2367 		}
2368 		#endif
2369 
2370 		if (rx_reg10 & 0x08) {
2371 			it66353_h2rxwr(0x10, 0x08);
2372 			DEBUG("..RX FW Timer Interrupt ...\r\n");
2373 		}
2374 	}
2375 }
2376 
it66353_sw_irq(u8 port)2377 static void it66353_sw_irq(u8 port)
2378 {
2379 	u8 sw_reg20;
2380 	u8 sw_reg21;
2381 	u8 rddata;
2382 	u8 sts_off0;
2383 
2384 
2385 	sw_reg20 = it66353_h2swrd(0x20 + port * 2);
2386 	sw_reg21 = it66353_h2swrd(0x21 + port * 2) & 0x01;
2387 
2388 	if (sw_reg20 || sw_reg21) {
2389 		it66353_h2swwr(0x20 + port * 2, sw_reg20);
2390 		it66353_h2swwr(0x21 + port * 2, sw_reg21);
2391 
2392 		sts_off0 = 0x60 + port * 3;
2393 
2394 		if (sw_reg20 & 0x01) {
2395 			// not here
2396 			rddata = it66353_h2swrd(sts_off0);
2397 			DEBUG("..RX-P%d PWR5V Chg => PWR5V = %d\r\n", port, (rddata & 0x01));
2398 			// _rx_wdog_rst(port);
2399 			if (0 == (rddata & 0x01)) {
2400 				it66353_fsm_chg_delayed(RX_UNPLUG);
2401 			}
2402 		}
2403 
2404 		if (sw_reg20 & 0x02) {
2405 			rddata = it66353_h2swrd(sts_off0);
2406 			DEBUG("..RXP%d RX Clock Valid Chg => RxCLK_Valid = %d\r\n",
2407 			      port, (rddata & 0x08) >> 3);
2408 			if (port == it66353_gdev.vars.Rx_active_port) {
2409 				if (0 == (rddata & 0x08)) {	// clock not valid
2410 					DBG_TM(CLK_UNSTABLE);
2411 					if (it66353_gdev.vars.RxHPDFlag[it66353_gdev.vars.Rx_active_port] > 0) {
2412 						it66353_fsm_chg_delayed(RX_WAIT_CLOCK);
2413 					}
2414 				} else {
2415 					DBG_TM(CLK_STABLE);
2416 				}
2417 			}
2418 		}
2419 
2420 		if (sw_reg20 & 0x04) {
2421 			msleep(10);
2422 			rddata = it66353_h2swrd(sts_off0);
2423 			DEBUG("..RXP%d RX Clock Stable Chg => RxCLK_Stb = %d\r\n\r\n",
2424 				   port, (rddata & 0x10) >> 4);
2425 			if (0 == (rddata & 0x10)) {
2426 				DBG_CLKSTABLE_0();
2427 				DBG_SYMLOCK_0();
2428 				if (it66353_gdev.vars.RxHPDFlag[port]) {
2429 					it66353_fsm_chg_delayed(RX_WAIT_CLOCK);
2430 				}
2431 			} else {
2432 				it66353_gdev.vars.vclk = it66353_get_rx_vclk(it66353_gdev.vars.Rx_active_port);
2433 				if ((it66353_gdev.vars.vclk != it66353_gdev.vars.vclk_prev)) {
2434 					it66353_gdev.vars.vclk_prev = it66353_gdev.vars.vclk;
2435 					if (it66353_gdev.vars.RxHPDFlag[port]) {
2436 						it66353_fsm_chg_delayed(RX_WAIT_CLOCK);
2437 					}
2438 				}
2439 			}
2440 		}
2441 
2442 
2443 		if (sw_reg20 & 0x08) {
2444 			DEBUG("..RXP%d RX Clock Frequency Chg ...\r\n", port);
2445 		}
2446 
2447 		if (sw_reg20 & 0x10) {
2448 			u8 new_ratio = (it66353_h2swrd(0x61 + port * 3) & 0x40) >> 6;
2449 
2450 			DEBUG("..RXP%d RX Clock Ratio Chg => Clk_Ratio = %d \r\n",
2451 			      port, new_ratio);
2452 
2453 			if (it66353_gdev.vars.Rx_active_port == port) {
2454 				if (new_ratio > 0) {
2455 					it66353_auto_txoe(it66353_gdev.opts.active_rx_opt->TxOEAlignment);
2456 				} else {
2457 					it66353_auto_txoe(0);
2458 				}
2459 				it66353_txoe(1);
2460 
2461 				if (new_ratio != it66353_gdev.vars.clock_ratio) {
2462 					// it66353_auto_detect_hdmi_encoding();
2463 					// it66353_fsm_chg_delayed(RX_WAIT_CLOCK);
2464 				}
2465 			}
2466 		}
2467 
2468 		if (sw_reg20 & 0x20) {
2469 			DEBUG("..RXP%d RX Scrambling Enable Chg => Scr_En = %d \r\n",
2470 			      port, (it66353_h2swrd(0x61 + port * 3) & 0x80) >> 7);
2471 		}
2472 
2473 		if (sw_reg20 & 0x40) {
2474 			u8 new_scramble = (it66353_h2swrd(0x62 + port * 3) & 0x02) >> 1;
2475 
2476 			DEBUG("..RXP%d RX Scrambling Status Chg => ScrbSts = %d \r\n",
2477 			      port, new_scramble);
2478 			if (it66353_gdev.vars.Rx_active_port == port) {
2479 				if (new_scramble != it66353_gdev.vars.h2_scramble) {
2480 					// it66353_fsm_chg_delayed(RX_WAIT_CLOCK);
2481 				}
2482 			}
2483 		}
2484 
2485 		if (sw_reg20 & 0x80) {
2486 			DEBUG("..RXP%d RX HDMI2 Detected Interrupt => HDMI2DetSts = %d \r\n",
2487 			      port, (it66353_h2swrd(0x62 + port * 3) & 0x3C) >> 2);
2488 		}
2489 
2490 		if (sw_reg21 & 0x01) {
2491 			DEBUG("..RXP%d EDID Bus Hang\r\n", port);
2492 		}
2493 	}
2494 }
2495 
2496 
it66353_tx_irq(void)2497 static void it66353_tx_irq(void)
2498 {
2499 	u8 sw_reg27;
2500 	u8 sw_reg28;
2501 	u8 rddata;
2502 	u8 reg3C;
2503 
2504 	sw_reg27 = it66353_h2swrd(0x27);
2505 	sw_reg28 = it66353_h2swrd(0x28) & ~(0x02|0x04);
2506 	it66353_h2swwr(0x27, sw_reg27);
2507 	it66353_h2swwr(0x28, sw_reg28);
2508 
2509 	if (sw_reg27 & 0x08) {
2510 		// dev_info(g_it66353->dev, " => HDCP 0x74 is detected\r\n");
2511 	}
2512 
2513 	if (sw_reg27 & 0x10) {
2514 		DEBUG("  => HDCP 0x74 NOACK\r\n");
2515 	}
2516 
2517 
2518 	if (sw_reg27 & 0x20) {
2519 		rddata = it66353_h2swrd(0x11);
2520 
2521 		if ((rddata & 0x20)) {
2522 			DEBUG("  => HPD High\r\n");
2523 		} else {
2524 			DEBUG("  => HPD Low\r\n");
2525 
2526 			if (it66353_gdev.vars.state_sys_fsm != RX_TOGGLE_HPD &&
2527 				 it66353_gdev.vars.state_sys_fsm != RX_UNPLUG) {
2528 				it66353_fsm_chg_delayed(TX_UNPLUG);
2529 			}
2530 		}
2531 	}
2532 
2533 	if (sw_reg27 & 0x40) {
2534 		DEBUG("  TX RxSen chg\r\n");
2535 
2536 		if (it66353_h2swrd(0x11) & 0x40) {
2537 			// rxsen = 1
2538 		} else {
2539 			// rxsen = 0
2540 			// _rx_int_enable_all(0);
2541 			// _rx_set_hpd_all(0);
2542 			// it66353_fsm_chg(TX_WAIT_HPD);
2543 		}
2544 	}
2545 
2546 	if (sw_reg27 & 0x80) {
2547 		// DEBUG("  TX DDC Bus Hang\r\n");
2548 
2549 		if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == false) {
2550 			reg3C = it66353_h2swrd(0x3C);
2551 			it66353_h2swset(0x3C, 0x01, 0x01);
2552 			it66353_h2swwr(0x3D, 0x0A);	// Generate SCL Clock
2553 			it66353_h2swwr(0x3C, reg3C);
2554 		}
2555 	}
2556 
2557 	if (sw_reg28 & 0x02) {
2558 		// dev_info(g_it66353->dev, "SW User Timer 0 Interrupt ...\r\n");
2559 	}
2560 
2561 	if (sw_reg28 & 0x04) {
2562 		// dev_info(g_it66353->dev, "SW User Timer 1 Interrupt ...\r\n");
2563 	}
2564 
2565 	if (sw_reg28 & 0x08) {
2566 		// DEBUG("  TX DDC Command Fail\r\n");
2567 		if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == false) {
2568 			reg3C = it66353_h2swrd(0x3C);
2569 			it66353_h2swset(0x3C, 0x01, 0x01);
2570 			it66353_h2swwr(0x3D, 0x0F);
2571 			it66353_h2swwr(0x3C, reg3C);
2572 		}
2573 
2574 	}
2575 
2576 	if (sw_reg28 & 0x80) {
2577 		DEBUG("  TX DDC FIFO Error\r\n");
2578 		if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == false) {
2579 			reg3C = it66353_h2swrd(0x3C);
2580 			it66353_h2swset(0x3C, 0x01, 0x01);
2581 			it66353_h2swwr(0x3D, 0x09);
2582 			it66353_h2swwr(0x3C, reg3C);
2583 		}
2584 	}
2585 }
2586 
it66353_wait_for_ddc_idle(void)2587 static void it66353_wait_for_ddc_idle(void)
2588 {
2589 	u8 ddc_sts;
2590 	u8 idle_cnt = 0;
2591 	u8 busy_cnt = 0;
2592 	u8 chk_dly = 3;
2593 
2594 	while (1) {
2595 		ddc_sts = it66353_h2swrd(0xB3);
2596 		if ((ddc_sts & 0x10)) {
2597 			busy_cnt = 0;
2598 			idle_cnt++;
2599 			chk_dly++;
2600 			if (idle_cnt >= 5) {
2601 				break;
2602 			}
2603 		} else {
2604 			busy_cnt++;
2605 			idle_cnt = 0;
2606 			chk_dly = 3;
2607 
2608 			msleep(100);
2609 			if (busy_cnt > 10) {
2610 				dev_err(g_it66353->dev, "**Wait DDC idle timeout\n");
2611 				break;
2612 			}
2613 		}
2614 
2615 		msleep(chk_dly);
2616 	}
2617 }
2618 
2619 #if DEBUG_FSM_CHANGE
__it66353_fsm_chg(u8 new_state,int caller)2620 void __it66353_fsm_chg(u8 new_state, int caller)
2621 #else
2622 void it66353_fsm_chg(u8 new_state)
2623 #endif
2624 {
2625 
2626 #if DEBUG_FSM_CHANGE
2627 	if (new_state <= IDLE && it66353_gdev.vars.state_sys_fsm <= IDLE) {
2628 		DEBUG("state_fsm %s -> %s (%d)\r\n",
2629 			s__SYS_FSM_STATE[it66353_gdev.vars.state_sys_fsm],
2630 			s__SYS_FSM_STATE[new_state], caller);
2631 	} else {
2632 		dev_err(g_it66353->dev, "state_fsm %d, new %d -> %d\r\n",
2633 			it66353_gdev.vars.state_sys_fsm, new_state, caller);
2634 	}
2635 #else
2636 	DEBUG("state_fsm %d -> %d\r\n", it66353_gdev.vars.state_sys_fsm, new_state);
2637 #endif
2638 
2639 	if (RX_PORT_CHANGE != new_state) {
2640 		if (it66353_gdev.vars.state_sys_fsm == new_state) {
2641 			DEBUG("skip fsm chg 1\r\n");
2642 			return;
2643 		}
2644 	}
2645 
2646 
2647 	if (new_state == RX_WAIT_CLOCK) {
2648 		if (it66353_gdev.vars.RxHPDFlag[it66353_gdev.vars.Rx_active_port] == 0) {
2649 			// don't change before HPD High
2650 			DEBUG("skip fsm chg 2\r\n");
2651 			return;
2652 		}
2653 	}
2654 
2655 
2656 	it66353_gdev.vars.state_sys_fsm = new_state;
2657 	it66353_gdev.vars.fsm_return = 0;
2658 
2659 	switch (it66353_gdev.vars.state_sys_fsm) {
2660 	case RX_TOGGLE_HPD:
2661 		_sw_enable_hpd_toggle_timer(it66353_gdev.vars.hpd_toggle_timeout);
2662 		break;
2663 	case RX_PORT_CHANGE:
2664 		it66353_txoe(0);
2665 		DBG_TM(RX_SWITCH_PORT);
2666 		DEBUG("Active port change from P%d to P%d\r\n",
2667 		      it66353_gdev.vars.Rx_active_port, it66353_gdev.vars.Rx_new_port);
2668 		if (it66353_gdev.vars.clock_ratio > 0 &&
2669 		    it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == false) {
2670 			_tx_scdc_write(0x20, 0x00);
2671 		}
2672 		if (it66353_gdev.opts.tx_opt->TurnOffTx5VWhenSwitchPort) {
2673 			it66353_set_tx_5v(0);
2674 		}
2675 		// _rx_int_enable(it66353_gdev.vars.Rx_active_port, 1);
2676 		// _rx_set_hpd(it66353_gdev.vars.Rx_active_port, 0);
2677 		// _rx_wdog_rst(it66353_gdev.vars.Rx_prev_port);
2678 
2679 		// make HPD low to stop DDC traffic
2680 		_rx_set_hpd(it66353_gdev.vars.Rx_active_port, 0, TERM_FOLLOW_HPD);
2681 		// wait 200ms for DDC traffic stopped
2682 		msleep(200);
2683 
2684 		// set it66353_gdev.vars.force_hpd_state to SW_HPD_AUTO
2685 		// this to reset the force hpd low in previous active port
2686 		// remove this line if you want to keep HPD low after port changing
2687 		it66353_gdev.vars.force_hpd_state = SW_HPD_AUTO;
2688 		it66353_gdev.vars.Rx_active_port = it66353_gdev.vars.Rx_new_port;
2689 
2690 		it66353_wait_for_ddc_idle();
2691 
2692 		it66353_h2swset(0x50, 0x03, it66353_gdev.vars.Rx_active_port);
2693 
2694 		it66353_set_RS(it66353_gdev.opts.active_rx_opt->DefaultEQ[0],
2695 					  it66353_gdev.opts.active_rx_opt->DefaultEQ[1],
2696 					  it66353_gdev.opts.active_rx_opt->DefaultEQ[2]);
2697 
2698 		it66353_gdev.EQ.sys_aEQ = SysAEQ_RUN;
2699 		it66353_auto_detect_hdmi_encoding();
2700 		it66353_eq_reset_state();
2701 		it66353_eq_reset_txoe_ready();
2702 		break;
2703 
2704 	case TX_OUTPUT:
2705 		it66353_gdev.vars.count_symlock_lost = 0;
2706 		it66353_gdev.vars.count_symlock_unstable = 0;
2707 		_sw_disable_hpd_toggle_timer();
2708 		if ((it66353_gdev.opts.active_rx_opt->FixIncorrectHdmiEnc) &&
2709 		    (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == FALSE)) {
2710 			if (it66353_gdev.vars.current_hdmi_mode == HDMI_MODE_20) {
2711 				_tx_scdc_write(0x20, 0x03);
2712 			} else if (it66353_gdev.vars.current_hdmi_mode == HDMI_MODE_14) {
2713 				// todo: to check sink support SCDC ?
2714 				_tx_scdc_write(0x20, 0x00);
2715 			}
2716 			it66353_auto_detect_hdmi_encoding();
2717 		}
2718 
2719 		_sw_hdcp_access_enable(1);
2720 		it66353_txoe(1);
2721 
2722 		if (it66353_gdev.vars.spmon == 1) {
2723 			if ((it66353_gdev.opts.active_rx_opt->DisableEdidRam &
2724 			    (1 << it66353_gdev.vars.Rx_active_port)) == 0) {
2725 				_rx_edid_ram_enable(it66353_gdev.vars.Rx_active_port);
2726 			}
2727 		}
2728 		break;
2729 
2730 	case TX_OUTPUT_PREPARE:
2731 		it66353_gdev.vars.count_try_force_hdmi_mode = 0;
2732 		// it66353_auto_txoe(1);
2733 		it66353_h2rxwr(0x05, 0xFF);
2734 		it66353_h2rxwr(0x06, 0xFF);
2735 		it66353_h2rxwr(0x07, 0xFF);
2736 		break;
2737 
2738 	#if EN_AUTO_RS
2739 	case RX_CHECK_EQ:
2740 		it66353_gdev.vars.count_symlock_fail = 0;
2741 		// _sw_hdcp_access_enable(0);
2742 		break;
2743 	#endif
2744 
2745 	case SETUP_AFE:
2746 		// it66353_gdev.vars.en_count_hdcp = 1;
2747 		// it66353_gdev.vars.tick_set_afe = get_tick_count();
2748 		it66353_rx_term_power_down(it66353_gdev.vars.Rx_active_port, 0x00);
2749 		it66353_gdev.vars.vclk = it66353_get_rx_vclk(it66353_gdev.vars.Rx_active_port);
2750 
2751 		if (it66353_gdev.vars.vclk) {
2752 			it66353_gdev.vars.clock_ratio =
2753 				((it66353_h2swrd(0x61 + it66353_gdev.vars.Rx_active_port * 3) >> 6) & 1);
2754 			dev_dbg(g_it66353->dev, "Clk Ratio = %d\r\n",
2755 				it66353_gdev.vars.clock_ratio);
2756 
2757 			if (it66353_gdev.vars.clock_ratio > 0) {
2758 				if (it66353_gdev.vars.vclk < 300000UL) {
2759 					it66353_gdev.vars.vclk = 300001UL;
2760 				}
2761 				// CED opt for HDBaseT disabled
2762 				it66353_h2rxset(0x3B, 0x10, 0x00);
2763 			} else {
2764 				if (it66353_gdev.vars.vclk >= 300000UL) {
2765 					it66353_gdev.vars.vclk = 297000UL;
2766 				}
2767 				// CED opt for HDBaseT enabled
2768 				it66353_h2rxset(0x3B, 0x10, 0x10);
2769 			}
2770 			#if 0 // for 8-7 480p
2771 			if (it66353_gdev.vars.vclk < 35000UL) {
2772 				dev_dbg("## ATC 480P\r\n");
2773 				// it66353_h2rxset(0x3c, 0x01, 0x00);
2774 				it66353_h2swset(0x2b, 0x02, 0x00);
2775 			} else {
2776 				// it66353_h2rxset(0x3c, 0x01, 0x01);
2777 				it66353_h2swset(0x2b, 0x02, 0x02);
2778 			}
2779 			#endif
2780 
2781 			_tx_power_on();
2782 			_rx_setup_afe(it66353_gdev.vars.vclk);
2783 			_tx_setup_afe(it66353_gdev.vars.vclk);
2784 
2785 			if (it66353_gdev.vars.clock_ratio == 0) {
2786 				it66353_auto_txoe(0);
2787 				dev_dbg(g_it66353->dev, "Clk Ratio==0, align=0\n");
2788 			} else {
2789 				it66353_auto_txoe(it66353_gdev.opts.active_rx_opt->TxOEAlignment);
2790 				dev_dbg(g_it66353->dev, "Clk Ratio==1, align=%d\n",
2791 					it66353_gdev.opts.active_rx_opt->TxOEAlignment);
2792 			}
2793 
2794 			it66353_txoe(1);
2795 
2796 		}
2797 		break;
2798 
2799 	case RX_WAIT_CLOCK:
2800 		it66353_txoe(0);
2801 		if (it66353_gdev.opts.dev_opt->TxPowerDownWhileWaitingClock) {
2802 			_tx_power_down();
2803 		}
2804 
2805 		it66353_sw_disable_timer0();
2806 		it66353_sw_clear_hdcp_status();
2807 		// _rx_wdog_rst(it66353_gdev.vars.Rx_active_port);
2808 
2809 		#if EN_AUTO_RS
2810 		it66353_gdev.vars.RxCEDErrRec[1][0] = 0xffff;
2811 		it66353_gdev.vars.RxCEDErrRec[1][1] = 0xffff;
2812 		it66353_gdev.vars.RxCEDErrRec[1][2] = 0xffff;
2813 		it66353_gdev.EQ.manu_eq_fine_tune_count[0] = 0;
2814 		it66353_gdev.EQ.manu_eq_fine_tune_count[1] = 0;
2815 		it66353_gdev.EQ.manu_eq_fine_tune_count[2] = 0;
2816 		it66353_gdev.EQ.ced_err_avg_prev[0] = 0x8888;
2817 		it66353_gdev.EQ.ced_err_avg_prev[1] = 0x8888;
2818 		it66353_gdev.EQ.ced_err_avg_prev[2] = 0x8888;
2819 		it66353_gdev.EQ.ced_acc_count = 0;
2820 		#endif
2821 		it66353_gdev.vars.count_symlock = 0;
2822 		it66353_gdev.vars.count_unlock = 0;
2823 		it66353_gdev.vars.check_for_hpd_toggle = 0;
2824 		it66353_gdev.vars.sdi_stable_count = 0;
2825 		it66353_gdev.vars.check_for_sdi = 1;
2826 		it66353_gdev.vars.rx_deskew_err = 0;
2827 		break;
2828 
2829 	case RX_HPD:
2830 		_rx_int_enable();
2831 
2832 		#if 1
2833 		// it66353it66353_rx_ovwr_hdmi_clk(it66353_gdev.vars.Rx_active_port, HDMI_MODE_14);
2834 		// it66353it66353_rx_ovwr_h20_scrb(it66353_gdev.vars.Rx_active_port, 0);
2835 		#else
2836 		it66353it66353_rx_ovwr_hdmi_clk(it66353_gdev.vars.Rx_active_port, RX_CLK_H20);
2837 		it66353it66353_rx_ovwr_h20_scrb(it66353_gdev.vars.Rx_active_port, 1);
2838 		#endif
2839 
2840 		// it66353_gdev.vars.Rx_prev_port = it66353_gdev.vars.Rx_active_port;
2841 		// _rx_int_enable_all(0);
2842 		// _rx_set_hpd_all(0);
2843 		_sw_hdcp_access_enable(1);
2844 		_sw_int_enable(it66353_gdev.vars.Rx_active_port, 1);
2845 		// _rx_set_hpd(it66353_gdev.vars.Rx_active_port, 1);
2846 		_rx_wdog_rst(it66353_gdev.vars.Rx_active_port);
2847 		if (it66353_gdev.vars.spmon == 1) {
2848 			if ((it66353_gdev.opts.active_rx_opt->DisableEdidRam &
2849 			    (1<<it66353_gdev.vars.Rx_active_port)) == 0) {
2850 				_rx_edid_ram_disable(it66353_gdev.vars.Rx_active_port);
2851 			}
2852 		}
2853 
2854 		_rx_set_hpd(it66353_gdev.vars.Rx_active_port, 1, TERM_FOLLOW_HPD);
2855 		if (it66353_gdev.vars.is_hdmi20_sink == 0) {
2856 			it66353_auto_txoe(0);
2857 		} else {
2858 			it66353_auto_txoe(it66353_gdev.opts.active_rx_opt->TxOEAlignment);
2859 		}
2860 		it66353_txoe(1);
2861 
2862 		break;
2863 
2864 	case TX_GOT_HPD:
2865 		it66353_txoe(0);
2866 
2867 		// _tx_power_on();
2868 		if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == false) {
2869 			it66353_setup_edid_ram(0);
2870 			it66353_gdev.vars.edid_ready = 1;
2871 		}
2872 
2873 		#if EN_CEC
2874 		if (it66353_gdev.opts.EnCEC) {
2875 			u8 u8phyAB = (it66353_gdev.vars.PhyAdr[0] << 4) | (it66353_gdev.vars.PhyAdr[1] & 0xF);
2876 			u8 u8phyCD = (it66353_gdev.vars.PhyAdr[2] << 4) | (it66353_gdev.vars.PhyAdr[3] & 0xF);
2877 
2878 			CecSys_Init(u8phyAB, u8phyCD, it66353_gdev.vars.Rx_active_port);
2879 		}
2880 		#endif
2881 
2882 		if (it66353_gdev.opts.active_rx_opt->NonActivePortReplyHPD) {
2883 			_rx_set_hpd_with_5v_all(true);
2884 		}
2885 
2886 		break;
2887 
2888 	case TX_WAIT_HPD:
2889 		it66353_txoe(0);
2890 		it66353_auto_txoe(0);
2891 		if (_rx_is_5v_active()) {
2892 			it66353_set_tx_5v(1);
2893 		} else {
2894 			it66353_set_tx_5v(0);
2895 		}
2896 
2897 		// it66353_set_RS(10);
2898 		break;
2899 
2900 	case TX_UNPLUG:
2901 		it66353_txoe(0);
2902 		it66353_auto_txoe(0);
2903 		it66353_gdev.vars.edid_ready = 0;
2904 		// _rx_int_enable(it66353_gdev.vars.Rx_active_port, 0);
2905 		_rx_set_hpd(it66353_gdev.vars.Rx_active_port, 0, TERM_FOLLOW_TX);
2906 		// _rx_set_hpd_all(0);
2907 		it66353_h2swset(0xB2, 0x0A, 0x0A);  // W1C AutoH2Mode and AutoScrbEn
2908 		_tx_power_down();
2909 		break;
2910 
2911 	case RX_UNPLUG:
2912 		it66353_txoe(0);
2913 		it66353_auto_txoe(0);
2914 		// _rx_int_enable(it66353_gdev.vars.Rx_active_port, 0);
2915 		if (it66353_gdev.vars.force_hpd_state == SW_HPD_LOW) {
2916 			_rx_set_hpd(it66353_gdev.vars.Rx_active_port, 0, TERM_FOLLOW_HPD);
2917 		} else {
2918 			_rx_set_hpd(it66353_gdev.vars.Rx_active_port, 0, TERM_FOLLOW_TX);
2919 		}
2920 		it66353_set_tx_5v(_rx_is_5v_active());
2921 		// it66353_gdev.EQ.sys_aEQ = SysAEQ_RUN;
2922 		it66353_h2swset(0xB2, 0x0A, 0x0A);  // W1C AutoH2Mode and AutoScrbEn
2923 		_tx_power_down();
2924 		break;
2925 	default:
2926 		break;
2927 	}
2928 }
2929 
2930 #if DEBUG_FSM_CHANGE
__it66353_fsm_chg2(u8 new_state,int caller)2931 void __it66353_fsm_chg2(u8 new_state, int caller)
2932 #else
2933 void it66353_fsm_chg_delayed(u8 new_state)
2934 #endif
2935 {
2936 
2937 #if DEBUG_FSM_CHANGE
2938 	if (new_state <= IDLE && it66353_gdev.vars.state_sys_fsm <= IDLE) {
2939 		dev_dbg(g_it66353->dev, "#state_fsm %s -> %s (%d)\r\n",
2940 				s__SYS_FSM_STATE[it66353_gdev.vars.state_sys_fsm],
2941 				s__SYS_FSM_STATE[new_state], caller);
2942 	} else {
2943 		dev_err(g_it66353->dev, "#state_fsm %d, new %d -> %d\r\n",
2944 				it66353_gdev.vars.state_sys_fsm, new_state, caller);
2945 	}
2946 #else
2947 	dev_dbg(g_it66353->dev, "#state_fsm %d -> %d\r\n",
2948 		it66353_gdev.vars.state_sys_fsm, new_state);
2949 #endif
2950 
2951 	it66353_fsm_chg(new_state);
2952 	it66353_gdev.vars.fsm_return = 1;
2953 }
2954 
_rx_pll_reset(void)2955 static void _rx_pll_reset(void)
2956 {
2957 	it66353_h2swset(0x06+it66353_gdev.vars.Rx_active_port, 0x01, 0x01);
2958 	msleep(2);
2959 	it66353_h2swset(0x06+it66353_gdev.vars.Rx_active_port, 0x01, 0x00);
2960 }
2961 
it66353_auto_detect_hdmi_encoding(void)2962 void it66353_auto_detect_hdmi_encoding(void)
2963 {
2964 	_rx_ovwr_hdmi_mode(it66353_gdev.vars.Rx_active_port, HDMI_MODE_AUTO);
2965 	_tx_ovwr_hdmi_mode(HDMI_MODE_AUTO);
2966 	it66353_gdev.vars.current_hdmi_mode = HDMI_MODE_AUTO;
2967 	// _rx_pll_reset();
2968 	dev_info(g_it66353->dev, "HDMI_MODE=AUTO \r\n");
2969 }
2970 
it66353_force_hdmi20(void)2971 void it66353_force_hdmi20(void)
2972 {
2973 	_rx_ovwr_hdmi_mode(it66353_gdev.vars.Rx_active_port, HDMI_MODE_20);
2974 	_tx_ovwr_hdmi_mode(HDMI_MODE_20);
2975 	it66353_gdev.vars.current_hdmi_mode = HDMI_MODE_20;
2976 	// _rx_pll_reset();
2977 	dev_info(g_it66353->dev, "HDMI_MODE=F20\r\n");
2978 }
2979 
it66353_force_hdmi14(void)2980 static void it66353_force_hdmi14(void)
2981 {
2982 	_rx_ovwr_hdmi_mode(it66353_gdev.vars.Rx_active_port, HDMI_MODE_14);
2983 	_tx_ovwr_hdmi_mode(HDMI_MODE_14);
2984 	it66353_gdev.vars.current_hdmi_mode = HDMI_MODE_14;
2985 	// _rx_pll_reset();
2986 	dev_info(g_it66353->dev, "HDMI_MODE=F14\r\n");
2987 }
2988 
2989 
it66353_fix_incorrect_hdmi_encoding(void)2990 void it66353_fix_incorrect_hdmi_encoding(void)
2991 {
2992 	switch (it66353_gdev.vars.current_hdmi_mode) {
2993 	case HDMI_MODE_AUTO:
2994 		// try HDMI 2.0
2995 		it66353_force_hdmi20();
2996 		break;
2997 	case HDMI_MODE_20:
2998 		// try HDMI 1.4
2999 		it66353_force_hdmi14();
3000 		break;
3001 	case HDMI_MODE_14:
3002 		// try HDMI 2.0
3003 		it66353_auto_detect_hdmi_encoding();
3004 		break;
3005 	default:
3006 		// try HDMI 2.0
3007 		it66353_auto_detect_hdmi_encoding();
3008 		break;
3009 	}
3010 
3011 	_rx_pll_reset();
3012 }
3013 
3014 #if EN_AUTO_RS
it66353_fsm_EQ_check(void)3015 static void it66353_fsm_EQ_check(void)
3016 {
3017 	static u8 aeq_retry;
3018 	u8 eq_state;
3019 
3020 	if (it66353_rx_is_clock_stable()) {
3021 		_rx_show_ced_info();
3022 
3023 		if (it66353_eq_get_txoe_ready() == 1) {
3024 			it66353_eq_load_previous();
3025 			dev_info(g_it66353->dev, "EQ restore2 !\r\n");
3026 			// it66353_fsm_chg(TX_OUTPUT);
3027 			it66353_fsm_chg(TX_OUTPUT_PREPARE);
3028 		} else {
3029 			eq_state = it66353_eq_get_state();
3030 			dev_info(g_it66353->dev, "[%d] eq_state=%d\r\n",
3031 				 __LINE__, (int)eq_state);
3032 
3033 			if (eq_state == SysAEQ_RUN) {
3034 				it66353_eq_set_txoe_ready(0);
3035 				if (it66353_auto_eq_adjust()) {
3036 					it66353_gdev.vars.check_for_hpd_toggle = 1;
3037 					it66353_eq_set_state(SysAEQ_DONE);
3038 					it66353_fsm_chg(TX_OUTPUT_PREPARE);
3039 					dev_info(g_it66353->dev, "EQ done !\r\n");
3040 				} else {
3041 					aeq_retry++;
3042 					if (aeq_retry > 5) {
3043 						aeq_retry = 0;
3044 						it66353_gdev.vars.check_for_hpd_toggle = 1;
3045 						it66353_eq_set_state(SysAEQ_DONE);
3046 						it66353_fsm_chg(TX_OUTPUT_PREPARE);
3047 						dev_info(g_it66353->dev, "EQ give up !\r\n");
3048 					}
3049 				}
3050 			} else {
3051 				if (eq_state == SysAEQ_DONE) {
3052 					it66353_eq_load_previous();
3053 					it66353_fsm_chg(TX_OUTPUT_PREPARE);
3054 					dev_info(g_it66353->dev, "EQ restore !\r\n");
3055 				} else if (eq_state == SysAEQ_OFF) {
3056 					it66353_eq_load_default();
3057 					it66353_fsm_chg(TX_OUTPUT_PREPARE);
3058 					dev_info(g_it66353->dev, "EQ default !\r\n");
3059 				} else {
3060 					dev_err(g_it66353->dev, "??eq_state=%d\r\n", eq_state);
3061 				}
3062 			}
3063 		}
3064 	} else {
3065 		it66353_fsm_chg(RX_WAIT_CLOCK);
3066 	}
3067 }
3068 #endif
3069 
it66353_fsm(void)3070 static void it66353_fsm(void)
3071 {
3072 	static __maybe_unused u8 prep_count;
3073 	static __maybe_unused u8 prep_fail_count;
3074 // LOOP_FSM:
3075 
3076 	switch (it66353_gdev.vars.state_sys_fsm) {
3077 	case RX_TOGGLE_HPD:
3078 		if ((it66353_gdev.opts.active_rx_opt->NonActivePortReplyHPD == 0) &&
3079 			(it66353_gdev.opts.tx_opt->TurnOffTx5VWhenSwitchPort == 0)) {
3080 			_sw_disable_hpd_toggle_timer();
3081 			it66353_fsm_chg(RX_UNPLUG);
3082 		} else {
3083 			if (_sw_check_hpd_toggle_timer()) {
3084 				_sw_disable_hpd_toggle_timer();
3085 				it66353_fsm_chg(RX_UNPLUG);
3086 			} else {
3087 				// keep waiting hpd toggle
3088 			}
3089 		}
3090 		break;
3091 	case RX_PORT_CHANGE:
3092 		_rx_set_hpd(it66353_gdev.vars.Rx_active_port, 0, TERM_FOLLOW_HPD);
3093 		it66353_rx_reset();
3094 		it66353_rx_caof_init(it66353_gdev.vars.Rx_active_port);
3095 		_rx_pll_reset();
3096 		it66353_gdev.vars.hpd_toggle_timeout = it66353_gdev.opts.active_rx_opt->HPDTogglePeriod;
3097 		it66353_fsm_chg(RX_TOGGLE_HPD);
3098 		break;
3099 	case TX_OUTPUT:
3100 
3101 		// if (it66353_gdev.opts.WaitSymlockBeforeTXOE)
3102 		{
3103 			if (0 == it66353_rx_is_all_ch_symlock()) {
3104 				if (0 == _rx_is_any_ch_symlock()) {
3105 					it66353_gdev.vars.count_symlock_lost++;
3106 					dev_err(g_it66353->dev,
3107 						"RX Symlock lost %d\r\n",
3108 						it66353_gdev.vars.count_symlock_lost);
3109 					if (it66353_gdev.vars.count_symlock_lost == 100) {
3110 						_rx_pll_reset();
3111 						it66353_toggle_hpd(1000);
3112 						// it66353_set_tx_5v(0);
3113 						// it66353_gdev.vars.count_symlock_lost = 0;
3114 						// it66353it66353_rx_handle_output_err();
3115 					}
3116 				} else {
3117 					it66353_gdev.vars.count_symlock_unstable++;
3118 					dev_err(g_it66353->dev,
3119 						"RX Symlock unstable %d\r\n",
3120 						it66353_gdev.vars.count_symlock_unstable);
3121 					if (it66353_gdev.vars.count_symlock_unstable > 8) {
3122 						_rx_pll_reset();
3123 						// it66353_fsm_chg(RX_WAIT_CLOCK);
3124 						it66353_toggle_hpd(1000);
3125 					}
3126 				}
3127 			} else {
3128 				it66353_gdev.vars.count_symlock_lost = 0;
3129 				it66353_gdev.vars.count_symlock_unstable = 0;
3130 			}
3131 		}
3132 
3133 		if (it66353_rx_monitor_ced_err()) {
3134 			it66353it66353_rx_handle_output_err();
3135 		}
3136 
3137 		// _sw_show_hdcp_status();
3138 
3139 		if (it66353_gdev.opts.active_rx_opt->FixIncorrectHdmiEnc) {
3140 			/*
3141 			 * check if source send incorrect SCDC clock ratio
3142 			 * after 66353 sent.
3143 			 */
3144 			if (it66353_gdev.vars.current_hdmi_mode !=
3145 			    HDMI_MODE_AUTO && it66353_gdev.opts.active_rx_opt->EnRxDDCBypass ==
3146 			    false) {
3147 				_sw_monitor_and_fix_scdc_write();
3148 			}
3149 		}
3150 
3151 		if (it66353_gdev.vars.check_for_sdi) {
3152 			_sw_sdi_check();
3153 		}
3154 
3155 		// _tx_show_sink_ced();
3156 
3157 		// _pr_port_info(it66353_gdev.vars.Rx_active_port);
3158 
3159 		break;
3160 
3161 	case TX_OUTPUT_PREPARE:
3162 	#if EN_AUTO_RS
3163 		// check symbol lock before tx output
3164 		if (0 == _rx_is_any_ch_symlock()) {
3165 			dev_err(g_it66353->dev, "RxChk-SymUnlock\r\n");
3166 			it66353_gdev.vars.count_symlock_fail++;
3167 			if (it66353_gdev.vars.count_symlock_fail > 3) {
3168 				it66353_gdev.vars.count_symlock_fail = 0;
3169 				// can not get any channel symbol lock,
3170 				// the HDMI encoding may be incorrect
3171 				if (it66353_gdev.opts.active_rx_opt->FixIncorrectHdmiEnc) {
3172 					if (it66353_gdev.vars.count_try_force_hdmi_mode < 6) {
3173 						it66353_gdev.vars.count_try_force_hdmi_mode++;
3174 						it66353_fix_incorrect_hdmi_encoding();
3175 					} else {
3176 						it66353_gdev.vars.count_try_force_hdmi_mode = 0;
3177 						it66353_fsm_chg(RX_WAIT_CLOCK);
3178 					}
3179 				} else {
3180 					it66353_eq_reset_state();
3181 					it66353_eq_reset_txoe_ready();
3182 					it66353_fsm_chg(RX_CHECK_EQ);
3183 				}
3184 			}
3185 		} else {
3186 			it66353_eq_set_txoe_ready(1);
3187 
3188 			if ((it66353_gdev.vars.check_for_hpd_toggle == 1) &&
3189 				(it66353_gdev.vars.current_txoe == 0) &&
3190 				(_rx_need_hpd_toggle())) {
3191 				DBG_TM(AEQ_TOGGLE_HPD);
3192 				it66353_set_tx_5v(0);
3193 				_rx_set_hpd(it66353_gdev.vars.Rx_active_port, 0, TERM_FOLLOW_HPD);
3194 				it66353_fsm_chg(RX_TOGGLE_HPD);
3195 			} else {
3196 				#if CHECK_INT_BEFORE_TXOE
3197 				u8 reg05 = it66353_h2rxrd(0x05);
3198 				u8 reg06 = it66353_h2rxrd(0x06);
3199 				u8 reg07 = it66353_h2rxrd(0x07);
3200 				if (reg05 == 0 && reg06 == 0 && reg07 == 0) {
3201 					prep_count++;
3202 				} else {
3203 					dev_err(g_it66353->dev,
3204 						"RX reg: 05=%02x, 06=%02x 07=%02x\r\n",
3205 						reg05, reg06, reg07);
3206 					it66353_h2rxwr(0x05, reg05);
3207 					it66353_h2rxwr(0x06, reg06);
3208 					it66353_h2rxwr(0x07, reg07);
3209 					prep_count = 0;
3210 					prep_fail_count++;
3211 				}
3212 
3213 				if (prep_count == 1) {
3214 					_sw_hdcp_access_enable(0);
3215 				}
3216 
3217 				if (prep_count >= 4) {
3218 					prep_count = 0;
3219 					it66353_fsm_chg(TX_OUTPUT);
3220 				} else {
3221 					if (prep_fail_count > 20) {
3222 						prep_fail_count = 0;
3223 						it66353_fsm_chg(RX_WAIT_CLOCK);
3224 					}
3225 				}
3226 				#else
3227 				it66353_fsm_chg(TX_OUTPUT);
3228 				#endif
3229 			}
3230 		}
3231 	#endif
3232 		break;
3233 
3234 	case RX_CHECK_EQ:
3235 	#if EN_AUTO_RS
3236 		it66353_fsm_EQ_check();
3237 	#endif
3238 		break;
3239 
3240 	case SETUP_AFE:
3241 		prep_count = 0;
3242 		prep_fail_count = 0;
3243 		if (it66353_gdev.vars.vclk == 0) {
3244 			it66353_fsm_chg(RX_WAIT_CLOCK);
3245 		} else {
3246 		#if EN_AUTO_RS
3247 			if (it66353_gdev.vars.try_fixed_EQ) {
3248 				it66353_eq_set_txoe_ready(1);
3249 				// it66353_fsm_chg(TX_OUTPUT);
3250 				it66353_fsm_chg(TX_OUTPUT_PREPARE);
3251 			} else {
3252 				if (it66353_gdev.opts.active_rx_opt->EnableAutoEQ) {
3253 					it66353_fsm_chg(RX_CHECK_EQ);
3254 				} else {
3255 					it66353_eq_set_txoe_ready(1);
3256 					// it66353_fsm_chg(TX_OUTPUT);
3257 					it66353_fsm_chg(TX_OUTPUT_PREPARE);
3258 				}
3259 			}
3260 		#else
3261 			it66353_eq_set_txoe_ready(1);
3262 			it66353_fsm_chg(TX_OUTPUT);
3263 			// it66353_fsm_chg(TX_OUTPUT_PREPARE);
3264 		#endif
3265 		}
3266 
3267 		break;
3268 
3269 	case RX_WAIT_CLOCK:
3270 
3271 		if (it66353_rx_is_clock_stable()) {
3272 			it66353_rx_clear_ced_err();
3273 			// _sw_enable_txoe_timer_check();
3274 			// _sw_hdcp_access_enable(0);
3275 			it66353_fsm_chg(SETUP_AFE);
3276 		} else {
3277 			if (it66353_gdev.vars.RxHPDFlag[it66353_gdev.vars.Rx_active_port] == 0) {
3278 				it66353_fsm_chg(RX_UNPLUG);
3279 			}
3280 
3281 			if (it66353_gdev.vars.current_hdmi_mode != HDMI_MODE_AUTO) {
3282 				it66353_gdev.vars.count_wait_clock++;
3283 				if (it66353_gdev.vars.count_wait_clock > 100) {
3284 					it66353_gdev.vars.count_wait_clock = 0;
3285 					it66353_auto_detect_hdmi_encoding();
3286 					it66353_fsm_chg(RX_UNPLUG);
3287 				}
3288 			}
3289 		}
3290 		break;
3291 
3292 	case RX_HPD:
3293 		it66353_fsm_chg(RX_WAIT_CLOCK);
3294 		break;
3295 
3296 	case TX_GOT_HPD:
3297 		it66353_fsm_chg(RX_HPD);
3298 		// scdcwr(0x30, 0x01);
3299 		break;
3300 
3301 	case TX_WAIT_HPD:
3302 		if (0 == _rx_is_5v_active()) {
3303 			it66353_fsm_chg_delayed(RX_UNPLUG);
3304 		}
3305 		if (_tx_is_sink_hpd_high()) {
3306 			it66353_fsm_chg(TX_GOT_HPD);
3307 		}
3308 		break;
3309 
3310 	case TX_UNPLUG:
3311 		if (_rx_is_5v_active()) {
3312 			it66353_fsm_chg_delayed(TX_WAIT_HPD);
3313 		} else {
3314 			it66353_fsm_chg_delayed(RX_UNPLUG);
3315 		}
3316 		break;
3317 
3318 	case RX_UNPLUG:
3319 		if (_rx_is_5v_active()) {
3320 			if (it66353_gdev.vars.force_hpd_state == SW_HPD_LOW) {
3321 				break;
3322 			}
3323 
3324 			if (it66353_gdev.vars.state_sys_fsm != RX_TOGGLE_HPD) {
3325 				it66353_fsm_chg_delayed(TX_WAIT_HPD);
3326 			}
3327 		} else {
3328 			if (_rx_get_all_port_5v()) {
3329 				// it66353_fsm_chg2(TX_WAIT_HPD);
3330 			}
3331 		}
3332 		break;
3333 
3334 	case IDLE:
3335 		break;
3336 	}
3337 
3338 	if (it66353_gdev.vars.fsm_return == 0) {
3339 		it66353_gdev.vars.fsm_return = 1;
3340 		// goto LOOP_FSM;
3341 	}
3342 }
3343 
3344 
it66353_irq(void)3345 static void it66353_irq(void)
3346 {
3347 	u8 sys_int_sts;
3348 	u8 currBD = 0;
3349 
3350 	it66353_detect_ports();
3351 
3352 	if (it66353_gdev.vars.state_sys_fsm == RX_TOGGLE_HPD) {
3353 		return;
3354 	}
3355 
3356 	// static u8 prevBD = 1;
3357 	currBD = it66353_h2swrd(0xBD);
3358 	// if (currBD != prevBD) {
3359 	if (currBD & 0xe0) {
3360 		// it66353_gdev.vars.tick_hdcp = get_tick_count();
3361 		dev_info(g_it66353->dev, "---HDCP BD=%02x\r\n", currBD);
3362 		// prevBD = currBD;
3363 		it66353_sw_clear_hdcp_status();
3364 
3365 		/*
3366 		 * if (currBD & 0x10) {
3367 		 *	if (prevBD) {
3368 		 *		prevBD = 0;
3369 		 *		_sw_hdcp_access_enable(0);
3370 		 *	} else {
3371 		 *		_sw_hdcp_access_enable(1);
3372 		 *	}
3373 		 * }
3374 		 */
3375 
3376 	}
3377 
3378 	sys_int_sts = it66353_h2swrd(0x0C);
3379 
3380 	if (sys_int_sts == 0x00) {
3381 		return;
3382 	}
3383 
3384 	if (sys_int_sts & 0x01) {
3385 		it66353_rx_irq();
3386 	}
3387 
3388 	if (sys_int_sts & 0x10) {
3389 		it66353_sw_irq(it66353_gdev.vars.Rx_active_port);
3390 		it66353_tx_irq();
3391 	}
3392 
3393 	#if EN_CEC
3394 	if (it66353_gdev.opts.EnCEC && (sys_int_sts & 0x80)) {
3395 		Cec_Irq();
3396 	}
3397 	if (it66353_gdev.opts.EnCEC) {
3398 		CecSys_TxHandler();
3399 		CecSys_RxHandler();
3400 	}
3401 	#endif
3402 }
3403 
it66353_device_init(void)3404 bool it66353_device_init(void)
3405 {
3406 	u8 i;
3407 	bool init_done = 0;
3408 
3409 	switch (it66353_gdev.vars.state_dev_init) {
3410 	case 0:
3411 		DBG_CLKSTABLE_0();
3412 		DBG_SYMLOCK_0();
3413 
3414 		it66353_set_tx_5v(0);
3415 
3416 		_sw_reset();
3417 		_rx_set_hpd_all(0);
3418 		it66353_rx_reset();
3419 		_tx_reset();
3420 
3421 		it66353_txoe(0);
3422 		it66353_sw_disable_timer0();
3423 		_sw_disable_timer1();
3424 		// _sw_config_timer1(50);
3425 		// _sw_enable_timer1();
3426 		// config default RS
3427 		it66353_set_RS(it66353_gdev.opts.active_rx_opt->DefaultEQ[0],
3428 					  it66353_gdev.opts.active_rx_opt->DefaultEQ[1],
3429 					  it66353_gdev.opts.active_rx_opt->DefaultEQ[2]);
3430 		if (it66353_gdev.opts.tx_opt->CopyEDIDFromSink) {
3431 			it66353_set_tx_5v(1);
3432 			it66353_gdev.vars.state_dev_init = 1;
3433 			it66353_gdev.vars.hpd_wait_count = 0;
3434 		} else {
3435 			it66353_gdev.vars.state_dev_init = 2;
3436 		}
3437 		break;
3438 
3439 	case 1:
3440 		if (_tx_is_sink_hpd_high()) {
3441 			if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == false) {
3442 				if (it66353_setup_edid_ram(0)) {
3443 					it66353_gdev.vars.edid_ready = 1;
3444 				}
3445 				it66353_gdev.vars.state_dev_init = 3;
3446 			} else {
3447 				it66353_gdev.vars.edid_ready = 1;
3448 				it66353_gdev.vars.state_dev_init = 3;
3449 			}
3450 		} else {
3451 			it66353_gdev.vars.hpd_wait_count++;
3452 			if (it66353_gdev.vars.hpd_wait_count > 200) {
3453 				// it66353_gdev.vars.state_dev_init = 2;
3454 				it66353_gdev.vars.hpd_wait_count = 0;
3455 				dev_info(g_it66353->dev, "waiting HPD...\r\n");
3456 			}
3457 			// it66353_set_tx_5v(_rx_is_5v_active());
3458 		}
3459 		break;
3460 
3461 	case 2:
3462 		// load FW default EDID
3463 		dev_info(g_it66353->dev, "Using internal EDID...\r\n");
3464 		if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == false) {
3465 			it66353_gdev.vars.default_edid[0] = it66353_s_default_edid_port0;
3466 			it66353_gdev.vars.default_edid[1] = it66353_s_default_edid_port0;
3467 			it66353_gdev.vars.default_edid[2] = it66353_s_default_edid_port0;
3468 			it66353_gdev.vars.default_edid[3] = it66353_s_default_edid_port0;
3469 
3470 			// note:
3471 			// The EDID can be different from each port.
3472 			// please set default_edid[?] pointer to a desired EDID array
3473 			// if you need different EDID.
3474 			//
3475 			// for example:
3476 			// it66353_gdev.vars.default_edid[1] = s_default_edid_port1;
3477 			// it66353_gdev.vars.default_edid[2] = s_default_edid_port2;
3478 			// it66353_gdev.vars.default_edid[3] = s_default_edid_port3;
3479 
3480 			for (i = 0; i < RX_PORT_COUNT; i++) {
3481 				it66353_setup_edid_ram(i);
3482 			}
3483 		}
3484 
3485 		it66353_gdev.vars.edid_ready = 1;
3486 		it66353_gdev.vars.state_dev_init = 3;
3487 
3488 		break;
3489 
3490 	case 3:
3491 		_sw_int_enable_all(1);
3492 		_rx_set_hpd_with_5v_all(1);
3493 
3494 		dev_info(g_it66353->dev, "Active port = P%d\r\n",
3495 			 it66353_gdev.vars.Rx_active_port);
3496 
3497 		it66353_set_tx_5v(_rx_is_5v_active());
3498 
3499 		init_done = 1;
3500 		break;
3501 
3502 	default:
3503 		it66353_gdev.vars.state_dev_init = 0;
3504 		break;
3505 	}
3506 
3507 	return init_done;
3508 }
3509 
it66353_vars_init(void)3510 void it66353_vars_init(void)
3511 {
3512 	// FW Variables init:
3513 	it66353_gdev.vars.state_dev_init = 0;
3514 	it66353_gdev.vars.VSDBOffset = 0xFF;
3515 	it66353_gdev.vars.PhyAdr[0] = 0;
3516 	it66353_gdev.vars.PhyAdr[1] = 0;
3517 	it66353_gdev.vars.PhyAdr[2] = 0;
3518 	it66353_gdev.vars.PhyAdr[3] = 0;
3519 	it66353_gdev.vars.RxHPDFlag[0] = -1;
3520 	it66353_gdev.vars.RxHPDFlag[1] = -1;
3521 	it66353_gdev.vars.RxHPDFlag[2] = -1;
3522 	it66353_gdev.vars.RxHPDFlag[3] = -1;
3523 	it66353_gdev.vars.Tx_current_5v = -1;
3524 	it66353_gdev.vars.count_eq_check = 0;
3525 	it66353_gdev.vars.count_fsm_err = 0;
3526 	it66353_gdev.vars.count_unlock = 0;
3527 	it66353_gdev.vars.state_sys_fsm = RX_UNPLUG;
3528 	it66353_gdev.EQ.AutoEQ_state = AEQ_OFF;
3529 	it66353_gdev.EQ.sys_aEQ = SysAEQ_RUN;
3530 	it66353_gdev.vars.edid_ready = 0;
3531 	it66353_gdev.vars.current_txoe = 0xFF;
3532 	it66353_gdev.vars.check_for_hpd_toggle = 0;
3533 	it66353_gdev.vars.sdi_stable_count = 0;
3534 	it66353_gdev.vars.check_for_sdi = 1;
3535 	it66353_gdev.vars.force_hpd_state = SW_HPD_AUTO;	// 1 : auto, don't modify here
3536 	it66353_gdev.vars.vclk_prev = 0;
3537 	if (it66353_gdev.opts.active_rx_opt->TryFixedEQFirst) {
3538 		it66353_gdev.vars.try_fixed_EQ = 1;
3539 	}
3540 	it66353_gdev.vars.current_hdmi_mode = HDMI_MODE_AUTO;
3541 	it66353_gdev.vars.rx_deskew_err = 0;
3542 	it66353_eq_reset_state();
3543 	it66353_eq_reset_txoe_ready();
3544 	it66353_dump_opts();
3545 }
3546 
3547 #if CHECK_DEV_PRESENT
it66353_is_device_lost(void)3548 static bool it66353_is_device_lost(void)
3549 {
3550 	u8 vendor_id[2] = { 0 };
3551 
3552 	vendor_id[0] = it66353_h2swrd(0x00);
3553 	vendor_id[1] = it66353_h2swrd(0x01);
3554 	if (vendor_id[0] == 0x54 && vendor_id[1] == 0x49) {
3555 		return FALSE;
3556 	}
3557 	return TRUE;
3558 }
3559 #endif
3560 
it66353_is_device_ready(void)3561 static bool it66353_is_device_ready(void)
3562 {
3563 	u8 vendor_id[2] = { 0 };
3564 
3565 	vendor_id[0] = it66353_h2swrd(0x00);
3566 	vendor_id[1] = it66353_h2swrd(0x01);
3567 	if (vendor_id[0] == 0x54 && vendor_id[1] == 0x49) {
3568 		vendor_id[0] = 0;
3569 		vendor_id[1] = 0;
3570 
3571 		vendor_id[1] = it66353_h2swrd(0x03);
3572 		if (vendor_id[1] == 0x66) {
3573 			vendor_id[0] = it66353_h2swrd(0x02);
3574 			if (vendor_id[0] == 0x35) {
3575 				it66353_gdev.vars.Rev = it66353_h2swrd(0x04);
3576 				dev_info(g_it66353->dev, "Find 6635 %02x !! \r\n",
3577 					 (int)it66353_gdev.vars.Rev);
3578 				return TRUE;
3579 			}
3580 		} else if (vendor_id[1] == 0x35) {
3581 			vendor_id[0] = it66353_h2swrd(0x04);
3582 			if (vendor_id[0] == 0x66) {
3583 				it66353_gdev.vars.Rev = it66353_h2swrd(0x05);
3584 				dev_info(g_it66353->dev, "Find 6635x %02x !! \r\n",
3585 					 (int)it66353_gdev.vars.Rev);
3586 				return TRUE;
3587 			}
3588 		}
3589 	}
3590 	dev_info(g_it66353->dev, "Find 6635 fail !!\r\n");
3591 
3592 	return FALSE;
3593 }
3594 
3595 
3596 
it66353_read_edid(u8 block,u8 offset,int length,u8 * edid_buffer)3597 bool it66353_read_edid(u8 block, u8 offset, int length, u8 *edid_buffer)
3598 {
3599 	bool result = false;
3600 	int off = block * 128 + offset;
3601 	u8 reg3C;
3602 	int retry = 0;
3603 
3604 	offset = off % 256;
3605 	reg3C = it66353_h2swrd(0x3C);
3606 
3607 __RETRY:
3608 
3609 	it66353_h2swset(0x3C, 0x01, 0x01);	// Enable PC DDC Mode
3610 	it66353_h2swset(0x38, 0x08, 0x08);	// Enable DDC Command Fail Interrupt
3611 	it66353_h2swset(0x37, 0x80, 0x80);	// Enable DDC Bus Hang Interrupt
3612 
3613 	it66353_h2swwr(0x3D, 0x09);		// DDC FIFO Clear
3614 	it66353_h2swwr(0x3E, 0xA0);		// EDID Address
3615 	it66353_h2swwr(0x3F, offset);		// EDID Offset
3616 	it66353_h2swwr(0x40, length);		// Read ByteNum[7:0]
3617 	it66353_h2swwr(0x41, block/2);		// EDID Segment
3618 
3619 	if (_tx_is_sink_hpd_high()) {
3620 		it66353_h2swwr(0x3D, 0x03);			// EDID Read Fire
3621 
3622 		if (_tx_ddcwait()) {
3623 			it66353_h2swbrd(0x42, length, edid_buffer);
3624 			result = true;
3625 		} else {
3626 			dev_err(g_it66353->dev, "ERROR: DDC EDID Read Fail !!!\r\n");
3627 			if (retry > 0) {
3628 				retry--;
3629 				msleep(100);
3630 				goto __RETRY;
3631 			}
3632 		}
3633 	} else {
3634 		dev_err(g_it66353->dev,
3635 			"Abort EDID read becasue of detecting unplug !!!\r\n");
3636 	}
3637 
3638 	it66353_h2swwr(0x3C, reg3C);		// restore PC DDC Mode
3639 
3640 	return result;
3641 }
3642 
3643 /**
3644  * it66353_read_one_block_edid - will read 128 byte EDID data
3645  *
3646  * @block: EDID block number. (0,1,2 or 3)
3647  *
3648  * @edid_buffer: 128 byte EDID data buffer to store data.
3649  *
3650  * Read 128 byte EDID data from assigned block.
3651  */
it66353_read_one_block_edid(u8 block,u8 * edid_buffer)3652 bool it66353_read_one_block_edid(u8 block, u8 *edid_buffer)
3653 {
3654 	u8 offset;
3655 	u8 i;
3656 	u8 read_len = 16;
3657 
3658 	offset = 0;
3659 	for (i = 0; i < 128 / read_len; i++) {
3660 		if (it66353_read_edid(block, offset, read_len, edid_buffer)) {
3661 			edid_buffer += read_len;
3662 			offset += read_len;
3663 			continue;
3664 		} else {
3665 			dev_err(g_it66353->dev,
3666 				"ERROR: read edid block 0, offset %d, length %d fail.\r\r\n",
3667 				(int)offset, (int)read_len);
3668 			return false;
3669 		}
3670 	}
3671 
3672 	return true;
3673 }
3674 
it66353_parse_edid_for_vsdb(u8 * edid)3675 static void it66353_parse_edid_for_vsdb(u8 *edid)
3676 {
3677 	int off;
3678 	u8 tag;
3679 	u8 len;
3680 
3681 	// to find HDMI2.0 VSDB in EDID
3682 
3683 	if (edid[0] == 0x02) {			// CTA ext tag
3684 		off = 4;
3685 		while (off < 0x100) {
3686 			tag = (edid[off] >> 5) & 0x7;
3687 			len = (edid[off] & 0x1F) + 1;
3688 
3689 			if (tag == 0x03) {		// VSDB
3690 				if ((edid[off+1] == 0xD8) &&
3691 				    (edid[off+2] == 0x5D) &&
3692 				    (edid[off+3] == 0xC4)) {
3693 					it66353_gdev.vars.is_hdmi20_sink = 1;
3694 					break;
3695 				}
3696 			}
3697 
3698 			if (len == 0)
3699 				break;
3700 			off += len;
3701 		}
3702 	}
3703 
3704 	dev_info(g_it66353->dev, "HDMI2 sink=%d\n", it66353_gdev.vars.is_hdmi20_sink);
3705 }
3706 
3707 /**
3708  * it66353_parse_edid_for_phyaddr - parse necessary data for RX
3709  * EDID
3710  *
3711  * @edid: 128 byte EDID data buffer that contains HDMI CEA ext
3712  *
3713  * Before set RX EDID, must call it66353_parse_edid_cea_ext to
3714  * initialize some variables.
3715  */
it66353_parse_edid_for_phyaddr(u8 * edid)3716 void it66353_parse_edid_for_phyaddr(u8 *edid)
3717 {
3718 	int off;
3719 	u8 tag;
3720 	u8 len;
3721 
3722 	// to find VSDB in EDID
3723 
3724 	if (edid[0] == 0x02) {			// CTA ext tag
3725 		off = 4;
3726 		while (off < 0x100) {
3727 			tag = (edid[off] >> 5) & 0x7;
3728 			len = (edid[off] & 0x1F) + 1;
3729 
3730 			if (tag == 0x03) {		// VSDB
3731 				if ((edid[off + 1] == 0x03) && (edid[off + 2] == 0x0C) &&
3732 				    (edid[off + 3] == 0x00)) {
3733 					it66353_gdev.vars.VSDBOffset = ((u8)off) + 0x80 + 4;
3734 					it66353_gdev.vars.PhyAdr[0] = (edid[off + 4] >> 4) & 0xF;
3735 					it66353_gdev.vars.PhyAdr[1] = edid[off + 4] & 0xF;
3736 					it66353_gdev.vars.PhyAdr[2] = (edid[off + 5] >> 4) & 0xF;
3737 					it66353_gdev.vars.PhyAdr[3] = edid[off + 5] & 0xF;
3738 					it66353_gdev.vars.EdidChkSum[1] =
3739 						(0x100 - edid[0x7F] -
3740 						edid[off + 4] -
3741 						edid[off + 5]) & 0xFF;
3742 					break;
3743 				}
3744 			}
3745 
3746 			if (len == 0)
3747 				break;
3748 			off += len;
3749 		}
3750 	}
3751 }
3752 
it66353_setup_edid_ram_step2(u8 block)3753 static void it66353_setup_edid_ram_step2(u8 block)
3754 {
3755 	int i;
3756 	u8 wcount = 16;
3757 	u8 phyAB, phyCD;
3758 	u8 mask;
3759 	u16 sum;
3760 
3761 	dev_info(g_it66353->dev, "Set RX EDID step2...\r\n");
3762 
3763 	if (block == 0) {
3764 		for (i = 0; i < 4; i++) {
3765 			_rx_edid_set_chksum(i, it66353_gdev.vars.EdidChkSum[0]);
3766 		}
3767 	}
3768 
3769 	if (block == 1) {
3770 		it66353_h2rxwr(0x4B, it66353_gdev.opts.dev_opt->EdidAddr | 0x01);
3771 		it66353_h2rxset(0x4C, 0x0F, 0x0F);
3772 
3773 		it66353_h2swwr(0xe9, it66353_gdev.vars.VSDBOffset);		// VSDB_Offset
3774 		dev_info(g_it66353->dev, "VSDB=%02x\r\n", it66353_gdev.vars.VSDBOffset);
3775 
3776 		// fill 0xF, if there is no zero address
3777 		if (it66353_gdev.vars.PhyAdr[0] && it66353_gdev.vars.PhyAdr[1] &&
3778 		    it66353_gdev.vars.PhyAdr[2] && it66353_gdev.vars.PhyAdr[3]) {
3779 			it66353_gdev.vars.PhyAdr[0] = 0xF;
3780 			it66353_gdev.vars.PhyAdr[1] = 0xF;
3781 			it66353_gdev.vars.PhyAdr[2] = 0xF;
3782 			it66353_gdev.vars.PhyAdr[3] = 0xF;
3783 		}
3784 
3785 		phyAB = (it66353_gdev.vars.PhyAdr[0] << 4) | (it66353_gdev.vars.PhyAdr[1] & 0xF);
3786 		phyCD = (it66353_gdev.vars.PhyAdr[2] << 4) | (it66353_gdev.vars.PhyAdr[3] & 0xF);
3787 
3788 		for (i = 0; i < 4; i++) {
3789 			it66353_h2swwr(0xd9 + i * 2, phyAB);	// Port0 VSDB_AB
3790 			it66353_h2swwr(0xda + i * 2, phyCD);	// Port0 VSDB_CD
3791 		}
3792 
3793 		for (i = 0; i < 4; i++) {
3794 			if (it66353_gdev.vars.PhyAdr[i] == 0) {
3795 				mask = 0xF0 >> (4 * (i & 0x01));
3796 				for (wcount = 0; wcount < 4; wcount++) {
3797 					phyAB = wcount + 1;
3798 					if (mask == 0xF0) {
3799 						phyAB = phyAB << 4;
3800 					}
3801 					it66353_h2swset(0xd9 + wcount * 2 + i / 2,
3802 							mask, phyAB);
3803 				}
3804 				break;
3805 			}
3806 		}
3807 
3808 		for (i = 0; i < 4; i++) {
3809 			phyAB = it66353_h2swrd(0xd9 + i * 2);	// Port(i) VSDB_AB
3810 			phyCD = it66353_h2swrd(0xda + i * 2);	// Port(i) VSDB_CD
3811 
3812 			// Port(i) Block1_ChkSum
3813 			sum = (0x100 - it66353_gdev.vars.EdidChkSum[1] - phyAB - phyCD) & 0xFF;
3814 			it66353_h2swwr(0xe2 + i * 2, (u8)sum);
3815 
3816 			// if (it66353_gdev.vars.Rev >= 0xC) {
3817 				#if 0
3818 				switch (i) {
3819 				case 0:
3820 					mask = 1 << 1;
3821 					break;
3822 				case 1:
3823 					mask = 1 << 2;
3824 					break;
3825 				case 2:
3826 					mask = 1 << 0;
3827 					break;
3828 				case 3:
3829 					mask = 1 << 3;
3830 					break;
3831 				default:
3832 					mask = 1 << 3;
3833 					break;
3834 				}
3835 				#endif
3836 
3837 				mask = 1 << i;
3838 
3839 				it66353_h2rxset(0x4C, 0x0F, mask);
3840 
3841 				it66353_h2rxedidwr(it66353_gdev.vars.VSDBOffset, &phyAB, 1);
3842 				it66353_h2rxedidwr(it66353_gdev.vars.VSDBOffset + 1, &phyCD, 1);
3843 				phyAB = (u8)sum;
3844 				it66353_h2rxedidwr(128 + 127, &phyAB, 1);
3845 			// }
3846 
3847 		}
3848 
3849 		it66353_h2rxwr(0x4B, it66353_gdev.opts.dev_opt->EdidAddr);
3850 	}
3851 }
3852 
it66353_ddc_abort(void)3853 static void it66353_ddc_abort(void)
3854 {
3855 	u8 reg3C = it66353_h2swrd(0x3C);
3856 	u8 i, j, uc;
3857 
3858 	it66353_h2swset(0x3C, 0x01, 0x01);
3859 	for (i = 0; i < 2; i++) {
3860 		it66353_h2swwr(0x3D, 0x0F);
3861 		for (j = 0; j < 50; j++) {
3862 			uc = it66353_h2swrd(0x1B);
3863 			if (uc & 0x80) {
3864 				// DDC_FW_Stus_DONE
3865 				break;
3866 			}
3867 			if (uc & 0x38) {
3868 				// DDC has something error
3869 				dev_err(g_it66353->dev, "ERROR: DDC 0x1B=%02X\r\n", uc);
3870 				break;
3871 			}
3872 			msleep(1);
3873 		}
3874 	}
3875 	it66353_h2swwr(0x3D, 0x0A);
3876 	it66353_h2swwr(0x3D, 0x09);
3877 	it66353_h2swwr(0x3C, reg3C);
3878 }
3879 
it66353_update_edid(u8 block,u8 * edid_buf,u8 flag)3880 static bool it66353_update_edid(u8 block, u8 *edid_buf, u8 flag)
3881 {
3882 	u8 i;
3883 	bool ret;
3884 	u8 retry = 0;
3885 
3886 __RETRY_EDID_READ:
3887 	if (it66353_gdev.opts.tx_opt->CopyEDIDFromSink) {
3888 		ret = it66353_read_one_block_edid(block, edid_buf);
3889 		if (false == ret) {
3890 			dev_err(g_it66353->dev, "ERROR: read edid block 0\r\n");
3891 			if (retry < 3) {
3892 				retry++;
3893 				it66353_ddc_abort();
3894 				goto __RETRY_EDID_READ;
3895 			}
3896 		}
3897 	} else {
3898 		u8 *def_edid = it66353_gdev.vars.default_edid[flag];
3899 
3900 		if (def_edid) {
3901 			for (i = 0; i < 128; i++) {
3902 				edid_buf[i] = def_edid[i+block*128];
3903 			}
3904 			ret = true;
3905 		} else {
3906 			ret = false;
3907 		}
3908 	}
3909 
3910 	return ret;
3911 }
3912 
it66353_setup_edid_ram(u8 flag)3913 bool it66353_setup_edid_ram(u8 flag)
3914 {
3915 	u8 edid_tmp[128];
3916 	u8 extblock;
3917 	u8 i;
3918 
3919 	it66353_gdev.vars.spmon = 0;
3920 	it66353_gdev.vars.is_hdmi20_sink = 0;
3921 
3922 	if (false == it66353_update_edid(0, edid_tmp, flag)) {
3923 		goto __err_exit;
3924 	}
3925 
3926 	if ((edid_tmp[0x08] == 0x5A) &&
3927 		 (edid_tmp[0x09] == 0x63) &&
3928 		 (edid_tmp[0x0a] == 0x32) &&
3929 		 (edid_tmp[0x0b] == 0x0e)) {
3930 		it66353_gdev.vars.spmon = 1;
3931 	}
3932 
3933 	if ((edid_tmp[0x71] == 0x4C) &&
3934 		 (edid_tmp[0x72] == 0x47) &&
3935 		 (edid_tmp[0x74] == 0x54) &&
3936 		 (edid_tmp[0x75] == 0x56) &&
3937 		 (edid_tmp[0x7F] == 0x63)) {
3938 		it66353_gdev.vars.spmon = 2;
3939 	}
3940 
3941 	if ((edid_tmp[0x60] == 0x48) &&
3942 		 (edid_tmp[0x61] == 0x4C) &&
3943 		 (edid_tmp[0x63] == 0x32) &&
3944 		 (edid_tmp[0x64] == 0x37) &&
3945 		 (edid_tmp[0x65] == 0x36) &&
3946 		 (edid_tmp[0x66] == 0x45) &&
3947 		 (edid_tmp[0x67] == 0x38) &&
3948 		 (edid_tmp[0x68] == 0x56)) {
3949 		it66353_gdev.vars.spmon = 3;
3950 	}
3951 
3952 	// read Ext block no
3953 	extblock = edid_tmp[0x7E];
3954 	it66353_gdev.vars.EdidChkSum[0] = edid_tmp[0x7F];
3955 
3956 	#if FIX_EDID_FOR_ATC_4BLOCK_CTS
3957 	if (extblock > 1) {
3958 		edid_tmp[0x7E] = 1;
3959 		it66353_gdev.vars.EdidChkSum[0] = _rx_calc_edid_sum(edid_tmp);
3960 	}
3961 	#endif
3962 
3963 	_pr_buf(edid_tmp, 128);
3964 
3965 	if (it66353_gdev.opts.tx_opt->CopyEDIDFromSink) {
3966 		// update EDID block 0 for all port
3967 		it66353_set_internal_EDID(0, edid_tmp, EDID_PORT_ALL);
3968 	} else {
3969 		// update EDID block 0 for assigned port
3970 		it66353_set_internal_EDID(0, edid_tmp, (1 << flag));
3971 	}
3972 	it66353_setup_edid_ram_step2(0);
3973 
3974 	if (extblock > 3) {
3975 		dev_err(g_it66353->dev, "Warning: Extblock = %d\r\n", extblock);
3976 		extblock = 3;
3977 	}
3978 
3979 	for (i = 1; i <= extblock; i++) {
3980 		if (false == it66353_update_edid(i, edid_tmp, flag)) {
3981 			goto __err_exit;
3982 		}
3983 
3984 		it66353_gdev.vars.VSDBOffset = 0;
3985 		it66353_parse_edid_for_vsdb(edid_tmp);
3986 
3987 		if (i == 1) {			// assume our sink has only 2 block EDID
3988 			if (it66353_gdev.vars.spmon == 2) {
3989 				if (edid_tmp[0x7F] != 0x6A) {
3990 					it66353_gdev.vars.spmon = 0;
3991 				}
3992 			}
3993 
3994 			_pr_buf(edid_tmp, 128);
3995 
3996 			if (it66353_gdev.opts.tx_opt->CopyEDIDFromSink) {
3997 				// update EDID block 0 for all port
3998 				it66353_set_internal_EDID(1, edid_tmp, EDID_PORT_ALL);
3999 			} else {
4000 				// update EDID block 0 for assigned port
4001 				it66353_set_internal_EDID(1, edid_tmp, (1<<flag));
4002 			}
4003 
4004 			if (it66353_gdev.opts.tx_opt->ParsePhysicalAddr) {
4005 				it66353_parse_edid_for_phyaddr(edid_tmp);
4006 
4007 				if (it66353_gdev.vars.VSDBOffset) {
4008 					it66353_setup_edid_ram_step2(1);
4009 
4010 					// break;
4011 					// break parsing here make the 4 block EDID CTS fail
4012 				}
4013 			}
4014 		}
4015 	} // for i
4016 
4017 	return true;
4018 
4019 __err_exit:
4020 	return false;
4021 }
4022 
it66353_dev_loop(void)4023 static void it66353_dev_loop(void)
4024 {
4025 	#if CHECK_DEV_PRESENT
4026 	if (dev_state < DEV_WAIT_DEVICE_READY) {
4027 		if (it66353_is_device_lost()) {
4028 			dev_state = DEV_FW_VAR_INIT;
4029 		}
4030 	}
4031 	#endif
4032 	switch (dev_state) {
4033 	case DEV_DEVICE_LOOP:
4034 		it66353_fsm();
4035 		it66353_irq();
4036 		it66353_rx_update_ced_err_from_hw();
4037 		break;
4038 
4039 	case DEV_DEVICE_INIT:
4040 		if (it66353_device_init()) {
4041 			dev_state = DEV_DEVICE_LOOP;
4042 		}
4043 		break;
4044 
4045 	case DEV_WAIT_DEVICE_READY:
4046 		if (it66353_is_device_ready()) {
4047 			dev_state = DEV_DEVICE_INIT;
4048 		}
4049 		break;
4050 
4051 	case DEV_FW_VAR_INIT:
4052 		it66353_vars_init();
4053 		dev_state = DEV_WAIT_DEVICE_READY;
4054 		break;
4055 
4056 	default:
4057 		break;
4058 	}
4059 
4060 }
4061 
4062 // APIs:
4063 
it66353_dump_opts(void)4064 void it66353_dump_opts(void)
4065 {
4066 	dev_info(g_it66353->dev, ".rx_opt->tag1=%d\r\n",
4067 		 it66353_gdev.opts.active_rx_opt->tag1);
4068 	dev_info(g_it66353->dev, ".rx_opt->EnRxDDCBypass=%d\r\n",
4069 		 it66353_gdev.opts.active_rx_opt->EnRxDDCBypass);
4070 	dev_info(g_it66353->dev, ".rx_opt->EnRxPWR5VBypass=%d\r\n",
4071 		 it66353_gdev.opts.active_rx_opt->EnRxPWR5VBypass);
4072 	dev_info(g_it66353->dev, ".rx_opt->EnRxHPDBypass=%d\r\n",
4073 		 it66353_gdev.opts.active_rx_opt->EnRxHPDBypass);
4074 	dev_info(g_it66353->dev, ".rx_opt->TryFixedEQFirst=%d\r\n",
4075 		 it66353_gdev.opts.active_rx_opt->TryFixedEQFirst);
4076 	dev_info(g_it66353->dev, ".rx_opt->EnableAutoEQ=%d\r\n",
4077 		 it66353_gdev.opts.active_rx_opt->EnableAutoEQ);
4078 	dev_info(g_it66353->dev, ".rx_opt->NonActivePortReplyHPD=%d\r\n",
4079 		 it66353_gdev.opts.active_rx_opt->NonActivePortReplyHPD);
4080 	dev_info(g_it66353->dev, ".rx_opt->DisableEdidRam=%d\r\n",
4081 		 it66353_gdev.opts.active_rx_opt->DisableEdidRam);
4082 	dev_info(g_it66353->dev, ".rx_opt->DefaultEQ=%x %x %x\r\n",
4083 		 it66353_gdev.opts.active_rx_opt->DefaultEQ[0],
4084 		 it66353_gdev.opts.active_rx_opt->DefaultEQ[1],
4085 		 it66353_gdev.opts.active_rx_opt->DefaultEQ[2]);
4086 	dev_info(g_it66353->dev, ".rx_opt->FixIncorrectHdmiEnc=%d\r\n",
4087 		 it66353_gdev.opts.active_rx_opt->FixIncorrectHdmiEnc);
4088 	dev_info(g_it66353->dev, ".rx_opt->HPDOutputInverse=%d\r\n",
4089 		 it66353_gdev.opts.active_rx_opt->HPDOutputInverse);
4090 	dev_info(g_it66353->dev, ".rx_opt->HPDTogglePeriod=%d\r\n",
4091 		 it66353_gdev.opts.active_rx_opt->HPDTogglePeriod);
4092 	dev_info(g_it66353->dev, ".rx_opt->TxOEAlignment=%d\r\n",
4093 		 it66353_gdev.opts.active_rx_opt->TxOEAlignment);
4094 	dev_info(g_it66353->dev, ".rx_opt->str_size=%d\r\n",
4095 		 it66353_gdev.opts.active_rx_opt->str_size);
4096 
4097 	dev_info(g_it66353->dev, ".tx_opt->tag1=%d\r\n", it66353_gdev.opts.tx_opt->tag1);
4098 	dev_info(g_it66353->dev, ".tx_opt->EnTxPNSwap=%d\r\n",
4099 		 it66353_gdev.opts.tx_opt->EnTxPNSwap);
4100 	dev_info(g_it66353->dev, ".tx_opt->EnTxChSwap=%d\r\n",
4101 		 it66353_gdev.opts.tx_opt->EnTxChSwap);
4102 	dev_info(g_it66353->dev, ".tx_opt->EnTxVCLKInv=%d\r\n",
4103 		 it66353_gdev.opts.tx_opt->EnTxVCLKInv);
4104 	dev_info(g_it66353->dev, ".tx_opt->EnTxOutD1t=%d\r\n",
4105 		 it66353_gdev.opts.tx_opt->EnTxOutD1t);
4106 	dev_info(g_it66353->dev, ".tx_opt->CopyEDIDFromSink=%d\r\n",
4107 		 it66353_gdev.opts.tx_opt->CopyEDIDFromSink);
4108 	dev_info(g_it66353->dev, ".tx_opt->ParsePhysicalAddr=%d\r\n",
4109 		 it66353_gdev.opts.tx_opt->ParsePhysicalAddr);
4110 	dev_info(g_it66353->dev, ".tx_opt->TurnOffTx5VWhenSwitchPort=%d\r\n",
4111 		 it66353_gdev.opts.tx_opt->TurnOffTx5VWhenSwitchPort);
4112 	dev_info(g_it66353->dev, ".tx_opt->str_size=%d\r\n",
4113 		 it66353_gdev.opts.tx_opt->str_size);
4114 
4115 	dev_info(g_it66353->dev, ".dev_opt->tag1=%d\r\n",
4116 		 it66353_gdev.opts.dev_opt->tag1);
4117 	dev_info(g_it66353->dev, ".dev_opt->SwAddr=%d\r\n",
4118 		 it66353_gdev.opts.dev_opt->SwAddr);
4119 	dev_info(g_it66353->dev, ".dev_opt->RxAddr=%d\r\n",
4120 		 it66353_gdev.opts.dev_opt->RxAddr);
4121 	dev_info(g_it66353->dev, ".dev_opt->CecAddr=%d\r\n",
4122 		 it66353_gdev.opts.dev_opt->CecAddr);
4123 	dev_info(g_it66353->dev, ".dev_opt->EdidAddr=%d\r\n",
4124 		 it66353_gdev.opts.dev_opt->EdidAddr);
4125 	dev_info(g_it66353->dev, ".dev_opt->ForceRxOn=%d\r\n",
4126 		 it66353_gdev.opts.dev_opt->ForceRxOn);
4127 	dev_info(g_it66353->dev, ".dev_opt->RxAutoPowerDown=%d\r\n",
4128 		 it66353_gdev.opts.dev_opt->RxAutoPowerDown);
4129 	dev_info(g_it66353->dev, ".dev_opt->DoTxPowerDown=%d\r\n",
4130 		 it66353_gdev.opts.dev_opt->DoTxPowerDown);
4131 	dev_info(g_it66353->dev, ".dev_opt->TxPowerDownWhileWaitingClock=%d\r\n",
4132 		 it66353_gdev.opts.dev_opt->TxPowerDownWhileWaitingClock);
4133 	dev_info(g_it66353->dev, ".dev_opt->str_size=%d\r\n",
4134 		 it66353_gdev.opts.dev_opt->str_size);
4135 }
4136 
4137 #define BUF_LEN 16
it66353_dump_register(u8 addr,char * reg_desc)4138 static void it66353_dump_register(u8 addr, char *reg_desc)
4139 {
4140 	u8 regbuf[BUF_LEN];
4141 	int i, j;
4142 
4143 	// print reg description
4144 	dev_info(g_it66353->dev, reg_desc);
4145 
4146 	// print table
4147 	dev_info(g_it66353->dev, "   | ");
4148 	for (j = 0; j < BUF_LEN; j++) {
4149 		if (j == (BUF_LEN/2)) {
4150 			dev_info(g_it66353->dev, "- ");
4151 		}
4152 		dev_info(g_it66353->dev, "%02X ", j);
4153 	}
4154 	dev_info(g_it66353->dev, "\n");
4155 
4156 	// print split line
4157 	for (j = 0; j < BUF_LEN + 2; j++) {
4158 		dev_info(g_it66353->dev, "---");
4159 	}
4160 	dev_info(g_it66353->dev, "\n");
4161 
4162 	// print register values
4163 	for (i = 0; i < 256; i += BUF_LEN) {
4164 		dev_info(g_it66353->dev, "%02X | ", i);
4165 		it66353_i2c_read(addr, i, BUF_LEN, regbuf);
4166 		for (j = 0; j < BUF_LEN; j++) {
4167 			if (j == (BUF_LEN / 2)) {
4168 				dev_info(g_it66353->dev, "- ");
4169 			}
4170 			dev_info(g_it66353->dev, "%02x ", regbuf[j]);
4171 		}
4172 		dev_info(g_it66353->dev, "\n");
4173 	}
4174 	dev_info(g_it66353->dev, "\n");
4175 }
4176 
it66353_dump_register_all(void)4177 void it66353_dump_register_all(void)
4178 {
4179 	it66353_dump_register(it66353_gdev.opts.dev_opt->SwAddr, "\n*** Switch Register:\n");
4180 
4181 	it66353_dump_register(it66353_gdev.opts.dev_opt->RxAddr, "\n*** RX Register(0):\n");
4182 	it66353_chgrxbank(3);
4183 	it66353_dump_register(it66353_gdev.opts.dev_opt->RxAddr, "\n*** RX Register(3):\n");
4184 	it66353_chgrxbank(5);
4185 	it66353_dump_register(it66353_gdev.opts.dev_opt->RxAddr, "\n*** RX Register(5):\n");
4186 	it66353_chgrxbank(0);
4187 
4188 	// dump EDID RAM, enable EDID RAM i2c address
4189 	it66353_h2rxwr(0x4B, it66353_gdev.opts.dev_opt->EdidAddr | 0x01);
4190 	it66353_h2rxset(0x4C, 0x30, 0x00);
4191 	it66353_dump_register(it66353_gdev.opts.dev_opt->EdidAddr, "\n*** EDID Port 0:\n");
4192 	it66353_h2rxset(0x4C, 0x30, 0x10);
4193 	it66353_dump_register(it66353_gdev.opts.dev_opt->EdidAddr, "\n*** EDID Port 1:\n");
4194 	it66353_h2rxset(0x4C, 0x30, 0x20);
4195 	it66353_dump_register(it66353_gdev.opts.dev_opt->EdidAddr, "\n*** EDID Port 2:\n");
4196 	it66353_h2rxwr(0x4B, it66353_gdev.opts.dev_opt->EdidAddr); // disable EDID RAM i2c address
4197 
4198 	#if EN_CEC
4199 	it66353_dump_register(it66353_gdev.opts.dev_opt->CecAddr, "\n*** CEC Register:\n");
4200 	#endif
4201 }
4202 
it66353_write_edid(u8 block,u8 offset,int length,u8 * data_buffer)4203 static bool it66353_write_edid(u8 block, u8 offset, int length, u8 *data_buffer)
4204 {
4205 	bool result = false;
4206 	int off = block * 128 + offset;
4207 	u8 reg3C;
4208 	u8 segment = off / 256;
4209 
4210 	offset = off % 256;
4211 	reg3C = it66353_h2swrd(0x3C);
4212 
4213 	it66353_h2swset(0xF5, 0x80, (1 << 7));
4214 	it66353_h2swset(0x3C, 0x01, 0x01);	// disable DDCRegen by set RegTxMastersel=1
4215 
4216 	it66353_h2swset(0x3C, 0x01, 0x01);	// Enable PC DDC Mode
4217 	it66353_h2swset(0x38, 0x08, 0x08);	// Enable DDC Command Fail Interrupt
4218 	it66353_h2swset(0x37, 0x80, 0x80);	// Enable DDC Bus Hang Interrupt
4219 
4220 	it66353_h2swwr(0x3D, 0x09);		// DDC FIFO Clear
4221 	it66353_h2swwr(0x3E, 0xA0);		// EDID Address
4222 	it66353_h2swwr(0x3F, offset);		// EDID Offset
4223 	it66353_h2swwr(0x40, length);		// Read ByteNum[7:0]
4224 	it66353_h2swwr(0x41, segment / 2);	// EDID Segment
4225 
4226 	while (length) {
4227 		it66353_h2swwr(0x42, *data_buffer);
4228 		length--;
4229 		data_buffer++;
4230 	}
4231 
4232 	it66353_h2swwr(0x3D, 0x07);		// EDID Write Fire
4233 
4234 	if (_tx_ddcwait()) {
4235 		result = true;
4236 	} else {
4237 		dev_err(g_it66353->dev, "ERROR: DDC EDID Write Fail !!!\r\n");
4238 	}
4239 
4240 	it66353_h2swwr(0x3C, reg3C);		// restore PC DDC Mode
4241 
4242 	it66353_h2swset(0xF5, 0x80, (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass << 7));
4243 	if (it66353_gdev.opts.active_rx_opt->EnRxDDCBypass == 0) {
4244 		// enable DDCRegen by set RegTxMastersel=1
4245 		it66353_h2swset(0x3C, 0x01, 0x00);
4246 	}
4247 
4248 	return result;
4249 }
4250 
it66353_write_one_block_edid(u8 block,u8 * edid_buffer)4251 bool it66353_write_one_block_edid(u8 block, u8 *edid_buffer)
4252 {
4253 	u8 offset;
4254 	u8 i;
4255 	u8 op_len = 16;
4256 
4257 	offset = 0;
4258 	for (i = 0; i < 128 / op_len; i++) {
4259 		if (it66353_write_edid(block, offset, op_len, edid_buffer)) {
4260 			edid_buffer += op_len;
4261 			offset += op_len;
4262 			continue;
4263 		} else {
4264 			dev_err(g_it66353->dev,
4265 				"ERROR: write edid block 0, offset %d, length %d fail.\r\r\n",
4266 				(int)offset, (int)op_len);
4267 			return false;
4268 		}
4269 	}
4270 
4271 	return true;
4272 }
4273 
it66353_is_5v_present(u8 port)4274 static u8 __maybe_unused it66353_is_5v_present(u8 port)
4275 {
4276 	if (port < RX_PORT_COUNT) {
4277 		if (it66353_get_port_info0(port, PI_5V)) {
4278 			return 1;
4279 		}
4280 	} else {
4281 		dev_err(g_it66353->dev, "Invalid port number:%d\r\n", port);
4282 	}
4283 
4284 	return 0;
4285 }
4286 
it66353_is_clock_detected(u8 port)4287 static u8 __maybe_unused it66353_is_clock_detected(u8 port)
4288 {
4289 	if (port < RX_PORT_COUNT) {
4290 		if (it66353_get_port_info0(port,
4291 					   (PI_CLK_STABLE | PI_CLK_VALID | PI_5V))) {
4292 			return 1;
4293 		}
4294 	} else {
4295 		dev_err(g_it66353->dev, "Invalid port number:%d\r\n", port);
4296 	}
4297 
4298 	return 0;
4299 }
4300 
it66353_set_active_port(u8 port)4301 bool it66353_set_active_port(u8 port)
4302 {
4303 	if (port < RX_PORT_COUNT) {
4304 		if (it66353_gdev.vars.Rx_active_port != port) {
4305 			it66353_gdev.vars.Rx_new_port = port;
4306 			it66353_fsm_chg_delayed(RX_PORT_CHANGE);
4307 
4308 			return 1;
4309 		}
4310 	} else {
4311 		dev_err(g_it66353->dev, "Invalid port number:%d\r\n", port);
4312 	}
4313 
4314 	return 0;
4315 }
4316 
it66353_get_active_port(void)4317 u8 it66353_get_active_port(void)
4318 {
4319 	return it66353_gdev.vars.Rx_active_port;
4320 }
4321 
it66353_set_option(IT6635_DEVICE_OPTION * Opts)4322 void it66353_set_option(IT6635_DEVICE_OPTION *Opts)
4323 {
4324 	if (Opts) {
4325 		// it66353_gdev.opts.EnableAutoEQ = Opts->EnableAutoEQ;
4326 		// it66353_gdev.opts.rx_opt->EnRxDDCBypass = Opts->EnRxDDCBypass;
4327 	}
4328 }
4329 
it66353_get_option(IT6635_DEVICE_OPTION * Opts)4330 void it66353_get_option(IT6635_DEVICE_OPTION *Opts)
4331 {
4332 	if (Opts) {
4333 		// Opts->EnableAutoEQ = it66353_gdev.opts.EnableAutoEQ;
4334 		// Opts->EnRxDDCBypass = it66353_gdev.opts.rx_opt->EnRxDDCBypass;
4335 	}
4336 }
4337 
it66353_dev_restart(void)4338 void it66353_dev_restart(void)
4339 {
4340 	// it66353_gdev.vars.Rx_prev_port = -1;
4341 	it66353_gdev.vars.state_sys_fsm = RX_UNPLUG;
4342 
4343 	dev_state = DEV_WAIT_DEVICE_READY;
4344 }
4345 
it66353_get_RS(void)4346 u8 it66353_get_RS(void)
4347 {
4348 	// return it66353_gdev.EQ.FixedRsIndex[it66353_gdev.vars.Rx_active_port];
4349 	return 0;
4350 }
4351 
it66353_set_RS(u8 rs_idx0,u8 rs_idx1,u8 rs_idx2)4352 void it66353_set_RS(u8 rs_idx0, u8 rs_idx1, u8 rs_idx2)
4353 {
4354 	u8 rs[3];
4355 	if ((rs_idx0 < 14) && (rs_idx1 < 14) && (rs_idx2 < 14)) {
4356 		// it66353_gdev.EQ.FixedRsIndex[it66353_gdev.vars.Rx_active_port] = rs_index;
4357 		rs[0] = it66353_rs_value[rs_idx0] | 0x80;
4358 		rs[1] = it66353_rs_value[rs_idx1] | 0x80;
4359 		rs[2] = it66353_rs_value[rs_idx2] | 0x80;
4360 		it66353_rx_set_rs_3ch(rs);
4361 		it66353_chgrxbank(3);
4362 		it66353_h2rxbrd(0x27, 3, rs);
4363 		// it66353_h2rxset(0x22, 0x40, 0x00);
4364 		it66353_chgrxbank(0);
4365 		dev_info(g_it66353->dev, "==> RS set to %02x %02x %02x\r\n",
4366 			 rs[0], rs[1], rs[2]);
4367 
4368 	}
4369 }
4370 
it66353_set_ch_RS(u8 ch,u8 rs_index)4371 void it66353_set_ch_RS(u8 ch, u8 rs_index)
4372 {
4373 	u8 rs;
4374 	if (rs_index < 14) {
4375 		rs = it66353_rs_value[rs_index] | 0x80;
4376 		it66353_rx_set_rs(ch, rs);
4377 	}
4378 }
4379 
it66353_set_rx_hpd(u8 hpd_value)4380 void it66353_set_rx_hpd(u8 hpd_value)
4381 {
4382 	_rx_set_hpd(it66353_gdev.vars.Rx_active_port, hpd_value, TERM_FOLLOW_HPD);
4383 }
4384 
4385 /*
4386  * it66353_set_internal_EDID - write data to EDID RAM
4387  *
4388  * @edid: 128 byte EDID data buffer.
4389  *
4390  * @block: EDID block number (0,1 or 2)
4391  *
4392  * target_port is a bitmap from 0x1 to 0xF
4393  *
4394  * ex: set port 1 EDID: target_port = EDID_PORT_1
4395  *	 set port 1,3 EDID: target_port = EDID_PORT_1|EDID_PORT_3
4396  */
it66353_set_internal_EDID(u8 block,u8 * edid,u8 target_port)4397 void it66353_set_internal_EDID(u8 block, u8 *edid, u8 target_port)
4398 {
4399 	int i;
4400 	u8 wcount = 16;
4401 
4402 	if (block > 1) {
4403 		dev_err(g_it66353->dev, "Invalid block %d\r\n", block);
4404 		return;
4405 	}
4406 	// enable EDID RAM i2c address
4407 	it66353_h2rxwr(0x4B, it66353_gdev.opts.dev_opt->EdidAddr | 0x01);
4408 	// for block 1, select port to be written
4409 	it66353_h2rxset(0x4C, 0x0F, target_port);
4410 
4411 	for (i = 0; i < 128; i += wcount) {
4412 		it66353_h2rxedidwr(i + 128 * block, edid, wcount);
4413 		edid += wcount;
4414 	}
4415 	// disable EDID RAM i2c address
4416 	it66353_h2rxwr(0x4B, it66353_gdev.opts.dev_opt->EdidAddr);
4417 }
4418 
4419 /**
4420  * it66353_get_internal_EDID - read data from EDID RAM
4421  *
4422  * @edid: 128 byte EDID data buffer.
4423  *
4424  * @block: EDID block number (0,1,2 or 3)
4425  *
4426  */
it66353_get_internal_EDID(u8 block,u8 * edid,u8 target_port)4427 void it66353_get_internal_EDID(u8 block, u8 *edid, u8 target_port)
4428 {
4429 	int i;
4430 	u8 wcount = 16;
4431 
4432 	if (block > 1) {
4433 		dev_err(g_it66353->dev, "Invalid block %d\r\n", block);
4434 		return;
4435 	}
4436 	if (target_port > 2) {
4437 		dev_err(g_it66353->dev, "Invalid port %d\r\n", target_port);
4438 		return;
4439 	}
4440 	// enable EDID RAM i2c address
4441 	it66353_h2rxwr(0x4B, it66353_gdev.opts.dev_opt->EdidAddr | 0x01);
4442 	it66353_h2rxset(0x4C, 0x30, target_port << 4);
4443 
4444 	for (i = 0; i < 128; i += wcount) {
4445 		it66353_h2rxedidrd(i + 128 * block, edid, wcount);
4446 		edid += wcount;
4447 	}
4448 	// disable EDID RAM i2c address
4449 	it66353_h2rxwr(0x4B, it66353_gdev.opts.dev_opt->EdidAddr);
4450 }
4451 
4452 
4453 /*
4454  * it66353_change_default_RS - set the default RS index for each
4455  * port
4456  *
4457  * @port: port number can be P0~P3.
4458  *
4459  * @new_rs_idx: RS index from 0 to 13
4460  *
4461  * @update_hw: 0: only update the vaule in RAM
4462  *			 1: update the value to RAM and Hardware register
4463  *				(for active port only)
4464  *
4465  */
it66353_change_default_RS(u8 port,u8 new_rs_idx0,u8 new_rs_idx1,u8 new_rs_idx2,u8 update_hw)4466 void it66353_change_default_RS(u8 port, u8 new_rs_idx0, u8 new_rs_idx1,
4467 			       u8 new_rs_idx2, u8 update_hw)
4468 {
4469 	if (port <= RX_PORT_3) {
4470 		it66353_gdev.opts.rx_opt[port]->DefaultEQ[0] = new_rs_idx0;
4471 		it66353_gdev.opts.rx_opt[port]->DefaultEQ[1] = new_rs_idx1;
4472 		it66353_gdev.opts.rx_opt[port]->DefaultEQ[2] = new_rs_idx2;
4473 		if (update_hw && (port == it66353_gdev.vars.Rx_active_port)) {
4474 			it66353_set_RS(new_rs_idx0, new_rs_idx1, new_rs_idx2);
4475 		}
4476 	} else {
4477 		dev_err(g_it66353->dev, "Invalid port number:%d\r\n", port);
4478 	}
4479 }
4480 
4481 
4482 /*
4483  * it66353_force_rx_hpd :
4484  * to force active port HPD low or auto control by driver
4485  *
4486  * @hpd_state: 0: Force HPD of active port to low
4487  *			 1: HPD of active port is controlled by it6635
4488  *				driver
4489  *
4490  * it66353_gdev.vars.force_hpd_state will reset to SW_HPD_AUTO when
4491  * active port changed by it66353_fsm_chg(RX_PORT_CHANGE)
4492  *
4493  */
it66353_force_rx_hpd(u8 hpd_state)4494 void it66353_force_rx_hpd(u8 hpd_state)
4495 {
4496 	it66353_gdev.vars.force_hpd_state = hpd_state;
4497 
4498 	if (hpd_state) {	// hpd 0 --> hpd auto
4499 		// nothing to do here:
4500 		// hpd will be controlled by it66353_fsm()
4501 	} else {			// hpd auto --> hpd 0
4502 		_rx_set_hpd(it66353_gdev.vars.Rx_active_port, hpd_state, TERM_FOLLOW_HPD);
4503 		it66353_fsm_chg_delayed(RX_UNPLUG);
4504 	}
4505 }
4506 
4507 
4508 /*
4509  * it66353_toggle_hpd : to make HPD toggle for active port with a
4510  * given duration.
4511  *
4512  * @ms_duration: duration of HPD low in millisecond.
4513  * range from 10ms to 12700ms
4514  *
4515  */
it66353_toggle_hpd(u16 ms_duration)4516 bool it66353_toggle_hpd(u16 ms_duration)
4517 {
4518 	u8 timeout = 0;
4519 	bool ret = true;
4520 
4521 	if (ms_duration <= (0x7F * 10)) {
4522 		timeout = ms_duration / 10;
4523 	} else if (ms_duration <= (0x7F * 100)) {
4524 		timeout = ms_duration/100;
4525 		timeout |= (BIT(7));
4526 	} else {
4527 		ret = false;
4528 	}
4529 
4530 	_rx_set_hpd(it66353_gdev.vars.Rx_active_port, 0, TERM_FOLLOW_HPD);
4531 	_tx_scdc_write(0x20, 0x00);
4532 	it66353_gdev.vars.hpd_toggle_timeout = timeout;
4533 	it66353_fsm_chg(RX_TOGGLE_HPD);
4534 
4535 	return ret;
4536 }
4537