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