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