[PATCHv2 3/3] drm/i2c: anx78xx: Add anx7814 driver support by analogix.

Enric Balletbo i Serra eballetbo at gmail.com
Tue Sep 8 00:25:33 PDT 2015


The ANX7814 is an ultra-low power Full-HD (1080p60) SlimPort transmitter
designed for portable devices.

This driver adds initial support and supports HDMI to DP pass-through mode.

Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
---
 drivers/gpu/drm/i2c/Kconfig                   |    2 +
 drivers/gpu/drm/i2c/Makefile                  |    2 +
 drivers/gpu/drm/i2c/anx78xx/Kconfig           |    7 +
 drivers/gpu/drm/i2c/anx78xx/Makefile          |    4 +
 drivers/gpu/drm/i2c/anx78xx/slimport.c        |  301 +++
 drivers/gpu/drm/i2c/anx78xx/slimport.h        |   49 +
 drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.c | 3335 +++++++++++++++++++++++++
 drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.h |  254 ++
 drivers/gpu/drm/i2c/anx78xx/slimport_tx_reg.h |  786 ++++++
 9 files changed, 4740 insertions(+)
 create mode 100644 drivers/gpu/drm/i2c/anx78xx/Kconfig
 create mode 100644 drivers/gpu/drm/i2c/anx78xx/Makefile
 create mode 100644 drivers/gpu/drm/i2c/anx78xx/slimport.c
 create mode 100644 drivers/gpu/drm/i2c/anx78xx/slimport.h
 create mode 100644 drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.c
 create mode 100644 drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.h
 create mode 100644 drivers/gpu/drm/i2c/anx78xx/slimport_tx_reg.h

diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
index 22c7ed6..e666ccd 100644
--- a/drivers/gpu/drm/i2c/Kconfig
+++ b/drivers/gpu/drm/i2c/Kconfig
@@ -31,4 +31,6 @@ config DRM_I2C_NXP_TDA998X
 	help
 	  Support for NXP Semiconductors TDA998X HDMI encoders.
 
+source "drivers/gpu/drm/i2c/anx78xx/Kconfig"
+
 endmenu
diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
index 2c72eb5..0ca15d2 100644
--- a/drivers/gpu/drm/i2c/Makefile
+++ b/drivers/gpu/drm/i2c/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
 
 tda998x-y := tda998x_drv.o
 obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
