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