+
+obj-$(CONFIG_DRM_I2C_ANX78XX) += anx78xx/
diff --git a/drivers/gpu/drm/i2c/anx78xx/Kconfig b/drivers/gpu/drm/i2c/anx78xx/Kconfig
new file mode 100644
index 0000000..4862c06
--- /dev/null
+++ b/drivers/gpu/drm/i2c/anx78xx/Kconfig
@@ -0,0 +1,7 @@
+config DRM_I2C_ANX78XX
+	tristate "Analogix Slimport transmitter ANX78XX support"
+	help
+        	Slimport Transmitter is a HD video transmitter chip
+		over micro-USB connector for smartphone device.
+
+
diff --git a/drivers/gpu/drm/i2c/anx78xx/Makefile b/drivers/gpu/drm/i2c/anx78xx/Makefile
new file mode 100644
index 0000000..e248ee5
--- /dev/null
+++ b/drivers/gpu/drm/i2c/anx78xx/Makefile
@@ -0,0 +1,4 @@
+obj-${CONFIG_DRM_I2C_ANX78XX} :=  anx78xx.o
+
+anx78xx-y := slimport.o
+anx78xx-y += slimport_tx_drv.o
diff --git a/drivers/gpu/drm/i2c/anx78xx/slimport.c b/drivers/gpu/drm/i2c/anx78xx/slimport.c
new file mode 100644
index 0000000..287562e
--- /dev/null
+++ b/drivers/gpu/drm/i2c/anx78xx/slimport.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright(c) 2015, Analogix Semiconductor. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/async.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/delay.h>
+
+#include "slimport.h"
+#include "slimport_tx_drv.h"
+
+/* HDCP switch for external block */
+/* external_block_en = 1: enable, 0: disable */
+int external_block_en = 1;
+
+struct i2c_client *anx78xx_client;
+
+int sp_read_reg_byte(uint8_t slave_addr, uint8_t offset)
+{
+	int ret = 0;
+	struct device *dev = &anx78xx_client->dev;
+
+	anx78xx_client->addr = (slave_addr >> 1);
+	ret = i2c_smbus_read_byte_data(anx78xx_client, offset);
+	if (ret < 0) {
+		dev_err(dev, "%s: failed to read i2c addr=%x\n", LOG_TAG,
+		      slave_addr);
+		return ret;
+	}
+	return 0;
+}
+
+int sp_read_reg(uint8_t slave_addr, uint8_t offset, uint8_t *buf)
+{
+	int ret = 0;
+	struct device *dev = &anx78xx_client->dev;
+
+	anx78xx_client->addr = (slave_addr >> 1);
+	ret = i2c_smbus_read_byte_data(anx78xx_client, offset);
+	if (ret < 0) {
+		dev_err(dev, "%s: failed to read i2c addr=%x\n", LOG_TAG,
+		       slave_addr);
+		return ret;
+	}
+	*buf = (uint8_t) ret;
+
+	return 0;
+}
+
+int sp_write_reg(uint8_t slave_addr, uint8_t offset, uint8_t value)
+{
+	int ret = 0;
+	struct device *dev = &anx78xx_client->dev;
+
+	anx78xx_client->addr = (slave_addr >> 1);
+	ret = i2c_smbus_write_byte_data(anx78xx_client, offset, value);
+	if (ret < 0) {
+		dev_err(dev, "%s: failed to write i2c addr=%x\n", LOG_TAG,
+		       slave_addr);
+	}
+	return ret;
+}
+
+void sp_tx_hardware_poweron(struct anx78xx_data *data)
+{
+	struct device *dev = &data->client->dev;
+	struct anx78xx_platform_data *pdata = data->pdata;
+
+	gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
+	usleep_range(1000, 2000);
+
+	gpiod_set_value_cansleep(pdata->gpiod_pd, 0);
+	usleep_range(1000, 2000);
+
+	gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
+
+	dev_info(dev, "%s: anx78xx power on\n", LOG_TAG);
+}
+
+void sp_tx_hardware_powerdown(struct anx78xx_data *data)
+{
+	struct device *dev = &data->client->dev;
+	struct anx78xx_platform_data *pdata = data->pdata;
+
+	gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
+	usleep_range(1000, 2000);
+
+	gpiod_set_value_cansleep(pdata->gpiod_pd, 1);
+	usleep_range(1000, 2000);
+
+	dev_info(dev, "%s: anx78xx power down\n", LOG_TAG);
+}
+
+static int anx78xx_init_gpio(struct anx78xx_data *data)
+{
+	struct device *dev = &data->client->dev;
+	struct anx78xx_platform_data *pdata = data->pdata;
+	int ret;
+
+	/* gpio for chip power down */
+	pdata->gpiod_pd = devm_gpiod_get(dev, "pd", GPIOD_OUT_HIGH);
+	if (IS_ERR(pdata->gpiod_pd)) {
+		dev_err(dev, "unable to claim pd gpio\n");
+		ret = PTR_ERR(pdata->gpiod_pd);
+		return ret;
+	}
+
+	/* gpio for chip reset */
+	pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(pdata->gpiod_reset)) {
+		dev_err(dev, "unable to claim reset gpio\n");
+		ret = PTR_ERR(pdata->gpiod_reset);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int anx78xx_system_init(struct anx78xx_data *data)
+{
+	struct device *dev = &data->client->dev;
+
+	int ret = 0;
+
+	ret = slimport_chip_detect(data);
+	if (ret == 0) {
+		sp_tx_hardware_powerdown(data);
+		dev_err(dev, "failed to detect anx78xx\n");
+		return -ENODEV;
+	}
+
+	sp_tx_variable_init();
+	return 0;
+}
+
+static void anx78xx_work_func(struct work_struct *work)
+{
+	struct anx78xx_data *data = container_of(work, struct anx78xx_data,
+					       work.work);
+	int workqueu_timer = 0;
+
+	if (sp_tx_cur_states() >= STATE_PLAY_BACK)
+		workqueu_timer = 500;
+	else
+		workqueu_timer = 100;
+	mutex_lock(&data->lock);
+	slimport_main_process(data);
+	mutex_unlock(&data->lock);
+	queue_delayed_work(data->workqueue, &data->work,
+			   msecs_to_jiffies(workqueu_timer));
+}
+
+static int anx78xx_i2c_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct anx78xx_data *data;
+	struct anx78xx_platform_data *pdata;
+	int ret = 0;
+
+	if (!i2c_check_functionality(client->adapter,
+		I2C_FUNC_SMBUS_I2C_BLOCK)) {
+		dev_err(&client->dev, "i2c bus does not support the device\n");
+		return -ENODEV;
+	}
+
+	data = devm_kzalloc(&client->dev,
+			sizeof(struct anx78xx_data),
+			GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	pdata = devm_kzalloc(&client->dev,
+			sizeof(struct anx78xx_platform_data),
+			GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	data->pdata = pdata;
+
+	data->client = client;
+	anx78xx_client = client;
+
+	mutex_init(&data->lock);
+
+	ret = anx78xx_init_gpio(data);
+	if (ret) {
+		dev_err(&client->dev, "failed to initialize gpios\n");
+		return ret;
+	}
+
+	INIT_DELAYED_WORK(&data->work, anx78xx_work_func);
+
+	data->workqueue = create_singlethread_workqueue("anx78xx_work");
+	if (data->workqueue == NULL) {
+		dev_err(&client->dev, "failed to create work queue\n");
+		return -ENOMEM;
+	}
+
+	ret = anx78xx_system_init(data);
+	if (ret) {
+		dev_err(&client->dev, "failed to initialize anx78xx\n");
+		goto cleanup;
+	}
+
+	i2c_set_clientdata(client, data);
+
+	/* enable driver */
+	queue_delayed_work(data->workqueue, &data->work, 0);
+
+	return 0;
+
+cleanup:
+	destroy_workqueue(data->workqueue);
+	return ret;
+}
+
+static int anx78xx_i2c_remove(struct i2c_client *client)
+{
+	struct anx78xx_data *data = i2c_get_clientdata(client);
+
+	destroy_workqueue(data->workqueue);
+
+	return 0;
+}
+
+static int anx78xx_i2c_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct anx78xx_data *data = i2c_get_clientdata(client);
+
+	dev_info(&client->dev, "suspend\n");
+	cancel_delayed_work_sync(&data->work);
+	flush_workqueue(data->workqueue);
+	sp_tx_hardware_powerdown(data);
+	sp_tx_clean_state_machine();
+
+	return 0;
+}
+
+static int anx78xx_i2c_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct anx78xx_data *anx78xx = i2c_get_clientdata(client);
+
+	dev_info(&client->dev, "resume\n");
+	queue_delayed_work(anx78xx->workqueue, &anx78xx->work, 0);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(anx78xx_i2c_pm_ops,
+			anx78xx_i2c_suspend, anx78xx_i2c_resume);
+
+static const struct i2c_device_id anx78xx_id[] = {
+	{"anx7814", 0},
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(i2c, anx78xx_id);
+
+static const struct of_device_id anx_match_table[] = {
+	{.compatible = "analogix,anx7814",},
+	{ /* sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, anx_match_table);
+
+static struct i2c_driver anx78xx_driver = {
+	.driver = {
+		   .name = "anx7814",
+		   .pm = &anx78xx_i2c_pm_ops,
+		   .of_match_table = of_match_ptr(anx_match_table),
+		   },
+	.probe = anx78xx_i2c_probe,
+	.remove = anx78xx_i2c_remove,
+	.id_table = anx78xx_id,
+};
+
+module_i2c_driver(anx78xx_driver);
+
+MODULE_DESCRIPTION("Slimport transmitter ANX78XX driver");
+MODULE_AUTHOR("Junhua Xia <jxia at analogixsemi.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.1");
diff --git a/drivers/gpu/drm/i2c/anx78xx/slimport.h b/drivers/gpu/drm/i2c/anx78xx/slimport.h
new file mode 100644
index 0000000..c7cb008
--- /dev/null
+++ b/drivers/gpu/drm/i2c/anx78xx/slimport.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright(c) 2015, Analogix Semiconductor. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _SLIMPORT_H
+#define _SLIMPORT_H
+
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/gpio/consumer.h>
+
+#define AUX_ERR  1
+#define AUX_OK   0
+
+#define LOG_TAG "SlimPort ANX78XX"
+
+struct anx78xx_platform_data {
+	struct gpio_desc *gpiod_pd;
+	struct gpio_desc *gpiod_reset;
+	spinlock_t lock;
+};
+
+struct anx78xx_data {
+	struct i2c_client *client;
+	struct anx78xx_platform_data *pdata;
+	struct delayed_work work;
+	struct workqueue_struct *workqueue;
+	struct mutex lock;
+};
+
+int sp_read_reg(uint8_t slave_addr, uint8_t offset, uint8_t *buf);
+int sp_write_reg(uint8_t slave_addr, uint8_t offset, uint8_t value);
+
+void sp_tx_hardware_poweron(struct anx78xx_data *data);
+void sp_tx_hardware_powerdown(struct anx78xx_data *data);
+
+#endif
diff --git a/drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.c b/drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.c
new file mode 100644
index 0000000..40d7d4a
--- /dev/null
+++ b/drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.c
@@ -0,0 +1,3335 @@
+/*
+ * Copyright(c) 2015, Analogix Semiconductor. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/types.h>
+
+#include "slimport.h"
+#include "slimport_tx_drv.h"
+
+#define XTAL_CLK_M10	pxtal_data[XTAL_27M].xtal_clk_m10
+#define XTAL_CLK	pxtal_data[XTAL_27M].xtal_clk
+
+static u8 sp_tx_test_bw;
+static bool sp_tx_test_lt;
+static bool sp_tx_test_edid;
+
+static u8 g_changed_bandwidth;
+static u8 g_hdmi_dvi_status;
+
+static u8 g_need_clean_status;
+
+static u8 ds_vid_stb_cntr;
+static u8 hdcp_fail_count;
+
+u8 g_edid_break;
+u8 g_edid_checksum;
+u8 edid_blocks[256];
+static u8 g_read_edid_flag;
+
+static struct packet_avi sp_tx_packet_avi;
+static struct packet_spd sp_tx_packet_spd;
+static struct packet_mpeg sp_tx_packet_mpeg;
+static struct audio_info_frame sp_tx_audioinfoframe;
+
+enum sp_tx_state sp_tx_system_state;
+
+enum audio_output_status sp_tx_ao_state;
+enum video_output_status sp_tx_vo_state;
+enum sink_connection_status sp_tx_sc_state;
+enum sp_tx_lt_status sp_tx_lt_state;
+enum sp_tx_state sp_tx_system_state_bak;
+enum hdcp_status hcdp_state;
+
+const uint chipid_list[] = {
+	0x7818,
+	0x7816,
+	0x7814,
+	0x7812,
+	0x7810,
+	0x7806,
+	0x7802
+};
+
+struct common_int common_int_status;
+struct hdmi_rx_int hdmi_rx_int_status;
+
+static u8 down_sample_en;
+
+static u8 sp_i2c_read_byte(u8 dev, u8 offset);
+static void hdmi_rx_new_vsi_int(void);
+
+static void reg_bit_ctl(u8 addr, u8 offset, u8 data, bool enable)
+{
+	u8 c;
+
+	sp_read_reg(addr, offset, &c);
+	if (enable) {
+		if ((c & data) != data) {
+			c |= data;
+			sp_write_reg(addr, offset, c);
+		}
+	} else
+		if ((c & data) == data) {
+			c &= ~data;
+			sp_write_reg(addr, offset, c);
+		}
+}
+
+static inline void sp_write_reg_or(u8 address, u8 offset, u8 mask)
+{
+	sp_write_reg(address, offset,
+		sp_i2c_read_byte(address, offset) | mask);
+}
+
+static inline void sp_write_reg_and(u8 address, u8 offset, u8 mask)
+{
+	sp_write_reg(address, offset,
+		sp_i2c_read_byte(address, offset) & mask);
+}
+
+static inline void sp_write_reg_and_or(u8 address, u8 offset,
+				u8 and_mask, u8 or_mask)
+{
+	sp_write_reg(address, offset,
+		(sp_i2c_read_byte(address, offset) & and_mask) | or_mask);
+}
+
+static inline void sp_write_reg_or_and(u8 address, u8 offset,
+				u8 or_mask, u8 and_mask)
+{
+	sp_write_reg(address, offset,
+		(sp_i2c_read_byte(address, offset) | or_mask) & and_mask);
+}
+
+static inline void sp_tx_video_mute(bool enable)
+{
+	reg_bit_ctl(TX_P2, VID_CTRL1, VIDEO_MUTE, enable);
+}
+
+static inline void hdmi_rx_mute_audio(bool enable)
+{
+	reg_bit_ctl(RX_P0, RX_MUTE_CTRL, AUD_MUTE, enable);
+}
+
+static inline void hdmi_rx_mute_video(bool enable)
+{
+	reg_bit_ctl(RX_P0, RX_MUTE_CTRL, VID_MUTE, enable);
+}
+
+static inline void sp_tx_addronly_set(bool enable)
+{
+	reg_bit_ctl(TX_P0, AUX_CTRL2, ADDR_ONLY_BIT, enable);
+}
+
+static inline void sp_tx_set_link_bw(u8 bw)
+{
+	sp_write_reg(TX_P0, SP_TX_LINK_BW_SET_REG, bw);
+}
+
+
+static inline u8 sp_tx_get_link_bw(void)
+{
+	return sp_i2c_read_byte(TX_P0, SP_TX_LINK_BW_SET_REG);
+}
+
+static inline bool sp_tx_get_pll_lock_status(void)
+{
+	u8 temp;
+
+	temp = sp_i2c_read_byte(TX_P0, TX_DEBUG1);
+
+	return (temp & DEBUG_PLL_LOCK) != 0 ? 1 : 0;
+}
+
+static inline void gen_m_clk_with_downspeading(void)
+{
+	sp_write_reg_or(TX_P0, SP_TX_M_CALCU_CTRL, M_GEN_CLK_SEL);
+}
+
+static inline void gen_m_clk_without_downspeading(void)
+{
+	sp_write_reg_and(TX_P0, SP_TX_M_CALCU_CTRL, (~M_GEN_CLK_SEL));
+}
+
+static inline void hdmi_rx_set_hpd(bool enable)
+{
+	if (enable)
+		sp_write_reg_or(TX_P2, SP_TX_VID_CTRL3_REG, HPD_OUT);
+	else
+		sp_write_reg_and(TX_P2, SP_TX_VID_CTRL3_REG, ~HPD_OUT);
+}
+
+static inline void hdmi_rx_set_termination(bool enable)
+{
+	if (enable)
+		sp_write_reg_and(RX_P0, HDMI_RX_TMDS_CTRL_REG7, ~TERM_PD);
+	else
+		sp_write_reg_or(RX_P0, HDMI_RX_TMDS_CTRL_REG7, TERM_PD);
+}
+
+static inline void sp_tx_clean_hdcp_status(void)
+{
+	sp_write_reg(TX_P0, TX_HDCP_CTRL0, 0x03);
+	sp_write_reg_or(TX_P0, TX_HDCP_CTRL0, RE_AUTH);
+	usleep_range(2000, 4000);
+	pr_info("%s %s : sp_tx_clean_hdcp_status\n", LOG_TAG, __func__);
+}
+
+static inline void sp_tx_link_phy_initialization(void)
+{
+	sp_write_reg(TX_P2, SP_TX_ANALOG_CTRL0, 0x02);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG0, 0x01);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG10, 0x00);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG1, 0x03);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG11, 0x00);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG2, 0x07);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG12, 0x00);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG3, 0x7f);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG13, 0x00);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG4, 0x71);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG14, 0x0c);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG5, 0x6b);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG15, 0x42);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG6, 0x7f);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG16, 0x1e);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG7, 0x73);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG17, 0x3e);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG8, 0x7f);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG18, 0x72);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG9, 0x7F);
+	sp_write_reg(TX_P1, SP_TX_LT_CTRL_REG19, 0x7e);
+}
+
+static inline void sp_tx_set_sys_state(u8 ss)
+{
+	pr_info("%s %s : set: clean_status: %x,\n ",
+			LOG_TAG, __func__, (uint)g_need_clean_status);
+
+	if ((sp_tx_system_state >= STATE_LINK_TRAINING)
+	   && (ss < STATE_LINK_TRAINING))
+		sp_write_reg_or(TX_P0, SP_TX_ANALOG_PD_REG, CH0_PD);
+
+	sp_tx_system_state_bak = sp_tx_system_state;
+	sp_tx_system_state = ss;
+	g_need_clean_status = 1;
+	print_sys_state(sp_tx_system_state);
+}
+
+static inline void reg_hardware_reset(void)
+{
+	sp_write_reg_or(TX_P2, SP_TX_RST_CTRL_REG, HW_RST);
+	sp_tx_clean_state_machine();
+	sp_tx_set_sys_state(STATE_SP_INITIALIZED);
+	msleep(500);
+}
+
+static inline void write_dpcd_addr(u8 addrh, u8 addrm, u8 addrl)
+{
+	u8 temp;
+
+	if (sp_i2c_read_byte(TX_P0, AUX_ADDR_7_0) != addrl)
+		sp_write_reg(TX_P0, AUX_ADDR_7_0, addrl);
+
+	if (sp_i2c_read_byte(TX_P0, AUX_ADDR_15_8) != addrm)
+		sp_write_reg(TX_P0, AUX_ADDR_15_8, addrm);
+
+	sp_read_reg(TX_P0, AUX_ADDR_19_16, &temp);
+
+	if ((temp & 0x0F) != (addrh & 0x0F))
+		sp_write_reg(TX_P0, AUX_ADDR_19_16, (temp  & 0xF0) | addrh);
+}
+
+static inline void goto_next_system_state(void)
+{
+	pr_info("%s %s : next: clean_status: %x,\n ",
+			LOG_TAG, __func__, (uint)g_need_clean_status);
+
+	sp_tx_system_state_bak = sp_tx_system_state;
+	sp_tx_system_state++;
+	print_sys_state(sp_tx_system_state);
+}
+
+static inline void redo_cur_system_state(void)
+{
+	pr_info("%s %s : redo: clean_status: %x,\n ",
+			LOG_TAG, __func__, (uint)g_need_clean_status);
+
+	g_need_clean_status = 1;
+	sp_tx_system_state_bak = sp_tx_system_state;
+	print_sys_state(sp_tx_system_state);
+}
+
+static inline void system_state_change_with_case(u8 status)
+{
+	if (sp_tx_system_state >= status) {
+		pr_info("%s %s : change_case: clean_status: %xm,\n ",
+			LOG_TAG, __func__, (uint)g_need_clean_status);
+
+		if ((sp_tx_system_state >= STATE_LINK_TRAINING)
+				&& (status < STATE_LINK_TRAINING))
+			sp_write_reg_or(TX_P0, SP_TX_ANALOG_PD_REG, CH0_PD);
+
+		g_need_clean_status = 1;
+		sp_tx_system_state_bak = sp_tx_system_state;
+		sp_tx_system_state = status;
+		print_sys_state(sp_tx_system_state);
+	}
+}
+
+static unsigned char sp_i2c_read_byte(unsigned char dev, unsigned char offset)
+{
+	unsigned char temp;
+
+	sp_read_reg(dev, offset, &temp);
+	return temp;
+}
+
+static void hardware_power_ctl(struct anx78xx_data *data, u8 enable)
+{
+	if (enable == 0)
+		sp_tx_hardware_powerdown(data);
+	else
+		sp_tx_hardware_poweron(data);
+}
+
+void wait_aux_op_finish(u8 *err_flag)
+{
+	u8 cnt;
+	u8 c;
+
+	*err_flag = 0;
+	cnt = 150;
+	while (sp_i2c_read_byte(TX_P0, AUX_CTRL2) & AUX_OP_EN) {
+		usleep_range(2000, 4000);
+		if ((cnt--) == 0) {
+			pr_info("%s %s :aux operate failed!\n",
+					LOG_TAG, __func__);
+			*err_flag = 1;
+			break;
+		}
+	}
+
+	sp_read_reg(TX_P0, SP_TX_AUX_STATUS, &c);
+	if (c & 0x0F) {
+		pr_info("%s %s : wait aux operation status %.2x\n",
+				LOG_TAG, __func__, (uint)c);
+		*err_flag = 1;
+	}
+}
+
+void print_sys_state(u8 ss)
+{
+	switch (ss) {
+	case STATE_WAITTING_CABLE_PLUG:
+		pr_info("%s %s : -STATE_WAITTING_CABLE_PLUG-\n",
+				LOG_TAG, __func__);
+		break;
+	case STATE_SP_INITIALIZED:
+		pr_info("%s %s : -STATE_SP_INITIALIZED-\n", LOG_TAG, __func__);
+		break;
+	case STATE_SINK_CONNECTION:
+		pr_info("%s %s : -STATE_SINK_CONNECTION-\n", LOG_TAG, __func__);
+		break;
+	case STATE_PARSE_EDID:
+		pr_info("%s %s : -STATE_PARSE_EDID-\n", LOG_TAG, __func__);
+		break;
+	case STATE_LINK_TRAINING:
+		pr_info("%s %s : -STATE_LINK_TRAINING-\n", LOG_TAG, __func__);
+		break;
+	case STATE_VIDEO_OUTPUT:
+		pr_info("%s %s : -STATE_VIDEO_OUTPUT-\n", LOG_TAG, __func__);
+		break;
+	case STATE_HDCP_AUTH:
+		pr_info("%s %s : -STATE_HDCP_AUTH-\n", LOG_TAG, __func__);
+		break;
+	case STATE_AUDIO_OUTPUT:
+		pr_info("%s %s : -STATE_AUDIO_OUTPUT-\n", LOG_TAG, __func__);
+		break;
+	case STATE_PLAY_BACK:
+		pr_info("%s %s : -STATE_PLAY_BACK-\n", LOG_TAG, __func__);
+		break;
+	default:
+		pr_err("%s %s : system state is error1\n", LOG_TAG, __func__);
+		break;
+	}
+}
+
+void sp_tx_rst_aux(void)
+{
+	sp_write_reg_or(TX_P2, RST_CTRL2, AUX_RST);
+	sp_write_reg_and(TX_P2, RST_CTRL2, ~AUX_RST);
+}
+
+u8 sp_tx_aux_dpcdread_bytes(u8 addrh, u8 addrm,
+		u8 addrl, u8 ccount, u8 *pbuf)
+{
+	u8 c, c1, i;
+	u8 bok;
+
+	sp_write_reg(TX_P0, BUF_DATA_COUNT, 0x80);
+	c = ((ccount - 1) << 4) | 0x09;
+	sp_write_reg(TX_P0, AUX_CTRL, c);
+	write_dpcd_addr(addrh, addrm, addrl);
+	sp_write_reg_or(TX_P0, AUX_CTRL2, AUX_OP_EN);
+	usleep_range(2000, 4000);
+
+	wait_aux_op_finish(&bok);
+	if (bok == AUX_ERR) {
+		pr_err("%s %s : aux read failed\n", LOG_TAG, __func__);
+		sp_read_reg(TX_P2, SP_TX_INT_STATUS1, &c);
+		sp_read_reg(TX_P0, TX_DEBUG1, &c1);
+		if (c1 & POLLING_EN) {
+			if (c & POLLING_ERR)
+				sp_tx_rst_aux();
+		} else
+			sp_tx_rst_aux();
+		return AUX_ERR;
+	}
+
+	for (i = 0; i < ccount; i++) {
+		sp_read_reg(TX_P0, BUF_DATA_0 + i, &c);
+		*(pbuf + i) = c;
+		if (i >= MAX_BUF_CNT)
+			break;
+	}
+	return AUX_OK;
+}
+
+u8 sp_tx_aux_dpcdwrite_bytes(u8 addrh, u8 addrm,
+		u8 addrl, u8 ccount, u8 *pbuf)
+{
+	u8 c, i, ret;
+
+	c =  ((ccount - 1) << 4) | 0x08;
+	sp_write_reg(TX_P0, AUX_CTRL, c);
+	write_dpcd_addr(addrh, addrm, addrl);
+	for (i = 0; i < ccount; i++) {
+		c = *pbuf;
+		pbuf++;
+		sp_write_reg(TX_P0, BUF_DATA_0 + i, c);
+
+		if (i >= 15)
+			break;
+	}
+	sp_write_reg_or(TX_P0, AUX_CTRL2, AUX_OP_EN);
+	wait_aux_op_finish(&ret);
+	return ret;
+}
+
+u8 sp_tx_aux_dpcdwrite_byte(u8 addrh, u8 addrm,
+		u8 addrl, u8 data1)
+{
+	u8 ret;
+
+	sp_write_reg(TX_P0, AUX_CTRL, 0x08);
+	write_dpcd_addr(addrh, addrm, addrl);
+	sp_write_reg(TX_P0, BUF_DATA_0, data1);
+	sp_write_reg_or(TX_P0, AUX_CTRL2, AUX_OP_EN);
+	wait_aux_op_finish(&ret);
+	return ret;
+}
+
+void slimport_block_power_ctrl(enum sp_tx_power_block sp_tx_pd_block,
+		u8 power)
+{
+	if (power == SP_POWER_ON)
+		sp_write_reg_and(TX_P2, SP_POWERD_CTRL_REG, (~sp_tx_pd_block));
+	else
+		sp_write_reg_or(TX_P2, SP_POWERD_CTRL_REG, (sp_tx_pd_block));
+	 pr_info("%s %s : sp_tx_power_on: %.2x\n",
+			LOG_TAG, __func__, (uint)sp_tx_pd_block);
+}
+
+void vbus_power_ctrl(unsigned char on)
+{
+	u8 i;
+
+	if (on == 0) {
+		sp_write_reg_and(TX_P2, TX_PLL_FILTER, ~V33_SWITCH_ON);
+		sp_write_reg_or(TX_P2, TX_PLL_FILTER5,
+					P5V_PROTECT_PD | SHORT_PROTECT_PD);
+		pr_info("%s %s : 3.3V output disabled\n", LOG_TAG, __func__);
+	} else {
+		for (i = 0; i < 5; i++) {
+			sp_write_reg_and(TX_P2, TX_PLL_FILTER5,
+					(~P5V_PROTECT_PD & ~SHORT_PROTECT_PD));
+			sp_write_reg_or(TX_P2, TX_PLL_FILTER, V33_SWITCH_ON);
+			if (!((u8)sp_i2c_read_byte(TX_P2, TX_PLL_FILTER5)
+				& 0xc0)) {
+				pr_info("%s %s : 3.3V output enabled\n",
+						LOG_TAG, __func__);
+				break;
+			}
+
+			pr_info("%s %s : VBUS power can not be supplied\n",
+				LOG_TAG, __func__);
+		}
+	}
+}
+
+void sp_tx_clean_state_machine(void)
+{
+	sp_tx_system_state = STATE_WAITTING_CABLE_PLUG;
+	sp_tx_system_state_bak = STATE_WAITTING_CABLE_PLUG;
+	sp_tx_sc_state = SC_INIT;
+	sp_tx_lt_state = LT_INIT;
+	hcdp_state = HDCP_CAPABLE_CHECK;
+	sp_tx_vo_state = VO_WAIT_VIDEO_STABLE;
+	sp_tx_ao_state = AO_INIT;
+}
+
+u8 sp_tx_cur_states(void)
+{
+	return sp_tx_system_state;
+}
+
+u8 sp_tx_cur_bw(void)
+{
+	return g_changed_bandwidth;
+}
+
+void sp_tx_set_bw(u8 bw)
+{
+	g_changed_bandwidth = bw;
+}
+
+void sp_tx_variable_init(void)
+{
+	uint i;
+
+	sp_tx_system_state = STATE_WAITTING_CABLE_PLUG;
+	sp_tx_system_state_bak = STATE_WAITTING_CABLE_PLUG;
+
+	g_edid_break = 0;
+	g_read_edid_flag = 0;
+	g_edid_checksum = 0;
+	for (i = 0; i < 256; i++)
+		edid_blocks[i] = 0;
+
+	sp_tx_lt_state = LT_INIT;
+	hcdp_state = HDCP_CAPABLE_CHECK;
+	g_need_clean_status = 0;
+	sp_tx_sc_state = SC_INIT;
+	sp_tx_vo_state = VO_WAIT_VIDEO_STABLE;
+	sp_tx_ao_state = AO_INIT;
+	g_changed_bandwidth = LINK_5P4G;
+	g_hdmi_dvi_status = HDMI_MODE;
+
+	sp_tx_test_lt = 0;
+	sp_tx_test_bw = 0;
+	sp_tx_test_edid = 0;
+
+	ds_vid_stb_cntr = 0;
+	hdcp_fail_count = 0;
+
+}
+
+static void hdmi_rx_tmds_phy_initialization(void)
+{
+	sp_write_reg(RX_P0, HDMI_RX_TMDS_CTRL_REG2, 0xa9);
+	sp_write_reg(RX_P0, HDMI_RX_TMDS_CTRL_REG7, 0x80);
+
+	sp_write_reg(RX_P0, HDMI_RX_TMDS_CTRL_REG1, 0x90);
+	sp_write_reg(RX_P0, HDMI_RX_TMDS_CTRL_REG6, 0x92);
+	sp_write_reg(RX_P0, HDMI_RX_TMDS_CTRL_REG20, 0xf2);
+}
+
+void hdmi_rx_initialization(void)
+{
+	sp_write_reg(RX_P0, RX_MUTE_CTRL, AUD_MUTE | VID_MUTE);
+	sp_write_reg_or(RX_P0, RX_CHIP_CTRL,
+		MAN_HDMI5V_DET | PLLLOCK_CKDT_EN | DIGITAL_CKDT_EN);
+
+	sp_write_reg_or(RX_P0, RX_SRST, HDCP_MAN_RST | SW_MAN_RST |
+		TMDS_RST | VIDEO_RST);
+	sp_write_reg_and(RX_P0, RX_SRST, (~HDCP_MAN_RST) & (~SW_MAN_RST) &
+		(~TMDS_RST) & (~VIDEO_RST));
+
+	sp_write_reg_or(RX_P0, RX_AEC_EN0, AEC_EN06 | AEC_EN05);
+	sp_write_reg_or(RX_P0, RX_AEC_EN2, AEC_EN21);
+	sp_write_reg_or(RX_P0, RX_AEC_CTRL, AVC_EN | AAC_OE | AAC_EN);
+
+	sp_write_reg_and(RX_P0, RX_SYS_PWDN1, ~PWDN_CTRL);
+
+	sp_write_reg_or(RX_P0, RX_VID_DATA_RNG, R2Y_INPUT_LIMIT);
+	sp_write_reg(RX_P0, 0x65, 0xc4);
+	sp_write_reg(RX_P0, 0x66, 0x18);
+
+	sp_write_reg(TX_P0, TX_EXTRA_ADDR, 0x50); /* enable DDC stretch */
+
+	hdmi_rx_tmds_phy_initialization();
+	hdmi_rx_set_hpd(0);
+	hdmi_rx_set_termination(0);
+	pr_info("%s %s : HDMI Rx is initialized...\n", LOG_TAG, __func__);
+}
+
+struct clock_data const pxtal_data[XTAL_CLK_NUM] = {
+	{19, 192},
+	{24, 240},
+	{25, 250},
+	{26, 260},
+	{27, 270},
+	{38, 384},
+	{52, 520},
+	{27, 270},
+};
+
+void xtal_clk_sel(void)
+{
+	pr_info("%s %s : define XTAL_CLK:  %x\n ",
+			LOG_TAG, __func__, (uint)XTAL_27M);
+	sp_write_reg_and_or(TX_P2,
+			TX_ANALOG_DEBUG2, (~0x3c), 0x3c & (XTAL_27M << 2));
+	sp_write_reg(TX_P0, 0xEC, (u8)(((uint)XTAL_CLK_M10)));
+	sp_write_reg(TX_P0, 0xED,
+		(u8)(((uint)XTAL_CLK_M10 & 0xFF00) >> 2) | XTAL_CLK);
+
+	sp_write_reg(TX_P0,
+			I2C_GEN_10US_TIMER0, (u8)(((uint)XTAL_CLK_M10)));
+	sp_write_reg(TX_P0, I2C_GEN_10US_TIMER1,
+			(u8)(((uint)XTAL_CLK_M10 & 0xFF00) >> 8));
+	sp_write_reg(TX_P0, 0xBF, (u8)(((uint)XTAL_CLK - 1)));
+
+	sp_write_reg_and_or(RX_P0, 0x49, 0x07,
+			(u8)(((((uint)XTAL_CLK) >> 1) - 2) << 3));
+
+}
+
+void sp_tx_initialization(void)
+{
+	sp_write_reg(TX_P0, AUX_CTRL2, 0x30);
+	sp_write_reg_or(TX_P0, AUX_CTRL2, 0x08);
+
+	sp_write_reg_and(TX_P0, TX_HDCP_CTRL,
+			(u8)(~AUTO_EN) & (~AUTO_START));
+	sp_write_reg(TX_P0, OTP_KEY_PROTECT1, OTP_PSW1);
+	sp_write_reg(TX_P0, OTP_KEY_PROTECT2, OTP_PSW2);
+	sp_write_reg(TX_P0, OTP_KEY_PROTECT3, OTP_PSW3);
+	sp_write_reg_or(TX_P0, HDCP_KEY_CMD, DISABLE_SYNC_HDCP);
+	sp_write_reg(TX_P2, SP_TX_VID_CTRL8_REG, VID_VRES_TH);
+
+	sp_write_reg(TX_P0, HDCP_AUTO_TIMER, HDCP_AUTO_TIMER_VAL);
+	sp_write_reg_or(TX_P0, TX_HDCP_CTRL, LINK_POLLING);
+
+	sp_write_reg_or(TX_P0, TX_LINK_DEBUG, M_VID_DEBUG);
+	sp_write_reg_or(TX_P2, TX_ANALOG_DEBUG2, POWERON_TIME_1P5MS);
+
+	xtal_clk_sel();
+	sp_write_reg(TX_P0, AUX_DEFER_CTRL, 0x8C);
+
+	sp_write_reg_or(TX_P0, TX_DP_POLLING, AUTO_POLLING_DISABLE);
+	/*
+	 * Short the link intergrity check timer to speed up bstatus
+	 * polling for HDCP CTS item 1A-07
+	 */
+	sp_write_reg(TX_P0, SP_TX_LINK_CHK_TIMER, 0x1d);
+	sp_write_reg_or(TX_P0, TX_MISC, EQ_TRAINING_LOOP);
+
+	sp_write_reg_or(TX_P0, SP_TX_ANALOG_PD_REG, CH0_PD);
+
+	sp_write_reg(TX_P2, SP_TX_INT_CTRL_REG, 0X01);
+	/* disable HDCP mismatch function for VGA dongle */
+	sp_tx_link_phy_initialization();
+	gen_m_clk_with_downspeading();
+
+	down_sample_en = 0;
+}
+
+bool slimport_chip_detect(struct anx78xx_data *data)
+{
+	uint16_t id;
+	uint8_t idh = 0, idl = 0;
+	int i;
+
+	hardware_power_ctl(data, 1);
+
+	/* check chip id */
+	sp_read_reg(TX_P2, SP_TX_DEV_IDL_REG, &idl);
+	sp_read_reg(TX_P2, SP_TX_DEV_IDH_REG, &idh);
+	id = idl | (idh << 8);
+
+	pr_info("%s %s : CHIPID: ANX%x\n", LOG_TAG, __func__, id & 0xffff);
+	for (i = 0; i < sizeof(chipid_list) / sizeof(uint16_t); i++) {
+		if (id == chipid_list[i])
+			return 1;
+	}
+	return 0;
+}
+
+void slimport_waitting_cable_plug_process(struct anx78xx_data *data)
+{
+	sp_tx_variable_init();
+	hardware_power_ctl(data, 1);
+	goto_next_system_state();
+}
+
+/*
+ * Check if it is ANALOGIX dongle.
+ */
+unsigned char ANX_OUI[3] = {0x00, 0x22, 0xB9};
+
+unsigned char is_anx_dongle(void)
+{
+	unsigned char buf[3];
+
+	/* 0x0500~0x0502: BRANCH_IEEE_OUI */
+	sp_tx_aux_dpcdread_bytes(0x00, 0x05, 0x00, 3, buf);
+	if (buf[0] == ANX_OUI[0] && buf[1] == ANX_OUI[1]
+	    && buf[2] == ANX_OUI[2])
+		return 1;
+
+	return 0;
+}
+
+void sp_tx_get_rx_bw(unsigned char *bw)
+{
+	u8 data_buf[4];
+	/*
+	 * When ANX dongle connected, if CHIP_ID = 0x7750, bandwidth is 6.75G,
+	 * ecause ANX7750 DPCD 0x052x was not available.
+	 */
+	if (is_anx_dongle()) {
+		sp_tx_aux_dpcdread_bytes(0x00, 0x05, 0x03, 0x04, data_buf);
+		if ((data_buf[0] == 0x37) && (data_buf[1] == 0x37)
+			&& (data_buf[2] == 0x35) && (data_buf[3] == 0x30))
+			*bw = LINK_6P75G;
+		else
+			sp_tx_aux_dpcdread_bytes(0x00, 0x05, 0x21, 1, bw);
+		/* just for Debug */
+		*bw = LINK_6P75G;
+	} else
+		sp_tx_aux_dpcdread_bytes(0x00, 0x00, DPCD_MAX_LINK_RATE, 1, bw);
+}
+
+static u8 sp_tx_get_cable_type(enum cable_type_status det_cable_type_state)
+{
+	u8 ds_port_preset;
+	u8 aux_status;
+	u8 data_buf[16];
+	u8 cur_cable_type;
+
+	ds_port_preset = 0;
+	cur_cable_type = DWN_STRM_IS_NULL;
+
+	aux_status =
+		sp_tx_aux_dpcdread_bytes(0x00, 0x00, 0x05, 1, &ds_port_preset);
+	pr_info("%s %s : DPCD 0x005: %x\n",
+			LOG_TAG, __func__, (int)ds_port_preset);
+
+	switch (det_cable_type_state) {
+	case CHECK_AUXCH:
+		if (AUX_OK == aux_status) {
+			sp_tx_aux_dpcdread_bytes(0x00, 0x00, 0, 0x0c, data_buf);
+			det_cable_type_state = GETTED_CABLE_TYPE;
+		} else {
+			msleep(50);
+			pr_err("%s %s :  AUX access error\n",
+					LOG_TAG, __func__);
+			break;
+		}
+	case GETTED_CABLE_TYPE:
+		switch ((ds_port_preset  & (_BIT1 | _BIT2)) >> 1) {
+		case 0x00:
+			cur_cable_type = DWN_STRM_IS_DIGITAL;
+			pr_info("%s %s : Downstream is DP dongle.\n",
+					LOG_TAG, __func__);
+			break;
+		case 0x01:
+		case 0x03:
+			cur_cable_type = DWN_STRM_IS_ANALOG;
+			pr_info("%s %s : Downstream is VGA dongle.\n",
+					LOG_TAG, __func__);
+			break;
+		case 0x02:
+			cur_cable_type = DWN_STRM_IS_HDMI;
+			pr_info("%s %s : Downstream is HDMI dongle.\n",
+					LOG_TAG, __func__);
+			break;
+		default:
+			cur_cable_type = DWN_STRM_IS_NULL;
+			pr_err("%s %s : Downstream can not recognized.\n",
+					LOG_TAG, __func__);
+			break;
+		}
+	default:
+		break;
+	}
+	return cur_cable_type;
+}
+
+u8 sp_tx_get_hdmi_connection(void)
+{
+	u8 c;
+
+	if (AUX_OK != sp_tx_aux_dpcdread_bytes(0x00, 0x05, 0x18, 1, &c))
+		return 0;
+
+	if ((c & 0x41) == 0x41)
+		return 1;
+	else
+		return 0;
+
+}
+
+u8 sp_tx_get_vga_connection(void)
+{
+	u8 c;
+
+	if (AUX_OK !=
+		sp_tx_aux_dpcdread_bytes(0x00, 0x02, DPCD_SINK_COUNT, 1, &c)) {
+		pr_err("%s %s : aux error.\n", LOG_TAG, __func__);
+		return 0;
+	}
+
+	if (c & 0x01)
+		return 1;
+	else
+		return 0;
+}
+
+u8 sp_tx_get_dp_connection(void)
+{
+	u8 c;
+
+	if (AUX_OK !=
+		sp_tx_aux_dpcdread_bytes(0x00, 0x02, DPCD_SINK_COUNT, 1, &c))
+		return 0;
+
+	if (c & 0x1f) {
+		sp_tx_aux_dpcdread_bytes(0x00, 0x00, 0x04, 1, &c);
+		if (c & 0x20) {
+			sp_tx_aux_dpcdread_bytes(0x00, 0x06, 0x00, 1, &c);
+			/*
+			 * Bit 5 = SET_DN_DEVICE_DP_PWR_5V
+			 * Bit 6 = SET_DN_DEVICE_DP_PWR_12V
+			 * Bit 7 = SET_DN_DEVICE_DP_PWR_18V
+			 */
+			c = c & 0x1F;
+			sp_tx_aux_dpcdwrite_byte(0x00, 0x06, 0x00, c | 0x20);
+		}
+		return 1;
+	} else
+		return 0;
+}
+
+u8 sp_tx_get_downstream_connection(void)
+{
+	return sp_tx_get_dp_connection();
+}
+
+void slimport_sink_connection(void)
+{
+	switch (sp_tx_sc_state) {
+	case SC_INIT:
+		sp_tx_sc_state++;
+	case SC_CHECK_CABLE_TYPE:
+	case SC_WAITTING_CABLE_TYPE:
+	default:
+		if (sp_tx_get_cable_type(CHECK_AUXCH) == DWN_STRM_IS_NULL) {
+			sp_tx_sc_state++;
+			if (sp_tx_sc_state >= SC_WAITTING_CABLE_TYPE) {
+				sp_tx_sc_state = SC_NOT_CABLE;
+				pr_info("%s %s : Can not get cable type!\n",
+						LOG_TAG, __func__);
+			}
+			break;
+		}
+
+		sp_tx_sc_state = SC_SINK_CONNECTED;
+	case SC_SINK_CONNECTED:
+		if (sp_tx_get_downstream_connection())
+			goto_next_system_state();
+		break;
+	case SC_NOT_CABLE:
+		vbus_power_ctrl(0);
+		reg_hardware_reset();
+		break;
+	}
+}
+
+/******************start EDID process********************/
+void sp_tx_enable_video_input(u8 enable)
+{
+	u8 c;
+
+	sp_read_reg(TX_P2, VID_CTRL1, &c);
+	if (enable) {
+		if ((c & VIDEO_EN) != VIDEO_EN) {
+			c = (c & 0xf7) | VIDEO_EN;
+			sp_write_reg(TX_P2, VID_CTRL1, c);
+			pr_info("%s %s : Slimport Video is enabled!\n",
+					LOG_TAG, __func__);
+		}
+	} else {
+		if ((c & VIDEO_EN) == VIDEO_EN) {
+			c &= ~VIDEO_EN;
+			sp_write_reg(TX_P2, VID_CTRL1, c);
+			pr_info("%s %s : Slimport Video is disabled!\n",
+					LOG_TAG, __func__);
+		}
+	}
+}
+
+static u8 read_dvi_hdmi_mode(void)
+{
+	return 1;
+}
+
+static u8 get_edid_detail(u8 *data_buf)
+{
+	uint pixclock_edid;
+
+	pixclock_edid = ((((uint)data_buf[1] << 8))
+			| ((uint)data_buf[0] & 0xFF));
+	if (pixclock_edid <= 5300)
+		return LINK_1P62G;
+	else if ((5300 < pixclock_edid) && (pixclock_edid <= 8900))
+		return LINK_2P7G;
+	else if ((8900 < pixclock_edid) && (pixclock_edid <= 18000))
+		return LINK_5P4G;
+	else
+		return LINK_6P75G;
+}
+
+static u8 parse_edid_to_get_bandwidth(void)
+{
+	u8 desc_offset = 0;
+	u8 i, bandwidth, temp;
+
+	bandwidth = LINK_1P62G;
+	temp = LINK_1P62G;
+	i = 0;
+	while (4 > i && 0 != edid_blocks[0x36 + desc_offset]) {
+		temp = get_edid_detail(edid_blocks + 0x36 + desc_offset);
+		pr_info("%s %s : bandwidth via EDID : %x\n",
+				LOG_TAG, __func__, (uint)temp);
+		if (bandwidth < temp)
+			bandwidth = temp;
+		if (bandwidth > LINK_5P4G)
+			break;
+		desc_offset += 0x12;
+		++i;
+	}
+	return bandwidth;
+
+}
+
+static void sp_tx_aux_wr(u8 offset)
+{
+	sp_write_reg(TX_P0, BUF_DATA_0, offset);
+	sp_write_reg(TX_P0, AUX_CTRL, 0x04);
+	sp_write_reg_or(TX_P0, AUX_CTRL2, AUX_OP_EN);
+	wait_aux_op_finish(&g_edid_break);
+}
+
+static void sp_tx_aux_rd(u8 len_cmd)
+{
+	sp_write_reg(TX_P0, AUX_CTRL, len_cmd);
+	sp_write_reg_or(TX_P0, AUX_CTRL2, AUX_OP_EN);
+	wait_aux_op_finish(&g_edid_break);
+}
+
+u8 sp_tx_get_edid_block(void)
+{
+	u8 c;
+
+	sp_tx_aux_wr(0x7e);
+	sp_tx_aux_rd(0x01);
+	sp_read_reg(TX_P0, BUF_DATA_0, &c);
+	pr_info("%s %s : EDID Block = %d\n", LOG_TAG, __func__, (int)(c + 1));
+
+	if (c > 3)
+		c = 1;
+	return c;
+}
+
+void edid_read(u8 offset, u8 *pblock_buf)
+{
+	u8 data_cnt, cnt;
+	u8 c;
+
+	sp_tx_aux_wr(offset);
+	sp_tx_aux_rd(0xf5);
+	data_cnt = 0;
+	cnt = 0;
+
+	while ((data_cnt) < 16)	{
+		sp_read_reg(TX_P0, BUF_DATA_COUNT, &c);
+
+		if ((c & 0x1f) != 0) {
+			data_cnt = data_cnt + c;
+			do {
+				sp_read_reg(TX_P0, BUF_DATA_0 + c - 1,
+					&(pblock_buf[c - 1]));
+				if (c == 1)
+					break;
+			} while (c--);
+		} else {
+			if (cnt++ <= 2) {
+				sp_tx_rst_aux();
+				c = 0x05 | ((0x0f - data_cnt) << 4);
+				sp_tx_aux_rd(c);
+			} else {
+				 g_edid_break = 1;
+				 break;
+			}
+		}
+	}
+	sp_write_reg(TX_P0, AUX_CTRL, 0x01);
+	sp_write_reg_or(TX_P0, AUX_CTRL2, ADDR_ONLY_BIT | AUX_OP_EN);
+	wait_aux_op_finish(&g_edid_break);
+	sp_tx_addronly_set(0);
+}
+
+void sp_tx_edid_read_initial(void)
+{
+	sp_write_reg(TX_P0, AUX_ADDR_7_0, 0x50);
+	sp_write_reg(TX_P0, AUX_ADDR_15_8, 0);
+	sp_write_reg_and(TX_P0, AUX_ADDR_19_16, 0xf0);
+}
+
+static void segments_edid_read(u8 segment, u8 offset)
+{
+	u8 c, cnt;
+	int i;
+
+	sp_write_reg(TX_P0, AUX_CTRL, 0x04);
+
+	sp_write_reg(TX_P0, AUX_ADDR_7_0, 0x30);
+
+	sp_write_reg_or(TX_P0, AUX_CTRL2, ADDR_ONLY_BIT | AUX_OP_EN);
+
+	sp_read_reg(TX_P0, AUX_CTRL2, &c);
+
+	wait_aux_op_finish(&g_edid_break);
+	sp_read_reg(TX_P0, AUX_CTRL, &c);
+
+	sp_write_reg(TX_P0, BUF_DATA_0, segment);
+
+	sp_write_reg(TX_P0, AUX_CTRL, 0x04);
+
+	sp_write_reg_and_or(TX_P0, AUX_CTRL2, ~ADDR_ONLY_BIT, AUX_OP_EN);
+	cnt = 0;
+	sp_read_reg(TX_P0, AUX_CTRL2, &c);
+	while (c & AUX_OP_EN) {
+		usleep_range(1000, 2000);
+		cnt++;
+		if (cnt == 10) {
+			pr_info("%s %s : write break", LOG_TAG, __func__);
+			sp_tx_rst_aux();
+			cnt = 0;
+			g_edid_break = 1;
+			return;
+		}
+		sp_read_reg(TX_P0, AUX_CTRL2, &c);
+
+	}
+
+	sp_write_reg(TX_P0, AUX_ADDR_7_0, 0x50);
+
+	sp_tx_aux_wr(offset);
+
+	sp_tx_aux_rd(0xf5);
+	cnt = 0;
+	for (i = 0; i < 16; i++) {
+		sp_read_reg(TX_P0, BUF_DATA_COUNT, &c);
+		while ((c & 0x1f) == 0) {
+			usleep_range(2000, 4000);
+			cnt++;
+			sp_read_reg(TX_P0, BUF_DATA_COUNT, &c);
+			if (cnt == 10) {
+				pr_info("%s %s : read break",
+						LOG_TAG, __func__);
+				sp_tx_rst_aux();
+				g_edid_break = 1;
+				return;
+			}
+		}
+
+
+		sp_read_reg(TX_P0, BUF_DATA_0+i, &c);
+	}
+
+	sp_write_reg(TX_P0, AUX_CTRL, 0x01);
+	sp_write_reg_or(TX_P0, AUX_CTRL2, ADDR_ONLY_BIT | AUX_OP_EN);
+	sp_write_reg_and(TX_P0, AUX_CTRL2, ~ADDR_ONLY_BIT);
+	sp_read_reg(TX_P0, AUX_CTRL2, &c);
+	while (c & AUX_OP_EN)
+		sp_read_reg(TX_P0, AUX_CTRL2, &c);
+}
+
+static bool edid_checksum_result(u8 *pbuf)
+{
+	u8 cnt, checksum;
+
+	checksum = 0;
+
+	for (cnt = 0; cnt < 0x80; cnt++)
+		checksum = checksum + pbuf[cnt];
+
+	g_edid_checksum = checksum - pbuf[0x7f];
+	g_edid_checksum = ~g_edid_checksum + 1;
+
+	return checksum == 0 ? 1 : 0;
+}
+
+static void edid_header_result(u8 *pbuf)
+{
+	 if ((pbuf[0] == 0) && (pbuf[7] == 0) && (pbuf[1] == 0xff)
+		&& (pbuf[2] == 0xff) && (pbuf[3] == 0xff)
+		&& (pbuf[4] == 0xff) && (pbuf[5] == 0xff) && (pbuf[6] == 0xff))
+		pr_info("%s %s : Good EDID header!\n", LOG_TAG, __func__);
+	 else
+		pr_err("%s %s : Bad EDID header!\n", LOG_TAG, __func__);
+
+}
+
+void check_edid_data(u8 *pblock_buf)
+{
+	u8 i;
+
+	edid_header_result(pblock_buf);
+	for (i = 0; i <= ((pblock_buf[0x7e] > 1) ? 1 : pblock_buf[0x7e]); i++) {
+		if (!edid_checksum_result(pblock_buf + i * 128))
+			pr_err("%s %s : Block %x edid checksum error\n",
+					LOG_TAG, __func__, (uint)i);
+		else
+			pr_info("%s %s : Block %x edid checksum OK\n",
+					LOG_TAG, __func__, (uint)i);
+	}
+}
+
+bool sp_tx_edid_read(u8 *pedid_blocks_buf)
+{
+	u8 offset = 0;
+	u8 count, blocks_num;
+	u8 pblock_buf[16];
+	u8 i, j, c;
+
+	g_edid_break = 0;
+	sp_tx_edid_read_initial();
+	sp_write_reg(TX_P0, AUX_CTRL, 0x04);
+	sp_write_reg_or(TX_P0, AUX_CTRL2, 0x03);
+	wait_aux_op_finish(&g_edid_break);
+	sp_tx_addronly_set(0);
+
+	blocks_num = sp_tx_get_edid_block();
+
+	count = 0;
+	do {
+		switch (count) {
+		case 0:
+		case 1:
+			for (i = 0; i < 8; i++) {
+				offset = (i + count * 8) * 16;
+				edid_read(offset, pblock_buf);
+				if (g_edid_break == 1)
+					break;
+				for (j = 0; j < 16; j++) {
+					pedid_blocks_buf[offset + j]
+						= pblock_buf[j];
+				}
+			}
+			break;
+		case 2:
+			offset = 0x00;
+			for (j = 0; j < 8; j++) {
+				if (g_edid_break == 1)
+					break;
+				segments_edid_read(count / 2, offset);
+				offset = offset + 0x10;
+			}
+			break;
+		case 3:
+			offset = 0x80;
+			for (j = 0; j < 8; j++) {
+				if (g_edid_break == 1)
+					break;
+				segments_edid_read(count / 2, offset);
+				offset = offset + 0x10;
+			}
+			break;
+		default:
+			break;
+		}
+		count++;
+		if (g_edid_break == 1)
+			break;
+	} while (blocks_num >= count);
+
+	sp_tx_rst_aux();
+	if (g_read_edid_flag == 0) {
+		check_edid_data(pedid_blocks_buf);
+		g_read_edid_flag = 1;
+	}
+	sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x18, 1, &c);
+	if (c & 0x04) {
+		pr_info("%s %s : check sum = %.2x\n",
+				LOG_TAG, __func__,  (uint)g_edid_checksum);
+		c = g_edid_checksum;
+		sp_tx_aux_dpcdwrite_bytes(0x00, 0x02, 0x61, 1, &c);
+		sp_tx_test_edid = 1;
+		c = 0x04;
+		sp_tx_aux_dpcdwrite_bytes(0x00, 0x02, 0x60, 1, &c);
+		pr_info("%s %s : Test EDID done\n", LOG_TAG, __func__);
+
+	}
+
+	return 0;
+}
+
+static bool check_with_pre_edid(u8 *org_buf)
+{
+	u8 i;
+	u8 temp_buf[16];
+	bool return_flag;
+
+	return_flag = 0;
+	g_edid_break = 0;
+	sp_tx_edid_read_initial();
+	sp_write_reg(TX_P0, AUX_CTRL, 0x04);
+	sp_write_reg_or(TX_P0, AUX_CTRL2, 0x03);
+	wait_aux_op_finish(&g_edid_break);
+	sp_tx_addronly_set(0);
+
+	edid_read(0x70, temp_buf);
+
+	if (g_edid_break == 0) {
+
+		for (i = 0; i < 16; i++) {
+			if (org_buf[0x70 + i] != temp_buf[i]) {
+				pr_info("%s %s : %s\n", LOG_TAG, __func__,
+					"different checksum and blocks num\n");
+				return_flag = 1;
+				break;
+			}
+		}
+	} else
+		return_flag = 1;
+
+	if (return_flag)
+		goto return_point;
+
+	edid_read(0x08, temp_buf);
+	if (g_edid_break == 0) {
+		for (i = 0; i < 16; i++) {
+			if (org_buf[i + 8] != temp_buf[i]) {
+				pr_info("%s %s : different edid information\n",
+						LOG_TAG, __func__);
+				return_flag = 1;
+				break;
+			}
+		}
+	} else
+		return_flag = 1;
+
+return_point:
+	sp_tx_rst_aux();
+	return return_flag;
+}
+
+void slimport_edid_process(void)
+{
+	u8 temp_value, temp_value1;
+	u8 i;
+
+	pr_info("%s %s : edid_process\n", LOG_TAG, __func__);
+
+	if (g_read_edid_flag == 1) {
+		if (check_with_pre_edid(edid_blocks))
+			g_read_edid_flag = 0;
+		else
+			pr_info("%s %s : Don`t need to read edid!\n",
+					LOG_TAG, __func__);
+	}
+
+	if (g_read_edid_flag == 0) {
+		sp_tx_edid_read(edid_blocks);
+		if (g_edid_break)
+			pr_err("%s %s : ERR:EDID corruption!\n",
+					LOG_TAG, __func__);
+	}
+
+
+	/* Release the HPD after the OTP loaddown */
+	i = 10;
+	do {
+		if ((sp_i2c_read_byte(TX_P0, HDCP_KEY_STATUS) & 0x01))
+			break;
+
+		pr_info("%s %s : waiting HDCP KEY loaddown\n",
+				LOG_TAG, __func__);
+		usleep_range(1000, 2000);
+	} while (--i);
+	sp_write_reg(RX_P0, HDMI_RX_INT_MASK1_REG, 0xe2);
+	hdmi_rx_set_hpd(1);
+	pr_info("%s %s : hdmi_rx_set_hpd 1 !\n", LOG_TAG, __func__);
+	hdmi_rx_set_termination(1);
+
+	sp_tx_get_rx_bw(&temp_value);
+	pr_info("%s %s : RX BW %x\n", LOG_TAG, __func__, (uint)temp_value);
+	temp_value1 = parse_edid_to_get_bandwidth();
+	if (temp_value <= temp_value1)
+		temp_value1 = temp_value;
+	pr_info("%s %s : set link bw in edid %x\n",
+			LOG_TAG, __func__, (uint)temp_value1);
+	g_changed_bandwidth = temp_value1;
+	goto_next_system_state();
+}
+/******************End EDID process********************/
+
+/******************start Link training process********************/
+static void sp_tx_lvttl_bit_mapping(void)
+{
+	u8 c, colorspace;
+	u8 vid_bit;
+
+	vid_bit = 0;
+	sp_read_reg(RX_P1, HDMI_RX_AVI_DATA00_REG, &colorspace);
+	colorspace &= 0x60;
+
+	switch (((sp_i2c_read_byte(RX_P0, HDMI_RX_VIDEO_STATUS_REG1)
+		& COLOR_DEPTH) >> 4)) {
+	default:
+	case HDMI_LEGACY:
+		c = IN_BPC_8BIT;
+		vid_bit = 0;
+		break;
+	case HDMI_24BIT:
+		c = IN_BPC_8BIT;
+		if (colorspace == 0x20)
+			vid_bit = 5;
+		else
+			vid_bit = 1;
+		break;
+	case HDMI_30BIT:
+		c = IN_BPC_10BIT;
+		if (colorspace == 0x20)
+			vid_bit = 6;
+		else
+			vid_bit = 2;
+		break;
+	case HDMI_36BIT:
+		c = IN_BPC_12BIT;
+		if (colorspace == 0x20)
+			vid_bit = 6;
+		else
+			vid_bit = 3;
+		break;
+
+	}
+	/*
+	 * For down sample video (12bit, 10bit ---> 8bit),
+	 * this register don`t change
+	 */
+	if (down_sample_en == 0)
+		sp_write_reg_and_or(TX_P2,
+			SP_TX_VID_CTRL2_REG, 0x8c, colorspace >> 5 | c);
+
+	/* Patch: for 10bit video must be set this value to 12bit by someone */
+	if (down_sample_en == 1 && c == IN_BPC_10BIT)
+		vid_bit = 3;
+
+	sp_write_reg_and_or(TX_P2,
+		BIT_CTRL_SPECIFIC, 0x00, ENABLE_BIT_CTRL | vid_bit << 1);
+
+	if (sp_tx_test_edid) {
+		sp_write_reg_and(TX_P2, SP_TX_VID_CTRL2_REG, 0x8f);
+		pr_info("%s %s : ***color space is set to 18bit***\n",
+				LOG_TAG, __func__);
+	}
+
+	if (colorspace) {
+		sp_write_reg(TX_P0, SP_TX_VID_BLANK_SET1, 0x80);
+		sp_write_reg(TX_P0, SP_TX_VID_BLANK_SET2, 0x00);
+		sp_write_reg(TX_P0, SP_TX_VID_BLANK_SET3, 0x80);
+	} else {
+		sp_write_reg(TX_P0, SP_TX_VID_BLANK_SET1, 0x0);
+		sp_write_reg(TX_P0, SP_TX_VID_BLANK_SET2, 0x0);
+		sp_write_reg(TX_P0, SP_TX_VID_BLANK_SET3, 0x0);
+	}
+}
+
+ulong sp_tx_pclk_calc(void)
+{
+	ulong str_plck;
+	uint vid_counter;
+	u8 c;
+
+	sp_read_reg(RX_P0, 0x8d, &c);
+	vid_counter = c;
+	vid_counter = vid_counter << 8;
+	sp_read_reg(RX_P0, 0x8c, &c);
+	vid_counter |= c;
+	str_plck = ((ulong)vid_counter * XTAL_CLK_M10)  >> 12;
+	pr_info("%s %s : PCLK = %d.%d\n",
+		LOG_TAG, __func__, (((uint)(str_plck))/10),
+		((uint)str_plck - (((uint)str_plck/10)*10)));
+	return str_plck;
+}
+
+static u8 sp_tx_bw_lc_sel(ulong pclk)
+{
+	ulong pixel_clk;
+	u8 c1;
+
+	switch (((sp_i2c_read_byte(RX_P0, HDMI_RX_VIDEO_STATUS_REG1)
+		& COLOR_DEPTH) >> 4)) {
+	case HDMI_LEGACY:
+	case HDMI_24BIT:
+	default:
+		pixel_clk = pclk;
+		break;
+	case HDMI_30BIT:
+		pixel_clk = (pclk * 5) >> 2;
+		break;
+	case HDMI_36BIT:
+		pixel_clk = (pclk * 3) >> 1;
+		break;
+	}
+	pr_info("%s %s : pixel_clk = %d.%d\n",
+		LOG_TAG, __func__, (((uint)(pixel_clk))/10),
+		((uint)pixel_clk - (((uint)pixel_clk/10)*10)));
+
+	down_sample_en = 0;
+	if (pixel_clk <= 530)
+		c1 = LINK_1P62G;
+	else if ((530 < pixel_clk) && (pixel_clk <= 890))
+		c1 = LINK_2P7G;
+	else if ((890 < pixel_clk) && (pixel_clk <= 1800))
+		c1 = LINK_5P4G;
+	else {
+		 c1 = LINK_6P75G;
+		 if (pixel_clk > 2240)
+			down_sample_en = 1;
+	}
+
+	if (sp_tx_get_link_bw() != c1) {
+		g_changed_bandwidth = c1;
+		pr_info("%s %s : %s! %.2x\n", LOG_TAG, __func__,
+		    "different bandwidth between sink support and cur video",
+		    (uint)c1);
+		return 1;
+	}
+	return 0;
+}
+
+void sp_tx_spread_enable(u8 benable)
+{
+	u8 c;
+
+	sp_read_reg(TX_P0, SP_TX_DOWN_SPREADING_CTRL1, &c);
+
+	if (benable) {
+		c |= SP_TX_SSC_DWSPREAD;
+		sp_write_reg(TX_P0, SP_TX_DOWN_SPREADING_CTRL1, c);
+
+		sp_tx_aux_dpcdread_bytes(0x00, 0x01,
+			DPCD_DOWNSPREAD_CTRL, 1, &c);
+		c |= SPREAD_AMPLITUDE;
+		sp_tx_aux_dpcdwrite_byte(0x00, 0x01, DPCD_DOWNSPREAD_CTRL, c);
+
+	} else {
+		c &= ~SP_TX_SSC_DISABLE;
+		sp_write_reg(TX_P0, SP_TX_DOWN_SPREADING_CTRL1, c);
+
+		sp_tx_aux_dpcdread_bytes(0x00, 0x01,
+			DPCD_DOWNSPREAD_CTRL, 1, &c);
+		c &= ~SPREAD_AMPLITUDE;
+		sp_tx_aux_dpcdwrite_byte(0x00, 0x01, DPCD_DOWNSPREAD_CTRL, c);
+	}
+
+}
+
+void sp_tx_config_ssc(enum sp_ssc_dep sscdep)
+{
+	sp_write_reg(TX_P0, SP_TX_DOWN_SPREADING_CTRL1, 0x0);
+	sp_write_reg(TX_P0, SP_TX_DOWN_SPREADING_CTRL1, sscdep);
+	sp_tx_spread_enable(1);
+}
+
+void sp_tx_enhancemode_set(void)
+{
+	u8 c;
+
+	sp_tx_aux_dpcdread_bytes(0x00, 0x00, DPCD_MAX_LANE_COUNT, 1, &c);
+	if (c & ENHANCED_FRAME_CAP) {
+		sp_write_reg_or(TX_P0, SP_TX_SYS_CTRL4_REG, ENHANCED_MODE);
+
+		sp_tx_aux_dpcdread_bytes(0x00, 0x01,
+			DPCD_LANE_COUNT_SET, 1, &c);
+		c |= ENHANCED_FRAME_EN;
+		sp_tx_aux_dpcdwrite_byte(0x00, 0x01,
+			DPCD_LANE_COUNT_SET, c);
+
+		pr_info("%s %s : Enhance mode enabled\n", LOG_TAG, __func__);
+	} else {
+
+		sp_write_reg_and(TX_P0, SP_TX_SYS_CTRL4_REG, ~ENHANCED_MODE);
+
+		sp_tx_aux_dpcdread_bytes(0x00, 0x01,
+			DPCD_LANE_COUNT_SET, 1, &c);
+		c &= ~ENHANCED_FRAME_EN;
+		sp_tx_aux_dpcdwrite_byte(0x00, 0x01,
+			DPCD_LANE_COUNT_SET, c);
+
+		pr_info("%s %s : Enhance mode disabled\n", LOG_TAG, __func__);
+	}
+}
+
+uint sp_tx_link_err_check(void)
+{
+	uint errl = 0, errh = 0;
+	u8 bytebuf[2];
+
+	sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x10, 2, bytebuf);
+	usleep_range(5000, 10000);
+	sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x10, 2, bytebuf);
+	errh = bytebuf[1];
+
+	if (errh & 0x80) {
+		errl = bytebuf[0];
+		errh = (errh & 0x7f) << 8;
+		errl = errh + errl;
+	}
+
+	pr_err("%s %s :  Err of Lane = %d\n", LOG_TAG, __func__, errl);
+	return errl;
+}
+
+static inline void sp_lt_finish(u8 temp_value)
+{
+	sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x02, 1, &temp_value);
+	if ((temp_value & 0x07) == 0x07) {
+		/*
+		 * if there is link error,
+		 * adjust pre-emphsis to check error again.
+		 * If there is no error,keep the setting,
+		 * otherwise use 400mv0db
+		 */
+		if (!sp_tx_test_lt) {
+			if (sp_tx_link_err_check()) {
+				sp_read_reg(TX_P0,
+					SP_TX_LT_SET_REG, &temp_value);
+				if (!(temp_value & MAX_PRE_REACH)) {
+					sp_write_reg(TX_P0,
+						SP_TX_LT_SET_REG,
+						(temp_value + 0x08));
+					if (sp_tx_link_err_check())
+						sp_write_reg(TX_P0,
+						SP_TX_LT_SET_REG,
+						temp_value);
+				}
+			}
+
+			sp_read_reg(TX_P0,
+				SP_TX_LINK_BW_SET_REG, &temp_value);
+			if (temp_value == g_changed_bandwidth) {
+				pr_info("%s %s : LT succeed, bw: %.2x",
+					LOG_TAG, __func__,
+					(uint) temp_value);
+				pr_info("Lane0 Set: %.2x\n",
+					(uint) sp_i2c_read_byte(TX_P0,
+						SP_TX_LT_SET_REG));
+				sp_tx_lt_state = LT_INIT;
+				goto_next_system_state();
+			} else {
+				pr_info("%s %s : cur:%.2x, per:%.2x\n",
+					LOG_TAG, __func__,
+					(uint)temp_value,
+					(uint)g_changed_bandwidth);
+				sp_tx_lt_state = LT_ERROR;
+			}
+		} else {
+			sp_tx_test_lt = 0;
+			sp_tx_lt_state = LT_INIT;
+			goto_next_system_state();
+		}
+	} else {
+		pr_info("%s %s : LANE0 Status error: %.2x\n",
+			LOG_TAG, __func__, (uint)(temp_value & 0x07));
+		sp_tx_lt_state = LT_ERROR;
+	}
+}
+
+void slimport_link_training(void)
+{
+	u8 temp_value, return_value, c;
+
+	return_value = 1;
+	pr_info("%s %s : sp_tx_lt_state : %x\n",
+			LOG_TAG, __func__, (int)sp_tx_lt_state);
+	switch (sp_tx_lt_state) {
+	case LT_INIT:
+		slimport_block_power_ctrl(SP_TX_PWR_VIDEO, SP_POWER_ON);
+		sp_tx_video_mute(1);
+		sp_tx_enable_video_input(0);
+		sp_tx_lt_state++;
+	/* fallthrough */
+	case LT_WAIT_PLL_LOCK:
+		if (!sp_tx_get_pll_lock_status()) {
+			sp_read_reg(TX_P0, SP_TX_PLL_CTRL_REG, &temp_value);
+			temp_value |= PLL_RST;
+			sp_write_reg(TX_P0, SP_TX_PLL_CTRL_REG, temp_value);
+			temp_value &= ~PLL_RST;
+			sp_write_reg(TX_P0, SP_TX_PLL_CTRL_REG, temp_value);
+			pr_info("%s %s : PLL not lock!\n", LOG_TAG, __func__);
+		} else
+			sp_tx_lt_state = LT_CHECK_LINK_BW;
+		SP_BREAK(LT_WAIT_PLL_LOCK, sp_tx_lt_state);
+	/* fallthrough */
+	case LT_CHECK_LINK_BW:
+		sp_tx_get_rx_bw(&temp_value);
+		if (temp_value < g_changed_bandwidth) {
+			pr_info("%s %s : ****Over bandwidth****\n",
+				LOG_TAG, __func__);
+			g_changed_bandwidth = temp_value;
+		} else
+			sp_tx_lt_state++;
+	/* fallthrough */
+	case LT_START:
+		if (sp_tx_test_lt) {
+			g_changed_bandwidth = sp_tx_test_bw;
+			sp_write_reg_and(TX_P2, SP_TX_VID_CTRL2_REG, 0x8f);
+		} else
+			sp_write_reg(TX_P0, SP_TX_LT_SET_REG, 0x00);
+
+		sp_write_reg_and(TX_P0, SP_TX_ANALOG_PD_REG, ~CH0_PD);
+
+		sp_tx_config_ssc(SSC_DEP_4000PPM);
+		sp_tx_set_link_bw(g_changed_bandwidth);
+		sp_tx_enhancemode_set();
+
+		sp_tx_aux_dpcdread_bytes(0x00, 0x00, 0x00, 0x01, &c);
+		sp_tx_aux_dpcdread_bytes(0x00, 0x06, 0x00, 0x01, &temp_value);
+		if (c >= 0x12)
+			temp_value &= 0xf8;
+		else
+			temp_value &= 0xfc;
+		temp_value |= 0x01;
+		sp_tx_aux_dpcdwrite_byte(0x00, 0x06, 0x00, temp_value);
+
+
+		sp_write_reg(TX_P0, LT_CTRL, SP_TX_LT_EN);
+		sp_tx_lt_state = LT_WAITTING_FINISH;
+	/* fallthrough */
+	case LT_WAITTING_FINISH:
+		/* here : waiting interrupt to change training state. */
+		break;
+
+	case LT_ERROR:
+		sp_write_reg_or(TX_P2, RST_CTRL2, SERDES_FIFO_RST);
+		msleep(20);
+		sp_write_reg_and(TX_P2, RST_CTRL2, (~SERDES_FIFO_RST));
+		pr_err("LT ERROR Status: SERDES FIFO reset.");
+		redo_cur_system_state();
+		sp_tx_lt_state = LT_INIT;
+		break;
+
+	case LT_FINISH:
+		sp_lt_finish(temp_value);
+		break;
+	default:
+		break;
+	}
+
+}
+/******************End Link training process********************/
+
+/******************Start Output video process********************/
+void sp_tx_set_colorspace(void)
+{
+	u8 color_space;
+
+	if (down_sample_en) {
+		sp_read_reg(RX_P1, HDMI_RX_AVI_DATA00_REG, &color_space);
+		color_space &= 0x60;
+		if (color_space == 0x20) {
+			pr_info("%s %s : YCbCr4:2:2 ---> PASS THROUGH.\n",
+				LOG_TAG, __func__);
+			sp_write_reg(TX_P2, SP_TX_VID_CTRL6_REG, 0x00);
+			sp_write_reg(TX_P2, SP_TX_VID_CTRL5_REG, 0x00);
+			sp_write_reg(TX_P2, SP_TX_VID_CTRL2_REG, 0x11);
+		} else if (color_space == 0x40) {
+			pr_info("%s %s : YCbCr4:4:4 ---> YCbCr4:2:2\n",
+				LOG_TAG, __func__);
+			sp_write_reg(TX_P2, SP_TX_VID_CTRL6_REG, 0x41);
+			sp_write_reg(TX_P2, SP_TX_VID_CTRL5_REG, 0x00);
+			sp_write_reg(TX_P2, SP_TX_VID_CTRL2_REG, 0x12);
+		} else if (color_space == 0x00) {
+			pr_info("%s %s : RGB4:4:4 ---> YCbCr4:2:2\n",
+				LOG_TAG, __func__);
+			sp_write_reg(TX_P2, SP_TX_VID_CTRL6_REG, 0x41);
+			sp_write_reg(TX_P2, SP_TX_VID_CTRL5_REG, 0x83);
+			sp_write_reg(TX_P2, SP_TX_VID_CTRL2_REG, 0x10);
+		}
+	} else {
+		sp_write_reg(TX_P2, SP_TX_VID_CTRL6_REG, 0x00);
+		sp_write_reg(TX_P2, SP_TX_VID_CTRL5_REG, 0x00);
+	}
+}
+
+void sp_tx_avi_setup(void)
+{
+	u8 c;
+	int i;
+
+	for (i = 0; i < 13; i++) {
+		sp_read_reg(RX_P1, (HDMI_RX_AVI_DATA00_REG + i), &c);
+		sp_tx_packet_avi.avi_data[i] = c;
+	}
+}
+
+static void sp_tx_load_packet(enum packets_type type)
+{
+	int i;
+	u8 c;
+
+	switch (type) {
+	case AVI_PACKETS:
+		sp_write_reg(TX_P2, SP_TX_AVI_TYPE, 0x82);
+		sp_write_reg(TX_P2, SP_TX_AVI_VER, 0x02);
+		sp_write_reg(TX_P2, SP_TX_AVI_LEN, 0x0d);
+
+		for (i = 0; i < 13; i++) {
+			sp_write_reg(TX_P2, SP_TX_AVI_DB0 + i,
+					sp_tx_packet_avi.avi_data[i]);
+		}
+
+		break;
+
+	case SPD_PACKETS:
+		sp_write_reg(TX_P2, SP_TX_SPD_TYPE, 0x83);
+		sp_write_reg(TX_P2, SP_TX_SPD_VER, 0x01);
+		sp_write_reg(TX_P2, SP_TX_SPD_LEN, 0x19);
+
+		for (i = 0; i < 25; i++) {
+			sp_write_reg(TX_P2, SP_TX_SPD_DB0 + i,
+					sp_tx_packet_spd.spd_data[i]);
+		}
+
+		break;
+
+	case VSI_PACKETS:
+		sp_write_reg(TX_P2, SP_TX_MPEG_TYPE, 0x81);
+		sp_write_reg(TX_P2, SP_TX_MPEG_VER, 0x01);
+		sp_read_reg(RX_P1, HDMI_RX_MPEG_LEN_REG, &c);
+		sp_write_reg(TX_P2, SP_TX_MPEG_LEN, c);
+
+		for (i = 0; i < 10; i++) {
+			sp_write_reg(TX_P2, SP_TX_MPEG_DB0 + i,
+					sp_tx_packet_mpeg.mpeg_data[i]);
+		}
+
+		break;
+	case MPEG_PACKETS:
+		sp_write_reg(TX_P2, SP_TX_MPEG_TYPE, 0x85);
+		sp_write_reg(TX_P2, SP_TX_MPEG_VER, 0x01);
+		sp_write_reg(TX_P2, SP_TX_MPEG_LEN, 0x0d);
+
+		for (i = 0; i < 10; i++) {
+			sp_write_reg(TX_P2, SP_TX_MPEG_DB0 + i,
+					sp_tx_packet_mpeg.mpeg_data[i]);
+		}
+
+		break;
+	case AUDIF_PACKETS:
+		sp_write_reg(TX_P2, SP_TX_AUD_TYPE, 0x84);
+		sp_write_reg(TX_P2, SP_TX_AUD_VER, 0x01);
+		sp_write_reg(TX_P2, SP_TX_AUD_LEN, 0x0a);
+		for (i = 0; i < 10; i++) {
+			sp_write_reg(TX_P2, SP_TX_AUD_DB0 + i,
+					sp_tx_audioinfoframe.pb_byte[i]);
+		}
+
+		break;
+
+	default:
+		break;
+	}
+}
+
+void sp_tx_config_packets(enum packets_type type)
+{
+	u8 c;
+
+	switch (type) {
+	case AVI_PACKETS:
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c &= ~AVI_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+		sp_tx_load_packet(AVI_PACKETS);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |= AVI_IF_UD;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |= AVI_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		break;
+
+	case SPD_PACKETS:
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c &= ~SPD_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+		sp_tx_load_packet(SPD_PACKETS);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |= SPD_IF_UD;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |=  SPD_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		break;
+
+	case VSI_PACKETS:
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c &= ~MPEG_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		sp_tx_load_packet(VSI_PACKETS);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |= MPEG_IF_UD;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |= MPEG_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		break;
+	case MPEG_PACKETS:
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c &= ~MPEG_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+
+		sp_tx_load_packet(MPEG_PACKETS);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |= MPEG_IF_UD;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |= MPEG_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		break;
+	case AUDIF_PACKETS:
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c &= ~AUD_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+
+		sp_tx_load_packet(AUDIF_PACKETS);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |= AUD_IF_UP;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		sp_read_reg(TX_P0, SP_TX_PKT_EN_REG, &c);
+		c |= AUD_IF_EN;
+		sp_write_reg(TX_P0, SP_TX_PKT_EN_REG, c);
+
+		break;
+
+	default:
+		break;
+	}
+
+}
+
+void slimport_config_video_output(void)
+{
+	u8 temp_value;
+
+	switch (sp_tx_vo_state) {
+	default:
+	case VO_WAIT_VIDEO_STABLE:
+		sp_read_reg(RX_P0, HDMI_RX_SYS_STATUS_REG, &temp_value);
+		if ((temp_value & (TMDS_DE_DET | TMDS_CLOCK_DET)) == 0x03) {
+			sp_tx_bw_lc_sel(sp_tx_pclk_calc());
+			sp_tx_enable_video_input(0);
+			sp_tx_avi_setup();
+			sp_tx_config_packets(AVI_PACKETS);
+			sp_tx_set_colorspace();
+			sp_tx_lvttl_bit_mapping();
+			if (sp_i2c_read_byte(RX_P0, RX_PACKET_REV_STA)
+			& VSI_RCVD)
+				hdmi_rx_new_vsi_int();
+			sp_tx_enable_video_input(1);
+			sp_tx_vo_state = VO_WAIT_TX_VIDEO_STABLE;
+		} else
+			pr_info("%s %s :HDMI input video not stable!\n",
+					LOG_TAG, __func__);
+		SP_BREAK(VO_WAIT_VIDEO_STABLE, sp_tx_vo_state);
+	/* fallthrough */
+	case VO_WAIT_TX_VIDEO_STABLE:
+		sp_read_reg(TX_P0, SP_TX_SYS_CTRL2_REG, &temp_value);
+		sp_write_reg(TX_P0, SP_TX_SYS_CTRL2_REG, temp_value);
+		sp_read_reg(TX_P0, SP_TX_SYS_CTRL2_REG, &temp_value);
+		if (temp_value & CHA_STA)
+			pr_info("%s %s : Stream clock not stable!\n",
+					LOG_TAG, __func__);
+		else {
+			sp_read_reg(TX_P0, SP_TX_SYS_CTRL3_REG, &temp_value);
+			sp_write_reg(TX_P0, SP_TX_SYS_CTRL3_REG, temp_value);
+			sp_read_reg(TX_P0, SP_TX_SYS_CTRL3_REG, &temp_value);
+			if (!(temp_value & STRM_VALID))
+				pr_err("%s %s : video stream not valid!\n",
+						LOG_TAG, __func__);
+			else
+				sp_tx_vo_state = VO_CHECK_VIDEO_INFO;
+		}
+		SP_BREAK(VO_WAIT_TX_VIDEO_STABLE, sp_tx_vo_state);
+	/* fallthrough */
+	case VO_CHECK_VIDEO_INFO:
+		if (!sp_tx_bw_lc_sel(sp_tx_pclk_calc()))
+			sp_tx_vo_state++;
+		else
+			sp_tx_set_sys_state(STATE_LINK_TRAINING);
+		SP_BREAK(VO_CHECK_VIDEO_INFO, sp_tx_vo_state);
+	/* fallthrough */
+	case VO_FINISH:
+		slimport_block_power_ctrl(SP_TX_PWR_AUDIO, SP_POWER_DOWN);
+		hdmi_rx_mute_video(0);
+		sp_tx_video_mute(0);
+		sp_tx_show_information();
+		goto_next_system_state();
+		break;
+	}
+}
+/******************End Output video process********************/
+
+/******************Start HDCP process********************/
+static void sp_tx_hdcp_encryption_disable(void)
+{
+	sp_write_reg_and(TX_P0, TX_HDCP_CTRL0, ~ENC_EN);
+}
+
+static void sp_tx_hdcp_encryption_enable(void)
+{
+	sp_write_reg_or(TX_P0, TX_HDCP_CTRL0, ENC_EN);
+}
+
+static void sp_tx_hw_hdcp_enable(void)
+{
+	u8 c;
+
+	sp_write_reg_and(TX_P0, TX_HDCP_CTRL0, (~ENC_EN) & (~HARD_AUTH_EN));
+	sp_write_reg_or(TX_P0, TX_HDCP_CTRL0,
+			HARD_AUTH_EN | BKSV_SRM_PASS | KSVLIST_VLD | ENC_EN);
+
+	sp_read_reg(TX_P0, TX_HDCP_CTRL0, &c);
+	pr_info("%s %s : TX_HDCP_CTRL0 = %.2x\n", LOG_TAG, __func__, (uint)c);
+	sp_write_reg(TX_P0, SP_TX_WAIT_R0_TIME, 0xb0);
+	sp_write_reg(TX_P0, SP_TX_WAIT_KSVR_TIME, 0xc8);
+
+	pr_info("%s %s : Hardware HDCP is enabled.\n", LOG_TAG, __func__);
+
+}
+
+void slimport_hdcp_process(void)
+{
+	switch (hcdp_state) {
+	case HDCP_CAPABLE_CHECK:
+		ds_vid_stb_cntr = 0;
+		hdcp_fail_count = 0;
+		if (is_anx_dongle())
+			hcdp_state = HDCP_WAITTING_VID_STB;
+		else
+			hcdp_state = HDCP_HW_ENABLE;
+		if (external_block_en == 0) {
+			if (slimport_hdcp_cap_check() == 0)
+				hcdp_state = HDCP_NOT_SUPPORT;
+		}
+		/*
+		 * Just for debug, pin: P2-2
+		 * There is a switch to disable/enable HDCP.
+		 */
+		hcdp_state = HDCP_NOT_SUPPORT;
+		/*****************************************/
+		SP_BREAK(HDCP_CAPABLE_CHECK, hcdp_state);
+	/* fallthrough */
+	case HDCP_WAITTING_VID_STB:
+		msleep(100);
+		hcdp_state = HDCP_HW_ENABLE;
+		SP_BREAK(HDCP_WAITTING_VID_STB, hcdp_state);
+	/* fallthrough */
+	case HDCP_HW_ENABLE:
+		sp_tx_video_mute(1);
+		sp_tx_clean_hdcp_status();
+		slimport_block_power_ctrl(SP_TX_PWR_HDCP, SP_POWER_DOWN);
+		msleep(20);
+		slimport_block_power_ctrl(SP_TX_PWR_HDCP, SP_POWER_ON);
+		sp_write_reg(TX_P2, SP_COMMON_INT_MASK2, 0x01);
+		msleep(50);
+		sp_tx_hw_hdcp_enable();
+		hcdp_state = HDCP_WAITTING_FINISH;
+	/* fallthrough */
+	case HDCP_WAITTING_FINISH:
+		break;
+	case HDCP_FINISH:
+		sp_tx_hdcp_encryption_enable();
+		hdmi_rx_mute_video(0);
+		sp_tx_video_mute(0);
+		goto_next_system_state();
+		hcdp_state = HDCP_CAPABLE_CHECK;
+		pr_info("%s %s : @@@@@@@hdcp_auth_pass@@@@@@\n",
+				LOG_TAG, __func__);
+		break;
+	case HDCP_FAILE:
+		if (hdcp_fail_count > 5) {
+			vbus_power_ctrl(0);
+			reg_hardware_reset();
+			hcdp_state = HDCP_CAPABLE_CHECK;
+			hdcp_fail_count = 0;
+			pr_info("%s %s : *********hdcp_auth_failed*********\n",
+					LOG_TAG, __func__);
+		} else {
+			hdcp_fail_count++;
+			hcdp_state = HDCP_WAITTING_VID_STB;
+		}
+		break;
+	default:
+	case HDCP_NOT_SUPPORT:
+		pr_info("%s %s : Sink is not capable HDCP\n",
+				LOG_TAG, __func__);
+		slimport_block_power_ctrl(SP_TX_PWR_HDCP, SP_POWER_DOWN);
+		sp_tx_video_mute(0);
+		goto_next_system_state();
+		hcdp_state = HDCP_CAPABLE_CHECK;
+		break;
+	}
+}
+/******************End HDCP process********************/
+
+/******************Start Audio process********************/
+static void sp_tx_audioinfoframe_setup(void)
+{
+	int i;
+	u8 c;
+
+	sp_read_reg(RX_P1, HDMI_RX_AUDIO_TYPE_REG, &c);
+	sp_tx_audioinfoframe.type = c;
+	sp_read_reg(RX_P1, HDMI_RX_AUDIO_VER_REG, &c);
+	sp_tx_audioinfoframe.version = c;
+	sp_read_reg(RX_P1, HDMI_RX_AUDIO_LEN_REG, &c);
+	sp_tx_audioinfoframe.length = c;
+	for (i = 0; i < 11; i++) {
+		sp_read_reg(RX_P1, (HDMI_RX_AUDIO_DATA00_REG + i), &c);
+		sp_tx_audioinfoframe.pb_byte[i] = c;
+	}
+
+}
+
+static void sp_tx_enable_audio_output(u8 benable)
+{
+	u8 c;
+
+	sp_read_reg(TX_P0, SP_TX_AUD_CTRL, &c);
+	if (benable) {
+		if (c & AUD_EN) {
+			c &= ~AUD_EN;
+			sp_write_reg(TX_P0, SP_TX_AUD_CTRL, c);
+		}
+		sp_tx_audioinfoframe_setup();
+		sp_tx_config_packets(AUDIF_PACKETS);
+
+		c |= AUD_EN;
+		sp_write_reg(TX_P0, SP_TX_AUD_CTRL, c);
+
+	} else {
+		c &= ~AUD_EN;
+		sp_write_reg(TX_P0, SP_TX_AUD_CTRL, c);
+		sp_write_reg_and(TX_P0, SP_TX_PKT_EN_REG, ~AUD_IF_EN);
+	}
+
+}
+
+static void sp_tx_config_audio(void)
+{
+	u8 c;
+	int i;
+	ulong M_AUD, LS_Clk = 0;
+	ulong AUD_Freq = 0;
+
+	pr_info("%s %s : **Config audio **\n", LOG_TAG, __func__);
+	slimport_block_power_ctrl(SP_TX_PWR_AUDIO, SP_POWER_ON);
+	sp_read_reg(RX_P0, 0xCA, &c);
+
+	switch (c & 0x0f) {
+	case 0x00:
+		AUD_Freq = 44.1;
+		break;
+	case 0x02:
+		AUD_Freq = 48;
+		break;
+	case 0x03:
+		AUD_Freq = 32;
+		break;
+	case 0x08:
+		AUD_Freq = 88.2;
+		break;
+	case 0x0a:
+		AUD_Freq = 96;
+		break;
+	case 0x0c:
+		AUD_Freq = 176.4;
+		break;
+	case 0x0e:
+		AUD_Freq = 192;
+		break;
+	default:
+		break;
+	}
+
+
+	switch (sp_tx_get_link_bw()) {
+	case LINK_1P62G:
+		LS_Clk = 162000;
+		break;
+	case LINK_2P7G:
+		LS_Clk = 270000;
+		break;
+	case LINK_5P4G:
+		LS_Clk = 540000;
+		break;
+	case LINK_6P75G:
+		LS_Clk = 675000;
+		break;
+	default:
+		break;
+	}
+
+	pr_info("%s %s : AUD_Freq = %ld , LS_CLK = %ld\n",
+			LOG_TAG, __func__, AUD_Freq, LS_Clk);
+
+	M_AUD = ((512 * AUD_Freq) / LS_Clk) * 32768;
+	M_AUD = M_AUD + 0x05;
+	sp_write_reg(TX_P1, SP_TX_AUD_INTERFACE_CTRL4, (M_AUD & 0xff));
+	M_AUD = M_AUD >> 8;
+	sp_write_reg(TX_P1, SP_TX_AUD_INTERFACE_CTRL5, (M_AUD & 0xff));
+	sp_write_reg(TX_P1, SP_TX_AUD_INTERFACE_CTRL6, 0x00);
+
+	sp_write_reg_and(TX_P1, SP_TX_AUD_INTERFACE_CTRL0,
+			(u8)~AUD_INTERFACE_DISABLE);
+
+	sp_write_reg_or(TX_P1, SP_TX_AUD_INTERFACE_CTRL2, M_AUD_ADJUST_ST);
+
+	sp_read_reg(RX_P0, HDMI_STATUS, &c);
+	if (c & HDMI_AUD_LAYOUT)
+		sp_write_reg_or(TX_P2, SP_TX_AUD_CH_NUM_REG5,
+				CH_NUM_8 | AUD_LAYOUT);
+	else
+		sp_write_reg_and(TX_P2, SP_TX_AUD_CH_NUM_REG5,
+				(u8)(~CH_NUM_8) & (~AUD_LAYOUT));
+
+	/* transfer audio chaneel status from HDMI Rx to Slinmport Tx */
+	for (i = 0; i < 5; i++) {
+		sp_read_reg(RX_P0, (HDMI_RX_AUD_IN_CH_STATUS1_REG + i), &c);
+		sp_write_reg(TX_P2, (SP_TX_AUD_CH_STATUS_REG1 + i), c);
+	}
+
+	/* enable audio */
+	sp_tx_enable_audio_output(1);
+}
+
+void slimport_config_audio_output(void)
+{
+	static u8 count;
+
+	switch (sp_tx_ao_state) {
+	default:
+	case AO_INIT:
+	case AO_CTS_RCV_INT:
+	case AO_AUDIO_RCV_INT:
+		if (!(sp_i2c_read_byte(RX_P0, HDMI_STATUS) & HDMI_MODE)) {
+			sp_tx_ao_state = AO_INIT;
+			goto_next_system_state();
+		}
+		break;
+	case AO_RCV_INT_FINISH:
+		if (count++ > 2)
+			sp_tx_ao_state = AO_OUTPUT;
+		else
+			sp_tx_ao_state = AO_INIT;
+		SP_BREAK(AO_INIT, sp_tx_ao_state);
+	/* fallthrough */
+	case AO_OUTPUT:
+		count = 0;
+		sp_tx_ao_state = AO_INIT;
+		hdmi_rx_mute_audio(0);
+		sp_tx_config_audio();
+		goto_next_system_state();
+		break;
+	}
+
+}
+/******************End Audio process********************/
+
+void slimport_initialization(void)
+{
+	/* Waitting Hot plug event! */
+	if (!(common_int_status.common_int[3] & PLUG))
+		return;
+
+	g_read_edid_flag = 0;
+
+	/* Power on all modules */
+	sp_write_reg(TX_P2, SP_POWERD_CTRL_REG, 0x00);
+	/* Driver Version */
+	sp_write_reg(TX_P1, FW_VER_REG, FW_VERSION);
+	hdmi_rx_initialization();
+	sp_tx_initialization();
+	msleep(200);
+	goto_next_system_state();
+}
+
+void hdcp_external_ctrl_flag_monitor(void)
+{
+	static u8 cur_flag;
+
+	if (external_block_en != cur_flag) {
+		cur_flag = external_block_en;
+		system_state_change_with_case(STATE_HDCP_AUTH);
+	}
+
+}
+
+void slimport_state_process(struct anx78xx_data *data)
+{
+	switch (sp_tx_system_state) {
+	case STATE_WAITTING_CABLE_PLUG:
+		slimport_waitting_cable_plug_process(data);
+		SP_BREAK(STATE_WAITTING_CABLE_PLUG, sp_tx_system_state);
+	/* fallthrough */
+	case STATE_SP_INITIALIZED:
+		slimport_initialization();
+		SP_BREAK(STATE_SP_INITIALIZED, sp_tx_system_state);
+	/* fallthrough */
+	case STATE_SINK_CONNECTION:
+		slimport_sink_connection();
+		SP_BREAK(STATE_SINK_CONNECTION, sp_tx_system_state);
+	/* fallthrough */
+	case STATE_PARSE_EDID:
+		slimport_edid_process();
+		SP_BREAK(STATE_PARSE_EDID, sp_tx_system_state);
+	/* fallthrough */
+	case STATE_LINK_TRAINING:
+		slimport_link_training();
+		SP_BREAK(STATE_LINK_TRAINING, sp_tx_system_state);
+	/* fallthrough */
+	case STATE_VIDEO_OUTPUT:
+		slimport_config_video_output();
+		SP_BREAK(STATE_VIDEO_OUTPUT, sp_tx_system_state);
+	/* fallthrough */
+	case STATE_HDCP_AUTH:
+		slimport_hdcp_process();
+		SP_BREAK(STATE_HDCP_AUTH, sp_tx_system_state);
+	/* fallthrough */
+	case STATE_AUDIO_OUTPUT:
+		slimport_config_audio_output();
+		SP_BREAK(STATE_AUDIO_OUTPUT, sp_tx_system_state);
+	/* fallthrough */
+	case STATE_PLAY_BACK:
+		SP_BREAK(STATE_PLAY_BACK, sp_tx_system_state);
+	/* fallthrough */
+	default:
+		break;
+	}
+}
+
+/******************Start INT process********************/
+void sp_tx_int_rec(void)
+{
+	sp_read_reg(TX_P2, SP_COMMON_INT_STATUS1,
+		&common_int_status.common_int[0]);
+	sp_write_reg(TX_P2, SP_COMMON_INT_STATUS1,
+		common_int_status.common_int[0]);
+
+	sp_read_reg(TX_P2, SP_COMMON_INT_STATUS1 + 1,
+		&common_int_status.common_int[1]);
+	sp_write_reg(TX_P2, SP_COMMON_INT_STATUS1 + 1,
+		common_int_status.common_int[1]);
+
+	sp_read_reg(TX_P2, SP_COMMON_INT_STATUS1 + 2,
+		&common_int_status.common_int[2]);
+	sp_write_reg(TX_P2, SP_COMMON_INT_STATUS1 + 2,
+		common_int_status.common_int[2]);
+
+	sp_read_reg(TX_P2, SP_COMMON_INT_STATUS1 + 3,
+		&common_int_status.common_int[3]);
+	sp_write_reg(TX_P2, SP_COMMON_INT_STATUS1 + 3,
+		common_int_status.common_int[3]);
+
+	sp_read_reg(TX_P2, SP_COMMON_INT_STATUS1 + 6,
+		&common_int_status.common_int[4]);
+	sp_write_reg(TX_P2, SP_COMMON_INT_STATUS1 + 6,
+		common_int_status.common_int[4]);
+}
+
+void hdmi_rx_int_rec(void)
+{
+	 sp_read_reg(RX_P0, HDMI_RX_INT_STATUS1_REG,
+		&hdmi_rx_int_status.hdmi_rx_int[0]);
+	 sp_write_reg(RX_P0, HDMI_RX_INT_STATUS1_REG,
+		hdmi_rx_int_status.hdmi_rx_int[0]);
+	 sp_read_reg(RX_P0, HDMI_RX_INT_STATUS2_REG,
+		&hdmi_rx_int_status.hdmi_rx_int[1]);
+	 sp_write_reg(RX_P0, HDMI_RX_INT_STATUS2_REG,
+		hdmi_rx_int_status.hdmi_rx_int[1]);
+	 sp_read_reg(RX_P0, HDMI_RX_INT_STATUS3_REG,
+		&hdmi_rx_int_status.hdmi_rx_int[2]);
+	 sp_write_reg(RX_P0, HDMI_RX_INT_STATUS3_REG,
+		hdmi_rx_int_status.hdmi_rx_int[2]);
+	 sp_read_reg(RX_P0, HDMI_RX_INT_STATUS4_REG,
+		&hdmi_rx_int_status.hdmi_rx_int[3]);
+	 sp_write_reg(RX_P0, HDMI_RX_INT_STATUS4_REG,
+		hdmi_rx_int_status.hdmi_rx_int[3]);
+	 sp_read_reg(RX_P0, HDMI_RX_INT_STATUS5_REG,
+		&hdmi_rx_int_status.hdmi_rx_int[4]);
+	 sp_write_reg(RX_P0, HDMI_RX_INT_STATUS5_REG,
+		hdmi_rx_int_status.hdmi_rx_int[4]);
+	 sp_read_reg(RX_P0, HDMI_RX_INT_STATUS6_REG,
+		&hdmi_rx_int_status.hdmi_rx_int[5]);
+	 sp_write_reg(RX_P0, HDMI_RX_INT_STATUS6_REG,
+		hdmi_rx_int_status.hdmi_rx_int[5]);
+	 sp_read_reg(RX_P0, HDMI_RX_INT_STATUS7_REG,
+		&hdmi_rx_int_status.hdmi_rx_int[6]);
+	 sp_write_reg(RX_P0, HDMI_RX_INT_STATUS7_REG,
+		hdmi_rx_int_status.hdmi_rx_int[6]);
+}
+
+void slimport_int_rec(void)
+{
+	sp_tx_int_rec();
+	hdmi_rx_int_rec();
+}
+/******************End INT process********************/
+
+/******************Start task process********************/
+static void sp_tx_pll_changed_int_handler(void)
+{
+	if (sp_tx_system_state >= STATE_LINK_TRAINING) {
+		if (!sp_tx_get_pll_lock_status()) {
+			pr_info("%s %s : PLL:PLL not lock!\n",
+				LOG_TAG, __func__);
+			sp_tx_set_sys_state(STATE_LINK_TRAINING);
+		}
+	}
+}
+
+static void sp_tx_hdcp_link_chk_fail_handler(void)
+{
+	system_state_change_with_case(STATE_HDCP_AUTH);
+
+	pr_info("%s %s : hdcp_link_chk_fail:HDCP Sync lost!\n",
+		LOG_TAG, __func__);
+}
+
+void link_down_check(void)
+{
+	u8 data_buf[6];
+
+	pr_info("%s %s : link_down_check\n", LOG_TAG, __func__);
+	sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x00, 6, data_buf);
+	if (sp_tx_system_state > STATE_LINK_TRAINING) {
+		if (!(data_buf[4] & 0x01)
+		|| ((data_buf[2] & (0x01 | 0x04)) != 0x05)) {
+			sp_tx_set_sys_state(STATE_LINK_TRAINING);
+			pr_info("%s %s : INT:re-LT request!\n",
+				LOG_TAG, __func__);
+		} else {
+			pr_info("%s %s : Lane align %x\n",
+				LOG_TAG, __func__, (uint)data_buf[4]);
+			pr_info("%s %s : Lane clock recovery %x\n",
+				LOG_TAG, __func__, (uint)data_buf[2]);
+		}
+	}
+}
+
+static void sp_tx_phy_auto_test(void)
+{
+	u8 b_sw;
+	u8 c1;
+	u8 bytebuf[16];
+	u8 link_bw;
+
+	/* DPCD 0x219 TEST_LINK_RATE */
+	sp_tx_aux_dpcdread_bytes(0x0, 0x02, 0x19, 1, bytebuf);
+	pr_info("%s %s : DPCD:0x00219 = %.2x\n",
+			LOG_TAG, __func__, (uint)bytebuf[0]);
+	switch (bytebuf[0]) {
+	case 0x06:
+	case 0x0A:
+	case 0x14:
+	case 0x19:
+		sp_tx_set_link_bw(bytebuf[0]);
+		sp_tx_test_bw = bytebuf[0];
+		break;
+	default:
+		sp_tx_set_link_bw(0x19);
+		sp_tx_test_bw = 0x19;
+		break;
+	}
+
+
+	/* DPCD 0x248 PHY_TEST_PATTERN */
+	sp_tx_aux_dpcdread_bytes(0x0, 0x02, 0x48, 1, bytebuf);
+	pr_info("%s %s : DPCD:0x00248 = %.2x\n",
+			LOG_TAG, __func__, (uint)bytebuf[0]);
+	switch (bytebuf[0]) {
+	case 0:
+		break;
+	case 1:
+		sp_write_reg(TX_P0, SP_TX_TRAINING_PTN_SET_REG, 0x04);
+		break;
+	case 2:
+		sp_write_reg(TX_P0, SP_TX_TRAINING_PTN_SET_REG, 0x08);
+		break;
+	case 3:
+		sp_write_reg(TX_P0, SP_TX_TRAINING_PTN_SET_REG, 0x0c);
+		break;
+	case 4:
+		sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x50, 0xa, bytebuf);
+		sp_write_reg(TX_P1, 0x80, bytebuf[0]);
+		sp_write_reg(TX_P1, 0x81, bytebuf[1]);
+		sp_write_reg(TX_P1, 0x82, bytebuf[2]);
+		sp_write_reg(TX_P1, 0x83, bytebuf[3]);
+		sp_write_reg(TX_P1, 0x84, bytebuf[4]);
+		sp_write_reg(TX_P1, 0x85, bytebuf[5]);
+		sp_write_reg(TX_P1, 0x86, bytebuf[6]);
+		sp_write_reg(TX_P1, 0x87, bytebuf[7]);
+		sp_write_reg(TX_P1, 0x88, bytebuf[8]);
+		sp_write_reg(TX_P1, 0x89, bytebuf[9]);
+		sp_write_reg(TX_P0, SP_TX_TRAINING_PTN_SET_REG, 0x30);
+		break;
+	case 5:
+		sp_write_reg(TX_P0, 0xA9, 0x00);
+		sp_write_reg(TX_P0, 0xAA, 0x01);
+		sp_write_reg(TX_P0, SP_TX_TRAINING_PTN_SET_REG, 0x14);
+		break;
+	}
+
+	sp_tx_aux_dpcdread_bytes(0x00, 0x00, 0x03, 1, bytebuf);
+	pr_info("%s %s : DPCD:0x00003 = %.2x\n",
+			LOG_TAG, __func__, (uint)bytebuf[0]);
+	switch (bytebuf[0] & 0x01) {
+	case 0:
+		sp_tx_spread_enable(0);
+		break;
+	case 1:
+		sp_read_reg(TX_P0, SP_TX_LINK_BW_SET_REG, &c1);
+		switch (c1) {
+		case 0x06:
+			link_bw = 0x06;
+			break;
+		case 0x0a:
+			link_bw = 0x0a;
+			break;
+		case 0x14:
+			link_bw = 0x14;
+			break;
+		case 0x19:
+			link_bw = 0x19;
+			break;
+		default:
+			link_bw = 0x00;
+			break;
+		}
+		sp_tx_config_ssc(SSC_DEP_4000PPM);
+		break;
+	}
+
+	/* get swing and emphasis adjust request */
+	sp_read_reg(TX_P0, 0xA3, &b_sw);
+
+	sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x06, 1, bytebuf);
+	pr_info("%s %s : DPCD:0x00206 = %.2x\n",
+			LOG_TAG, __func__, (uint)bytebuf[0]);
+	c1 = bytebuf[0] & 0x0f;
+	switch (c1) {
+	case 0x00:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x00);
+		break;
+	case 0x01:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x01);
+		break;
+	case 0x02:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x02);
+		break;
+	case 0x03:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x03);
+		break;
+	case 0x04:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x08);
+		break;
+	case 0x05:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x09);
+		break;
+	case 0x06:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x0a);
+		break;
+	case 0x08:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x10);
+		break;
+	case 0x09:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x11);
+		break;
+	case 0x0c:
+		sp_write_reg(TX_P0, 0xA3, (b_sw & ~0x1b) | 0x18);
+		break;
+	default:
+		break;
+	}
+}
+
+static void hpd_irq_process(void)
+{
+	u8 c, c1;
+	u8 test_vector;
+	u8 data_buf[6];
+
+	sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x00, 6, data_buf);
+	pr_info("+++++++++++++Get HPD IRQ %x\n", (int)data_buf[1]);
+
+	if (data_buf[1] != 0)
+		sp_tx_aux_dpcdwrite_bytes(0x00, 0x02, DPCD_SERVICE_IRQ_VECTOR,
+					1, &(data_buf[1]));
+
+	/* HDCP IRQ */
+	if (data_buf[1] & CP_IRQ) {
+		if (hcdp_state > HDCP_WAITTING_FINISH
+			|| sp_tx_system_state > STATE_HDCP_AUTH) {
+			sp_tx_aux_dpcdread_bytes(0x06, 0x80, 0x29, 1, &c1);
+			if (c1 & 0x04) {
+				system_state_change_with_case(STATE_HDCP_AUTH);
+				pr_info("%s %s : IRQ:_______HDCP Sync lost!\n",
+					LOG_TAG, __func__);
+			}
+		}
+	}
+
+	/* AUTOMATED TEST IRQ */
+	if (data_buf[1] & TEST_IRQ) {
+		sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x18, 1, &test_vector);
+
+		if (test_vector & 0x01) {
+			sp_tx_test_lt = 1;
+
+			sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x19, 1, &c);
+			switch (c) {
+			case 0x06:
+			case 0x0A:
+			case 0x14:
+			case 0x19:
+				sp_tx_set_link_bw(c);
+				sp_tx_test_bw = c;
+				break;
+			default:
+				sp_tx_set_link_bw(0x19);
+				sp_tx_test_bw = 0x19;
+				break;
+			}
+
+			pr_info("%s %s :  test_bw = %.2x\n",
+					LOG_TAG, __func__, (uint)sp_tx_test_bw);
+
+			sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x60, 1, &c);
+			c = c | TEST_ACK;
+			sp_tx_aux_dpcdwrite_bytes(0x00, 0x02, 0x60, 1, &c);
+
+			pr_info("%s %s : Set TEST_ACK!\n", LOG_TAG, __func__);
+			if (sp_tx_system_state >= STATE_LINK_TRAINING) {
+				sp_tx_lt_state = LT_INIT;
+				sp_tx_set_sys_state(STATE_LINK_TRAINING);
+			}
+			pr_info("%s %s : IRQ:test-LT request!\n",
+					LOG_TAG, __func__);
+		}
+
+		if (test_vector & 0x02) {
+			sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x60, 1, &c);
+			c = c | TEST_ACK;
+			sp_tx_aux_dpcdwrite_bytes(0x00, 0x02, 0x60, 1, &c);
+		}
+		if (test_vector & 0x04) {
+			if (sp_tx_system_state > STATE_PARSE_EDID)
+				sp_tx_set_sys_state(STATE_PARSE_EDID);
+			sp_tx_test_edid = 1;
+			pr_info("%s %s : Test EDID Requested!\n",
+					LOG_TAG, __func__);
+		}
+
+		if (test_vector & 0x08) {
+			sp_tx_test_lt = 1;
+
+			sp_tx_phy_auto_test();
+
+			sp_tx_aux_dpcdread_bytes(0x00, 0x02, 0x60, 1, &c);
+			c = c | 0x01;
+			sp_tx_aux_dpcdwrite_bytes(0x00, 0x02, 0x60, 1, &c);
+		}
+	}
+
+	if (sp_tx_system_state > STATE_LINK_TRAINING) {
+		if (!(data_buf[4] & 0x01)
+		|| ((data_buf[2] & (0x01 | 0x04)) != 0x05)) {
+			sp_tx_set_sys_state(STATE_LINK_TRAINING);
+			pr_info("%s %s : INT:re-LT request!\n",
+				LOG_TAG, __func__);
+			return;
+		}
+
+		pr_info("%s %s : Lane align %x\n",
+			LOG_TAG, __func__, (uint)data_buf[4]);
+		pr_info("%s %s : Lane clock recovery %x\n",
+			LOG_TAG, __func__, (uint)data_buf[2]);
+	}
+}
+
+static void sp_tx_vsi_setup(void)
+{
+	u8 c;
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		sp_read_reg(RX_P1, (HDMI_RX_MPEG_DATA00_REG + i), &c);
+		sp_tx_packet_mpeg.mpeg_data[i] = c;
+	}
+}
+
+static void sp_tx_mpeg_setup(void)
+{
+	u8 c;
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		sp_read_reg(RX_P1, (HDMI_RX_MPEG_DATA00_REG + i), &c);
+		sp_tx_packet_mpeg.mpeg_data[i] = c;
+	}
+}
+
+static void sp_tx_auth_done_int_handler(void)
+{
+	u8 bytebuf[2];
+
+	if (hcdp_state > HDCP_HW_ENABLE
+		&& sp_tx_system_state == STATE_HDCP_AUTH) {
+		sp_read_reg(TX_P0, SP_TX_HDCP_STATUS, bytebuf);
+		if (bytebuf[0] & SP_TX_HDCP_AUTH_PASS) {
+			sp_tx_aux_dpcdread_bytes(0x06, 0x80, 0x2A, 2, bytebuf);
+			if ((bytebuf[1] & 0x08) || (bytebuf[0] & 0x80)) {
+				pr_info("%s %s : max cascade/devs exceeded!\n",
+						LOG_TAG, __func__);
+				sp_tx_hdcp_encryption_disable();
+			} else
+				pr_info("%s %s : %s\n",	LOG_TAG, __func__,
+					"Authentication pass in Auth_Done");
+
+			hcdp_state = HDCP_FINISH;
+		} else {
+			pr_err("%s %s : Authentication failed in AUTH_done\n",
+					LOG_TAG, __func__);
+			sp_tx_video_mute(1);
+			sp_tx_clean_hdcp_status();
+			hcdp_state = HDCP_FAILE;
+		}
+	}
+
+	pr_info("%s %s : sp_tx_auth_done_int_handler\n", LOG_TAG, __func__);
+
+}
+
+static void sp_tx_lt_done_int_handler(void)
+{
+	u8 c;
+
+	if (sp_tx_lt_state == LT_WAITTING_FINISH
+		&& sp_tx_system_state == STATE_LINK_TRAINING) {
+		sp_read_reg(TX_P0, LT_CTRL, &c);
+		if (c & 0x70) {
+			c = (c & 0x70) >> 4;
+			pr_info("%s %s : LT failed in interrupt, ERR = %.2x\n",
+				LOG_TAG, __func__, (uint) c);
+			sp_tx_lt_state = LT_ERROR;
+		} else {
+			pr_info("%s %s : lt_done: LT Finish\n",
+					LOG_TAG, __func__);
+			sp_tx_lt_state = LT_FINISH;
+		}
+	}
+
+}
+
+static void hdmi_rx_clk_det_int(void)
+{
+	pr_info("%s %s : *HDMI_RX Interrupt: Pixel Clock Change.\n",
+			LOG_TAG, __func__);
+	if (sp_tx_system_state > STATE_VIDEO_OUTPUT) {
+		sp_tx_video_mute(1);
+		sp_tx_enable_audio_output(0);
+		sp_tx_set_sys_state(STATE_VIDEO_OUTPUT);
+	}
+}
+
+static void hdmi_rx_sync_det_int(void)
+{
+	pr_info("%s %s : *HDMI_RX Interrupt: Sync Detect.\n",
+			LOG_TAG, __func__);
+}
+
+static void hdmi_rx_hdmi_dvi_int(void)
+{
+	u8 c;
+
+	pr_info("%s %s : hdmi_rx_hdmi_dvi_int.\n", LOG_TAG, __func__);
+	sp_read_reg(RX_P0, HDMI_STATUS, &c);
+	g_hdmi_dvi_status = read_dvi_hdmi_mode();
+	if ((c & _BIT0) != (g_hdmi_dvi_status & _BIT0)) {
+		pr_info("%s %s : hdmi_dvi_int: Is HDMI MODE: %x.\n",
+				LOG_TAG, __func__, (uint)(c & HDMI_MODE));
+		g_hdmi_dvi_status = (c & _BIT0);
+		hdmi_rx_mute_audio(1);
+		system_state_change_with_case(STATE_LINK_TRAINING);
+	}
+}
+
+static void hdmi_rx_new_avi_int(void)
+{
+	pr_info("%s %s : *HDMI_RX Interrupt: New AVI Packet.\n",
+			LOG_TAG, __func__);
+	sp_tx_lvttl_bit_mapping();
+	sp_tx_set_colorspace();
+	sp_tx_avi_setup();
+	sp_tx_config_packets(AVI_PACKETS);
+}
+
+static void hdmi_rx_new_vsi_int(void)
+{
+	u8 hdmi_video_format, v3d_structure;
+
+	pr_info("%s %s : *HDMI_RX Interrupt: NEW VSI packet.\n",
+			LOG_TAG, __func__);
+
+	sp_write_reg_and(TX_P0, SP_TX_3D_VSC_CTRL, ~INFO_FRAME_VSC_EN);
+	/* VSI package header */
+	if ((sp_i2c_read_byte(RX_P1, HDMI_RX_MPEG_TYPE_REG) != 0x81)
+		|| (sp_i2c_read_byte(RX_P1, HDMI_RX_MPEG_VER_REG) != 0x01))
+		return;
+	pr_info("%s %s : Setup VSI package!\n", LOG_TAG, __func__);
+
+	sp_tx_vsi_setup();
+	sp_tx_config_packets(VSI_PACKETS);
+
+	sp_read_reg(RX_P1, HDMI_RX_MPEG_DATA03_REG, &hdmi_video_format);
+	if ((hdmi_video_format & 0xe0) == 0x40) {
+		pr_info("%s %s : 3D VSI packet detected. Config VSC packet\n",
+			LOG_TAG, __func__);
+		sp_read_reg(RX_P1, HDMI_RX_MPEG_DATA05_REG, &v3d_structure);
+		switch (v3d_structure&0xf0) {
+		case 0x00:
+			v3d_structure = 0x02;
+			break;
+		case 0x20:
+			v3d_structure = 0x03;
+			break;
+		case 0x30:
+			v3d_structure = 0x04;
+			break;
+		default:
+			v3d_structure = 0x00;
+			pr_info("%s %s : 3D structure is not supported\n",
+					LOG_TAG, __func__);
+			break;
+		}
+		sp_write_reg(TX_P0, SP_TX_VSC_DB1, v3d_structure);
+	}
+	sp_write_reg_or(TX_P0, SP_TX_3D_VSC_CTRL, INFO_FRAME_VSC_EN);
+	sp_write_reg_and(TX_P0, SP_TX_PKT_EN_REG, ~SPD_IF_EN);
+	sp_write_reg_or(TX_P0, SP_TX_PKT_EN_REG, SPD_IF_UD);
+	sp_write_reg_or(TX_P0, SP_TX_PKT_EN_REG, SPD_IF_EN);
+}
+
+static void hdmi_rx_no_vsi_int(void)
+{
+
+	u8 c;
+
+	sp_read_reg(TX_P0, SP_TX_3D_VSC_CTRL, &c);
+	if (c & INFO_FRAME_VSC_EN) {
+		pr_info("%s %s : No new VSI is received, disable  VSC packet\n",
+				LOG_TAG, __func__);
+		c &= ~INFO_FRAME_VSC_EN;
+		sp_write_reg(TX_P0, SP_TX_3D_VSC_CTRL, c);
+		sp_tx_mpeg_setup();
+		sp_tx_config_packets(MPEG_PACKETS);
+	}
+
+}
+
+static void hdmi_rx_restart_audio_chk(void)
+{
+	pr_info("%s %s : WAIT_AUDIO: hdmi_rx_restart_audio_chk.\n",
+			LOG_TAG, __func__);
+	system_state_change_with_case(STATE_AUDIO_OUTPUT);
+}
+
+static void hdmi_rx_cts_rcv_int(void)
+{
+	if (sp_tx_ao_state == AO_INIT)
+		sp_tx_ao_state = AO_CTS_RCV_INT;
+	else if (sp_tx_ao_state == AO_AUDIO_RCV_INT)
+		sp_tx_ao_state = AO_RCV_INT_FINISH;
+}
+
+static void hdmi_rx_audio_rcv_int(void)
+{
+	if (sp_tx_ao_state == AO_INIT)
+		sp_tx_ao_state = AO_AUDIO_RCV_INT;
+	else if (sp_tx_ao_state == AO_CTS_RCV_INT)
+		sp_tx_ao_state = AO_RCV_INT_FINISH;
+}
+
+static void hdmi_rx_audio_samplechg_int(void)
+{
+	uint i;
+	u8 c;
+	/* transfer audio chaneel status from HDMI Rx to Slinmport Tx */
+	for (i = 0; i < 5; i++) {
+		sp_read_reg(RX_P0, (HDMI_RX_AUD_IN_CH_STATUS1_REG + i), &c);
+		sp_write_reg(TX_P2, (SP_TX_AUD_CH_STATUS_REG1 + i), c);
+	}
+}
+
+static void hdmi_rx_hdcp_error_int(void)
+{
+	static u8 count;
+
+	pr_info("%s %s : *HDMI_RX Interrupt: hdcp error.\n", LOG_TAG, __func__);
+	if (count >= 40) {
+		count = 0;
+		pr_info("%s %s : Lots of hdcp error occurred ...\n",
+				LOG_TAG, __func__);
+		hdmi_rx_mute_audio(1);
+		hdmi_rx_mute_video(1);
+		hdmi_rx_set_hpd(0);
+		usleep_range(10000, 11000);
+		hdmi_rx_set_hpd(1);
+	} else
+		count++;
+}
+
+static void hdmi_rx_new_gcp_int(void)
+{
+	u8 c;
+
+	sp_read_reg(RX_P1, HDMI_RX_GENERAL_CTRL, &c);
+	if (c&SET_AVMUTE) {
+			hdmi_rx_mute_video(1);
+			hdmi_rx_mute_audio(1);
+
+	} else if (c&CLEAR_AVMUTE) {
+			hdmi_rx_mute_video(0);
+			hdmi_rx_mute_audio(0);
+	}
+}
+
+static void sp_tx_hpd_int_handler(u8 hpd_source)
+{
+	pr_info("%s %s : sp_tx_hpd_int_handler\n", LOG_TAG, __func__);
+
+	switch (hpd_source) {
+	case HPD_LOST:
+		hdmi_rx_set_hpd(0);
+		sp_tx_set_sys_state(STATE_WAITTING_CABLE_PLUG);
+		break;
+	case HPD_CHANGE:
+		pr_info("HPD:____________HPD changed!\n");
+		usleep_range(2000, 4000);
+		if (common_int_status.common_int[3] & HPD_IRQ)
+			hpd_irq_process();
+
+		if (sp_i2c_read_byte(TX_P0, SP_TX_SYS_CTRL3_REG) & HPD_STATUS) {
+			if (common_int_status.common_int[3] & HPD_IRQ)
+				hpd_irq_process();
+		} else {
+			if (sp_i2c_read_byte(TX_P0, SP_TX_SYS_CTRL3_REG)
+				& HPD_STATUS) {
+				hdmi_rx_set_hpd(0);
+				sp_tx_set_sys_state(STATE_WAITTING_CABLE_PLUG);
+			}
+		}
+		break;
+	case PLUG:
+		pr_info("HPD:____________HPD changed!\n");
+		if (sp_tx_system_state < STATE_SP_INITIALIZED)
+			sp_tx_set_sys_state(STATE_SP_INITIALIZED);
+		break;
+	default:
+		break;
+	}
+}
+
+void system_isr_handler(void)
+{
+	if (common_int_status.common_int[3] & HPD_CHANGE)
+		sp_tx_hpd_int_handler(HPD_CHANGE);
+	if (common_int_status.common_int[3] & HPD_LOST)
+		sp_tx_hpd_int_handler(HPD_LOST);
+	if (common_int_status.common_int[3] & HPD_IRQ)
+		pr_info("++++++++++++++++========HDCP_IRQ interrupt\n");
+	if (common_int_status.common_int[0] & PLL_LOCK_CHG)
+		sp_tx_pll_changed_int_handler();
+
+	if (common_int_status.common_int[1] & HDCP_AUTH_DONE)
+		sp_tx_auth_done_int_handler();
+
+	if (common_int_status.common_int[2] & HDCP_LINK_CHECK_FAIL)
+		sp_tx_hdcp_link_chk_fail_handler();
+
+	if (common_int_status.common_int[4] & TRAINING_Finish)
+		sp_tx_lt_done_int_handler();
+
+	if (sp_tx_system_state > STATE_SINK_CONNECTION) {
+		if (hdmi_rx_int_status.hdmi_rx_int[5] & NEW_AVI)
+			hdmi_rx_new_avi_int();
+	}
+
+	if (sp_tx_system_state > STATE_VIDEO_OUTPUT) {
+		if (hdmi_rx_int_status.hdmi_rx_int[6] & NEW_VS) {
+			hdmi_rx_int_status.hdmi_rx_int[6] &= ~NO_VSI;
+			hdmi_rx_new_vsi_int();
+		}
+		if (hdmi_rx_int_status.hdmi_rx_int[6] & NO_VSI)
+			hdmi_rx_no_vsi_int();
+	}
+
+	if (sp_tx_system_state >= STATE_VIDEO_OUTPUT) {
+		if (hdmi_rx_int_status.hdmi_rx_int[0] & CKDT_CHANGE)
+			hdmi_rx_clk_det_int();
+
+		if (hdmi_rx_int_status.hdmi_rx_int[0] & SCDT_CHANGE)
+			hdmi_rx_sync_det_int();
+
+		if (hdmi_rx_int_status.hdmi_rx_int[0] & HDMI_DVI)
+			hdmi_rx_hdmi_dvi_int();
+
+		if ((hdmi_rx_int_status.hdmi_rx_int[5] & NEW_AUD)
+		     || (hdmi_rx_int_status.hdmi_rx_int[2] & AUD_MODE_CHANGE))
+			hdmi_rx_restart_audio_chk();
+
+
+		if (hdmi_rx_int_status.hdmi_rx_int[5] & CTS_RCV)
+			hdmi_rx_cts_rcv_int();
+
+		if (hdmi_rx_int_status.hdmi_rx_int[4] & AUDIO_RCV)
+			hdmi_rx_audio_rcv_int();
+
+
+		if (hdmi_rx_int_status.hdmi_rx_int[1] & HDCP_ERR)
+			hdmi_rx_hdcp_error_int();
+
+		if (hdmi_rx_int_status.hdmi_rx_int[5] & NEW_CP)
+			hdmi_rx_new_gcp_int();
+
+		if (hdmi_rx_int_status.hdmi_rx_int[1] & AUDIO_SAMPLE_CHANGE)
+			hdmi_rx_audio_samplechg_int();
+	}
+
+}
+
+void sp_tx_show_information(void)
+{
+	u8 c, c1;
+	uint h_res, h_act, v_res, v_act;
+	uint h_fp, h_sw, h_bp, v_fp, v_sw, v_bp;
+	ulong fresh_rate;
+	ulong pclk;
+
+	pr_info("\n******************SP Video Information*******************\n");
+
+	sp_read_reg(TX_P0, SP_TX_LINK_BW_SET_REG, &c);
+	switch (c) {
+	case 0x06:
+		pr_info("%s %s : BW = 1.62G\n", LOG_TAG, __func__);
+		break;
+	case 0x0a:
+		pr_info("%s %s : BW = 2.7G\n", LOG_TAG, __func__);
+		break;
+	case 0x14:
+		pr_info("%s %s : BW = 5.4G\n", LOG_TAG, __func__);
+		break;
+	case 0x19:
+		pr_info("%s %s : BW = 6.75G\n", LOG_TAG, __func__);
+		break;
+	default:
+		break;
+	}
+
+	pclk = sp_tx_pclk_calc();
+	pclk = pclk / 10;
+
+	sp_read_reg(TX_P2, SP_TX_TOTAL_LINE_STA_L, &c);
+	sp_read_reg(TX_P2, SP_TX_TOTAL_LINE_STA_H, &c1);
+
+	v_res = c1;
+	v_res = v_res << 8;
+	v_res = v_res + c;
+
+
+	sp_read_reg(TX_P2, SP_TX_ACT_LINE_STA_L, &c);
+	sp_read_reg(TX_P2, SP_TX_ACT_LINE_STA_H, &c1);
+
+	v_act = c1;
+	v_act = v_act << 8;
+	v_act = v_act + c;
+
+
+	sp_read_reg(TX_P2, SP_TX_TOTAL_PIXEL_STA_L, &c);
+	sp_read_reg(TX_P2, SP_TX_TOTAL_PIXEL_STA_H, &c1);
+
+	h_res = c1;
+	h_res = h_res << 8;
+	h_res = h_res + c;
+
+
+	sp_read_reg(TX_P2, SP_TX_ACT_PIXEL_STA_L, &c);
+	sp_read_reg(TX_P2, SP_TX_ACT_PIXEL_STA_H, &c1);
+
+	h_act = c1;
+	h_act = h_act << 8;
+	h_act = h_act + c;
+
+	sp_read_reg(TX_P2, SP_TX_H_F_PORCH_STA_L, &c);
+	sp_read_reg(TX_P2, SP_TX_H_F_PORCH_STA_H, &c1);
+
+	h_fp = c1;
+	h_fp = h_fp << 8;
+	h_fp = h_fp + c;
+
+	sp_read_reg(TX_P2, SP_TX_H_SYNC_STA_L, &c);
+	sp_read_reg(TX_P2, SP_TX_H_SYNC_STA_H, &c1);
+
+	h_sw = c1;
+	h_sw = h_sw << 8;
+	h_sw = h_sw + c;
+
+	sp_read_reg(TX_P2, SP_TX_H_B_PORCH_STA_L, &c);
+	sp_read_reg(TX_P2, SP_TX_H_B_PORCH_STA_H, &c1);
+
+	h_bp = c1;
+	h_bp = h_bp << 8;
+	h_bp = h_bp + c;
+
+	sp_read_reg(TX_P2, SP_TX_V_F_PORCH_STA, &c);
+	v_fp = c;
+
+	sp_read_reg(TX_P2, SP_TX_V_SYNC_STA, &c);
+	v_sw = c;
+
+	sp_read_reg(TX_P2, SP_TX_V_B_PORCH_STA, &c);
+	v_bp = c;
+
+	pr_info("%s %s : Total resolution is %d * %d\n",
+			LOG_TAG, __func__, h_res, v_res);
+
+	pr_info("%s %s : HF=%d, HSW=%d, HBP=%d\n",
+			LOG_TAG, __func__, h_fp, h_sw, h_bp);
+	pr_info("%s %s : VF=%d, VSW=%d, VBP=%d\n",
+			LOG_TAG, __func__, v_fp, v_sw, v_bp);
+	pr_info("%s %s : Active resolution is %d * %d",
+			LOG_TAG, __func__, h_act, v_act);
+
+	if (h_res == 0 || v_res == 0)
+		fresh_rate = 0;
+	else {
+		fresh_rate = pclk * 1000;
+		fresh_rate = fresh_rate / h_res;
+		fresh_rate = fresh_rate * 1000;
+		fresh_rate = fresh_rate / v_res;
+	}
+	pr_info("   @ %ldHz\n", fresh_rate);
+
+	sp_read_reg(TX_P0, SP_TX_VID_CTRL, &c);
+
+	if ((c & 0x06) == 0x00)
+		pr_info("%s %s : ColorSpace: RGB,", LOG_TAG, __func__);
+	else if ((c & 0x06) == 0x02)
+		pr_info("%s %s : ColorSpace: YCbCr422,", LOG_TAG, __func__);
+	else if ((c & 0x06) == 0x04)
+		pr_info("%s %s : ColorSpace: YCbCr444,", LOG_TAG, __func__);
+
+	sp_read_reg(TX_P0, SP_TX_VID_CTRL, &c);
+
+	if ((c & 0xe0) == 0x00)
+		pr_info("6 BPC\n");
+	else if ((c & 0xe0) == 0x20)
+		pr_info("8 BPC\n");
+	else if ((c & 0xe0) == 0x40)
+		pr_info("10 BPC\n");
+	else if ((c & 0xe0) == 0x60)
+		pr_info("12 BPC\n");
+
+
+	if (is_anx_dongle()) {
+		sp_tx_aux_dpcdread_bytes(0x00, 0x05, 0x23, 1, &c);
+		pr_info("%s %s : Analogix Dongle FW Ver %.2x\n",
+				LOG_TAG, __func__, (uint)(c & 0x7f));
+	}
+
+	pr_info("\n**************************************************\n");
+
+}
+
+void hdmi_rx_show_video_info(void)
+{
+	u8 c, c1;
+	u8 cl, ch;
+	uint n;
+	uint h_res, v_res;
+
+	sp_read_reg(RX_P0, HDMI_RX_HACT_LOW, &cl);
+	sp_read_reg(RX_P0, HDMI_RX_HACT_HIGH, &ch);
+	n = ch;
+	n = (n << 8) + cl;
+	h_res = n;
+
+	sp_read_reg(RX_P0, HDMI_RX_VACT_LOW, &cl);
+	sp_read_reg(RX_P0, HDMI_RX_VACT_HIGH, &ch);
+	n = ch;
+	n = (n << 8) + cl;
+	v_res = n;
+
+	pr_info("%s %s : >HDMI_RX Info<\n", LOG_TAG, __func__);
+	sp_read_reg(RX_P0, HDMI_STATUS, &c);
+	if (c & HDMI_MODE)
+		pr_info("%s %s : HDMI_RX Mode = HDMI Mode.\n",
+				LOG_TAG, __func__);
+	else
+		pr_info("%s %s : HDMI_RX Mode = DVI Mode.\n",
+				LOG_TAG, __func__);
+
+	sp_read_reg(RX_P0, HDMI_RX_VIDEO_STATUS_REG1, &c);
+	if (c & VIDEO_TYPE)
+		v_res += v_res;
+	pr_info("%s %s : HDMI_RX Video Resolution = %d * %d ",
+			LOG_TAG, __func__, h_res, v_res);
+	sp_read_reg(RX_P0, HDMI_RX_VIDEO_STATUS_REG1, &c);
+	if (c & VIDEO_TYPE)
+		pr_info("Interlace Video.\n");
+	else
+		pr_info("Progressive Video.\n");
+
+	sp_read_reg(RX_P0, HDMI_RX_SYS_CTRL1_REG, &c);
+	if ((c & 0x30) == 0x00)
+		pr_info("%s %s : Input Pixel Clock = Not Repeated.\n",
+				LOG_TAG, __func__);
+	else if ((c & 0x30) == 0x10)
+		pr_info("%s %s : Input pclk = 2x Video Clock. Repeated.\n",
+			LOG_TAG, __func__);
+	else if ((c & 0x30) == 0x30)
+		pr_info("%s %s : Input pclk = 4x Vvideo Clock. Repeated.\n",
+			LOG_TAG, __func__);
+
+	if ((c & 0xc0) == 0x00)
+		pr_info("%s %s : Output Video Clock = Not Divided.\n",
+				LOG_TAG, __func__);
+	else if ((c & 0xc0) == 0x40)
+		pr_info("%s %s : Output Video Clock = Divided By 2.\n",
+				LOG_TAG, __func__);
+	else if ((c & 0xc0) == 0xc0)
+		pr_info("%s %s : Output Video Clock = Divided By 4.\n",
+				LOG_TAG, __func__);
+
+	if (c & 0x02)
+		pr_info("%s %s : %s\n", LOG_TAG, __func__,
+			"Output Video Using Rising Edge To Latch Data.\n");
+	else
+		pr_info("%s %s : %s\n", LOG_TAG, __func__,
+			"Output Video Using Falling Edge To Latch Data.\n");
+
+
+	pr_info("Input Video Color Depth = ");
+	sp_read_reg(RX_P0, 0x70, &c1);
+	c1 &= 0xf0;
+	if (c1 == 0x00)
+		pr_info("%s %s : Legacy Mode.\n", LOG_TAG, __func__);
+	else if (c1 == 0x40)
+		pr_info("%s %s : 24 Bit Mode.\n", LOG_TAG, __func__);
+	else if (c1 == 0x50)
+		pr_info("%s %s : 30 Bit Mode.\n", LOG_TAG, __func__);
+	else if (c1 == 0x60)
+		pr_info("%s %s : 36 Bit Mode.\n", LOG_TAG, __func__);
+	else if (c1 == 0x70)
+		pr_info("%s %s : 48 Bit Mode.\n", LOG_TAG, __func__);
+
+	pr_info("%s %s : Input Video Color Space = ", LOG_TAG, __func__);
+	sp_read_reg(RX_P1, HDMI_RX_AVI_DATA00_REG, &c);
+	c &= 0x60;
+	if (c == 0x20)
+		pr_info("YCbCr4:2:2 .\n");
+	else if (c == 0x40)
+		pr_info("YCbCr4:4:4 .\n");
+	else if (c == 0x00)
+		pr_info("RGB.\n");
+	else
+		pr_err("Unknown 0x44 = 0x%.2x\n", (int)c);
+
+	sp_read_reg(RX_P1, HDMI_RX_HDCP_STATUS_REG, &c);
+	if (c & AUTH_EN)
+		pr_info("%s %s : Authentication is attempted.\n",
+				LOG_TAG, __func__);
+	else
+		pr_info("%s %s : Authentication is not attempted.\n",
+				LOG_TAG, __func__);
+
+	for (cl = 0; cl < 20; cl++) {
+		sp_read_reg(RX_P1, HDMI_RX_HDCP_STATUS_REG, &c);
+		if (c & DECRYPT_EN)
+			break;
+
+		usleep_range(10000, 11000);
+	}
+
+	if (cl < 20)
+		pr_info("%s %s : Decryption is active.\n", LOG_TAG, __func__);
+	else
+		pr_info("%s %s : Decryption is not active.\n",
+				LOG_TAG, __func__);
+}
+
+void clean_system_status(void)
+{
+	if (g_need_clean_status) {
+		pr_info("%s %s : clean_system_status. A -> B;\n",
+				LOG_TAG, __func__);
+		pr_info("A:");
+		print_sys_state(sp_tx_system_state_bak);
+		pr_info("B:");
+		print_sys_state(sp_tx_system_state);
+
+		g_need_clean_status = 0;
+		if (sp_tx_system_state_bak >= STATE_LINK_TRAINING) {
+			if (sp_tx_system_state >= STATE_AUDIO_OUTPUT)
+				hdmi_rx_mute_audio(1);
+			else {
+				hdmi_rx_mute_video(1);
+				sp_tx_video_mute(1);
+			}
+		}
+		if (sp_tx_system_state_bak >= STATE_HDCP_AUTH
+			&& sp_tx_system_state <= STATE_HDCP_AUTH) {
+			if (sp_i2c_read_byte(TX_P0, TX_HDCP_CTRL0) & 0xFC)
+				sp_tx_clean_hdcp_status();
+		}
+
+		if (hcdp_state != HDCP_CAPABLE_CHECK)
+			hcdp_state = HDCP_CAPABLE_CHECK;
+
+		if (sp_tx_sc_state != SC_INIT)
+			sp_tx_sc_state = SC_INIT;
+		if (sp_tx_lt_state != LT_INIT)
+			sp_tx_lt_state = LT_INIT;
+		if (sp_tx_vo_state != VO_WAIT_VIDEO_STABLE)
+			sp_tx_vo_state = VO_WAIT_VIDEO_STABLE;
+	}
+}
+
+/******************add for HDCP cap check********************/
+void sp_tx_get_ddc_hdcp_BCAP(u8 *bcap)
+{
+	u8 c;
+
+	sp_write_reg(TX_P0, AUX_ADDR_7_0, 0X3A);
+	sp_write_reg(TX_P0, AUX_ADDR_15_8, 0);
+	sp_read_reg(TX_P0, AUX_ADDR_19_16, &c);
+	c &= 0xf0;
+	sp_write_reg(TX_P0, AUX_ADDR_19_16, c);
+
+	sp_tx_aux_wr(0x00);
+	sp_tx_aux_rd(0x01);
+	sp_read_reg(TX_P0, BUF_DATA_0, &c);
+
+
+	sp_tx_aux_wr(0x40);
+	sp_tx_aux_rd(0x01);
+	sp_read_reg(TX_P0, BUF_DATA_0, bcap);
+
+}
+
+void sp_tx_get_ddc_hdcp_BKSV(u8 *bksv)
+{
+	u8 c;
+
+	sp_write_reg(TX_P0, AUX_ADDR_7_0, 0X3A);
+	sp_write_reg(TX_P0, AUX_ADDR_15_8, 0);
+	sp_read_reg(TX_P0, AUX_ADDR_19_16, &c);
+	c &= 0xf0;
+	sp_write_reg(TX_P0, AUX_ADDR_19_16, c);
+
+	sp_tx_aux_wr(0x00);
+	sp_tx_aux_rd(0x01);
+	sp_read_reg(TX_P0, BUF_DATA_0, &c);
+
+
+	sp_tx_aux_wr(0x00);
+	sp_tx_aux_rd(0x01);
+	sp_read_reg(TX_P0, BUF_DATA_0, bksv);
+
+}
+
+u8 slimport_hdcp_cap_check(void)
+{
+	u8 g_hdcp_cap = 0;
+	u8 temp;
+
+	if (AUX_OK == sp_tx_aux_dpcdread_bytes(0x06, 0x80, 0x28, 1, &temp))
+		g_hdcp_cap = (temp & 0x01) ? 1 : 0;
+	else
+		pr_info("HDCP CAPABLE: read AUX err!\n");
+
+	pr_info("%s %s :hdcp cap check: %s Supported\n",
+		LOG_TAG, __func__, g_hdcp_cap ? "" : "No");
+	return g_hdcp_cap;
+}
+/******************End HDCP cap check********************/
+
+void slimport_tasks_handler(void)
+{
+	system_isr_handler();
+	hdcp_external_ctrl_flag_monitor();
+	clean_system_status();
+	/*clear up backup system state*/
+	if (sp_tx_system_state_bak != sp_tx_system_state)
+		sp_tx_system_state_bak = sp_tx_system_state;
+}
+/******************End task  process********************/
+
+void slimport_main_process(struct anx78xx_data *data)
+{
+	slimport_state_process(data);
+	if (sp_tx_system_state > STATE_WAITTING_CABLE_PLUG) {
+		slimport_int_rec();
+		slimport_tasks_handler();
+	}
+}
+
diff --git a/drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.h b/drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.h
new file mode 100644
index 0000000..4928b0a
--- /dev/null
+++ b/drivers/gpu/drm/i2c/anx78xx/slimport_tx_drv.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright(c) 2015, Analogix Semiconductor. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _SP_TX_DRV_H
+#define _SP_TX_DRV_H
+
+#include "slimport.h"
+#include "slimport_tx_reg.h"
+
+#define FW_VERSION	0x22
+
+#define _BIT0		0x01
+#define _BIT1		0x02
+#define _BIT2		0x04
+#define _BIT3		0x08
+#define _BIT4		0x10
+#define _BIT5		0x20
+#define _BIT6		0x40
+#define _BIT7		0x80
+
+#define DVI_MODE	0x00
+#define HDMI_MODE	0x01
+
+#define SP_POWER_ON	1
+#define SP_POWER_DOWN	0
+
+#define MAX_BUF_CNT	16
+
+#define SP_BREAK(current_status, next_status) \
+	{ if (next_status != (current_status) + 1) break; }
+
+extern u8 edid_blocks[256];
+
+/* HDCP control enable/ disable from AP */
+/* external_block_en = 1: enable, 0: disable*/
+extern int external_block_en;
+
+enum rx_cbl_type {
+	DWN_STRM_IS_NULL,
+	DWN_STRM_IS_HDMI,
+	DWN_STRM_IS_DIGITAL,
+	DWN_STRM_IS_ANALOG,
+	DWN_STRM_NUM
+};
+
+enum sp_tx_state {
+	STATE_WAITTING_CABLE_PLUG,
+	STATE_SP_INITIALIZED,
+	STATE_SINK_CONNECTION,
+	STATE_PARSE_EDID,
+	STATE_LINK_TRAINING,
+	STATE_VIDEO_OUTPUT,
+	STATE_HDCP_AUTH,
+	STATE_AUDIO_OUTPUT,
+	STATE_PLAY_BACK
+};
+
+enum sp_tx_power_block {
+	SP_TX_PWR_REG = REGISTER_PD,
+	SP_TX_PWR_HDCP = HDCP_PD,
+	SP_TX_PWR_AUDIO = AUDIO_PD,
+	SP_TX_PWR_VIDEO = VIDEO_PD,
+	SP_TX_PWR_LINK = LINK_PD,
+	SP_TX_PWR_TOTAL = TOTAL_PD,
+	SP_TX_PWR_NUMS
+};
+
+enum hdmi_color_depth {
+	HDMI_LEGACY = 0x00,
+	HDMI_24BIT = 0x04,
+	HDMI_30BIT = 0x05,
+	HDMI_36BIT = 0x06,
+	HDMI_48BIT = 0x07,
+};
+
+enum sp_tx_send_msg {
+	MSG_OCM_EN,
+	MSG_INPUT_HDMI,
+	MSG_INPUT_DVI,
+	MSG_CLEAR_IRQ,
+};
+
+enum sink_connection_status {
+	SC_INIT,
+	SC_CHECK_CABLE_TYPE,
+	SC_WAITTING_CABLE_TYPE = SC_CHECK_CABLE_TYPE+5,
+	SC_SINK_CONNECTED,
+	SC_NOT_CABLE,
+	SC_STATE_NUM
+};
+
+enum cable_type_status {
+	CHECK_AUXCH,
+	GETTED_CABLE_TYPE,
+	CABLE_TYPE_STATE_NUM
+};
+
+enum sp_tx_lt_status {
+	LT_INIT,
+	LT_WAIT_PLL_LOCK,
+	LT_CHECK_LINK_BW,
+	LT_START,
+	LT_WAITTING_FINISH,
+	LT_ERROR,
+	LT_FINISH,
+	LT_END,
+	LT_STATES_NUM
+};
+
+enum hdcp_status {
+	HDCP_CAPABLE_CHECK,
+	HDCP_WAITTING_VID_STB,
+	HDCP_HW_ENABLE,
+	HDCP_WAITTING_FINISH,
+	HDCP_FINISH,
+	HDCP_FAILE,
+	HDCP_NOT_SUPPORT,
+	HDCP_PROCESS_STATE_NUM
+};
+
+enum video_output_status {
+	VO_WAIT_VIDEO_STABLE,
+	VO_WAIT_TX_VIDEO_STABLE,
+	VO_CHECK_VIDEO_INFO,
+	VO_FINISH,
+	VO_STATE_NUM
+};
+
+enum audio_output_status {
+	AO_INIT,
+	AO_CTS_RCV_INT,
+	AO_AUDIO_RCV_INT,
+	AO_RCV_INT_FINISH,
+	AO_OUTPUT,
+	AO_STATE_NUM
+};
+
+struct packet_avi {
+	u8 avi_data[13];
+};
+
+
+struct packet_spd {
+	u8 spd_data[25];
+};
+
+struct packet_mpeg {
+	u8 mpeg_data[13];
+};
+
+struct audio_info_frame {
+	u8 type;
+	u8 version;
+	u8 length;
+	u8 pb_byte[11];
+};
+
+enum packets_type {
+	AVI_PACKETS,
+	SPD_PACKETS,
+	MPEG_PACKETS,
+	VSI_PACKETS,
+	AUDIF_PACKETS
+};
+
+struct common_int {
+	u8 common_int[5];
+	u8 change_flag;
+};
+
+struct hdmi_rx_int {
+	u8 hdmi_rx_int[7];
+	u8 change_flag;
+};
+
+enum xtal_enum {
+	XTAL_19D2M,
+	XTAL_24M,
+	XTAL_25M,
+	XTAL_26M,
+	XTAL_27M,
+	XTAL_38D4M,
+	XTAL_52M,
+	XTAL_NOT_SUPPORT,
+	XTAL_CLK_NUM
+};
+
+enum sp_ssc_dep {
+	SSC_DEP_DISABLE = 0x0,
+	SSC_DEP_500PPM,
+	SSC_DEP_1000PPM,
+	SSC_DEP_1500PPM,
+	SSC_DEP_2000PPM,
+	SSC_DEP_2500PPM,
+	SSC_DEP_3000PPM,
+	SSC_DEP_3500PPM,
+	SSC_DEP_4000PPM,
+	SSC_DEP_4500PPM,
+	SSC_DEP_5000PPM,
+	SSC_DEP_5500PPM,
+	SSC_DEP_6000PPM
+};
+
+struct clock_data {
+	unsigned char xtal_clk;
+	unsigned int xtal_clk_m10;
+};
+
+void sp_tx_edid_read_initial(void);
+u8 sp_tx_get_edid_block(void);
+void sp_tx_rst_aux(void);
+void edid_read(u8 offset, u8 *pblock_buf);
+bool sp_tx_edid_read(u8 *pbuf);
+void check_edid_data(u8 *pblock_buf);
+
+bool slimport_chip_detect(struct anx78xx_data *data);
+
+void slimport_main_process(struct anx78xx_data *data);
+
+void sp_tx_variable_init(void);
+
+u8 sp_tx_aux_dpcdread_bytes(u8 addrh, u8 addrm,
+	u8 addrl, u8 cCount, u8 *pBuf);
+u8 sp_tx_aux_dpcdwrite_bytes(u8 addrh, u8 addrm,
+	u8 addrl, u8 cCount, u8 *pBuf);
+u8 sp_tx_aux_dpcdwrite_byte(u8 addrh, u8 addrm,
+	u8 addrl, u8 data1);
+void sp_tx_show_information(void);
+void hdmi_rx_show_video_info(void);
+void slimport_block_power_ctrl(enum sp_tx_power_block sp_tx_pd_block,
+	u8 power);
+void vbus_power_ctrl(unsigned char on);
+void slimport_initialization(void);
+void sp_tx_clean_state_machine(void);
+u8 sp_tx_cur_states(void);
+void print_sys_state(u8 ss);
+u8 slimport_hdcp_cap_check(void);
+
+void sp_tx_initialization(void);
+u8 sp_tx_cur_bw(void);
+void sp_tx_set_bw(u8 bw);
+
+#endif
diff --git a/drivers/gpu/drm/i2c/anx78xx/slimport_tx_reg.h b/drivers/gpu/drm/i2c/anx78xx/slimport_tx_reg.h
new file mode 100644
index 0000000..db00e7d
--- /dev/null
+++ b/drivers/gpu/drm/i2c/anx78xx/slimport_tx_reg.h
@@ -0,0 +1,786 @@
+/*
+ * Copyright(c) 2015, Analogix Semiconductor. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _SP_TX_REG_DEF_H
+#define _SP_TX_REG_DEF_H
+
+#define TX_P0				0x70
+#define TX_P1				0x7A
+#define TX_P2				0x72
+
+#define RX_P0				0x7e
+#define RX_P1				0x80
+
+/***************************************************************/
+/*Register definition of device address 0x7e*/
+#define HDMI_RX_PORT_SEL_REG		0x10
+#define DDC_EN				0x10
+#define TMDS_EN				0x01
+
+#define RX_SRST				0x11
+#define VIDEO_RST			0x10
+#define HDCP_MAN_RST			0X04
+#define TMDS_RST			0X02
+#define SW_MAN_RST			0X01
+
+#define RX_SW_RST2			0x12
+#define DDC_RST				0x04
+
+#define HDMI_RX_SYS_STATUS_REG		0X14
+#define PWR5V				0X08
+#define TMDS_VSYNC_DET			0X04
+#define TMDS_CLOCK_DET			0X02
+#define TMDS_DE_DET			0X01
+
+#define HDMI_STATUS			0X15
+#define DEEP_COLOR_MODE			0X40
+#define HDMI_AUD_LAYOUT			0X08
+#define MUTE_STAT			0X04
+
+#define RX_MUTE_CTRL			0X16
+#define MUTE_POL			0X04
+#define AUD_MUTE			0X02
+#define VID_MUTE			0X01
+
+#define HDMI_RX_SYS_CTRL1_REG		0X17
+
+#define RX_SYS_PWDN1			0X18
+#define PWDN_CTRL			0X01
+
+#define RX_AEC_CTRL			0X20
+#define AVC_OE				0x80
+#define AAC_OE				0X40
+#define AVC_EN				0X02
+#define AAC_EN				0X01
+
+#define RX_AEC_EN0			0X24
+#define AEC_EN07			0X80
+#define AEC_EN06			0X40
+#define AEC_EN05			0X20
+#define AEC_EN04			0X10
+#define AEC_EN03			0X08
+#define AEC_EN02			0X04
+#define AEC_EN01			0X02
+#define AEC_EN00			0X01
+
+#define RX_AEC_EN1			0X25
+#define AEC_EN15			0X80
+#define AEC_EN14			0X40
+#define AEC_EN13			0X20
+#define AEC_EN12			0X10
+#define AEC_EN11			0X08
+#define AEC_EN10			0X04
+#define AEC_EN09			0X02
+#define AEC_EN08			0X01
+
+#define RX_AEC_EN2			0X26
+#define AEC_EN23			0X80
+#define AEC_EN22			0X40
+#define AEC_EN21			0X20
+#define AEC_EN20			0X10
+#define AEC_EN19			0X08
+#define AEC_EN18			0X04
+#define AEC_EN17			0X02
+#define AEC_EN16			0X01
+
+
+#define HDMI_RX_INT_STATUS1_REG		0X31
+#define HDMI_DVI			0X80
+#define CKDT_CHANGE			0X40
+#define SCDT_CHANGE			0X20
+#define PCLK_CHANGE			0X10
+#define PLL_UNLOCK			0X08
+#define CABLE_UNPLUG			0X04
+#define SET_MUTE			0X02
+#define SW_INTR				0X01
+
+#define HDMI_RX_INT_STATUS2_REG		0X32
+#define AUTH_START			0X80
+#define AUTH_DONE			0X40
+#define HDCP_ERR			0X20
+#define ECC_ERR				0X10
+#define AUDIO_SAMPLE_CHANGE		0X01
+
+#define HDMI_RX_INT_STATUS3_REG		0X33
+#define AUD_MODE_CHANGE			0X01
+
+#define HDMI_RX_INT_STATUS4_REG		0X34
+#define VSYNC_DET			0X80
+#define SYNC_POL_CHANGE			0X40
+#define V_RES_CHANGE			0X20
+#define H_RES_CHANGE			0X10
+#define I_P_CHANGE			0X08
+#define DP_CHANGE			0X04
+#define COLOR_DEPTH_CHANGE		0X02
+#define COLOR_MODE_CHANGE		0X01
+
+#define HDMI_RX_INT_STATUS5_REG		0X35
+#define VFIFO_OVERFLOW			0X80
+#define VFIFO_UNDERFLOW			0X40
+#define CTS_N_ERR			0X08
+#define NO_AVI				0X02
+#define AUDIO_RCV			0X01
+
+#define HDMI_RX_INT_STATUS6_REG		0X36
+#define CTS_RCV				0X80
+#define NEW_UNR_PKT			0X40
+#define NEW_MPEG			0X20
+#define NEW_AUD				0X10
+#define NEW_SPD				0X08
+#define NEW_ACP				0X04
+#define NEW_AVI				0X02
+#define NEW_CP				0X01
+
+#define HDMI_RX_INT_STATUS7_REG		0X37
+#define NO_VSI				0X80
+#define HSYNC_DET			0X20
+#define NEW_VS				0X10
+#define NO_ACP				0X08
+#define REF_CLK_CHG			0X04
+#define CEC_RX_READY			0X02
+#define CEC_TX_DONE			0X01
+
+#define HDMI_RX_PKT_RX_INDU_INT_CTRL	0X3F
+#define NEW_VS_CTRL			0X80
+#define NEW_UNR				0X40
+#define NEW_MPEG			0X20
+#define NEW_AUD				0X10
+#define NEW_SPD				0X08
+#define NEW_ACP				0X04
+#define NEW_AVI				0X02
+
+
+#define HDMI_RX_INT_MASK1_REG		0X41
+#define HDMI_RX_INT_MASK2_REG		0X42
+#define HDMI_RX_INT_MASK3_REG		0X43
+#define HDMI_RX_INT_MASK4_REG		0X44
+#define HDMI_RX_INT_MASK5_REG		0X45
+#define HDMI_RX_INT_MASK6_REG		0X46
+#define HDMI_RX_INT_MASK7_REG		0X47
+
+#define HDMI_RX_TMDS_CTRL_REG1		0X50
+#define HDMI_RX_TMDS_CTRL_REG2		0X51
+#define HDMI_RX_TMDS_CTRL_REG4		0X53
+#define HDMI_RX_TMDS_CTRL_REG5		0X54
+#define HDMI_RX_TMDS_CTRL_REG6		0X55
+#define HDMI_RX_TMDS_CTRL_REG7		0X56
+#define TERM_PD				0x01
+
+#define HDMI_RX_TMDS_CTRL_REG18		0X61
+#define PLL_RESET			0x10
+
+#define HDMI_RX_TMDS_CTRL_REG19		0X62
+#define HDMI_RX_TMDS_CTRL_REG20		0X63
+#define HDMI_RX_TMDS_CTRL_REG21		0X64
+#define HDMI_RX_TMDS_CTRL_REG22		0X65
+
+
+#define HDMI_RX_VIDEO_STATUS_REG1	0x70
+#define COLOR_DEPTH			0xF0
+#define DEFAULT_PHASE			0X08
+#define VIDEO_TYPE			0X04
+
+
+#define HDMI_RX_HTOTAL_LOW		0X71
+#define HDMI_RX_HTOTAL_HIGH		0X72
+#define HDMI_RX_VTOTAL_LOW		0X73
+#define HDMI_RX_VTOTAL_HIGH		0X74
+
+#define HDMI_RX_HACT_LOW		0X75
+#define HDMI_RX_HACT_HIGH		0X76
+#define HDMI_RX_VACT_LOW		0X77
+#define HDMI_RX_VACT_HIGH		0X78
+
+#define HDMI_RX_V_SYNC_WIDTH		0X79
+#define HDMI_RX_V_BACK_PORCH		0X7A
+#define HDMI_RX_H_FRONT_PORCH_LOW	0X7B
+#define HDMI_RX_H_FRONT_PORCH_HIGH	0X7C
+
+#define HDMI_RX_H_SYNC_WIDTH_LOW	0X7D
+#define HDMI_RX_H_SYNC_WIDTH_HIGH	0X7E
+
+#define RX_VID_DATA_RNG			0X83
+#define YC_LIMT				0X10
+#define OUTPUT_LIMIT_EN			0X08
+#define OUTPUT_LIMIT_RANGE		0X04
+#define R2Y_INPUT_LIMIT			0X02
+#define XVYCC_LIMIT			0X01
+
+#define HDMI_RX_VID_OUTPUT_CTRL3_REG	0X86
+
+#define HDMI_RX_VID_PCLK_CNTR_REG	0X8B
+
+#define HDMI_RX_AUD_IN_CH_STATUS1_REG	0xC7
+#define HDMI_RX_AUD_IN_CH_STATUS4_REG	0XCA
+
+#define RX_CEC_CTRL			0XD0
+#define CEC_RX_EN			0X08
+#define CEC_TX_ST			0X04
+#define CEC_PIN_SEL			0X02
+#define CEC_RST				0X01
+
+#define HDMI_RX_CEC_RX_STATUS_REG	0XD1
+#define HDMI_RX_CEC_RX_BUSY		0X80
+#define HDMI_RX_CEC_RX_FULL		0X20
+#define HDMI_RX_CEC_RX_EMP		0X10
+
+#define HDMI_RX_CEC_TX_STATUS_REG	0XD2
+#define HDMI_RX_CEC_TX_BUSY		0X80
+#define HDMI_RX_CEC_TX_FAIL		0X40
+#define HDMI_RX_CEC_TX_FULL		0X20
+#define HDMI_RX_CEC_TX_EMP		0X10
+
+
+#define HDMI_RX_CEC_FIFO_REG		0XD3
+
+#define RX_CEC_SPEED			0XD4
+#define CEC_SPEED_27M			0x40
+
+#define HDMI_RX_HDMI_CRITERIA_REG	0XE1
+
+#define HDMI_RX_HDCP_EN_CRITERIA_REG	0XE2
+#define ENC_EN_MODE			0X20
+
+#define RX_CHIP_CTRL			0XE3
+#define MAN_HDMI5V_DET			0X08
+#define PLLLOCK_CKDT_EN			0X04
+#define ANALOG_CKDT_EN			0X02
+#define DIGITAL_CKDT_EN			0X01
+
+#define RX_PACKET_REV_STA		0XF3
+#define AVI_RCVD			0X40
+#define VSI_RCVD			0X20
+/***************************************************************/
+/*Register definition of device address 0x80*/
+
+
+#define HDMI_RX_HDCP_STATUS_REG		0X3F
+#define ADV_CIPHER			0X80
+#define LOAD_KEY_DONE			0X40
+#define DECRYPT_EN			0X20
+#define AUTH_EN				0X10
+#define BKSV_DISABLE			0X02
+#define CLEAR_RI			0X01
+
+#define HDMI_RX_SPD_TYPE_REG		0X40
+#define HDMI_RX_SPD_VER_REG		0X41
+#define HDMI_RX_SPD_LEN_REG		0X42
+#define HDMI_RX_SPD_CHKSUM_REG		0X43
+#define HDMI_RX_SPD_DATA00_REG		0X44
+
+#define HDMI_RX_ACP_HB0_REG		0X60
+#define HDMI_RX_ACP_HB1_REG		0X61
+#define HDMI_RX_ACP_HB2_REG		0X62
+#define HDMI_RX_ACP_DATA00_REG		0X63
+
+#define HDMI_RX_AVI_TYPE_REG		0XA0
+#define HDMI_RX_AVI_VER_REG		0XA1
+#define HDMI_RX_AVI_LEN_REG		0XA2
+#define HDMI_RX_AVI_CHKSUM_REG		0XA3
+#define HDMI_RX_AVI_DATA00_REG		0XA4
+
+#define HDMI_RX_AUDIO_TYPE_REG		0XC0
+#define HDMI_RX_AUDIO_VER_REG		0XC1
+#define HDMI_RX_AUDIO_LEN_REG		0XC2
+#define HDMI_RX_AUDIO_CHKSUM_REG	0XC3
+#define HDMI_RX_AUDIO_DATA00_REG	0XC4
+
+#define HDMI_RX_MPEG_TYPE_REG		0XE0
+#define HDMI_RX_MPEG_VER_REG		0XE1
+#define HDMI_RX_MPEG_LEN_REG		0XE2
+#define HDMI_RX_MPEG_CHKSUM_REG		0XE3
+#define HDMI_RX_MPEG_DATA00_REG		0XE4
+#define HDMI_RX_MPEG_DATA03_REG		0XE7
+#define HDMI_RX_MPEG_DATA05_REG		0XE9
+
+#define HDMI_RX_SPD_INFO_CTRL		0X5F
+#define HDMI_RX_ACP_INFO_CTRL		0X7F
+
+#define HDMI_RX_GENERAL_CTRL		0X9F
+#define CLEAR_AVMUTE			0x10
+#define SET_AVMUTE			0x01
+
+#define HDMI_RX_MPEG_VS_CTRL		0XDF
+#define HDMI_RX_MPEG_VS_INFO_CTRL	0XFF
+
+
+/***************************************************************/
+/*Register definition of device address 0x70*/
+#define SP_TX_HDCP_STATUS		0x00
+#define SP_TX_HDCP_AUTH_PASS		0x02
+
+#define TX_HDCP_CTRL0			0x01
+#define STORE_AN			0x80
+#define RX_REPEATER			0x40
+#define RE_AUTH				0x20
+#define SW_AUTH_OK			0x10
+#define HARD_AUTH_EN			0x08
+#define ENC_EN				0x04
+#define BKSV_SRM_PASS			0x02
+#define KSVLIST_VLD			0x01
+
+#define SP_TX_HDCP_CTRL1_REG		0x02
+#define AINFO_EN			0x04
+#define RCV_11_EN			0x02
+#define HDCP_11_EN			0x01
+
+#define SP_TX_HDCP_LINK_CHK_FRAME_NUM	0x03
+#define SP_TX_HDCP_CTRL2_REG		0x04
+
+
+#define SP_TX_VID_BLANK_SET1		0X2C
+#define SP_TX_VID_BLANK_SET2		0X2D
+#define SP_TX_VID_BLANK_SET3		0X2E
+
+#define SP_TX_WAIT_R0_TIME		0x40
+#define SP_TX_LINK_CHK_TIMER		0x41
+#define SP_TX_WAIT_KSVR_TIME		0X42
+
+#define HDCP_KEY_STATUS			0x5E
+
+
+#define M_VID_0				0xC0
+#define M_VID_1				0xC1
+#define M_VID_2				0xC2
+#define N_VID_0				0xC3
+#define N_VID_1				0xC4
+#define N_VID_2				0xC5
+#define HDCP_AUTO_TIMER			0x51
+#define HDCP_AUTO_TIMER_VAL		0x00
+
+#define HDCP_KEY_CMD			0x5F
+#define DISABLE_SYNC_HDCP		0x04
+
+#define OTP_KEY_PROTECT1		0x60
+#define OTP_KEY_PROTECT2		0x61
+#define OTP_KEY_PROTECT3		0x62
+#define OTP_PSW1			0xa2
+#define OTP_PSW2			0x7e
+#define OTP_PSW3			0xc6
+
+
+#define SP_TX_SYS_CTRL1_REG		0x80
+#define CHIP_AUTH_RESET			0x80
+#define PD_BYPASS_CHIP_AUTH		0x40
+#define DET_STA				0x04
+#define FORCE_DET			0x02
+#define DET_CTRL			0x01
+
+#define SP_TX_SYS_CTRL2_REG		0x81
+#define CHA_STA				0x04
+#define FORCE_CHA			0x02
+#define CHA_CTRL			0x01
+
+#define SP_TX_SYS_CTRL3_REG		0x82
+#define HPD_STATUS			0x40
+#define F_HPD				0x20
+#define HPD_CTRL			0x10
+#define STRM_VALID			0x04
+#define F_VALID				0x02
+#define VALID_CTRL			0x01
+
+#define SP_TX_SYS_CTRL4_REG		0x83
+#define ENHANCED_MODE			0x08
+
+#define SP_TX_VID_CTRL			0x84
+
+#define SP_TX_AUD_CTRL			0x87
+#define AUD_EN				0x01
+
+#define  I2C_GEN_10US_TIMER0		0x88
+#define  I2C_GEN_10US_TIMER1		0x89
+
+#define SP_TX_PKT_EN_REG		0x90
+#define AUD_IF_UP			0x80
+#define AVI_IF_UD			0x40
+#define MPEG_IF_UD			0x20
+#define SPD_IF_UD			0x10
+#define AUD_IF_EN			0x08
+#define AVI_IF_EN			0x04
+#define MPEG_IF_EN			0x02
+#define SPD_IF_EN			0x01
+
+#define TX_HDCP_CTRL			0x92
+#define AUTO_EN				0x80
+#define AUTO_START			0x20
+#define LINK_POLLING			0x02
+
+#define SP_TX_LINK_BW_SET_REG		0xA0
+#define LINK_6P75G			0x19
+#define LINK_5P4G			0x14
+#define LINK_2P7G			0x0A
+#define LINK_1P62G			0x06
+
+#define SP_TX_TRAINING_PTN_SET_REG	0xA2
+#define SCRAMBLE_DISABLE		0x20
+
+#define SP_TX_LT_SET_REG		0xA3
+#define MAX_PRE_REACH			0x20
+#define MAX_DRIVE_REACH			0x04
+#define DRVIE_CURRENT_LEVEL1		0x01
+#define PRE_EMP_LEVEL1			0x08
+
+
+#define LT_CTRL				0xA8
+#define SP_TX_LT_EN			0x01
+
+#define TX_DEBUG1			0xB0
+#define FORCE_HPD			0X80
+#define HPD_POLLING_DET			0x40
+#define HPD_POLLING_EN			0x20
+#define DEBUG_PLL_LOCK			0x10
+#define FORCE_PLL_LOCK			0X08
+#define POLLING_EN			0x02
+
+#define SP_TX_DP_POLLING_PERIOD		0xB3
+
+#define TX_DP_POLLING			0xB4
+#define AUTO_POLLING_DISABLE		0x01
+
+#define TX_LINK_DEBUG			0xB8
+#define M_VID_DEBUG			0x20
+#define NEW_PRBS7			0x10
+#define INSERT_ER			0x02
+#define PRBS31_EN			0x01
+
+#define DPCD_200			0xB9
+#define DPCD_201			0xBA
+#define DPCD_202			0xBB
+#define DPCD_203			0xBC
+#define DPCD_204			0xBD
+#define DPCD_205			0xBE
+
+#define SP_TX_PLL_CTRL_REG		0xC7
+#define PLL_RST				0x40
+
+#define SP_TX_ANALOG_PD_REG		0xC8
+#define MACRO_PD			0x20
+#define AUX_PD				0x10
+#define CH0_PD				0x01
+
+#define TX_MISC				0xCD
+#define EQ_TRAINING_LOOP		0x40
+
+
+#define SP_TX_DOWN_SPREADING_CTRL1	0xD0
+#define SP_TX_SSC_DISABLE		0xC0
+#define SP_TX_SSC_DWSPREAD		0x40
+
+
+#define SP_TX_M_CALCU_CTRL		0xD9
+#define M_GEN_CLK_SEL			0x01
+
+#define TX_EXTRA_ADDR			0xCE
+#define I2C_STRETCH_DISABLE		0X80
+#define I2C_EXTRA_ADDR			0X50
+
+#define SP_TX_AUX_STATUS		0xE0
+#define AUX_BUSY			0x10
+
+#define AUX_DEFER_CTRL			0xE2
+#define BUF_DATA_COUNT			0xE4
+
+#define AUX_CTRL			0xE5
+#define AUX_ADDR_7_0			0xE6
+#define AUX_ADDR_15_8			0xE7
+#define AUX_ADDR_19_16			0xE8
+
+#define AUX_CTRL2			0xE9
+#define ADDR_ONLY_BIT			0x02
+#define AUX_OP_EN			0x01
+
+#define SP_TX_3D_VSC_CTRL		0xEA
+#define INFO_FRAME_VSC_EN		0x01
+
+#define SP_TX_VSC_DB1			0xEB
+
+#define BUF_DATA_0			0xF0
+
+
+/***************************************************************/
+/*Register definition of device address 0x72*/
+#define SP_TX_VND_IDL_REG		0x00
+#define SP_TX_VND_IDH_REG		0x01
+#define SP_TX_DEV_IDL_REG		0x02
+#define SP_TX_DEV_IDH_REG		0x03
+#define SP_TX_DEV_REV_REG		0x04
+
+#define SP_POWERD_CTRL_REG		0x05
+#define REGISTER_PD			0x80
+#define HDCP_PD				0x20
+#define AUDIO_PD			0x10
+#define VIDEO_PD			0x08
+#define LINK_PD				0x04
+#define TOTAL_PD			0x02
+
+#define SP_TX_RST_CTRL_REG		0x06
+#define MISC_RST			0x80
+#define VIDCAP_RST			0x40
+#define VIDFIF_RST			0x20
+#define AUDFIF_RST			0x10
+#define AUDCAP_RST			0x08
+#define HDCP_RST			0x04
+#define SW_RST				0x02
+#define HW_RST				0x01
+
+#define RST_CTRL2			0x07
+#define AUX_RST				0x04
+#define SERDES_FIFO_RST			0x02
+#define I2C_REG_RST			0x01
+
+#define VID_CTRL1			0x08
+#define VIDEO_EN			0x80
+#define VIDEO_MUTE			0x40
+#define IN_BIT_SEl			0x04
+#define DDR_CTRL			0x02
+#define EDGE_CTRL			0x01
+
+#define SP_TX_VID_CTRL2_REG		0x09
+#define IN_BPC_12BIT			0x30
+#define IN_BPC_10BIT			0x20
+#define IN_BPC_8BIT			0x10
+
+#define SP_TX_VID_CTRL3_REG		0x0A
+#define HPD_OUT				0x40
+
+#define SP_TX_VID_CTRL5_REG		0x0C
+#define CSC_STD_SEL			0x80
+#define RANGE_Y2R			0x20
+#define CSPACE_Y2R			0x10
+
+#define SP_TX_VID_CTRL6_REG		0x0D
+#define VIDEO_PROCESS_EN		0x40
+#define UP_SAMPLE			0x02
+#define DOWN_SAMPLE			0x01
+
+#define SP_TX_VID_CTRL8_REG		0x0F
+#define VID_VRES_TH			0x01
+
+#define SP_TX_TOTAL_LINE_STA_L		0x24
+#define SP_TX_TOTAL_LINE_STA_H		0x25
+#define SP_TX_ACT_LINE_STA_L		0x26
+#define SP_TX_ACT_LINE_STA_H		0x27
+#define SP_TX_V_F_PORCH_STA		0x28
+#define SP_TX_V_SYNC_STA		0x29
+#define SP_TX_V_B_PORCH_STA		0x2A
+#define SP_TX_TOTAL_PIXEL_STA_L		0x2B
+#define SP_TX_TOTAL_PIXEL_STA_H		0x2C
+#define SP_TX_ACT_PIXEL_STA_L		0x2D
+#define SP_TX_ACT_PIXEL_STA_H		0x2E
+#define SP_TX_H_F_PORCH_STA_L		0x2F
+#define SP_TX_H_F_PORCH_STA_H		0x30
+#define SP_TX_H_SYNC_STA_L		0x31
+#define SP_TX_H_SYNC_STA_H		0x32
+#define SP_TX_H_B_PORCH_STA_L		0x33
+#define SP_TX_H_B_PORCH_STA_H		0x34
+
+#define SP_TX_DP_ADDR_REG1		0x3E
+
+#define SP_TX_VID_BIT_CTRL0_REG		0x40
+#define SP_TX_VID_BIT_CTRL10_REG	0x4a
+#define SP_TX_VID_BIT_CTRL20_REG	0x54
+
+#define SP_TX_AVI_TYPE			0x70
+#define SP_TX_AVI_VER			0x71
+#define SP_TX_AVI_LEN			0x72
+#define SP_TX_AVI_DB0			0x73
+
+#define BIT_CTRL_SPECIFIC		0x80
+#define ENABLE_BIT_CTRL			0x01
+
+#define SP_TX_AUD_TYPE			0x83
+#define SP_TX_AUD_VER			0x84
+#define SP_TX_AUD_LEN			0x85
+#define SP_TX_AUD_DB0			0x86
+
+#define SP_TX_SPD_TYPE			0x91
+#define SP_TX_SPD_VER			0x92
+#define SP_TX_SPD_LEN			0x93
+#define SP_TX_SPD_DB0			0x94
+
+#define SP_TX_MPEG_TYPE			0xB0
+#define SP_TX_MPEG_VER			0xB1
+#define SP_TX_MPEG_LEN			0xB2
+#define SP_TX_MPEG_DB0			0xB3
+
+#define SP_TX_AUD_CH_STATUS_REG1	0xD0
+
+#define SP_TX_AUD_CH_NUM_REG5		0xD5
+#define CH_NUM_8			0xE0
+#define AUD_LAYOUT			0x01
+
+#define GPIO_1_CONTROL			0xD6
+#define GPIO_1_PULL_UP			0x04
+#define GPIO_1_OEN			0x02
+#define GPIO_1_DATA			0x01
+
+#define TX_ANALOG_DEBUG2		0xDD
+#define POWERON_TIME_1P5MS		0X03
+
+#define TX_PLL_FILTER			0xDF
+#define PD_RING_OSC			0x40
+#define V33_SWITCH_ON			0x08
+
+#define TX_PLL_FILTER5			0xE0
+#define SP_TX_ANALOG_CTRL0		0xE1
+#define P5V_PROTECT			0X80
+#define SHORT_PROTECT			0X40
+#define P5V_PROTECT_PD			0X20
+#define SHORT_PROTECT_PD		0X10
+
+#define TX_ANALOG_CTRL			0xE5
+#define SHORT_DPDM			0X4
+
+#define SP_COMMON_INT_STATUS1		0xF1
+#define PLL_LOCK_CHG			0x40
+#define VIDEO_FORMAT_CHG		0x08
+#define AUDIO_CLK_CHG			0x04
+#define VIDEO_CLOCK_CHG			0x02
+
+#define SP_COMMON_INT_STATUS2		0xF2
+#define HDCP_AUTH_CHG			0x02
+#define HDCP_AUTH_DONE			0x01
+
+#define SP_COMMON_INT_STATUS3		0xF3
+#define HDCP_LINK_CHECK_FAIL		0x01
+
+#define SP_COMMON_INT_STATUS4		0xF4
+#define PLUG				0x01
+#define ESYNC_ERR			0x10
+#define HPD_LOST			0x02
+#define HPD_CHANGE			0x04
+#define HPD_IRQ				0x40
+
+#define SP_TX_INT_STATUS1		0xF7
+#define DPCD_IRQ_REQUEST		0x80
+#define HPD				0x40
+#define TRAINING_Finish			0x20
+#define POLLING_ERR			0x10
+#define LINK_CHANGE			0x04
+#define SINK_CHG			0x08
+
+#define SP_COMMON_INT_MASK1		0xF8
+#define SP_COMMON_INT_MASK2		0xF9
+#define SP_COMMON_INT_MASK3		0xFA
+#define SP_COMMON_INT_MASK4		0xFB
+#define SP_INT_MASK			0xFE
+#define SP_TX_INT_CTRL_REG		0xFF
+
+
+/***************************************************************/
+/*Register definition of device address 0x7a*/
+
+#define SP_TX_LT_CTRL_REG0		0x30
+#define SP_TX_LT_CTRL_REG1		0x31
+#define SP_TX_LT_CTRL_REG2		0x34
+#define SP_TX_LT_CTRL_REG3		0x35
+#define SP_TX_LT_CTRL_REG4		0x36
+#define SP_TX_LT_CTRL_REG5		0x37
+#define SP_TX_LT_CTRL_REG6		0x38
+#define SP_TX_LT_CTRL_REG7		0x39
+#define SP_TX_LT_CTRL_REG8		0x3A
+#define SP_TX_LT_CTRL_REG9		0x3B
+#define SP_TX_LT_CTRL_REG10		0x40
+#define SP_TX_LT_CTRL_REG11		0x41
+#define SP_TX_LT_CTRL_REG12		0x44
+#define SP_TX_LT_CTRL_REG13		0x45
+#define SP_TX_LT_CTRL_REG14		0x46
+#define SP_TX_LT_CTRL_REG15		0x47
+#define SP_TX_LT_CTRL_REG16		0x48
+#define SP_TX_LT_CTRL_REG17		0x49
+#define SP_TX_LT_CTRL_REG18		0x4A
+#define SP_TX_LT_CTRL_REG19		0x4B
+
+#define SP_TX_AUD_INTERFACE_CTRL0	0x5f
+#define AUD_INTERFACE_DISABLE		0x80
+
+#define SP_TX_AUD_INTERFACE_CTRL2	0x60
+#define M_AUD_ADJUST_ST			0x04
+
+#define SP_TX_AUD_INTERFACE_CTRL3	0x62
+#define SP_TX_AUD_INTERFACE_CTRL4	0x67
+#define SP_TX_AUD_INTERFACE_CTRL5	0x68
+#define SP_TX_AUD_INTERFACE_CTRL6	0x69
+
+#define OCM_REG3			0x96
+#define OCM_RST				0x80
+
+#define FW_VER_REG			0xB7
+
+
+/***************************************************************/
+/*Definition of DPCD*/
+
+
+#define DOWN_R_TERM_DET _BIT6
+#define SRAM_EEPROM_LOAD_DONE _BIT5
+#define SRAM_CRC_CHK_DONE _BIT4
+#define SRAM_CRC_CHK_PASS _BIT3
+#define DOWN_STRM_ENC _BIT2
+#define DOWN_STRM_AUTH _BIT1
+#define DOWN_STRM_HPD _BIT0
+
+
+#define DPCD_DPCD_REV			0x00
+#define DPCD_MAX_LINK_RATE		0x01
+
+#define DPCD_MAX_LANE_COUNT		0x02
+#define ENHANCED_FRAME_CAP		0x80
+
+#define DPCD_MAX_DOWNSPREAD		0x03
+#define DPCD_NORP			0x04
+#define DPCD_DSPORT_PRESENT		0x05
+
+#define DPCD_LINK_BW_SET		0x00
+#define DPCD_LANE_COUNT_SET		0x01
+#define ENHANCED_FRAME_EN		0x80
+
+#define DPCD_TRAINING_PATTERN_SET	0x02
+#define DPCD_TRAINNIG_LANE0_SET		0x03
+
+#define DPCD_DOWNSPREAD_CTRL		0x07
+#define SPREAD_AMPLITUDE		0X10
+
+#define DPCD_SINK_COUNT			0x00
+#define DPCD_SERVICE_IRQ_VECTOR		0x01
+#define TEST_IRQ			0x02
+#define CP_IRQ				0x04
+#define SINK_SPECIFIC_IRQ		0x40
+
+#define DPCD_LANE0_1_STATUS		0x02
+
+#define DPCD_LANE_ALIGN_UD		0x04
+#define DPCD_SINK_STATUS		0x05
+
+#define DPCD_TEST_RESPONSE		0x60
+#define TEST_ACK			0x01
+#define DPCD_TEST_EDID_CHECKSUM_WRITE	0x04
+
+#define DPCD_TEST_EDID_CHECKSUM		0x61
+
+
+#define DPCD_SPECIFIC_INTERRUPT1	0x10
+#define DPCD_USER_COMM1			0x22
+
+#define DPCD_SPECIFIC_INTERRUPT2	0x11
+
+#define DPCD_TEST_REQUEST		0x18
+#define DPCD_TEST_LINK_RATE		0x19
+
+#define DPCD_TEST_LANE_COUNT		0x20
+
+#define DPCD_PHY_TEST_PATTERN		0x48
+
+#endif
+
-- 
2.1.0



More information about the dri-devel mailing list