linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: jasondong <jason.dong@ite.com.tw>
To: linux-media@vger.kernel.org
Subject: [PATCH 1/1] Add driver support for ITE IT9135 device
Date: Fri, 05 Aug 2011 18:24:55 +0800	[thread overview]
Message-ID: <1312539895.2763.33.camel@Jason-Linux> (raw)

This is DVB USB Linux driver for ITEtech IT9135 base USB TV module.
It supported the IT9135 AX and BX chip versions.

Signed-off-by: jasondong <jason.dong@ite.com.tw>
---
 Documentation/dvb/get_dvb_firmware      |   17 +-
 drivers/media/dvb/dvb-usb/Kconfig       |    6 +
 drivers/media/dvb/dvb-usb/Makefile      |    3 +
 drivers/media/dvb/dvb-usb/dvb-usb-ids.h |    4 +
 drivers/media/dvb/dvb-usb/it9135-fe.c   | 4743 +++++++++++++++++++++++++++++++
 drivers/media/dvb/dvb-usb/it9135-fe.h   | 1632 +++++++++++
 drivers/media/dvb/dvb-usb/it9135.c      | 2492 ++++++++++++++++
 drivers/media/dvb/dvb-usb/it9135.h      |  155 +
 8 files changed, 9051 insertions(+), 1 deletions(-)
 mode change 100644 => 100755 Documentation/dvb/get_dvb_firmware
 create mode 100644 drivers/media/dvb/dvb-usb/it9135-fe.c
 create mode 100644 drivers/media/dvb/dvb-usb/it9135-fe.h
 create mode 100644 drivers/media/dvb/dvb-usb/it9135.c
 create mode 100644 drivers/media/dvb/dvb-usb/it9135.h

diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
old mode 100644
new mode 100755
index 3348d31..1b30198
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -27,7 +27,7 @@ use IO::Handle;
 		"or51211", "or51132_qam", "or51132_vsb", "bluebird",
 		"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
 		"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
-		"lme2510c_s7395_old");
+		"lme2510c_s7395_old", "it9135");
 
 # Check args
 syntax() if (scalar(@ARGV) != 1);
@@ -634,6 +634,21 @@ sub lme2510c_s7395_old {
     $outfile;
 }
 
+sub it9135 {
+	my $sourcefile = "dvb-usb-it9135.zip";
+	my $url = "http://www.ite.com.tw/uploads/firmware/v3.6.0.0/$sourcefile";
+	my $hash = "1e55f6c8833f1d0ae067c2bb2953e6a9";
+	my $outfile = "dvb-usb-it9135.fw";
+
+	checkstandard();
+
+	wgetfile($sourcefile, $url);
+	unzip($sourcefile, "");
+	verify("$outfile", $hash);
+
+	$outfile;
+}
+
 # ---------------------------------------------------------------
 # Utilities
 
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index e85304c..468fe8e 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -373,3 +373,9 @@ config DVB_USB_TECHNISAT_USB2
 	select DVB_STV6110x if !DVB_FE_CUSTOMISE
 	help
 	  Say Y here to support the Technisat USB2 DVB-S/S2 device
+
+config DVB_USB_IT9135
+	tristate "ITEtech IT9135 DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the ITE IT9135 based DVB-T USB2.0 receiver
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 4bac13d..466b23c 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -94,6 +94,9 @@ obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o
 dvb-usb-technisat-usb2-objs = technisat-usb2.o
 obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
 
+dvb-usb-it9135-objs := it9135.o it9135-fe.o
+obj-$(CONFIG_DVB_USB_IT9135) += dvb-usb-it9135.o
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 21b1549..ffeb338 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -67,6 +67,7 @@
 #define USB_VID_EVOLUTEPC			0x1e59
 #define USB_VID_AZUREWAVE			0x13d3
 #define USB_VID_TECHNISAT			0x14f7
+#define USB_VID_ITETECH				0x048d
 
 /* Product IDs */
 #define USB_PID_ADSTECH_USB2_COLD			0xa333
@@ -320,4 +321,7 @@
 #define USB_PID_TECHNISAT_USB2_HDCI_V2			0x0002
 #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2		0x0004
 #define USB_PID_TECHNISAT_USB2_DVB_S2			0x0500
+#define USB_PID_ITETECH_IT9135				0x9135
+#define USB_PID_ITETECH_IT9135_9005			0x9005
+#define USB_PID_ITETECH_IT9135_9006			0x9006
 #endif
diff --git a/drivers/media/dvb/dvb-usb/it9135-fe.c b/drivers/media/dvb/dvb-usb/it9135-fe.c
new file mode 100644
index 0000000..e3ddbf3
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/it9135-fe.c
@@ -0,0 +1,4743 @@
+/*
+ * DVB USB Linux driver for IT9135 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2011 ITE Technologies, INC.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+
+#include "it9135.h"
+
+static unsigned long it9135_enter_mutex(struct it9135_data *data)
+{
+	/*
+	 *  ToDo:  Add code here
+	 */
+	return ERROR_NO_ERROR;
+}
+
+static unsigned long it9135_leave_mutex(struct it9135_data *data)
+{
+	/*
+	 *  ToDo:  Add code here
+	 */
+	return ERROR_NO_ERROR;
+}
+
+/*
+ * IT9135 command functions
+ */
+#define IT9135_MAX_CMD_SIZE		63
+
+static unsigned long it9135_cmd_add_checksum(struct it9135_data *data,
+					     unsigned long *buff_len,
+					     unsigned char *buffer)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long loop = (*buff_len - 1) / 2;
+	unsigned long remain = (*buff_len - 1) % 2;
+	unsigned long i;
+	unsigned short checksum = 0;
+
+	for (i = 0; i < loop; i++)
+		checksum +=
+		    (unsigned short)(buffer[2 * i + 1] << 8) +
+		    (unsigned short)(buffer[2 * i + 2]);
+	if (remain)
+		checksum += (unsigned short)(buffer[*buff_len - 1] << 8);
+
+	checksum = ~checksum;
+	buffer[*buff_len] = (unsigned char)((checksum & 0xFF00) >> 8);
+	buffer[*buff_len + 1] = (unsigned char)(checksum & 0x00FF);
+	buffer[0] = (unsigned char)(*buff_len + 1);
+	*buff_len += 2;
+
+	return error;
+}
+
+static unsigned long it9135_cmd_remove_checksum(struct it9135_data *data,
+						unsigned long *buff_len,
+						unsigned char *buffer)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long loop = (*buff_len - 3) / 2;
+	unsigned long remain = (*buff_len - 3) % 2;
+	unsigned long i;
+	unsigned short checksum = 0;
+
+	for (i = 0; i < loop; i++)
+		checksum +=
+		    (unsigned short)(buffer[2 * i + 1] << 8) +
+		    (unsigned short)(buffer[2 * i + 2]);
+	if (remain)
+		checksum += (unsigned short)(buffer[*buff_len - 3] << 8);
+
+	checksum = ~checksum;
+	if (((unsigned short)(buffer[*buff_len - 2] << 8) +
+	     (unsigned short)(buffer[*buff_len - 1])) != checksum) {
+		error = ERROR_WRONG_CHECKSUM;
+		goto exit;
+	}
+	if (buffer[2])
+		error = ERROR_FIRMWARE_STATUS | buffer[2];
+
+	buffer[0] = (unsigned char)(*buff_len - 3);
+	*buff_len -= 2;
+
+exit:
+	return error;
+}
+
+#define IT9135_USB_BULK_TIMEOUT		2000
+
+static unsigned long it9135_cmd_bus_tx(struct it9135_data *data,
+				       unsigned long buff_len,
+				       unsigned char *buffer)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	int act_len, ret;
+
+	ret = usb_bulk_msg(usb_get_dev(data->driver),
+			   usb_sndbulkpipe(usb_get_dev(data->driver), 0x02),
+			   buffer, buff_len, &act_len, IT9135_USB_BULK_TIMEOUT);
+
+	if (ret) {
+		error = ERROR_USB_WRITE_FAIL;
+		err(" it9135_cmd_bus_tx fail : %d!", ret);
+	}
+
+	return error;
+}
+
+static unsigned long it9135_cmd_bus_rx(struct it9135_data *data,
+				       unsigned long buff_len,
+				       unsigned char *buffer)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	int act_len, ret;
+
+	ret = usb_bulk_msg(usb_get_dev(data->driver),
+			   usb_rcvbulkpipe(usb_get_dev(data->driver), 129),
+			   buffer, 125, &act_len, IT9135_USB_BULK_TIMEOUT);
+
+	if (ret) {
+		error = ERROR_USB_WRITE_FAIL;
+		err(" it9135_cmd_bus_rx fail: %d!", ret);
+	}
+
+	return error;
+}
+
+static unsigned long it9135_cmd_loadfirmware(struct it9135_data *data,
+					     unsigned long length,
+					     unsigned char *firmware)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned short command;
+	unsigned long loop;
+	unsigned long remain;
+	unsigned long i, j, k;
+	unsigned char buffer[255];
+	unsigned long payloadLength;
+	unsigned long buff_len;
+	unsigned long remain_len;
+	unsigned long send_len;
+
+	it9135_enter_mutex(data);
+
+	payloadLength = (IT9135_MAX_CMD_SIZE - 6);
+	loop = length / payloadLength;
+	remain = length % payloadLength;
+
+	k = 0;
+	command = it9135_build_command(CMD_FW_DOWNLOAD, PROCESSOR_LINK, 0);
+	for (i = 0; i < loop; i++) {
+		buffer[1] = (unsigned char)(command >> 8);
+		buffer[2] = (unsigned char)command;
+		buffer[3] = (unsigned char)data->cmd_seq++;
+
+		for (j = 0; j < payloadLength; j++)
+			buffer[4 + j] = firmware[j + i * payloadLength];
+
+		buff_len = 4 + payloadLength;
+		error = it9135_cmd_add_checksum(data, &buff_len, buffer);
+		if (error)
+			goto exit;
+
+		send_len = 0;
+		remain_len = IT9135_MAX_CMD_SIZE;
+		while (remain_len > 0) {
+			k = (remain_len >
+			     IT9135_MAX_PKT_SIZE) ? (IT9135_MAX_PKT_SIZE)
+			    : (remain_len);
+			error = it9135_cmd_bus_tx(data, k, &buffer[send_len]);
+			if (error)
+				goto exit;
+
+			send_len += k;
+			remain_len -= k;
+		}
+	}
+
+	if (remain) {
+		buffer[1] = (unsigned char)(command >> 8);
+		buffer[2] = (unsigned char)command;
+		buffer[3] = (unsigned char)data->cmd_seq++;
+
+		for (j = 0; j < remain; j++)
+			buffer[4 + j] = firmware[j + i * payloadLength];
+
+		buff_len = 4 + remain;
+		error = it9135_cmd_add_checksum(data, &buff_len, buffer);
+		if (error)
+			goto exit;
+
+		send_len = 0;
+		remain_len = buff_len;
+		while (remain_len > 0) {
+			k = (remain_len >
+			     IT9135_MAX_PKT_SIZE) ? (IT9135_MAX_PKT_SIZE)
+			    : (remain_len);
+			error = it9135_cmd_bus_tx(data, k, &buffer[send_len]);
+			if (error)
+				goto exit;
+
+			send_len += k;
+			remain_len -= k;
+		}
+	}
+
+exit:
+	it9135_leave_mutex(data);
+	return error;
+}
+
+static unsigned long it9135_cmd_reboot(struct it9135_data *data,
+				       unsigned char chip)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned short command;
+	unsigned char buffer[255];
+	unsigned long buff_len;
+
+	it9135_enter_mutex(data);
+
+	command = it9135_build_command(CMD_REBOOT, PROCESSOR_LINK, chip);
+	buffer[1] = (unsigned char)(command >> 8);
+	buffer[2] = (unsigned char)command;
+	buffer[3] = (unsigned char)data->cmd_seq++;
+	buff_len = 4;
+	error = it9135_cmd_add_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+	error = it9135_cmd_bus_tx(data, buff_len, buffer);
+	if (error)
+		goto exit;
+
+exit:
+	it9135_leave_mutex(data);
+	return error;
+}
+
+/*
+ * Send the command to device.
+ *
+ * @param struct it9135_data the handle of IT9135.
+ * @param command the command to be send.
+ * @param chip The index of IT9135. The possible values are 0~7.
+ * @param processor The processor of specified register. Because each chip
+ *        has two processor so user have to specify the processor. The
+ *        possible values are PROCESSOR_LINK and PROCESSOR_OFDM.
+ * @param w_buff_len the number of registers to be write.
+ * @param w_buff a unsigned char array which is used to store values to be write.
+ * @param r_buff_len the number of registers to be read.
+ * @param r_buff a unsigned char array which is used to store values to be read.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+static unsigned long it9135_cmd_sendcommand(struct it9135_data *data,
+					    unsigned short command,
+					    unsigned char chip,
+					    unsigned char processor,
+					    unsigned long w_buff_len,
+					    unsigned char *w_buff,
+					    unsigned long r_buff_len,
+					    unsigned char *r_buff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char buffer[255];
+	unsigned long buff_len;
+	unsigned long remain_len;
+	unsigned long send_len;
+	unsigned long i, k;
+
+	it9135_enter_mutex(data);
+
+	if ((w_buff_len + 6) > IT9135_MAX_CMD_SIZE) {
+		error = ERROR_INVALID_DATA_LENGTH;
+		goto exit;
+	}
+
+	if ((r_buff_len + 5) > IT9135_MAX_PKT_SIZE) {
+		error = ERROR_INVALID_DATA_LENGTH;
+		goto exit;
+	}
+
+	if ((r_buff_len + 5) > IT9135_MAX_CMD_SIZE) {
+		error = ERROR_INVALID_DATA_LENGTH;
+		goto exit;
+	}
+
+	if (w_buff_len == 0) {
+		command = it9135_build_command(command, processor, chip);
+		buffer[1] = (unsigned char)(command >> 8);
+		buffer[2] = (unsigned char)command;
+		buffer[3] = (unsigned char)data->cmd_seq++;
+		buff_len = 4;
+		error = it9135_cmd_add_checksum(data, &buff_len, buffer);
+		if (error)
+			goto exit;
+
+		/* send command packet */
+		i = 0;
+		send_len = 0;
+		remain_len = buff_len;
+		while (remain_len > 0) {
+			i = (remain_len >
+			     IT9135_MAX_PKT_SIZE) ? (IT9135_MAX_PKT_SIZE)
+			    : (remain_len);
+			error = it9135_cmd_bus_tx(data, i, &buffer[send_len]);
+			if (error)
+				goto exit;
+
+			send_len += i;
+			remain_len -= i;
+		}
+	} else {
+		command = it9135_build_command(command, processor, chip);
+		buffer[1] = (unsigned char)(command >> 8);
+		buffer[2] = (unsigned char)command;
+		buffer[3] = (unsigned char)data->cmd_seq++;
+		for (k = 0; k < w_buff_len; k++)
+			buffer[k + 4] = w_buff[k];
+
+		buff_len = 4 + w_buff_len;
+		error = it9135_cmd_add_checksum(data, &buff_len, buffer);
+		if (error)
+			goto exit;
+
+		/* send command */
+		i = 0;
+		send_len = 0;
+		remain_len = buff_len;
+		while (remain_len > 0) {
+			i = (remain_len >
+			     IT9135_MAX_PKT_SIZE) ? (IT9135_MAX_PKT_SIZE)
+			    : (remain_len);
+			error = it9135_cmd_bus_tx(data, i, &buffer[send_len]);
+			if (error)
+				goto exit;
+
+			send_len += i;
+			remain_len -= i;
+		}
+	}
+
+	buff_len = 5 + r_buff_len;
+
+	error = it9135_cmd_bus_rx(data, buff_len, buffer);
+	if (error)
+		goto exit;
+
+	error = it9135_cmd_remove_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+	if (r_buff_len) {
+		for (k = 0; k < r_buff_len; k++)
+			r_buff[k] = buffer[k + 3];
+	}
+
+exit:
+	it9135_leave_mutex(data);
+	return error;
+}
+
+/*
+ * IT9135 tuner functions
+ */
+
+static unsigned int it9135_tuner_get_nv(unsigned int nc)
+{
+	unsigned int nv;
+
+	switch (nc) {
+	case 0:
+		nv = 48;
+		break;
+	case 1:
+		nv = 32;
+		break;
+	case 2:
+		nv = 24;
+		break;
+	case 3:
+		nv = 16;
+		break;
+	case 4:
+		nv = 12;
+		break;
+	case 5:
+		nv = 8;
+		break;
+	case 6:
+		nv = 6;
+		break;
+	case 7:
+		nv = 4;
+		break;
+	case 8:		/* L-band */
+		nv = 2;
+		break;
+	default:
+		nv = 2;
+		break;
+	}
+
+	return nv;
+}
+
+static unsigned int it9135_fn_min[] = {
+	53000, 74000, 111000, 148000, 222000, 296000, 445000, 573000, 950000
+};
+
+static unsigned long it9135_tuner_init(struct it9135_data *data,
+				       unsigned char chip)
+{
+	unsigned long error = 0;
+	unsigned char buf[4], val;
+	unsigned int m_bdry, nc, nv;
+	unsigned long tmp_numer, tmp_denom;
+	unsigned int cnt;
+
+#define OMEGA_TUNER_INIT_POLL_INTERVAL	2
+#define OMEGA_TUNER_INIT_POLL_COUNTS	50
+
+	/* ----- read ----- */
+	/* p_reg_p_tsm_init_clock_mode */
+	error = it9135_read_regs(data, chip, PROCESSOR_OFDM, 0xEC86, 1, buf);
+	if (error)
+		goto exit;
+	/* p_reg_p_fbc_n_code */
+	error =
+	    it9135_read_regs(data, chip, PROCESSOR_OFDM, 0xED03, 1, &buf[1]);
+	if (error)
+		goto exit;
+	/* r_reg_r_fbc_m_bdry_7_0 */
+	error =
+	    it9135_read_regs(data, chip, PROCESSOR_OFDM, 0xED23, 2, &buf[2]);
+	if (error)
+		goto exit;
+
+	/* ----- set_clock_mode ----- */
+	data->clock_mode = buf[0];
+
+	/* ----- set_fref_kHz & m_cal ----- */
+	switch (data->clock_mode) {
+	case 0:		/* 12.00MHz, 12000/18 = 2000/3 */
+		data->fxtal_khz = 2000;
+		data->fdiv = 3;
+		val = 16;
+		break;
+	case 1:		/* 20.48MHz, 20480/32 = 640/1 */
+		data->fxtal_khz = 640;
+		data->fdiv = 1;
+		val = 6;
+		break;
+	default:		/* 20.48MHz, 20480/32 = 640/1 */
+		data->fxtal_khz = 640;
+		data->fdiv = 1;
+		val = 6;
+		break;
+	}
+
+	/* ----- set_fbdry ----- */
+	nc = buf[1];
+	nv = it9135_tuner_get_nv(nc);
+	m_bdry = (buf[3] << 8) + buf[2];	/* m_bdry = m_bdry_15_8 << 8 + m_bdry_7_0 */
+
+	/* ----- patch to wait for fbc done ----- */
+	cnt = 1;
+	while (m_bdry == 0 && cnt < OMEGA_TUNER_INIT_POLL_COUNTS) {
+		mdelay(OMEGA_TUNER_INIT_POLL_INTERVAL);
+		/* r_reg_r_fbc_m_bdry_7_0 */
+		error =
+		    it9135_read_regs(data, chip, PROCESSOR_OFDM, 0xED23, 2,
+				     &buf[2]);
+		if (error)
+			goto exit;
+		m_bdry = (buf[3] << 8) + buf[2];	/* m_bdry = m_bdry_15_8 << 8 + m_bdry_7_0 */
+		cnt++;
+	}
+
+	if (m_bdry == 0) {
+		error = ERROR_TUNER_INIT_FAIL;
+		goto exit;
+	}
+
+	tmp_numer = (unsigned long)data->fxtal_khz * (unsigned long)m_bdry;
+	tmp_denom = (unsigned long)data->fdiv * (unsigned long)nv;
+	it9135_fn_min[7] = (unsigned int)(tmp_numer / tmp_denom);
+
+	/* ----- patch to wait for all cal done, borrow p_reg_p_tsm_init_mode ----- */
+	cnt = 1;
+
+	if (data->chip_type == 0x9135 && data->chip_ver == 2) {
+		mdelay(50);	/* for omega2 */
+	} else {
+		/* p_reg_p_tsm_init_mode */
+		error =
+		    it9135_read_regs(data, chip, PROCESSOR_OFDM, 0xEC82, 1,
+				     buf);
+		if (error)
+			goto exit;
+
+		while (buf[0] == 0 && cnt < OMEGA_TUNER_INIT_POLL_COUNTS) {
+			mdelay(OMEGA_TUNER_INIT_POLL_INTERVAL);
+			/* p_reg_p_tsm_init_mode */
+			error =
+			    it9135_read_regs(data, chip, PROCESSOR_OFDM, 0xEC82,
+					     1, buf);
+			if (error)
+				goto exit;
+			cnt++;
+		}
+		if (buf[0] == 0) {
+			error = ERROR_TUNER_INIT_FAIL;
+			goto exit;
+		}
+	}
+
+	/* p_reg_p_iqik_m_cal */
+	error = it9135_write_regs(data, chip, PROCESSOR_OFDM, 0xED81, 1, &val);
+
+exit:
+	return error;
+}
+
+static unsigned int it9135_tuner_get_nc(unsigned int rf_freq_khz)
+{
+	unsigned int nc;
+
+	if ((rf_freq_khz <= it9135_fn_min[1])) {	/* 74 */
+		nc = 0;
+	} else if ((rf_freq_khz > it9135_fn_min[1]) && (rf_freq_khz <= it9135_fn_min[2])) {	/* 74 111 */
+		nc = 1;
+	} else if ((rf_freq_khz > it9135_fn_min[2]) && (rf_freq_khz <= it9135_fn_min[3])) {	/* 111 148 */
+		nc = 2;
+	} else if ((rf_freq_khz > it9135_fn_min[3]) && (rf_freq_khz <= it9135_fn_min[4])) {	/* 148 222 */
+		nc = 3;
+	} else if ((rf_freq_khz > it9135_fn_min[4]) && (rf_freq_khz <= it9135_fn_min[5])) {	/* 222 296 */
+		nc = 4;
+	} else if ((rf_freq_khz > it9135_fn_min[5]) && (rf_freq_khz <= it9135_fn_min[6])) {	/* 296 445 */
+		nc = 5;
+	} else if ((rf_freq_khz > it9135_fn_min[6]) && (rf_freq_khz <= it9135_fn_min[7])) {	/* 445 573 */
+		nc = 6;
+	} else if ((rf_freq_khz > it9135_fn_min[7]) && (rf_freq_khz <= it9135_fn_min[8])) {	/* 573 890 */
+		nc = 7;
+	} else {		/* L-band */
+		nc = 8;
+	}
+
+	return nc;
+}
+
+static unsigned int it9135_tuner_get_freq_code(struct it9135_data *data,
+					       unsigned int rf_freq_khz,
+					       unsigned int *nc,
+					       unsigned int *nv,
+					       unsigned int *mv)
+{
+	unsigned int freq_code;
+	unsigned long tmp_tg, tmp_cal, tmp_m;
+
+	*nc = it9135_tuner_get_nc(rf_freq_khz);
+	*nv = it9135_tuner_get_nv(*nc);
+	tmp_tg =
+	    (unsigned long)rf_freq_khz * (unsigned long)(*nv) *
+	    (unsigned long)data->fdiv;
+	tmp_m = (tmp_tg / (unsigned long)data->fxtal_khz);
+	tmp_cal = tmp_m * (unsigned long)data->fxtal_khz;
+
+	if ((tmp_tg - tmp_cal) >= (data->fxtal_khz >> 1))
+		tmp_m = tmp_m + 1;
+
+	*mv = (unsigned int)(tmp_m);
+
+	freq_code = (((*nc) & 0x07) << 13) + (*mv);
+
+	return freq_code;
+}
+
+static unsigned int it9135_tuner_get_freq_iqik(struct it9135_data *data,
+					       unsigned int rf_freq_khz,
+					       unsigned char iqik_m_cal)
+{
+	unsigned int nc, nv, mv, cal_freq;
+
+#define OMEGA_IQIK_M_CAL_MAX	64
+#define OMEGA_IQIK_M_CAL_MID	32
+
+	cal_freq = it9135_tuner_get_freq_code(data, rf_freq_khz, &nc, &nv, &mv);
+	if (data->clock_mode == 0 && (iqik_m_cal < OMEGA_IQIK_M_CAL_MID)) {
+		mv = mv + ((((unsigned int)iqik_m_cal) * nv * 9) >> 5);
+	} else if (data->clock_mode == 0
+		   && (iqik_m_cal >= OMEGA_IQIK_M_CAL_MID)) {
+		iqik_m_cal = OMEGA_IQIK_M_CAL_MAX - iqik_m_cal;
+		mv = mv - ((((unsigned int)iqik_m_cal) * nv * 9) >> 5);
+	} else if (data->clock_mode == 1 && (iqik_m_cal < OMEGA_IQIK_M_CAL_MID)) {
+		mv = mv + ((((unsigned int)iqik_m_cal) * nv) >> 1);
+	} else {		/* (data->clock_mode==1 && (iqik_m_cal >= OMEGA_IQIK_M_CAL_MID)) */
+		iqik_m_cal = OMEGA_IQIK_M_CAL_MAX - iqik_m_cal;
+		mv = mv - ((((unsigned int)iqik_m_cal) * nv) >> 1);
+	}
+	cal_freq = ((nc & 0x07) << 13) + mv;
+
+	return cal_freq;
+}
+
+/* the reason to use 392000(but not 400000) because cal_rssi will use 400000-8000= 392000; */
+static unsigned int it9135_lna_fband_min[] = {
+	392000, 440000, 484000, 533000, 587000, 645000, 710000, 782000, 860000,
+	1450000, 1492000, 1660000, 1685000
+};
+
+static unsigned char it9135_tuner_get_lna_cap_sel(unsigned int rf_freq_khz)
+{
+	unsigned char lna_cap_sel;
+
+	if (rf_freq_khz <= it9135_lna_fband_min[1]) {	/* <=440 */
+		lna_cap_sel = 0;
+	} else if (rf_freq_khz > it9135_lna_fband_min[1] && rf_freq_khz <= it9135_lna_fband_min[2]) {	/* 440 484 */
+		lna_cap_sel = 1;
+	} else if (rf_freq_khz > it9135_lna_fband_min[2] && rf_freq_khz <= it9135_lna_fband_min[3]) {	/* 484 533 */
+		lna_cap_sel = 2;
+	} else if (rf_freq_khz > it9135_lna_fband_min[3] && rf_freq_khz <= it9135_lna_fband_min[4]) {	/* 533 587 */
+		lna_cap_sel = 3;
+	} else if (rf_freq_khz > it9135_lna_fband_min[4] && rf_freq_khz <= it9135_lna_fband_min[5]) {	/* 587 645 */
+		lna_cap_sel = 4;
+	} else if (rf_freq_khz > it9135_lna_fband_min[5] && rf_freq_khz <= it9135_lna_fband_min[6]) {	/* 645 710 */
+		lna_cap_sel = 5;
+	} else if (rf_freq_khz > it9135_lna_fband_min[6] && rf_freq_khz <= it9135_lna_fband_min[7]) {	/* 710 782 */
+		lna_cap_sel = 6;
+	} else {		/* >782 */
+		lna_cap_sel = 7;
+	}
+
+	return lna_cap_sel;
+}
+
+static unsigned int it9135_tuner_get_lo_freq(struct it9135_data *data,
+					     unsigned int rf_freq_khz)
+{
+	unsigned int nc, nv, mv, lo_freq;
+
+	lo_freq = it9135_tuner_get_freq_code(data, rf_freq_khz, &nc, &nv, &mv);
+
+	return lo_freq;
+}
+
+static unsigned char it9135_tuner_get_lpf_bw(unsigned int bw_khz)
+{
+	unsigned char lpf_bw;
+
+	switch (bw_khz) {	/*5.0MHz */
+	case 5000:
+		lpf_bw = 0;
+		break;
+	case 5500:		/*5.5MHz */
+		lpf_bw = 1;
+		break;
+	case 6000:		/*6.0MHz */
+		lpf_bw = 2;
+		break;
+	case 6500:		/*6.5MHz */
+		lpf_bw = 3;
+		break;
+	case 7000:		/*7.0MHz */
+		lpf_bw = 4;
+		break;
+	case 7500:		/*7.5MHz */
+		lpf_bw = 5;
+		break;
+	case 8000:		/*8.0MHz */
+		lpf_bw = 6;
+		break;
+	case 8500:		/*8.5MHz */
+		lpf_bw = 7;
+		break;
+	default:		/*default: 8MHz */
+		lpf_bw = 6;
+		break;
+	}
+
+	return lpf_bw;
+}
+
+static unsigned long it9135_tuner_set_freq(struct it9135_data *data,
+					   unsigned char chip,
+					   unsigned int bw_khz,
+					   unsigned int rf_freq_khz)
+{
+	unsigned long error = 0;
+	unsigned char val[7];
+	unsigned char buf[2];
+	unsigned int tmp;
+
+#define IT9135_CAP_FREQ_UHF_MIN		392000
+
+	/* p_reg_t_ctrl */
+	error = it9135_read_regs(data, chip, PROCESSOR_OFDM, 0xEC4C, 1, buf);
+	if (error)
+		goto exit;
+	/* p_reg_p_iqik_m_cal */
+	error =
+	    it9135_read_regs(data, chip, PROCESSOR_OFDM, 0xED81, 1, &buf[1]);
+	if (error)
+		goto exit;
+
+	val[0] = it9135_tuner_get_lna_cap_sel(rf_freq_khz);
+	val[1] = it9135_tuner_get_lpf_bw(bw_khz);
+
+	/* ----- set_rf_mode ----- */
+	if (rf_freq_khz < IT9135_CAP_FREQ_UHF_MIN)
+		val[2] = buf[0] & 0xE7;	/* ctrl<4:3>=0b00 for VHF */
+	else
+		val[2] = (buf[0] & 0xE7) | 0x08;	/* ctrl<4:3>=0b01 for UHF */
+
+	/* ----- set_cal_freq ----- */
+	tmp = it9135_tuner_get_freq_iqik(data, rf_freq_khz, buf[1]);
+	val[3] = (unsigned char)(tmp & 0xFF);
+	val[4] = (unsigned char)((tmp >> 8) & 0xFF);
+	/* ----- set_lo_freq ----- */
+	tmp = it9135_tuner_get_lo_freq(data, rf_freq_khz);
+	val[5] = (unsigned char)(tmp & 0xFF);
+	val[6] = (unsigned char)((tmp >> 8) & 0xFF);
+	/* ----- write ----- */
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM, var_pre_lna_cap_sel,
+			      1, val);
+	if (error)
+		goto exit;
+	/* p_reg_t_lpf_bw */
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM, 0xEC56, 1, &val[1]);
+	if (error)
+		goto exit;
+	/* p_reg_t_ctrl */
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM, 0xEC4C, 1, &val[2]);
+	if (error)
+		goto exit;
+	/*----- the writing sequence is important for cal_freq and lo_freq, thus separate ----- */
+	/* p_reg_t_cal_freq_7_0 */
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM, 0xEC4D, 1, &val[3]);
+	if (error)
+		goto exit;
+	/* p_reg_t_cal_freq_15_8 */
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM, 0xEC4E, 1, &val[4]);
+	if (error)
+		goto exit;
+
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM, var_pre_lo_freq_7_0,
+			      1, &val[5]);
+	if (error)
+		goto exit;
+
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM, var_pre_lo_freq_15_8,
+			      1, &val[6]);
+
+exit:
+	return error;
+}
+
+/*
+ * Demodular functions
+ */
+
+static unsigned long it9135_divider(struct it9135_data *data, unsigned long a,
+				    unsigned long b, unsigned long x)
+{
+	unsigned long answer = 0;
+	unsigned long c = 0;
+	unsigned long i = 0;
+
+	if (a > b) {
+		c = a / b;
+		a = a - c * b;
+	}
+
+	for (i = 0; i < x; i++) {
+		if (a >= b) {
+			answer += 1;
+			a -= b;
+		}
+		a <<= 1;
+		answer <<= 1;
+	}
+
+	answer = (c << (long)x) + answer;
+
+	return answer;
+}
+
+/* @param crystal_Freq: Crystal frequency (Hz) */
+static unsigned long it9135_compute_crystal(struct it9135_data *data,
+					    long crystal_frequency,
+					    unsigned long *crystal)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	*crystal =
+	    (long)it9135_divider(data, (unsigned long)crystal_frequency,
+				 1000000ul, 19ul);
+
+	return error;
+}
+
+/* @param adcFrequency: ADC frequency (Hz) */
+static unsigned long it9135_compute_adc(struct it9135_data *data, long adc_freq,
+					unsigned long *adc)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	*adc =
+	    (long)it9135_divider(data, (unsigned long)adc_freq, 1000000ul,
+				 19ul);
+
+	return error;
+}
+
+/*
+ * @param adcFrequency: ADC frequency (Hz)
+ * @param ifFrequency:  IF frequency (Hz)
+ * @param inversion:    RF spectrum inversion
+ */
+static unsigned long it9135_compute_fcw(struct it9135_data *data,
+					long adc_frequency, long if_frequency,
+					int inversion, unsigned long *fcw)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	long if_freq;
+	long adc_freq;
+	long adc_freq_half;
+	long adc_freq_sample;
+	long inv_bfs;
+	long ctrl_word;
+	unsigned char adc_multiplier;
+
+	adc_freq = adc_frequency;
+	if_freq = if_frequency;
+	adc_freq_half = adc_freq / 2;
+
+	if (inversion)
+		if_freq = -1 * if_freq;
+
+	adc_freq_sample = if_freq;
+
+	if (adc_freq_sample >= 0) {
+		inv_bfs = 1;
+	} else {
+		inv_bfs = -1;
+		adc_freq_sample = adc_freq_sample * -1;
+	}
+
+	while (adc_freq_sample > adc_freq_half)
+		adc_freq_sample = adc_freq_sample - adc_freq;
+
+	/* Sample, spectrum at positive frequency */
+	if (adc_freq_sample >= 0) {
+		inv_bfs = inv_bfs * -1;
+	} else {
+		inv_bfs = inv_bfs * 1;
+		adc_freq_sample = adc_freq_sample * (-1);	/* Absolute value */
+	}
+
+	ctrl_word =
+	    (long)it9135_divider(data, (unsigned long)adc_freq_sample,
+				 (unsigned long)adc_freq, 23ul);
+
+	if (inv_bfs == -1)
+		ctrl_word *= -1;
+
+	/* Get ADC multiplier */
+	error =
+	    it9135_read_reg(data, 0, PROCESSOR_OFDM, adcx2, &adc_multiplier);
+	if (error)
+		goto exit;
+
+	if (adc_multiplier == 1)
+		ctrl_word /= 2;
+
+	*fcw = ctrl_word & 0x7FFFFF;
+
+exit:
+	return error;
+}
+
+static unsigned long it9135_mask_dca_output(struct it9135_data *data)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char i;
+
+	if ((data->chip_num > 1)
+	    && (data->architecture == ARCHITECTURE_DCA)) {
+		for (i = 0; i < data->chip_num; i++) {
+			error =
+			    it9135_write_reg_bits(data, i,
+						  PROCESSOR_OFDM,
+						  p_reg_dca_upper_out_en,
+						  reg_dca_upper_out_en_pos,
+						  reg_dca_upper_out_en_len, 0);
+			if (error)
+				goto exit;
+		}
+		mdelay(5);
+	}
+
+exit:
+	return error;
+}
+
+static struct it9135_coeff_param coeff_tab[] = {
+	/* adc_freq 20156250 */
+	{20156250, 5000, 0x02449b5c, 0x01224dae, 0x00912b60, 0x009126d7,
+	 0x0091224e, 0x01224dae, 0x009126d7, 0x0048936b, 0x0387, 0x0122},
+	{20156250, 6000, 0x02b8ba6e, 0x015c5d37, 0x00ae340d, 0x00ae2e9b,
+	 0x00ae292a, 0x015c5d37, 0x00ae2e9b, 0x0057174e, 0x02f1, 0x015c},
+	{20156250, 7000, 0x032cd980, 0x01966cc0, 0x00cb3cba, 0x00cb3660,
+	 0x00cb3007, 0x01966cc0, 0x00cb3660, 0x00659b30, 0x0285, 0x0196},
+	{20156250, 8000, 0x03a0f893, 0x01d07c49, 0x00e84567, 0x00e83e25,
+	 0x00e836e3, 0x01d07c49, 0x00e83e25, 0x00741f12, 0x0234, 0x01d0},
+	/* adc_freq 20187500 */
+	{20187500, 5000, 0x0243b546, 0x0121daa3, 0x0090f1d9, 0x0090ed51,
+	 0x0090e8ca, 0x0121daa3, 0x0090ed51, 0x004876a9, 0x0388, 0x0122},
+	{20187500, 6000, 0x02b7a654, 0x015bd32a, 0x00adef04, 0x00ade995,
+	 0x00ade426, 0x015bd32a, 0x00ade995, 0x0056f4ca, 0x02f2, 0x015c},
+	{20187500, 7000, 0x032b9761, 0x0195cbb1, 0x00caec30, 0x00cae5d8,
+	 0x00cadf81, 0x0195cbb1, 0x00cae5d8, 0x006572ec, 0x0286, 0x0196},
+	{20187500, 8000, 0x039f886f, 0x01cfc438, 0x00e7e95b, 0x00e7e21c,
+	 0x00e7dadd, 0x01cfc438, 0x00e7e21c, 0x0073f10e, 0x0235, 0x01d0},
+	/* adc_freq 20250000 */
+	{20250000, 5000, 0x0241eb3b, 0x0120f59e, 0x00907f53, 0x00907acf,
+	 0x0090764b, 0x0120f59e, 0x00907acf, 0x00483d67, 0x038b, 0x0121},
+	{20250000, 6000, 0x02b580ad, 0x015ac057, 0x00ad6597, 0x00ad602b,
+	 0x00ad5ac1, 0x015ac057, 0x00ad602b, 0x0056b016, 0x02f4, 0x015b},
+	{20250000, 7000, 0x03291620, 0x01948b10, 0x00ca4bda, 0x00ca4588,
+	 0x00ca3f36, 0x01948b10, 0x00ca4588, 0x006522c4, 0x0288, 0x0195},
+	{20250000, 8000, 0x039cab92, 0x01ce55c9, 0x00e7321e, 0x00e72ae4,
+	 0x00e723ab, 0x01ce55c9, 0x00e72ae4, 0x00739572, 0x0237, 0x01ce},
+	/* adc_freq 20583333 */
+	{20583333, 5000, 0x02388f54, 0x011c47aa, 0x008e2846, 0x008e23d5,
+	 0x008e1f64, 0x011c47aa, 0x008e23d5, 0x004711ea, 0x039a, 0x011c},
+	{20583333, 6000, 0x02aa4598, 0x015522cc, 0x00aa96bb, 0x00aa9166,
+	 0x00aa8c12, 0x015522cc, 0x00aa9166, 0x005548b3, 0x0300, 0x0155},
+	{20583333, 7000, 0x031bfbdc, 0x018dfdee, 0x00c7052f, 0x00c6fef7,
+	 0x00c6f8bf, 0x018dfdee, 0x00c6fef7, 0x00637f7b, 0x0293, 0x018e},
+	{20583333, 8000, 0x038db21f, 0x01c6d910, 0x00e373a3, 0x00e36c88,
+	 0x00e3656d, 0x01c6d910, 0x00e36c88, 0x0071b644, 0x0240, 0x01c7},
+	/* adc_freq 20416667 */
+	{20416667, 5000, 0x023d337f, 0x011e99c0, 0x008f515a, 0x008f4ce0,
+	 0x008f4865, 0x011e99c0, 0x008f4ce0, 0x0047a670, 0x0393, 0x011f},
+	{20416667, 6000, 0x02afd765, 0x0157ebb3, 0x00abfb39, 0x00abf5d9,
+	 0x00abf07a, 0x0157ebb3, 0x00abf5d9, 0x0055faed, 0x02fa, 0x0158},
+	{20416667, 7000, 0x03227b4b, 0x01913da6, 0x00c8a518, 0x00c89ed3,
+	 0x00c8988e, 0x01913da6, 0x00c89ed3, 0x00644f69, 0x028d, 0x0191},
+	{20416667, 8000, 0x03951f32, 0x01ca8f99, 0x00e54ef7, 0x00e547cc,
+	 0x00e540a2, 0x01ca8f99, 0x00e547cc, 0x0072a3e6, 0x023c, 0x01cb},
+	/* adc_freq 20480000 */
+	{20480000, 5000, 0x023b6db7, 0x011db6db, 0x008edfe5, 0x008edb6e,
+	 0x008ed6f7, 0x011db6db, 0x008edb6e, 0x00476db7, 0x0396, 0x011e},
+	{20480000, 6000, 0x02adb6db, 0x0156db6e, 0x00ab7312, 0x00ab6db7,
+	 0x00ab685c, 0x0156db6e, 0x00ab6db7, 0x0055b6db, 0x02fd, 0x0157},
+	{20480000, 7000, 0x03200000, 0x01900000, 0x00c80640, 0x00c80000,
+	 0x00c7f9c0, 0x01900000, 0x00c80000, 0x00640000, 0x028f, 0x0190},
+	{20480000, 8000, 0x03924925, 0x01c92492, 0x00e4996e, 0x00e49249,
+	 0x00e48b25, 0x01c92492, 0x00e49249, 0x00724925, 0x023d, 0x01c9},
+	/* adc_freq 20500000 */
+	{20500000, 5000, 0x023adeff, 0x011d6f80, 0x008ebc36, 0x008eb7c0,
+	 0x008eb34a, 0x011d6f80, 0x008eb7c0, 0x00475be0, 0x0396, 0x011d},
+	{20500000, 6000, 0x02ad0b99, 0x015685cc, 0x00ab4840, 0x00ab42e6,
+	 0x00ab3d8c, 0x015685cc, 0x00ab42e6, 0x0055a173, 0x02fd, 0x0157},
+	{20500000, 7000, 0x031f3832, 0x018f9c19, 0x00c7d44b, 0x00c7ce0c,
+	 0x00c7c7ce, 0x018f9c19, 0x00c7ce0c, 0x0063e706, 0x0290, 0x0190},
+	{20500000, 8000, 0x039164cb, 0x01c8b266, 0x00e46056, 0x00e45933,
+	 0x00e45210, 0x01c8b266, 0x00e45933, 0x00722c99, 0x023e, 0x01c9},
+	/* adc_freq 20625000 */
+	{20625000, 5000, 0x02376948, 0x011bb4a4, 0x008ddec1, 0x008dda52,
+	 0x008dd5e3, 0x011bb4a4, 0x008dda52, 0x0046ed29, 0x039c, 0x011c},
+	{20625000, 6000, 0x02a8e4bd, 0x0154725e, 0x00aa3e81, 0x00aa392f,
+	 0x00aa33de, 0x0154725e, 0x00aa392f, 0x00551c98, 0x0302, 0x0154},
+	{20625000, 7000, 0x031a6032, 0x018d3019, 0x00c69e41, 0x00c6980c,
+	 0x00c691d8, 0x018d3019, 0x00c6980c, 0x00634c06, 0x0294, 0x018d},
+	{20625000, 8000, 0x038bdba6, 0x01c5edd3, 0x00e2fe02, 0x00e2f6ea,
+	 0x00e2efd2, 0x01c5edd3, 0x00e2f6ea, 0x00717b75, 0x0242, 0x01c6}
+};
+
+static int it915_coeff_tab_count = ARRAY_SIZE(coeff_tab);
+
+static unsigned long it9135_get_coeff_param(struct it9135_coeff_param *coeff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	int i;
+
+	deb_info("it9135_get_coeff_param - %ld, %d\n", coeff->adc_freq,
+		 coeff->bandwidth);
+
+	for (i = 0; i < it915_coeff_tab_count; i++) {
+		if ((coeff->adc_freq == coeff_tab[i].adc_freq)
+		    && (coeff->bandwidth == coeff_tab[i].bandwidth)) {
+			memcpy(coeff, &coeff_tab[i], sizeof(*coeff));
+			deb_info("find coeff table - %ld, %d\n",
+				 coeff->adc_freq, coeff->bandwidth);
+			break;
+		}
+	}
+
+	if (i == it915_coeff_tab_count)
+		error = ERROR_INVALID_BW;
+
+	return error;
+}
+
+/*
+ * Program the bandwidth related parameters to IT9135.
+ *
+ * @param struct it9135_data the handle of IT9135.
+ * @param chip The index of IT9135. The possible values are 0~7.
+ *        NOTE: When the architecture is set to ARCHITECTURE_DCA
+ *        this parameter is regard as don't care.
+ * @param bandwidth DVB channel bandwidth in KHz. The possible values
+ *        are 5000, 6000, 7000, and 8000 (KHz).
+ * @param adc_freq The value of desire internal ADC frequency (Hz) ex: 20480000.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+static unsigned long it9135_select_bandwidth(struct it9135_data *data,
+					     unsigned char chip,
+					     unsigned short bandwidth,
+					     unsigned long adc_freq)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	struct it9135_coeff_param coeff;
+	unsigned char temp0;
+	unsigned char temp1;
+	unsigned char temp2;
+	unsigned char temp3;
+	unsigned char buffer[36];
+	unsigned char bw;
+	unsigned char adc_multiplier;
+
+	switch (bandwidth) {
+	case 5000:
+		bw = 3;
+		break;
+	case 6000:
+		bw = 0;
+		break;
+	case 7000:
+		bw = 1;
+		break;
+	case 8000:
+		bw = 2;
+		break;
+	default:
+		error = ERROR_INVALID_BW;
+		goto exit;
+	}
+
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM, g_reg_bw,
+				  reg_bw_pos, reg_bw_len, bw);
+	if (error)
+		goto exit;
+
+	/* Program CFOE */
+	coeff.adc_freq = adc_freq;
+	coeff.bandwidth = bandwidth;
+	error = it9135_get_coeff_param(&coeff);
+	if (error)
+		goto exit;
+
+	/* Get ADC multiplier */
+	error =
+	    it9135_read_reg(data, 0, PROCESSOR_OFDM, adcx2, &adc_multiplier);
+	if (error)
+		goto exit;
+
+	if (adc_multiplier == 1) {
+		coeff.coeff1_2048Nu /= 2;
+		coeff.coeff1_4096Nu /= 2;
+		coeff.coeff1_8191Nu /= 2;
+		coeff.coeff1_8192Nu /= 2;
+		coeff.coeff1_8193Nu /= 2;
+		coeff.coeff2_2k /= 2;
+		coeff.coeff2_4k /= 2;
+		coeff.coeff2_8k /= 2;
+	}
+
+	/* Write coeff1_2048Nu */
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)(coeff.coeff1_2048Nu & 0x000000FF);
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.coeff1_2048Nu & 0x0000FF00) >> 8);
+	/* Get unsigned char2 */
+	temp2 = (unsigned char)((coeff.coeff1_2048Nu & 0x00FF0000) >> 16);
+	/* Get unsigned char3 */
+	temp3 = (unsigned char)((coeff.coeff1_2048Nu & 0x03000000) >> 24);
+
+	/* Big endian to make 8051 happy */
+	buffer[cfoe_NS_2048_coeff1_25_24 - cfoe_NS_2048_coeff1_25_24] = temp3;
+	buffer[cfoe_NS_2048_coeff1_23_16 - cfoe_NS_2048_coeff1_25_24] = temp2;
+	buffer[cfoe_NS_2048_coeff1_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[cfoe_NS_2048_coeff1_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	/* Write coeff2_2k */
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)((coeff.coeff2_2k & 0x000000FF));
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.coeff2_2k & 0x0000FF00) >> 8);
+	/* Get unsigned char2 */
+	temp2 = (unsigned char)((coeff.coeff2_2k & 0x00FF0000) >> 16);
+	/* Get unsigned char3 */
+	temp3 = (unsigned char)((coeff.coeff2_2k & 0x01000000) >> 24);
+
+	/* Big endian to make 8051 happy */
+	buffer[cfoe_NS_2k_coeff2_24 - cfoe_NS_2048_coeff1_25_24] = temp3;
+	buffer[cfoe_NS_2k_coeff2_23_16 - cfoe_NS_2048_coeff1_25_24] = temp2;
+	buffer[cfoe_NS_2k_coeff2_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[cfoe_NS_2k_coeff2_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	/* Write coeff1_8191Nu */
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)((coeff.coeff1_8191Nu & 0x000000FF));
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.coeff1_8191Nu & 0x0000FF00) >> 8);
+	/* Get unsigned char2 */
+	temp2 = (unsigned char)((coeff.coeff1_8191Nu & 0x00FFC000) >> 16);
+	/* Get unsigned char3 */
+	temp3 = (unsigned char)((coeff.coeff1_8191Nu & 0x03000000) >> 24);
+
+	/* Big endian to make 8051 happy */
+	buffer[cfoe_NS_8191_coeff1_25_24 - cfoe_NS_2048_coeff1_25_24] = temp3;
+	buffer[cfoe_NS_8191_coeff1_23_16 - cfoe_NS_2048_coeff1_25_24] = temp2;
+	buffer[cfoe_NS_8191_coeff1_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[cfoe_NS_8191_coeff1_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	/* Write coeff1_8192Nu */
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)(coeff.coeff1_8192Nu & 0x000000FF);
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.coeff1_8192Nu & 0x0000FF00) >> 8);
+	/* Get unsigned char2 */
+	temp2 = (unsigned char)((coeff.coeff1_8192Nu & 0x00FFC000) >> 16);
+	/* Get unsigned char3 */
+	temp3 = (unsigned char)((coeff.coeff1_8192Nu & 0x03000000) >> 24);
+
+	/* Big endian to make 8051 happy */
+	buffer[cfoe_NS_8192_coeff1_25_24 - cfoe_NS_2048_coeff1_25_24] = temp3;
+	buffer[cfoe_NS_8192_coeff1_23_16 - cfoe_NS_2048_coeff1_25_24] = temp2;
+	buffer[cfoe_NS_8192_coeff1_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[cfoe_NS_8192_coeff1_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	/* Write coeff1_8193Nu */
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)((coeff.coeff1_8193Nu & 0x000000FF));
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.coeff1_8193Nu & 0x0000FF00) >> 8);
+	/* Get unsigned char2 */
+	temp2 = (unsigned char)((coeff.coeff1_8193Nu & 0x00FFC000) >> 16);
+	/* Get unsigned char3 */
+	temp3 = (unsigned char)((coeff.coeff1_8193Nu & 0x03000000) >> 24);
+
+	/* Big endian to make 8051 happy */
+	buffer[cfoe_NS_8193_coeff1_25_24 - cfoe_NS_2048_coeff1_25_24] = temp3;
+	buffer[cfoe_NS_8193_coeff1_23_16 - cfoe_NS_2048_coeff1_25_24] = temp2;
+	buffer[cfoe_NS_8193_coeff1_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[cfoe_NS_8193_coeff1_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	/* Write coeff2_8k */
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)((coeff.coeff2_8k & 0x000000FF));
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.coeff2_8k & 0x0000FF00) >> 8);
+	/* Get unsigned char2 */
+	temp2 = (unsigned char)((coeff.coeff2_8k & 0x00FF0000) >> 16);
+	/* Get unsigned char3 */
+	temp3 = (unsigned char)((coeff.coeff2_8k & 0x01000000) >> 24);
+
+	/* Big endian to make 8051 happy */
+	buffer[cfoe_NS_8k_coeff2_24 - cfoe_NS_2048_coeff1_25_24] = temp3;
+	buffer[cfoe_NS_8k_coeff2_23_16 - cfoe_NS_2048_coeff1_25_24] = temp2;
+	buffer[cfoe_NS_8k_coeff2_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[cfoe_NS_8k_coeff2_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	/* Write coeff1_4096Nu */
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)(coeff.coeff1_4096Nu & 0x000000FF);
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.coeff1_4096Nu & 0x0000FF00) >> 8);
+	/* Get unsigned char2 */
+	temp2 = (unsigned char)((coeff.coeff1_4096Nu & 0x00FF0000) >> 16);
+	/* Get unsigned char3[1:0] */
+	/* Bit[7:2] will be written soon and so don't have to care them */
+	temp3 = (unsigned char)((coeff.coeff1_4096Nu & 0x03000000) >> 24);
+
+	/* Big endian to make 8051 happy */
+	buffer[cfoe_NS_4096_coeff1_25_24 - cfoe_NS_2048_coeff1_25_24] = temp3;
+	buffer[cfoe_NS_4096_coeff1_23_16 - cfoe_NS_2048_coeff1_25_24] = temp2;
+	buffer[cfoe_NS_4096_coeff1_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[cfoe_NS_4096_coeff1_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	/* Write coeff2_4k */
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)((coeff.coeff2_4k & 0x000000FF));
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.coeff2_4k & 0x0000FF00) >> 8);
+	/* Get unsigned char2 */
+	temp2 = (unsigned char)((coeff.coeff2_4k & 0x00FF0000) >> 16);
+	/* Get unsigned char3 */
+	temp3 = (unsigned char)((coeff.coeff2_4k & 0x01000000) >> 24);
+
+	/* Big endian to make 8051 happy */
+	buffer[cfoe_NS_4k_coeff2_24 - cfoe_NS_2048_coeff1_25_24] = temp3;
+	buffer[cfoe_NS_4k_coeff2_23_16 - cfoe_NS_2048_coeff1_25_24] = temp2;
+	buffer[cfoe_NS_4k_coeff2_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[cfoe_NS_4k_coeff2_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)(coeff.bfsfcw_fftindex_ratio & 0x00FF);
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.bfsfcw_fftindex_ratio & 0xFF00) >> 8);
+
+	/* Big endian to make 8051 happy */
+	buffer[bfsfcw_fftindex_ratio_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[bfsfcw_fftindex_ratio_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	/* Get unsigned char0 */
+	temp0 = (unsigned char)(coeff.fftindex_bfsfcw_ratio & 0x00FF);
+	/* Get unsigned char1 */
+	temp1 = (unsigned char)((coeff.fftindex_bfsfcw_ratio & 0xFF00) >> 8);
+
+	/* Big endian to make 8051 happy */
+	buffer[fftindex_bfsfcw_ratio_15_8 - cfoe_NS_2048_coeff1_25_24] = temp1;
+	buffer[fftindex_bfsfcw_ratio_7_0 - cfoe_NS_2048_coeff1_25_24] = temp0;
+
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM,
+			      cfoe_NS_2048_coeff1_25_24, 36, buffer);
+	if (error)
+		goto exit;
+
+exit:
+	return error;
+}
+
+/*
+ * The type defination of band table.
+ */
+struct it9135_freq_band {
+	unsigned long mini;	/* The minimum frequency of this band */
+	unsigned long max;	/* The maximum frequency of this band */
+};
+
+static struct it9135_freq_band it9135_freq_band_tab[] = {
+	{30000, 300000},	/* VHF 30MHz ~ 300MHz */
+	{300000, 1000000},	/* UHF 300MHz ~ 1000MHz */
+	{1670000, 1680000}	/* L-BAND */
+};
+
+static int it915_freq_band_tab_count = ARRAY_SIZE(it9135_freq_band_tab);
+
+/*
+ * Set frequency.
+ *
+ * @param struct it9135_data the handle of IT9135.
+ * @param chip The index of IT9135. The possible values are 0~7.
+ * @param frequency The desired frequency.
+ * @return ERROR_NO_ERROR: successful, other non-zero error code otherwise.
+ */
+static unsigned long it9135_set_frequency(struct it9135_data *data,
+					  unsigned char chip,
+					  unsigned long frequency)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long freq = frequency;
+	unsigned char band;
+	unsigned char i;
+
+	/* Clear easy mode flag first */
+	error =
+	    it9135_write_reg(data, chip, PROCESSOR_OFDM, Training_Mode, 0x00);
+	if (error)
+		goto exit;
+
+	/* Clear empty_channel_status lock flag */
+	error =
+	    it9135_write_reg(data, chip, PROCESSOR_OFDM, empty_channel_status,
+			     0x00);
+	if (error)
+		goto exit;
+
+	/* Clear MPEG2 lock flag */
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM,
+				  r_mp2if_sync_byte_locked,
+				  mp2if_sync_byte_locked_pos,
+				  mp2if_sync_byte_locked_len, 0x00);
+	if (error)
+		goto exit;
+
+	/* Determine frequency band */
+	band = 0xFF;
+	for (i = 0; i < it915_freq_band_tab_count; i++) {
+		if ((frequency >= it9135_freq_band_tab[i].mini)
+		    && (frequency <= it9135_freq_band_tab[i].max)) {
+			band = i;
+			break;
+		}
+	}
+	error = it9135_write_reg(data, chip, PROCESSOR_OFDM, FreBand, band);
+	if (error)
+		goto exit;
+
+	if (data->chip_num > 1 && chip == 0)
+		freq += 100;
+	else if (data->chip_num > 1 && chip == 1)
+		freq -= 100;
+
+	error =
+	    it9135_tuner_set_freq(data, chip, data->bandwidth[chip], frequency);
+	if (error)
+		goto exit;
+
+	/* Trigger ofsm */
+	error = it9135_write_reg(data, chip, PROCESSOR_OFDM, trigger_ofsm, 0);
+	if (error)
+		goto exit;
+
+	data->frequency[chip] = frequency;
+
+exit:
+	return error;
+}
+
+/*
+ * Load firmware to device
+ *
+ * @param struct it9135_data the handle of IT9135.
+ * @fw_codes pointer to fw binary.
+ * @fw_segs pointer to fw segments.
+ * @fw_parts pointer to fw partition.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+static unsigned long it9135_load_firmware(struct it9135_data *data,
+					  unsigned char *fw_codes,
+					  struct it9135_segment *fw_segs,
+					  unsigned char *fw_parts)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long beginPartition = 0;
+	unsigned long endPartition = 0;
+	unsigned long version;
+	unsigned long firmwareLength;
+	unsigned char *firmwareCodesPointer;
+	unsigned short command;
+	unsigned long i;
+
+/* Define I2C master speed, the default value 0x07 means 366KHz (1000000000 / (24.4 * 16 * User_I2C_SPEED)). */
+#define User_I2C_SPEED              0x07
+
+	/* Set I2C master clock speed. */
+	error =
+	    it9135_write_reg(data, 0, PROCESSOR_LINK,
+			     p_reg_one_cycle_counter_tuner, User_I2C_SPEED);
+	if (error)
+		goto exit;
+
+	firmwareCodesPointer = fw_codes;
+
+	beginPartition = 0;
+	endPartition = fw_parts[0];
+
+	for (i = beginPartition; i < endPartition; i++) {
+		firmwareLength = fw_segs[i].length;
+		if (fw_segs[i].type == 0) {
+			/* Dwonload firmware */
+			error =
+			    it9135_cmd_sendcommand(data, CMD_FW_DOWNLOAD_BEGIN,
+						   0, PROCESSOR_LINK, 0, NULL,
+						   0, NULL);
+			if (error)
+				goto exit;
+			error =
+			    it9135_cmd_loadfirmware(data, firmwareLength,
+						    firmwareCodesPointer);
+			if (error)
+				goto exit;
+			error =
+			    it9135_cmd_sendcommand(data, CMD_FW_DOWNLOAD_END, 0,
+						   PROCESSOR_LINK, 0, NULL, 0,
+						   NULL);
+			if (error)
+				goto exit;
+		} else if (fw_segs[i].type == 1) {
+			/* Copy firmware */
+			error =
+			    it9135_cmd_sendcommand(data,
+						   CMD_SCATTER_WRITE, 0,
+						   PROCESSOR_LINK,
+						   firmwareLength,
+						   firmwareCodesPointer, 0,
+						   NULL);
+			if (error)
+				goto exit;
+		} else {
+			/* Direct write firmware */
+			command =
+			    (unsigned short)(firmwareCodesPointer[0] << 8) +
+			    (unsigned short)firmwareCodesPointer[1];
+			error =
+			    it9135_cmd_sendcommand(data, command, 0,
+						   PROCESSOR_LINK,
+						   firmwareLength - 2,
+						   firmwareCodesPointer + 2, 0,
+						   NULL);
+			if (error)
+				goto exit;
+		}
+		firmwareCodesPointer += firmwareLength;
+	}
+
+	/* Boot */
+	error =
+	    it9135_cmd_sendcommand(data, CMD_BOOT, 0, PROCESSOR_LINK, 0, NULL,
+				   0, NULL);
+	if (error)
+		goto exit;
+
+	mdelay(10);
+
+	/* Check if firmware is running */
+	version = 0;
+	error = it9135_get_fw_ver(data, PROCESSOR_LINK, &version);
+	if (error)
+		goto exit;
+	if (version == 0)
+		error = ERROR_BOOT_FAIL;
+
+exit:
+	return error;
+}
+
+/*
+ * Load initial script to device
+ *
+ * @param struct it9135_data the handle of IT9135.
+ * @script_sets pointer to script_sets.
+ * @scripts pointer to fw scripts.
+ * @tuner_script_sets pointer to tunerScriptSets.
+ * @tuner_scripts pointer to tunerScripts.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+static unsigned long it9135_load_script(struct it9135_data *data,
+					unsigned short *script_sets,
+					struct it9135_val_set *scripts,
+					unsigned short *tuner_script_sets,
+					struct it9135_val_set *tuner_scripts)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned short beginScript;
+	unsigned short endScript;
+	unsigned char i, value1 = 0, prechip_version = 0, supportRelay =
+	    0, chip_num = 0, bufferLens = 1;
+	unsigned short j;
+	unsigned char buffer[20] = { 0 };
+	unsigned long tunerAddr, tunerAddrTemp;
+
+	/* Querry SupportRelayCommandWrite */
+	error = it9135_read_reg(data, 0, PROCESSOR_OFDM, 0x004D, &supportRelay);
+	if (error)
+		goto exit;
+
+	if (supportRelay && data->chip_num == 2)
+		chip_num = 1;
+	else
+		chip_num = data->chip_num;
+
+	/* Enable RelayCommandWrite */
+	if (supportRelay) {
+		error = it9135_write_reg(data, 0, PROCESSOR_OFDM, 0x004E, 1);
+		if (error)
+			goto exit;
+	}
+
+	if ((script_sets[0] != 0) && (scripts != NULL)) {
+		beginScript = 0;
+		endScript = script_sets[0];
+
+		for (i = 0; i < chip_num; i++) {
+			/* Load OFSM init script */
+			for (j = beginScript; j < endScript; j++) {
+				tunerAddr = tunerAddrTemp = scripts[j].address;
+				buffer[0] = scripts[j].value;
+
+				while (j < endScript && bufferLens < 20) {
+					tunerAddrTemp += 1;
+					if (tunerAddrTemp !=
+					    scripts[j + 1].address)
+						break;
+
+					buffer[bufferLens] =
+					    scripts[j + 1].value;
+					bufferLens++;
+					j++;
+				}
+
+				error =
+				    it9135_write_regs(data, i, PROCESSOR_OFDM,
+						      tunerAddr, bufferLens,
+						      buffer);
+				if (error)
+					goto exit;
+				bufferLens = 1;
+			}
+		}
+	}
+
+	/* Distinguish chip type */
+	error =
+	    it9135_read_reg(data, 0, PROCESSOR_LINK, chip_version_7_0, &value1);
+	if (error)
+		goto exit;
+
+	error =
+	    it9135_read_reg(data, 0, PROCESSOR_LINK, prechip_version_7_0,
+			    &prechip_version);
+	if (error)
+		goto exit;
+
+	if ((tuner_script_sets[0] != 0) && (tuner_scripts != NULL)) {
+		if (tuner_script_sets[1] == tuner_script_sets[0]
+		    && !(data->chip_ver == 0xF8 && prechip_version == 0xEA)) {
+			/* New version */
+			beginScript = tuner_script_sets[0];
+			endScript = tuner_script_sets[0] + tuner_script_sets[1];
+		} else {
+			/* Old version */
+			beginScript = 0;
+			endScript = tuner_script_sets[0];
+		}
+
+		for (i = 0; i < chip_num; i++) {
+			/* Load tuner init script */
+			for (j = beginScript; j < endScript; j++) {
+				tunerAddr = tunerAddrTemp =
+				    tuner_scripts[j].address;
+				buffer[0] = tuner_scripts[j].value;
+
+				while (j < endScript && bufferLens < 20) {
+					tunerAddrTemp += 1;
+					if (tunerAddrTemp !=
+					    tuner_scripts[j + 1].address)
+						break;
+
+					buffer[bufferLens] =
+					    tuner_scripts[j + 1].value;
+					bufferLens++;
+					j++;
+				}
+
+				error =
+				    it9135_write_regs(data, i, PROCESSOR_OFDM,
+						      tunerAddr, bufferLens,
+						      buffer);
+				if (error)
+					goto exit;
+				bufferLens = 1;
+			}
+		}
+	}
+
+	/* Disable RelayCommandWrite */
+	if (supportRelay) {
+		error = it9135_write_reg(data, 0, PROCESSOR_OFDM, 0x004E, 0);
+		if (error)
+			goto exit;
+	}
+
+exit:
+	return error;
+}
+
+/* end of local functions */
+
+unsigned long it9135_write_regs(struct it9135_data *data, unsigned char chip,
+				unsigned char processor, unsigned long reg_addr,
+				unsigned long w_buff_len, unsigned char *w_buff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned short command;
+	unsigned char buffer[255];
+	unsigned long buff_len;
+	unsigned long remain_len;
+	unsigned long send_len;
+	unsigned long i;
+	unsigned char reg_addr_len = 2;
+
+	it9135_enter_mutex(data);
+
+	if (w_buff_len == 0)
+		goto exit;
+	if (reg_addr_len > 4) {
+		error = ERROR_PROTOCOL_FORMAT_INVALID;
+		goto exit;
+	}
+
+	if ((w_buff_len + 12) > IT9135_MAX_CMD_SIZE) {
+		error = ERROR_INVALID_DATA_LENGTH;
+		goto exit;
+	}
+
+	/* add frame header */
+	command = it9135_build_command(CMD_REG_DEMOD_WRITE, processor, chip);
+	buffer[1] = (unsigned char)(command >> 8);
+	buffer[2] = (unsigned char)command;
+	buffer[3] = (unsigned char)data->cmd_seq++;
+	buffer[4] = (unsigned char)w_buff_len;
+	buffer[5] = (unsigned char)reg_addr_len;
+	buffer[6] = (unsigned char)((reg_addr) >> 24);	/* Get first unsigned char of reg. address  */
+	buffer[7] = (unsigned char)((reg_addr) >> 16);	/* Get second unsigned char of reg. address */
+	buffer[8] = (unsigned char)((reg_addr) >> 8);	/* Get third unsigned char of reg. address  */
+	buffer[9] = (unsigned char)(reg_addr);	/* Get fourth unsigned char of reg. address */
+
+	/* add frame data */
+	for (i = 0; i < w_buff_len; i++)
+		buffer[10 + i] = w_buff[i];
+
+	/* add frame check-sum */
+	buff_len = 10 + w_buff_len;
+	error = it9135_cmd_add_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+	/* send frame */
+	i = 0;
+	send_len = 0;
+	remain_len = buff_len;
+	while (remain_len > 0) {
+		i = (remain_len > IT9135_MAX_PKT_SIZE) ? (IT9135_MAX_PKT_SIZE)
+		    : (remain_len);
+		error = it9135_cmd_bus_tx(data, i, &buffer[send_len]);
+		if (error)
+			goto exit;
+
+		send_len += i;
+		remain_len -= i;
+	}
+
+	/* get reply frame */
+	buff_len = 5;
+	error = it9135_cmd_bus_rx(data, buff_len, buffer);
+	if (error)
+		goto exit;
+
+	/* remove check-sum from reply frame */
+	error = it9135_cmd_remove_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+exit:
+	it9135_leave_mutex(data);
+	return error;
+}
+
+unsigned long it9135_write_gen_regs(struct it9135_data *data,
+				    unsigned char chip,
+				    unsigned char interfaceIndex,
+				    unsigned char slaveAddress,
+				    unsigned char buff_len,
+				    unsigned char *buffer)
+{
+	unsigned char w_buff[256];
+	unsigned char i;
+
+	w_buff[0] = buff_len;
+	w_buff[1] = interfaceIndex;
+	w_buff[2] = slaveAddress;
+
+	for (i = 0; i < buff_len; i++)
+		w_buff[3 + i] = buffer[i];
+
+	return it9135_cmd_sendcommand(data, CMD_GENERIC_WRITE, chip,
+				      PROCESSOR_LINK, buff_len + 3, w_buff, 0,
+				      NULL);
+}
+
+unsigned long it9135_write_reg(struct it9135_data *data, unsigned char chip,
+			       unsigned char processor, unsigned long reg_addr,
+			       unsigned char value)
+{
+	return it9135_write_regs(data, chip, processor, reg_addr, 1, &value);
+}
+
+unsigned long it9135_write_ee_vals(struct it9135_data *data, unsigned char chip,
+				   unsigned short reg_addr,
+				   unsigned char w_buff_len,
+				   unsigned char *w_buff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned short command;
+	unsigned char buffer[255];
+	unsigned long buff_len;
+	unsigned long remain_len;
+	unsigned long send_len;
+	unsigned long i;
+	unsigned char eeprom_addr = 1;
+	unsigned char reg_addr_len = 1;
+
+	it9135_enter_mutex(data);
+
+	if (w_buff_len == 0)
+		goto exit;
+
+	if ((unsigned long)(w_buff_len + 11) > IT9135_MAX_CMD_SIZE) {
+		error = ERROR_INVALID_DATA_LENGTH;
+		goto exit;
+	}
+
+	/* add frame header */
+	command =
+	    it9135_build_command(CMD_REG_EEPROM_WRITE, PROCESSOR_LINK, chip);
+	buffer[1] = (unsigned char)(command >> 8);
+	buffer[2] = (unsigned char)command;
+	buffer[3] = (unsigned char)data->cmd_seq++;
+	buffer[4] = (unsigned char)w_buff_len;
+	buffer[5] = (unsigned char)eeprom_addr;
+	buffer[6] = (unsigned char)reg_addr_len;
+	buffer[7] = (unsigned char)(reg_addr >> 8);	/* Get high unsigned char of reg. address */
+	buffer[8] = (unsigned char)reg_addr;	/* Get low unsigned char of reg. address  */
+
+	/* add frame data */
+	for (i = 0; i < w_buff_len; i++)
+		buffer[9 + i] = w_buff[i];
+
+	/* add frame check-sum */
+	buff_len = 9 + w_buff_len;
+	error = it9135_cmd_add_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+	/* send frame */
+	i = 0;
+	send_len = 0;
+	remain_len = buff_len;
+	while (remain_len > 0) {
+		i = (remain_len > IT9135_MAX_PKT_SIZE) ? (IT9135_MAX_PKT_SIZE)
+		    : (remain_len);
+		error = it9135_cmd_bus_tx(data, i, &buffer[send_len]);
+		if (error)
+			goto exit;
+
+		send_len += i;
+		remain_len -= i;
+	}
+
+	/* get reply frame */
+	buff_len = 5;
+	error = it9135_cmd_bus_rx(data, buff_len, buffer);
+	if (error)
+		goto exit;
+
+	/* remove check-sum from reply frame */
+	error = it9135_cmd_remove_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+exit:
+	it9135_leave_mutex(data);
+	return error;
+}
+
+static unsigned char it9135_reg_bit_mask[8] = {
+	0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
+};
+
+unsigned long it9135_write_reg_bits(struct it9135_data *data,
+				    unsigned char chip, unsigned char processor,
+				    unsigned long reg_addr,
+				    unsigned char position,
+				    unsigned char length, unsigned char value)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char temp;
+
+	if (length == 8) {
+		error =
+		    it9135_write_regs(data, chip, processor, reg_addr, 1,
+				      &value);
+	} else {
+		error =
+		    it9135_read_regs(data, chip, processor, reg_addr, 1, &temp);
+		if (error)
+			goto exit;
+
+		temp =
+		    REG_CREATE(it9135_reg_bit_mask, value, temp, position,
+			       length);
+
+		error =
+		    it9135_write_regs(data, chip, processor, reg_addr, 1,
+				      &temp);
+	}
+
+exit:
+	return error;
+}
+
+unsigned long it9135_read_reg(struct it9135_data *data, unsigned char chip,
+			      unsigned char processor, unsigned long reg_addr,
+			      unsigned char *value)
+{
+	return it9135_read_regs(data, chip, processor, reg_addr, 1, value);
+}
+
+unsigned long it9135_read_regs(struct it9135_data *data, unsigned char chip,
+			       unsigned char processor, unsigned long reg_addr,
+			       unsigned long r_buff_len, unsigned char *r_buff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned short command;
+	unsigned char buffer[255];
+	unsigned long buff_len;
+	unsigned long send_len;
+	unsigned long remain_len;
+	unsigned long i, k;
+	unsigned char reg_addr_len = 2;
+
+	it9135_enter_mutex(data);
+
+	if (r_buff_len == 0)
+		goto exit;
+	if (reg_addr_len > 4) {
+		error = ERROR_PROTOCOL_FORMAT_INVALID;
+		goto exit;
+	}
+
+	if ((r_buff_len + 5) > IT9135_MAX_PKT_SIZE) {
+		error = ERROR_INVALID_DATA_LENGTH;
+		goto exit;
+	}
+
+	if ((r_buff_len + 5) > IT9135_MAX_CMD_SIZE) {
+		error = ERROR_INVALID_DATA_LENGTH;
+		goto exit;
+	}
+
+	/* add frame header */
+	command = it9135_build_command(CMD_REG_DEMOD_READ, processor, chip);
+	buffer[1] = (unsigned char)(command >> 8);
+	buffer[2] = (unsigned char)command;
+	buffer[3] = (unsigned char)data->cmd_seq++;
+	buffer[4] = (unsigned char)r_buff_len;
+	buffer[5] = (unsigned char)reg_addr_len;
+	buffer[6] = (unsigned char)(reg_addr >> 24);	/* Get first unsigned char of reg. address  */
+	buffer[7] = (unsigned char)(reg_addr >> 16);	/* Get second unsigned char of reg. address */
+	buffer[8] = (unsigned char)(reg_addr >> 8);	/* Get third unsigned char of reg. address  */
+	buffer[9] = (unsigned char)(reg_addr);	/* Get fourth unsigned char of reg. address */
+
+	/* add frame check-sum */
+	buff_len = 10;
+	error = it9135_cmd_add_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+	/* send frame */
+	i = 0;
+	send_len = 0;
+	remain_len = buff_len;
+	while (remain_len > 0) {
+		i = (remain_len > IT9135_MAX_PKT_SIZE) ? (IT9135_MAX_PKT_SIZE)
+		    : (remain_len);
+		error = it9135_cmd_bus_tx(data, i, &buffer[send_len]);
+		if (error)
+			goto exit;
+
+		send_len += i;
+		remain_len -= i;
+	}
+
+	/* get reply frame */
+	buff_len = 5 + r_buff_len;
+	error = it9135_cmd_bus_rx(data, buff_len, buffer);
+	if (error)
+		goto exit;
+
+	/* remove check-sum from reply frame */
+	error = it9135_cmd_remove_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+	for (k = 0; k < r_buff_len; k++)
+		r_buff[k] = buffer[k + 3];
+
+exit:
+	it9135_leave_mutex(data);
+	return error;
+}
+
+unsigned long it9135_read_gen_regs(struct it9135_data *data, unsigned char chip,
+				   unsigned char interfaceIndex,
+				   unsigned char slaveAddress,
+				   unsigned char buff_len,
+				   unsigned char *buffer)
+{
+	unsigned char w_buff[3];
+
+	w_buff[0] = buff_len;
+	w_buff[1] = interfaceIndex;
+	w_buff[2] = slaveAddress;
+
+	return it9135_cmd_sendcommand(data, CMD_GENERIC_READ, chip,
+				      PROCESSOR_LINK, 3, w_buff, buff_len,
+				      buffer);
+}
+
+unsigned long it9135_read_ee_vals(struct it9135_data *data, unsigned char chip,
+				  unsigned short reg_addr,
+				  unsigned char r_buff_len,
+				  unsigned char *r_buff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned short command;
+	unsigned char buffer[255];
+	unsigned long buff_len;
+	unsigned long remain_len;
+	unsigned long send_len;
+	unsigned long i, k;
+	unsigned char eeprom_addr = 1;
+	unsigned char reg_addr_len = 1;
+
+	it9135_enter_mutex(data);
+
+	if (r_buff_len == 0)
+		goto exit;
+
+	if ((unsigned long)(r_buff_len + 5) > IT9135_MAX_PKT_SIZE) {
+		error = ERROR_INVALID_DATA_LENGTH;
+		goto exit;
+	}
+
+	if ((unsigned long)(r_buff_len + 5) > IT9135_MAX_CMD_SIZE) {
+		error = ERROR_INVALID_DATA_LENGTH;
+		goto exit;
+	}
+
+	/* add command header */
+	command =
+	    it9135_build_command(CMD_REG_EEPROM_READ, PROCESSOR_LINK, chip);
+	buffer[1] = (unsigned char)(command >> 8);
+	buffer[2] = (unsigned char)command;
+	buffer[3] = (unsigned char)data->cmd_seq++;
+	buffer[4] = (unsigned char)r_buff_len;
+	buffer[5] = (unsigned char)eeprom_addr;
+	buffer[6] = (unsigned char)reg_addr_len;
+	buffer[7] = (unsigned char)(reg_addr >> 8);	/* Get high unsigned char of reg. address */
+	buffer[8] = (unsigned char)reg_addr;	/* Get low unsigned char of reg. address  */
+
+	/* add frame check-sum */
+	buff_len = 9;
+	error = it9135_cmd_add_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+	/* send frame */
+	i = 0;
+	send_len = 0;
+	remain_len = buff_len;
+	while (remain_len > 0) {
+		i = (remain_len > IT9135_MAX_PKT_SIZE) ? (IT9135_MAX_PKT_SIZE)
+		    : (remain_len);
+		error = it9135_cmd_bus_tx(data, i, &buffer[send_len]);
+		if (error)
+			goto exit;
+
+		send_len += i;
+		remain_len -= i;
+	}
+
+	/* get reply frame */
+	buff_len = 5 + r_buff_len;
+	error = it9135_cmd_bus_rx(data, buff_len, buffer);
+	if (error)
+		goto exit;
+
+	/* remove frame check-sum */
+	error = it9135_cmd_remove_checksum(data, &buff_len, buffer);
+	if (error)
+		goto exit;
+
+	for (k = 0; k < r_buff_len; k++)
+		r_buff[k] = buffer[k + 3];
+
+exit:
+	it9135_leave_mutex(data);
+	return error;
+}
+
+unsigned long it9135_read_reg_bits(struct it9135_data *data,
+				   unsigned char chip, unsigned char processor,
+				   unsigned long reg_addr,
+				   unsigned char position, unsigned char length,
+				   unsigned char *value)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char temp = 0;
+
+	error = it9135_read_regs(data, chip, processor, reg_addr, 1, &temp);
+	if (error)
+		goto exit;
+
+	if (length == 8) {
+		*value = temp;
+	} else {
+		temp = REG_GET(it9135_reg_bit_mask, temp, position, length);
+		*value = temp;
+	}
+
+exit:
+	return error;
+}
+
+unsigned long it9135_get_fw_ver(struct it9135_data *data,
+				unsigned char processor, unsigned long *version)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char w_buff[1] = { 1 };
+	unsigned char r_buff[4] = { 0, 0, 0, 0 };
+
+	error =
+	    it9135_cmd_sendcommand(data, CMD_QUERYINFO, 0, processor, 1, w_buff,
+				   4, r_buff);
+	if (error)
+		goto exit;
+
+	*version =
+	    (unsigned long)(((unsigned long)r_buff[0] << 24) +
+			    ((unsigned long)r_buff[1] << 16) +
+			    ((unsigned long)r_buff[2] << 8) +
+			    (unsigned long)r_buff[3]);
+
+exit:
+	return error;
+}
+
+/*
+ * Set the counting range for Post-Viterbi and Post-Viterbi.
+ *
+ * @param struct it9135_data the handle of IT9135.
+ * @param chip The index of IT9135. The possible values are 0~7.
+ *        NOTE: When the architecture is set to ARCHITECTURE_DCA
+ *        this parameter is regard as don't care.
+ * @param post_err_cnt the number of super frame for Pre-Viterbi (24 bits).
+ * @param post_bit_cnt the number of packet unit for Post-Viterbi (16 bits).
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_get_post_vitber(struct it9135_data *data,
+				     unsigned char chip,
+				     unsigned long *post_err_cnt,
+				     unsigned long *post_bit_cnt,
+				     unsigned short *abort_cnt)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long err_cnt;
+	unsigned long bit_cnt;
+	unsigned char buffer[7];
+	unsigned short abort;
+
+	*post_err_cnt = 0;
+	*post_bit_cnt = 0;
+
+	error =
+	    it9135_read_regs(data, chip, PROCESSOR_OFDM,
+			     rsd_abort_packet_cnt_7_0,
+			     r_rsd_packet_unit_15_8 - rsd_abort_packet_cnt_7_0 +
+			     1, buffer);
+	if (error)
+		goto exit;
+
+	abort = ((unsigned short)
+		 buffer[rsd_abort_packet_cnt_15_8 - rsd_abort_packet_cnt_7_0]
+		 << 8) + buffer[rsd_abort_packet_cnt_7_0 -
+				rsd_abort_packet_cnt_7_0];
+	err_cnt = ((unsigned long)
+		   buffer[rsd_bit_err_cnt_23_16 -
+			  rsd_abort_packet_cnt_7_0] << 16) + ((unsigned long)
+							      buffer
+							      [rsd_bit_err_cnt_15_8
+							       -
+							       rsd_abort_packet_cnt_7_0]
+							      << 8) +
+	    buffer[rsd_bit_err_cnt_7_0 - rsd_abort_packet_cnt_7_0];
+	bit_cnt = ((unsigned long)
+		   buffer[r_rsd_packet_unit_15_8 -
+			  rsd_abort_packet_cnt_7_0] << 8) +
+	    buffer[r_rsd_packet_unit_7_0 - rsd_abort_packet_cnt_7_0];
+
+	if (bit_cnt == 0) {
+		/*error = ERROR_RSD_PKT_CNT_0; */
+		*post_err_cnt = 1;
+		*post_bit_cnt = 2;
+		*abort_cnt = 1000;
+		goto exit;
+	}
+
+	*abort_cnt = abort;
+	bit_cnt = bit_cnt - (unsigned long)abort;
+	if (bit_cnt == 0) {
+		*post_err_cnt = 1;
+		*post_bit_cnt = 2;
+	} else {
+		*post_err_cnt = err_cnt - (unsigned long)abort * 8 * 8;
+		*post_bit_cnt = bit_cnt * 204 * 8;
+	}
+
+exit:
+	return error;
+}
+
+/* NorDig 3.4.4.6 & Table 3.4 */
+static int it9135_Pref_values[3][5] = {
+	{-93, -91, -90, -89, -88},	/* QPSK    CodeRate 1/2 ~ 7/8 Pref Values */
+	{-87, -85, -84, -83, -82},	/* 16QAM   CodeRate 1/2 ~ 7/8 Pref Values */
+	{-82, -80, -78, -77, -76},	/* 64QAM   CodeRate 1/2 ~ 7/8 Pref Values */
+};
+
+/*
+ * Get siganl quality.
+ *
+ * @param struct it9135_data the handle of IT9135.
+ * @param chip The index of IT9135. The possible values are 0~7.
+ *        NOTE: When the architecture is set to ARCHITECTURE_DCA
+ *        this parameter is regard as don't care.
+ * @param quality The value of signal quality.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_get_signal_quality(struct it9135_data *data,
+					unsigned char chip,
+					unsigned char *quality)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	error = it9135_read_reg(data, chip, PROCESSOR_OFDM, signal_quality, quality);
+	
+	return (error);
+}
+
+unsigned long it9135_get_strength(struct it9135_data *data, unsigned char chip,
+				  unsigned char *strength)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char temp, lna_gain_offset;
+	struct it9135_ch_modulation ch_modulation;
+	int Prec, Pref, Prel;
+
+	error =
+	    it9135_read_reg(data, chip, PROCESSOR_OFDM, var_p_inband, &temp);
+	if (error)
+		goto exit;
+
+	error = it9135_get_ch_modulation(data, chip, &ch_modulation);
+	if (error)
+		goto exit;
+
+	if (ch_modulation.frequency < 300000)
+		lna_gain_offset = 7;	/* VHF */
+	else
+		lna_gain_offset = 14;	/* UHF */
+
+	Prec = (temp - 100) - lna_gain_offset;
+
+	if (ch_modulation.priority == PRIORITY_HIGH)
+		Pref = it9135_Pref_values[ch_modulation.constellation]
+		    [ch_modulation.h_code_rate];
+	else
+		Pref = it9135_Pref_values[ch_modulation.constellation]
+		    [ch_modulation.l_code_rate];
+
+	Prel = Prec - Pref;
+
+	if (Prel < -15)
+		*strength = 0;
+	else if ((-15 <= Prel) && (Prel < 0))
+		*strength = (unsigned char)((2 * (Prel + 15)) / 3);
+	else if ((0 <= Prel) && (Prel < 20))
+		*strength = (unsigned char)(4 * Prel + 10);
+	else if ((20 <= Prel) && (Prel < 35))
+		*strength = ((unsigned char)(2 * (Prel - 20)) / 3 + 90);
+	else if (Prel >= 35)
+		*strength = 100;
+
+exit:
+	return error;
+}
+
+/* @param strength_dbm: DBm */
+unsigned long it9135_get_strength_dbm(struct it9135_data *data,
+				      unsigned char chip, long *strength_dbm)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char temp;
+
+	error =
+	    it9135_read_reg(data, chip, PROCESSOR_OFDM, var_p_inband, &temp);
+	if (error)
+		goto exit;
+
+	*strength_dbm = (long)(temp - 100);
+
+exit:
+	return error;
+}
+
+unsigned long it9135_load_ir_tab(struct it9135_data *data,
+				 unsigned short tab_len, unsigned char *table)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char base_high;
+	unsigned char base_low;
+	unsigned short reg_base;
+	unsigned short i;
+
+	error =
+	    it9135_read_reg(data, 0, PROCESSOR_LINK, ir_table_start_15_8,
+			    &base_high);
+	if (error)
+		goto exit;
+	error =
+	    it9135_read_reg(data, 0, PROCESSOR_LINK, ir_table_start_7_0,
+			    &base_low);
+	if (error)
+		goto exit;
+
+	reg_base = (unsigned short)(base_high << 8) + (unsigned short)base_low;
+
+	if (reg_base) {
+		for (i = 0; i < tab_len; i++) {
+			error =
+			    it9135_write_reg(data, 0, PROCESSOR_LINK,
+					     reg_base + i, table[i]);
+			if (error)
+				goto exit;
+		}
+	}
+
+exit:
+	return error;
+}
+
+static struct it9135_freq_clk it9135_freq_clk_tab[2] = {
+	{12000, 20250000},
+	{20480, 20480000}
+};
+
+unsigned long it9135_dev_init(struct it9135_data *data, unsigned char chip_num,
+			      unsigned short saw_band, unsigned char streamType,
+			      unsigned char architecture)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long crystal = 0;
+	unsigned long adc = 0;
+	unsigned long fcw = 0;
+	unsigned char buffer[4];
+	unsigned long version = 0;
+	unsigned short *tuner_script_sets = NULL;
+	struct it9135_val_set *tuner_scripts = NULL;
+	unsigned char i;
+	unsigned char var[2];
+
+#define IT9135_IF_FREQUENCY				0
+#define IT9135_IF_INVERSION				0
+/* Define I2C address of secondary chip when Diversity mode or PIP mode is active. */
+#define IT9135_CHIP2_I2C_ADDR      0x3A
+
+	data->chip_num = chip_num;
+	data->fcw = 0x00000000;
+	data->frequency[0] = 642000;
+	data->frequency[1] = 642000;
+	data->inited = 0;
+	data->host_if[0] = 0;
+	data->cmd_seq = 0;
+	data->pid_info.pid_init = 0;
+
+	error =
+	    it9135_read_reg(data, 0, PROCESSOR_LINK, chip_version_7_0,
+			    &data->chip_ver);
+	if (error)
+		goto exit;
+	error =
+	    it9135_read_regs(data, 0, PROCESSOR_LINK, chip_version_7_0 + 1, 2,
+			     var);
+	if (error)
+		goto exit;
+	data->chip_type = var[1] << 8 | var[0];
+
+	if (data->busId == 0xFFFF || data->tuner_desc.id == 0xFFFF)
+		goto exit;
+
+	error = it9135_get_fw_ver(data, PROCESSOR_LINK, &version);
+	if (error)
+		goto exit;
+	if (version != 0)
+		data->booted = 1;
+	else
+		data->booted = 0;
+
+	/*if (data->chip_type == 0x9135 && data->chip_ver == 2) {
+	   data->fw_codes = FirmwareV2_codes;
+	   data->fw_segs = FirmwareV2_segments;
+	   data->fw_parts = FirmwareV2_partitions;
+	   data->script_sets = FirmwareV2_scriptSets;
+	   data->scripts = FirmwareV2_scripts;
+	   } else {
+	   data->fw_codes = Firmware_codes;
+	   data->fw_segs = Firmware_segments;
+	   data->fw_parts = Firmware_partitions;
+	   data->script_sets = Firmware_scriptSets;
+	   data->scripts = Firmware_scripts;
+	   } */
+	tuner_script_sets = data->tuner_desc.script_sets;
+	tuner_scripts = data->tuner_desc.scripts;
+
+	error =
+	    it9135_read_reg_bits(data, 0, PROCESSOR_LINK,
+				 r_io_mux_pwron_clk_strap,
+				 io_mux_pwron_clk_strap_pos,
+				 io_mux_pwron_clk_strap_len, &i);
+	if (error)
+		goto exit;
+
+	data->crystal_Freq = it9135_freq_clk_tab[0].crystal_Freq;
+	data->adc_freq = it9135_freq_clk_tab[0].adc_freq;
+
+	/* Write secondary I2C address to device */
+	/* Enable or disable clock for 2nd chip power saving */
+	if (data->chip_num > 1) {
+		error =
+		    it9135_write_reg(data, 0, PROCESSOR_LINK,
+				     second_i2c_address, IT9135_CHIP2_I2C_ADDR);
+		if (error)
+			goto exit;
+
+		error =
+		    it9135_write_reg(data, 0, PROCESSOR_LINK, p_reg_top_clkoen,
+				     1);
+		if (error)
+			goto exit;
+
+	} else {
+		error =
+		    it9135_write_reg(data, 0, PROCESSOR_LINK,
+				     second_i2c_address, 0x00);
+		if (error)
+			goto exit;
+
+		error =
+		    it9135_write_reg(data, 0, PROCESSOR_LINK, p_reg_top_clkoen,
+				     0);
+		if (error)
+			goto exit;
+	}
+
+	/* Load firmware */
+	if (data->fw_codes != NULL) {
+		if (!data->booted) {
+			error =
+			    it9135_load_firmware(data,
+						 data->fw_codes, data->fw_segs,
+						 &data->fw_parts);
+			if (error)
+				goto exit;
+			data->booted = 1;
+		}
+	}
+
+	/* Set I2C master clock 100k in order to support tuner I2C. */
+	error =
+	    it9135_write_reg(data, 0, PROCESSOR_LINK,
+			     p_reg_one_cycle_counter_tuner, 0x1a);
+	if (error)
+		goto exit;
+
+	for (i = 0; i < data->chip_num; i++) {
+		error = it9135_write_reg(data, i, PROCESSOR_OFDM, 0xEC4C, 0x68);
+		if (error)
+			goto exit;
+		mdelay(10);
+	}
+
+	if (data->chip_type == 0x9135 && data->chip_ver == 1) {
+		/* Open tuner */
+		for (i = 0; i < data->chip_num; i++) {
+
+			/* Set 0xD827 to 0 as open drain for tuner i2c */
+			error =
+			    it9135_write_reg(data, i, PROCESSOR_LINK,
+					     p_reg_top_padodpu, 0);
+			if (error)
+				goto exit;
+
+			/* Set 0xD829 to 0 as push pull for tuner AGC */
+			error =
+			    it9135_write_reg(data, i, PROCESSOR_LINK,
+					     p_reg_top_agc_od, 0);
+			if (error)
+				goto exit;
+		}
+
+		for (i = 0; i < data->chip_num; i++) {
+			error = it9135_tuner_init(data, i);
+			if (error)
+				goto exit;
+		}
+	}
+
+	for (i = 0; i < data->chip_num; i++) {
+		/* Tell firmware the type of tuner. */
+		error =
+		    it9135_write_reg(data, i, PROCESSOR_LINK,
+				     p_reg_link_ofsm_dummy_15_8,
+				     (unsigned char)data->tuner_desc.id);
+		if (error)
+			goto exit;
+	}
+
+	/* Initialize OFDM */
+	if (data->booted) {
+		for (i = 0; i < data->chip_num; i++) {
+			/* Set read-update bit to 1 for constellation */
+			error =
+			    it9135_write_reg_bits(data, i,
+						  PROCESSOR_OFDM,
+						  p_reg_feq_read_update,
+						  reg_feq_read_update_pos,
+						  reg_feq_read_update_len, 1);
+			if (error)
+				goto exit;
+
+			/* Enable FEC Monitor */
+			error =
+			    it9135_write_reg_bits(data, i,
+						  PROCESSOR_OFDM,
+						  p_fec_vtb_rsd_mon_en,
+						  fec_vtb_rsd_mon_en_pos,
+						  fec_vtb_rsd_mon_en_len, 1);
+			if (error)
+				goto exit;
+		}
+
+		/* Compute ADC and load them to device */
+		error =
+		    it9135_compute_crystal(data,
+					   (long)data->crystal_Freq * 1000,
+					   &crystal);
+		if (error)
+			goto exit;
+
+		buffer[0] = (unsigned char)(crystal & 0x000000FF);
+		buffer[1] = (unsigned char)((crystal & 0x0000FF00) >> 8);
+		buffer[2] = (unsigned char)((crystal & 0x00FF0000) >> 16);
+		buffer[3] = (unsigned char)((crystal & 0xFF000000) >> 24);
+		for (i = 0; i < data->chip_num; i++) {
+			error =
+			    it9135_write_regs(data, i, PROCESSOR_OFDM,
+					      crystal_clk_7_0, 4, buffer);
+			if (error)
+				goto exit;
+		}
+
+		/* Compute ADC and load them to device */
+		error = it9135_compute_adc(data, (long)data->adc_freq, &adc);
+		if (error)
+			goto exit;
+
+		buffer[0] = (unsigned char)(adc & 0x000000FF);
+		buffer[1] = (unsigned char)((adc & 0x0000FF00) >> 8);
+		buffer[2] = (unsigned char)((adc & 0x00FF0000) >> 16);
+		for (i = 0; i < data->chip_num; i++) {
+			error =
+			    it9135_write_regs(data, i, PROCESSOR_OFDM,
+					      p_reg_f_adc_7_0, 3, buffer);
+			if (error)
+				goto exit;
+		}
+
+		/* Compute FCW and load them to device */
+		error =
+		    it9135_compute_fcw(data,
+				       (long)data->adc_freq,
+				       (long)IT9135_IF_FREQUENCY,
+				       IT9135_IF_INVERSION, &fcw);
+		if (error)
+			goto exit;
+		data->fcw = fcw;
+
+		buffer[0] = (unsigned char)(fcw & 0x000000FF);
+		buffer[1] = (unsigned char)((fcw & 0x0000FF00) >> 8);
+		buffer[2] = (unsigned char)((fcw & 0x007F0000) >> 16);
+		for (i = 0; i < data->chip_num; i++) {
+			error =
+			    it9135_write_regs(data, i,
+					      PROCESSOR_OFDM, bfs_fcw_7_0,
+					      bfs_fcw_22_16 - bfs_fcw_7_0 + 1,
+					      buffer);
+			if (error)
+				goto exit;
+		}
+	}
+
+	/* Load script */
+	if (data->scripts != NULL) {
+		error =
+		    it9135_load_script(data, data->script_sets,
+				       data->scripts, tuner_script_sets,
+				       tuner_scripts);
+		if (error)
+			goto exit;
+	}
+
+	if ((data->chip_type == 0x9135 && data->chip_ver == 2)
+	    || data->chip_type == 0x9175) {
+		for (i = 0; i < data->chip_num; i++) {
+			error =
+			    it9135_write_reg(data, i, PROCESSOR_OFDM,
+					     trigger_ofsm, 0x01);
+			if (error)
+				goto exit;
+		}
+
+		/* Open tuner */
+		for (i = 0; i < data->chip_num; i++) {
+
+			/* Set 0xD827 to 0 as open drain for tuner i2c */
+			error =
+			    it9135_write_reg(data, i, PROCESSOR_LINK,
+					     p_reg_top_padodpu, 0);
+			if (error)
+				goto exit;
+
+			/* Set 0xD829 to 0 as push pull for tuner AGC */
+			error =
+			    it9135_write_reg(data, i, PROCESSOR_LINK,
+					     p_reg_top_agc_od, 0);
+			if (error)
+				goto exit;
+		}
+
+		for (i = 0; i < data->chip_num; i++) {
+			error = it9135_tuner_init(data, i);
+			if (error)
+				goto exit;
+		}
+	}
+
+	/* Set the desired stream type */
+	error = it9135_set_stream_type(data, streamType);
+	if (error)
+		goto exit;
+
+	/* Set the desired architecture type */
+	error = it9135_set_arch(data, architecture);
+	if (error)
+		goto exit;
+
+	for (i = 0; i < data->chip_num; i++) {
+		/* Set H/W MPEG2 locked detection */
+		error =
+		    it9135_write_reg(data, i, PROCESSOR_LINK,
+				     p_reg_top_lock3_out, 1);
+		if (error)
+			goto exit;
+		error =
+		    it9135_write_reg(data, i, PROCESSOR_LINK,
+				     p_reg_top_padmiscdrsr, 1);
+		if (error)
+			goto exit;
+		/* Set registers for driving power 0xD830 */
+		error =
+		    it9135_write_reg(data, i, PROCESSOR_LINK,
+				     p_reg_top_padmiscdr2, 0);
+		if (error)
+			goto exit;
+		/* enhance the performance while using DIP crystals */
+		error = it9135_write_reg(data, i, PROCESSOR_OFDM, 0xEC57, 0);
+		if (error)
+			goto exit;
+		error = it9135_write_reg(data, i, PROCESSOR_OFDM, 0xEC58, 0);
+		if (error)
+			goto exit;
+		/* Set ADC frequency multiplier */
+		error = it9135_set_multiplier(data, Multiplier_2X);
+		if (error)
+			goto exit;
+		/* Set registers for driving power 0xD831 */
+		error =
+		    it9135_write_reg(data, i, PROCESSOR_LINK,
+				     p_reg_top_padmiscdr4, 0);
+		if (error)
+			goto exit;
+		/* Set registers for driving power 0xD832 */
+		error =
+		    it9135_write_reg(data, i, PROCESSOR_LINK,
+				     p_reg_top_padmiscdr8, 0);
+		if (error)
+			goto exit;
+	}
+
+	data->inited = 1;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_tps_locked(struct it9135_data *data, unsigned char chip,
+				int *locked)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char temp;
+
+	*locked = 0;
+
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM, p_fd_tpsd_lock,
+				 fd_tpsd_lock_pos, fd_tpsd_lock_len, &temp);
+	if (error)
+		goto exit;
+	if (temp)
+		*locked = 1;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_mp2_locked(struct it9135_data *data, unsigned char chip,
+				int *locked)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char temp;
+
+	*locked = 0;
+
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM,
+				 r_mp2if_sync_byte_locked,
+				 mp2if_sync_byte_locked_pos,
+				 mp2if_sync_byte_locked_len, &temp);
+	if (error)
+		goto exit;
+
+	if (temp)
+		*locked = 1;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_freq_locked(struct it9135_data *data, unsigned char chip,
+				 int *locked)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned short empty_loop = 0;
+	unsigned short tps_loop = 0;
+	unsigned short mpeg2_loop = 0;
+	unsigned char channels[2];
+	unsigned char begin;
+	unsigned char end;
+	unsigned char i;
+	unsigned char empty_ch = 1;
+	unsigned char tps_locked = 0;
+	int retry = 1;
+
+check_lock:
+	*locked = 0;
+
+	if (data->architecture == ARCHITECTURE_DCA) {
+		begin = 0;
+		end = data->chip_num;
+	} else {
+		begin = chip;
+		end = begin + 1;
+	}
+
+	for (i = begin; i < end; i++) {
+		data->statistic[i].presented = 0;
+		data->statistic[i].locked = 0;
+		data->statistic[i].quality = 0;
+		data->statistic[i].strength = 0;
+	}
+
+	channels[0] = 2;
+	channels[1] = 2;
+	while (empty_loop < 40) {
+		for (i = begin; i < end; i++) {
+			error =
+			    it9135_read_reg(data, i, PROCESSOR_OFDM,
+					    empty_channel_status, &channels[i]);
+			if (error)
+				goto exit;
+		}
+		if ((channels[0] == 1) || (channels[1] == 1)) {
+			empty_ch = 0;
+			break;
+		}
+		if ((channels[0] == 2) && (channels[1] == 2)) {
+			empty_ch = 1;
+			goto exit;
+		}
+		mdelay(25);
+		empty_loop++;
+	}
+
+	if (empty_ch == 1)
+		goto exit;
+
+	while (tps_loop < 50) {
+		for (i = begin; i < end; i++) {
+			/* TPS check */
+			error =
+			    it9135_tps_locked(data, i,
+					      &data->statistic[i].presented);
+			if (error)
+				goto exit;
+			if (data->statistic[i].presented) {
+				tps_locked = 1;
+				break;
+			}
+		}
+
+		if (tps_locked == 1)
+			break;
+
+		mdelay(25);
+		tps_loop++;
+	}
+
+	if (tps_locked == 0)
+		goto exit;
+
+	while (mpeg2_loop < 40) {
+		if (data->architecture == ARCHITECTURE_DCA) {
+			error =
+			    it9135_mp2_locked(data, 0,
+					      &data->statistic[0].locked);
+			if (error)
+				goto exit;
+			if (data->statistic[0].locked) {
+				for (i = begin; i < end; i++) {
+					data->statistic[i].quality = 80;
+					data->statistic[i].strength = 80;
+				}
+				*locked = 1;
+				break;
+			}
+		} else {
+			error =
+			    it9135_mp2_locked(data, chip,
+					      &data->statistic[chip].locked);
+			if (error)
+				goto exit;
+			if (data->statistic[chip].locked) {
+				data->statistic[chip].quality = 80;
+				data->statistic[chip].strength = 80;
+				*locked = 1;
+				break;
+			}
+		}
+		mdelay(25);
+		mpeg2_loop++;
+	}
+	for (i = begin; i < end; i++) {
+		data->statistic[i].quality = 0;
+		data->statistic[i].strength = 20;
+	}
+
+exit:
+	if (*locked == 0 && retry == 1) {
+		retry = 0;
+		mpeg2_loop = 0;
+		tps_loop = 0;
+		empty_loop = 0;
+		empty_ch = 1;
+		tps_locked = 0;
+		/* Clear empty_channel_status lock flag */
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM,
+				     empty_channel_status, 0x00);
+		if (error)
+			goto exit;
+
+		/* Trigger ofsm */
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, trigger_ofsm,
+				     0);
+		if (error)
+			goto exit;
+
+		goto check_lock;
+	}
+
+	return error;
+}
+
+unsigned long it9135_get_ch_modulation(struct it9135_data *data,
+				       unsigned char chip,
+				       struct it9135_ch_modulation
+				       *ch_modulation)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char temp;
+
+	/* Get constellation type */
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM,
+				 g_reg_tpsd_const, reg_tpsd_const_pos,
+				 reg_tpsd_const_len, &temp);
+	if (error)
+		goto exit;
+	ch_modulation->constellation = temp;
+
+	/* Get TPS hierachy and alpha value */
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM,
+				 g_reg_tpsd_hier, reg_tpsd_hier_pos,
+				 reg_tpsd_hier_len, &temp);
+	if (error)
+		goto exit;
+	ch_modulation->hierarchy = temp;
+
+	/* Get high/low priority */
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM, g_reg_dec_pri,
+				 reg_dec_pri_pos, reg_dec_pri_len, &temp);
+	if (error)
+		goto exit;
+	if (temp)
+		ch_modulation->priority = PRIORITY_HIGH;
+	else
+		ch_modulation->priority = PRIORITY_LOW;
+
+	/* Get high code rate */
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM,
+				 g_reg_tpsd_hpcr, reg_tpsd_hpcr_pos,
+				 reg_tpsd_hpcr_len, &temp);
+	if (error)
+		goto exit;
+	ch_modulation->h_code_rate = temp;
+
+	/* Get low code rate */
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM,
+				 g_reg_tpsd_lpcr, reg_tpsd_lpcr_pos,
+				 reg_tpsd_lpcr_len, &temp);
+	if (error)
+		goto exit;
+	ch_modulation->l_code_rate = temp;
+
+	/* Get guard interval */
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM, g_reg_tpsd_gi,
+				 reg_tpsd_gi_pos, reg_tpsd_gi_len, &temp);
+	if (error)
+		goto exit;
+	ch_modulation->interval = temp;
+
+	/* Get FFT mode */
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM,
+				 g_reg_tpsd_txmod, reg_tpsd_txmod_pos,
+				 reg_tpsd_txmod_len, &temp);
+	if (error)
+		goto exit;
+	ch_modulation->trans_mode = temp;
+
+	/* Get bandwidth */
+	error =
+	    it9135_read_reg_bits(data, chip, PROCESSOR_OFDM, g_reg_bw,
+				 reg_bw_pos, reg_bw_len, &temp);
+	if (error)
+		goto exit;
+	ch_modulation->bandwidth = temp;
+
+	/* Get frequency */
+	ch_modulation->frequency = data->frequency[chip];
+
+exit:
+	return error;
+}
+
+unsigned long it9135_acquire_ch(struct it9135_data *data, unsigned char chip,
+				unsigned short bandwidth,
+				unsigned long frequency)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char begin;
+	unsigned char end;
+	unsigned char i;
+
+	if (data->architecture == ARCHITECTURE_DCA) {
+		begin = 0;
+		end = data->chip_num;
+	} else {
+		begin = chip;
+		end = begin + 1;
+	}
+
+	for (i = begin; i < end; i++) {
+		error =
+		    it9135_select_bandwidth(data, i, bandwidth, data->adc_freq);
+		if (error)
+			goto exit;
+		data->bandwidth[i] = bandwidth;
+	}
+
+	error = it9135_mask_dca_output(data);
+	if (error)
+		goto exit;
+
+	/* Set frequency */
+	for (i = begin; i < end; i++) {
+		error = it9135_set_frequency(data, i, frequency);
+		if (error)
+			goto exit;
+	}
+
+exit:
+	return error;
+}
+
+unsigned long it9135_set_stream_type(struct it9135_data *data,
+				     unsigned char streamType)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char i;
+
+	for (i = 0; i < data->chip_num; i++) {
+		error =
+		    it9135_write_reg_bits(data, i, PROCESSOR_OFDM,
+					  p_reg_mpeg_full_speed,
+					  reg_mpeg_full_speed_pos,
+					  reg_mpeg_full_speed_len, 0);
+		if (error)
+			goto exit;
+	}
+
+	/* Enable DVB-T mode */
+	for (i = 0; i < data->chip_num; i++) {
+		error =
+		    it9135_write_reg_bits(data, i, PROCESSOR_LINK,
+					  p_reg_dvbt_en, reg_dvbt_en_pos,
+					  reg_dvbt_en_len, 1);
+		if (error)
+			goto exit;
+	}
+
+	/* Pictor & Orion & Omega & Omega_LNA */
+	if (data->tuner_desc.id == 0x35
+	    || data->tuner_desc.id == 0x39
+	    || data->tuner_desc.id == 0x3A || data->chip_type == 0x9135
+	    || data->chip_type == 0x9175) {
+		/* Enter sub mode */
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_mp2if_mpeg_ser_mode,
+					  mp2if_mpeg_ser_mode_pos,
+					  mp2if_mpeg_ser_mode_len, 0);
+		if (error)
+			goto exit;
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_mp2if_mpeg_par_mode,
+					  mp2if_mpeg_par_mode_pos,
+					  mp2if_mpeg_par_mode_len, 0);
+		if (error)
+			goto exit;
+		/* Fix current leakage */
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_LINK,
+					  p_reg_top_hostb_mpeg_ser_mode,
+					  reg_top_hostb_mpeg_ser_mode_pos,
+					  reg_top_hostb_mpeg_ser_mode_len, 0);
+		if (error)
+			goto exit;
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_LINK,
+					  p_reg_top_hostb_mpeg_par_mode,
+					  reg_top_hostb_mpeg_par_mode_pos,
+					  reg_top_hostb_mpeg_par_mode_len, 0);
+		if (error)
+			goto exit;
+	} else {
+		/* Enter sub mode */
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_mp2if_mpeg_ser_mode,
+					  mp2if_mpeg_ser_mode_pos,
+					  mp2if_mpeg_ser_mode_len, 0);
+		if (error)
+			goto exit;
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_mp2if_mpeg_par_mode,
+					  mp2if_mpeg_par_mode_pos,
+					  mp2if_mpeg_par_mode_len, 0);
+		if (error)
+			goto exit;
+		/* Fix current leakage */
+		if (data->chip_num > 1) {
+			if (data->host_if[0]) {
+				error =
+				    it9135_write_reg_bits(data, 0,
+							  PROCESSOR_LINK,
+							  p_reg_top_hostb_mpeg_ser_mode,
+							  reg_top_hostb_mpeg_ser_mode_pos,
+							  reg_top_hostb_mpeg_ser_mode_len,
+							  0);
+				if (error)
+					goto exit;
+				error =
+				    it9135_write_reg_bits(data, 0,
+							  PROCESSOR_LINK,
+							  p_reg_top_hostb_mpeg_par_mode,
+							  reg_top_hostb_mpeg_par_mode_pos,
+							  reg_top_hostb_mpeg_par_mode_len,
+							  1);
+				if (error)
+					goto exit;
+			} else {
+				error =
+				    it9135_write_reg_bits(data, 0,
+							  PROCESSOR_LINK,
+							  p_reg_top_hosta_mpeg_ser_mode,
+							  reg_top_hosta_mpeg_ser_mode_pos,
+							  reg_top_hosta_mpeg_ser_mode_len,
+							  0);
+				if (error)
+					goto exit;
+				error =
+				    it9135_write_reg_bits(data, 0,
+							  PROCESSOR_LINK,
+							  p_reg_top_hosta_mpeg_par_mode,
+							  reg_top_hosta_mpeg_par_mode_pos,
+							  reg_top_hosta_mpeg_par_mode_len,
+							  1);
+				if (error)
+					goto exit;
+			}
+		} else {
+			error =
+			    it9135_write_reg_bits(data, 0,
+						  PROCESSOR_LINK,
+						  p_reg_top_hosta_mpeg_ser_mode,
+						  reg_top_hosta_mpeg_ser_mode_pos,
+						  reg_top_hosta_mpeg_ser_mode_len,
+						  0);
+			if (error)
+				goto exit;
+			error =
+			    it9135_write_reg_bits(data, 0,
+						  PROCESSOR_LINK,
+						  p_reg_top_hosta_mpeg_par_mode,
+						  reg_top_hosta_mpeg_par_mode_pos,
+						  reg_top_hosta_mpeg_par_mode_len,
+						  1);
+			if (error)
+				goto exit;
+			error =
+			    it9135_write_reg_bits(data, 0,
+						  PROCESSOR_LINK,
+						  p_reg_top_hostb_mpeg_ser_mode,
+						  reg_top_hostb_mpeg_ser_mode_pos,
+						  reg_top_hostb_mpeg_ser_mode_len,
+						  0);
+			if (error)
+				goto exit;
+			error =
+			    it9135_write_reg_bits(data, 0,
+						  PROCESSOR_LINK,
+						  p_reg_top_hostb_mpeg_par_mode,
+						  reg_top_hostb_mpeg_par_mode_pos,
+						  reg_top_hostb_mpeg_par_mode_len,
+						  1);
+			if (error)
+				goto exit;
+		}
+	}
+
+exit:
+	return error;
+}
+
+unsigned long it9135_set_arch(struct it9135_data *data,
+			      unsigned char architecture)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned short frame_sz;
+	unsigned char packet_sz;
+	unsigned char buffer[2];
+	unsigned char standalone[2];
+	unsigned char upper_chip[2];
+	unsigned char upper_host[2];
+	unsigned char lower_chip[2];
+	unsigned char lower_host[2];
+	unsigned char dca_en[2];
+	unsigned char phase_latch[2];
+	unsigned char fpga_latch[2];
+	unsigned char i;
+	int pip_valid = 0;
+
+/* Define USB frame size */
+#define IT9135_USB20_MAX_PACKET_SIZE      512
+#ifdef DVB_USB_ADAP_NEED_PID_FILTER
+#define IT9135_USB20_FRAME_SIZE           (188 * 21)
+#else
+#define IT9135_USB20_FRAME_SIZE           (188 * 348)
+#endif
+#define IT9135_USB20_FRAME_SIZE_DW        (IT9135_USB20_FRAME_SIZE / 4)
+#define IT9135_USB11_MAX_PACKET_SIZE      64
+#define IT9135_USB11_FRAME_SIZE           (188 * 21)
+#define IT9135_USB11_FRAME_SIZE_DW        (IT9135_USB11_FRAME_SIZE / 4)
+
+	if (architecture == ARCHITECTURE_DCA) {
+		for (i = 0; i < data->chip_num; i++) {
+			standalone[i] = 0;
+			upper_chip[i] = 0;
+			upper_host[i] = 0;
+			lower_chip[i] = 0;
+			lower_host[i] = 0;
+			dca_en[i] = 1;
+			phase_latch[i] = 0;
+			fpga_latch[i] = 0;
+		}
+
+		if (data->chip_num == 1) {
+			standalone[0] = 1;
+			dca_en[0] = 0;
+		} else {
+			/* Pictor & Orion & Omega */
+			if (data->tuner_desc.id == 0x35
+			    || data->tuner_desc.id == 0x39
+			    || data->tuner_desc.id == 0x3A) {
+				upper_chip[data->chip_num - 1] = 1;
+				upper_host[0] = 1;
+				lower_chip[0] = 1;
+				lower_host[data->chip_num - 1] = 1;
+				phase_latch[0] = 0;
+				phase_latch[data->chip_num - 1] = 0;
+				fpga_latch[0] = 0;
+				fpga_latch[data->chip_num - 1] = 0;
+			} else if (data->chip_type == 0x9135
+				   || data->chip_type == 0x9175) {
+				upper_chip[data->chip_num - 1] = 1;
+				upper_host[0] = 1;
+
+				lower_chip[0] = 1;
+				lower_host[data->chip_num - 1] = 1;
+
+				phase_latch[0] = 1;
+				phase_latch[data->chip_num - 1] = 1;
+
+				fpga_latch[0] = 0x44;
+				fpga_latch[data->chip_num - 1] = 0x44;
+			} else {
+				upper_chip[data->chip_num - 1] = 1;
+				upper_host[0] = 1;
+				lower_chip[0] = 1;
+				lower_host[data->chip_num - 1] = 1;
+				phase_latch[0] = 1;
+				phase_latch[data->chip_num - 1] = 1;
+				fpga_latch[0] = 0x77;
+				fpga_latch[data->chip_num - 1] = 0x77;
+			}
+		}
+	} else {
+		for (i = 0; i < data->chip_num; i++) {
+			standalone[i] = 1;
+			upper_chip[i] = 0;
+			upper_host[i] = 0;
+			lower_chip[i] = 0;
+			lower_host[i] = 0;
+			dca_en[i] = 0;
+			phase_latch[i] = 0;
+			fpga_latch[i] = 0;
+		}
+	}
+
+	if (data->inited) {
+		error = it9135_mask_dca_output(data);
+		if (error)
+			goto exit;
+	}
+
+	/* Pictor & Orion & Omega & Omega_LNA */
+	if (data->tuner_desc.id == 0x35
+	    || data->tuner_desc.id == 0x39
+	    || data->tuner_desc.id == 0x3A || data->chip_type == 0x9135
+	    || data->chip_type == 0x9175) {
+		for (i = data->chip_num; i > 0; i--) {
+			/* Set dca_upper_chip */
+			error =
+			    it9135_write_reg_bits(data, i - 1,
+						  PROCESSOR_OFDM,
+						  p_reg_dca_upper_chip,
+						  reg_dca_upper_chip_pos,
+						  reg_dca_upper_chip_len,
+						  upper_chip[i - 1]);
+			if (error)
+				goto exit;
+			error =
+			    it9135_write_reg_bits(data, i - 1,
+						  PROCESSOR_LINK,
+						  p_reg_top_hostb_dca_upper,
+						  reg_top_hostb_dca_upper_pos,
+						  reg_top_hostb_dca_upper_len,
+						  upper_host[i - 1]);
+			if (error)
+				goto exit;
+
+			/* Set dca_lower_chip */
+			error =
+			    it9135_write_reg_bits(data, i - 1,
+						  PROCESSOR_OFDM,
+						  p_reg_dca_lower_chip,
+						  reg_dca_lower_chip_pos,
+						  reg_dca_lower_chip_len,
+						  lower_chip[i - 1]);
+			if (error)
+				goto exit;
+			error =
+			    it9135_write_reg_bits(data, i - 1,
+						  PROCESSOR_LINK,
+						  p_reg_top_hostb_dca_lower,
+						  reg_top_hostb_dca_lower_pos,
+						  reg_top_hostb_dca_lower_len,
+						  lower_host[i - 1]);
+			if (error)
+				goto exit;
+
+			/* Set phase latch */
+			error =
+			    it9135_write_reg_bits(data, i - 1,
+						  PROCESSOR_OFDM,
+						  p_reg_dca_platch,
+						  reg_dca_platch_pos,
+						  reg_dca_platch_len,
+						  phase_latch[i - 1]);
+			if (error)
+				goto exit;
+
+			/* Set fpga latch */
+			error =
+			    it9135_write_reg_bits(data, i - 1, PROCESSOR_OFDM,
+						  p_reg_dca_fpga_latch,
+						  reg_dca_fpga_latch_pos,
+						  reg_dca_fpga_latch_len,
+						  fpga_latch[i - 1]);
+			if (error)
+				goto exit;
+		}
+	} else {
+		/* Set upper chip first in order to avoid I/O conflict */
+		for (i = data->chip_num; i > 0; i--) {
+			/* Set dca_upper_chip */
+			error =
+			    it9135_write_reg_bits(data, i - 1,
+						  PROCESSOR_OFDM,
+						  p_reg_dca_upper_chip,
+						  reg_dca_upper_chip_pos,
+						  reg_dca_upper_chip_len,
+						  upper_chip[i - 1]);
+			if (error)
+				goto exit;
+			if (i == 1) {
+				if (data->host_if[0]) {
+					error =
+					    it9135_write_reg_bits
+					    (data, i - 1, PROCESSOR_LINK,
+					     p_reg_top_hosta_dca_upper,
+					     reg_top_hosta_dca_upper_pos,
+					     reg_top_hosta_dca_upper_len,
+					     upper_host[i - 1]);
+					if (error)
+						goto exit;
+					error =
+					    it9135_write_reg_bits
+					    (data, i - 1, PROCESSOR_LINK,
+					     p_reg_top_hostb_dca_upper,
+					     reg_top_hostb_dca_upper_pos,
+					     reg_top_hostb_dca_upper_len, 0);
+					if (error)
+						goto exit;
+				} else {
+					error =
+					    it9135_write_reg_bits
+					    (data, i - 1, PROCESSOR_LINK,
+					     p_reg_top_hostb_dca_upper,
+					     reg_top_hostb_dca_upper_pos,
+					     reg_top_hostb_dca_upper_len,
+					     upper_host[i - 1]);
+					if (error)
+						goto exit;
+					error =
+					    it9135_write_reg_bits
+					    (data, i - 1, PROCESSOR_LINK,
+					     p_reg_top_hosta_dca_upper,
+					     reg_top_hosta_dca_upper_pos,
+					     reg_top_hosta_dca_upper_len, 0);
+					if (error)
+						goto exit;
+				}
+			} else {
+				error =
+				    it9135_write_reg_bits(data,
+							  i - 1,
+							  PROCESSOR_LINK,
+							  p_reg_top_hostb_dca_upper,
+							  reg_top_hostb_dca_upper_pos,
+							  reg_top_hostb_dca_upper_len,
+							  upper_host[i - 1]);
+				if (error)
+					goto exit;
+				error =
+				    it9135_write_reg_bits(data,
+							  i - 1,
+							  PROCESSOR_LINK,
+							  p_reg_top_hosta_dca_upper,
+							  reg_top_hosta_dca_upper_pos,
+							  reg_top_hosta_dca_upper_len,
+							  0);
+				if (error)
+					goto exit;
+			}
+
+			/* Set dca_lower_chip */
+			error =
+			    it9135_write_reg_bits(data, i - 1,
+						  PROCESSOR_OFDM,
+						  p_reg_dca_lower_chip,
+						  reg_dca_lower_chip_pos,
+						  reg_dca_lower_chip_len,
+						  lower_chip[i - 1]);
+			if (error)
+				goto exit;
+			if (i == 1) {
+				if (data->host_if[0]) {
+					error =
+					    it9135_write_reg_bits
+					    (data, i - 1, PROCESSOR_LINK,
+					     p_reg_top_hosta_dca_lower,
+					     reg_top_hosta_dca_lower_pos,
+					     reg_top_hosta_dca_lower_len,
+					     lower_host[i - 1]);
+					if (error)
+						goto exit;
+					error =
+					    it9135_write_reg_bits
+					    (data, i - 1, PROCESSOR_LINK,
+					     p_reg_top_hostb_dca_lower,
+					     reg_top_hostb_dca_lower_pos,
+					     reg_top_hostb_dca_lower_len, 0);
+					if (error)
+						goto exit;
+				} else {
+					error =
+					    it9135_write_reg_bits
+					    (data, i - 1, PROCESSOR_LINK,
+					     p_reg_top_hostb_dca_lower,
+					     reg_top_hostb_dca_lower_pos,
+					     reg_top_hostb_dca_lower_len,
+					     lower_host[i - 1]);
+					if (error)
+						goto exit;
+					error =
+					    it9135_write_reg_bits
+					    (data, i - 1, PROCESSOR_LINK,
+					     p_reg_top_hosta_dca_lower,
+					     reg_top_hosta_dca_lower_pos,
+					     reg_top_hosta_dca_lower_len, 0);
+					if (error)
+						goto exit;
+				}
+			} else {
+				error =
+				    it9135_write_reg_bits(data,
+							  i - 1,
+							  PROCESSOR_LINK,
+							  p_reg_top_hostb_dca_lower,
+							  reg_top_hostb_dca_lower_pos,
+							  reg_top_hostb_dca_lower_len,
+							  lower_host[i - 1]);
+				if (error)
+					goto exit;
+				error =
+				    it9135_write_reg_bits(data,
+							  i - 1,
+							  PROCESSOR_LINK,
+							  p_reg_top_hosta_dca_lower,
+							  reg_top_hosta_dca_lower_pos,
+							  reg_top_hosta_dca_lower_len,
+							  0);
+				if (error)
+					goto exit;
+			}
+
+			/* Set phase latch */
+			error =
+			    it9135_write_reg_bits(data, i - 1,
+						  PROCESSOR_OFDM,
+						  p_reg_dca_platch,
+						  reg_dca_platch_pos,
+						  reg_dca_platch_len,
+						  phase_latch[i - 1]);
+			if (error)
+				goto exit;
+
+			/* Set fpga latch */
+			error =
+			    it9135_write_reg_bits(data, i - 1,
+						  PROCESSOR_OFDM,
+						  p_reg_dca_fpga_latch,
+						  reg_dca_fpga_latch_pos,
+						  reg_dca_fpga_latch_len,
+						  fpga_latch[i - 1]);
+			if (error)
+				goto exit;
+		}
+	}
+
+	for (i = 0; i < data->chip_num; i++) {
+		/* Set stand alone */
+		error =
+		    it9135_write_reg_bits(data, i, PROCESSOR_OFDM,
+					  p_reg_dca_stand_alone,
+					  reg_dca_stand_alone_pos,
+					  reg_dca_stand_alone_len,
+					  standalone[i]);
+		if (error)
+			goto exit;
+
+		/* Set DCA enable */
+		error =
+		    it9135_write_reg_bits(data, i, PROCESSOR_OFDM,
+					  p_reg_dca_en, reg_dca_en_pos,
+					  reg_dca_en_len, dca_en[i]);
+		if (error)
+			goto exit;
+	}
+
+	if (data->inited) {
+		for (i = 0; i < data->chip_num; i++) {
+			error =
+			    it9135_write_reg(data, i, PROCESSOR_OFDM,
+					     trigger_ofsm, 0);
+			if (error)
+				goto exit;
+		}
+	}
+
+	frame_sz = IT9135_USB20_FRAME_SIZE_DW;
+	packet_sz = (unsigned char)(IT9135_USB20_MAX_PACKET_SIZE / 4);
+
+	if (data->busId == IT9135_BUS_USB11) {
+		frame_sz = IT9135_USB11_FRAME_SIZE_DW;
+		packet_sz = (unsigned char)(IT9135_USB11_MAX_PACKET_SIZE / 4);
+	}
+
+	if ((data->chip_num > 1) && (architecture == ARCHITECTURE_PIP))
+		pip_valid = 1;
+
+	/* Reset EP4 */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM, p_reg_mp2_sw_rst,
+				  reg_mp2_sw_rst_pos, reg_mp2_sw_rst_len, 1);
+	if (error)
+		goto exit;
+
+	/* Reset EP5 */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+				  p_reg_mp2if2_sw_rst, reg_mp2if2_sw_rst_pos,
+				  reg_mp2if2_sw_rst_len, 1);
+	if (error)
+		goto exit;
+
+	/* Disable EP4 */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_LINK, p_reg_ep4_tx_en,
+				  reg_ep4_tx_en_pos, reg_ep4_tx_en_len, 0);
+	if (error)
+		goto exit;
+
+	/* Disable EP5 */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_LINK, p_reg_ep5_tx_en,
+				  reg_ep5_tx_en_pos, reg_ep5_tx_en_len, 0);
+	if (error)
+		goto exit;
+
+	/* Disable EP4 NAK */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_LINK, p_reg_ep4_tx_nak,
+				  reg_ep4_tx_nak_pos, reg_ep4_tx_nak_len, 0);
+	if (error)
+		goto exit;
+
+	/* Disable EP5 NAK */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_LINK, p_reg_ep5_tx_nak,
+				  reg_ep5_tx_nak_pos, reg_ep5_tx_nak_len, 0);
+	if (error)
+		goto exit;
+
+	/* Enable EP4 */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_LINK, p_reg_ep4_tx_en,
+				  reg_ep4_tx_en_pos, reg_ep4_tx_en_len, 1);
+	if (error)
+		goto exit;
+
+	/* Set EP4 transfer length */
+	buffer[p_reg_ep4_tx_len_7_0 - p_reg_ep4_tx_len_7_0] =
+	    (unsigned char)frame_sz;
+	buffer[p_reg_ep4_tx_len_15_8 - p_reg_ep4_tx_len_7_0] =
+	    (unsigned char)(frame_sz >> 8);
+	error =
+	    it9135_write_regs(data, 0, PROCESSOR_LINK, p_reg_ep4_tx_len_7_0, 2,
+			      buffer);
+
+	/* Set EP4 packet size */
+	error =
+	    it9135_write_reg(data, 0, PROCESSOR_LINK, p_reg_ep4_max_pkt,
+			     packet_sz);
+	if (error)
+		goto exit;
+
+	if (pip_valid) {
+		/* Enable EP5 */
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_LINK,
+					  p_reg_ep5_tx_en, reg_ep5_tx_en_pos,
+					  reg_ep5_tx_en_len, 1);
+		if (error)
+			goto exit;
+
+		/* Set EP5 transfer length */
+		buffer[p_reg_ep5_tx_len_7_0 - p_reg_ep5_tx_len_7_0] =
+		    (unsigned char)frame_sz;
+		buffer[p_reg_ep5_tx_len_15_8 - p_reg_ep5_tx_len_7_0] =
+		    (unsigned char)(frame_sz >> 8);
+		error =
+		    it9135_write_regs(data, 0, PROCESSOR_LINK,
+				      p_reg_ep5_tx_len_7_0, 2, buffer);
+
+		/* Set EP5 packet size */
+		error =
+		    it9135_write_reg(data, 0, PROCESSOR_LINK, p_reg_ep5_max_pkt,
+				     packet_sz);
+		if (error)
+			goto exit;
+	}
+
+	/* Disable 15 SER/PAR mode */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+				  p_mp2if_mpeg_ser_mode,
+				  mp2if_mpeg_ser_mode_pos,
+				  mp2if_mpeg_ser_mode_len, 0);
+	if (error)
+		goto exit;
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+				  p_mp2if_mpeg_par_mode,
+				  mp2if_mpeg_par_mode_pos,
+				  mp2if_mpeg_par_mode_len, 0);
+	if (error)
+		goto exit;
+
+	if (pip_valid) {
+		/* Enable mp2if2 */
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_reg_mp2if2_en, reg_mp2if2_en_pos,
+					  reg_mp2if2_en_len, 1);
+		if (error)
+			goto exit;
+
+		for (i = 1; i < data->chip_num; i++) {
+			/* Enable serial mode */
+			error =
+			    it9135_write_reg_bits(data, i,
+						  PROCESSOR_OFDM,
+						  p_mp2if_mpeg_ser_mode,
+						  mp2if_mpeg_ser_mode_pos,
+						  mp2if_mpeg_ser_mode_len, 1);
+			if (error)
+				goto exit;
+
+			/* Enable HostB serial */
+			error =
+			    it9135_write_reg_bits(data, i,
+						  PROCESSOR_LINK,
+						  p_reg_top_hostb_mpeg_ser_mode,
+						  reg_top_hostb_mpeg_ser_mode_pos,
+						  reg_top_hostb_mpeg_ser_mode_len,
+						  1);
+			if (error)
+				goto exit;
+		}
+
+		/* Enable tsis */
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_reg_tsis_en, reg_tsis_en_pos,
+					  reg_tsis_en_len, 1);
+		if (error)
+			goto exit;
+	} else {
+		/* Disable mp2if2 */
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_reg_mp2if2_en, reg_mp2if2_en_pos,
+					  reg_mp2if2_en_len, 0);
+		if (error)
+			goto exit;
+
+		for (i = 1; i < data->chip_num; i++) {
+			/* Disable serial mode */
+			error =
+			    it9135_write_reg_bits(data, i,
+						  PROCESSOR_OFDM,
+						  p_mp2if_mpeg_ser_mode,
+						  mp2if_mpeg_ser_mode_pos,
+						  mp2if_mpeg_ser_mode_len, 0);
+			if (error)
+				goto exit;
+
+			/* Disable HostB serial */
+			error =
+			    it9135_write_reg_bits(data, i,
+						  PROCESSOR_LINK,
+						  p_reg_top_hostb_mpeg_ser_mode,
+						  reg_top_hostb_mpeg_ser_mode_pos,
+						  reg_top_hostb_mpeg_ser_mode_len,
+						  0);
+			if (error)
+				goto exit;
+		}
+
+		/* Disable tsis */
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_reg_tsis_en, reg_tsis_en_pos,
+					  reg_tsis_en_len, 0);
+		if (error)
+			goto exit;
+	}
+
+	/* Negate EP4 reset */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM, p_reg_mp2_sw_rst,
+				  reg_mp2_sw_rst_pos, reg_mp2_sw_rst_len, 0);
+	if (error)
+		goto exit;
+
+	/* Negate EP5 reset */
+	error =
+	    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+				  p_reg_mp2if2_sw_rst, reg_mp2if2_sw_rst_pos,
+				  reg_mp2if2_sw_rst_len, 0);
+	if (error)
+		goto exit;
+
+	if (pip_valid) {
+		/* Split 15 PSB to 1K + 1K and enable flow control */
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_reg_mp2if2_half_psb,
+					  reg_mp2if2_half_psb_pos,
+					  reg_mp2if2_half_psb_len, 0);
+		if (error)
+			goto exit;
+		error =
+		    it9135_write_reg_bits(data, 0, PROCESSOR_OFDM,
+					  p_reg_mp2if_stop_en,
+					  reg_mp2if_stop_en_pos,
+					  reg_mp2if_stop_en_len, 1);
+		if (error)
+			goto exit;
+
+		for (i = 1; i < data->chip_num; i++) {
+			error =
+			    it9135_write_reg_bits(data, i, PROCESSOR_OFDM,
+						  p_reg_mpeg_full_speed,
+						  reg_mpeg_full_speed_pos,
+						  reg_mpeg_full_speed_len, 1);
+			if (error)
+				goto exit;
+			error =
+			    it9135_write_reg_bits(data, i,
+						  PROCESSOR_OFDM,
+						  p_reg_mp2if_stop_en,
+						  reg_mp2if_stop_en_pos,
+						  reg_mp2if_stop_en_len, 0);
+			if (error)
+				goto exit;
+		}
+	}
+
+	data->architecture = architecture;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_get_statistic(struct it9135_data *data, unsigned char chip,
+				   struct it9135_statistic *statistic)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char quality = 0;
+	unsigned char strength;
+	unsigned char buffer[2];
+
+	/* Get statistic by stream type */
+	error =
+	    it9135_read_regs(data, chip, PROCESSOR_OFDM, tpsd_lock,
+			     mpeg_lock - tpsd_lock + 1, buffer);
+	if (error)
+		goto exit;
+
+	if (buffer[tpsd_lock - tpsd_lock])
+		data->statistic[chip].presented = 1;
+	else
+		data->statistic[chip].presented = 0;
+
+	if (buffer[mpeg_lock - tpsd_lock])
+		data->statistic[chip].locked = 1;
+	else
+		data->statistic[chip].locked = 0;
+
+	error = it9135_get_signal_quality(data, chip, &quality);
+	if (error)
+		goto exit;
+
+	data->statistic[chip].quality = quality;
+	error = it9135_get_strength(data, chip, &strength);
+	if (error)
+		goto exit;
+
+	data->statistic[chip].strength = strength;
+
+	*statistic = data->statistic[chip];
+
+exit:
+	return error;
+}
+
+/* get ir raw code (4 unsigned chars) */
+unsigned long it9135_get_ir_code(struct it9135_data *data, unsigned long *code)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char r_buff[4];
+
+	error =
+	    it9135_cmd_sendcommand(data, CMD_IR_GET, 0, PROCESSOR_LINK, 0, NULL,
+				   4, r_buff);
+	if (error)
+		goto exit;
+
+	*code =
+	    (unsigned long)((r_buff[0] << 24) + (r_buff[1] << 16) +
+			    (r_buff[2] << 8) + r_buff[3]);
+
+exit:
+	return error;
+}
+
+unsigned long it9135_dev_reboot(struct it9135_data *data)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long version;
+	unsigned char i;
+
+	error = it9135_get_fw_ver(data, PROCESSOR_LINK, &version);
+	if (error)
+		goto exit;
+	if (version == 0xFFFFFFFF)
+		goto exit;	/* I2M and I2U */
+	if (version != 0) {
+		for (i = data->chip_num; i > 0; i--) {
+			error = it9135_cmd_reboot(data, i - 1);
+			mdelay(1);
+			if (error)
+				goto exit;
+		}
+	}
+
+	data->booted = 0;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_ctrl_pw_saving(struct it9135_data *data,
+				    unsigned char chip, unsigned char control)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char temp;
+	unsigned char j;
+
+	if (control) {
+		/* Power up case */
+		error =
+		    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM,
+					  p_reg_afe_mem0, 3, 1, 0);
+		if (error)
+			goto exit;
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_reg_dyn0_clk,
+				     0);
+		if (error)
+			goto exit;
+
+		/* Fixed current leakage */
+		if ((data->chip_num > 1) && (chip > 0)) {
+			/* Pictor & Orion & Omega & Omega_LNA */
+			if (data->tuner_desc.id == 0x35
+			    || data->tuner_desc.id == 0x39) {
+				/* Disable HostB parallel */
+				error =
+				    it9135_write_reg_bits
+				    (data, chip, PROCESSOR_LINK,
+				     p_reg_top_hostb_mpeg_ser_mode,
+				     reg_top_hostb_mpeg_ser_mode_pos,
+				     reg_top_hostb_mpeg_ser_mode_len, 0);
+				if (error)
+					goto exit;
+				error =
+				    it9135_write_reg_bits
+				    (data, chip, PROCESSOR_LINK,
+				     p_reg_top_hostb_mpeg_par_mode,
+				     reg_top_hostb_mpeg_par_mode_pos,
+				     reg_top_hostb_mpeg_par_mode_len, 0);
+				if (error)
+					goto exit;
+			} else if (data->chip_type == 0x9135
+				   || data->chip_type == 0x9175) {
+				/* Enable HostB serial */
+				if ((data->architecture == ARCHITECTURE_PIP))
+					error =
+					    it9135_write_reg_bits
+					    (data, chip,
+					     PROCESSOR_LINK,
+					     p_reg_top_hostb_mpeg_ser_mode,
+					     reg_top_hostb_mpeg_ser_mode_pos,
+					     reg_top_hostb_mpeg_ser_mode_len,
+					     1);
+				else
+					error =
+					    it9135_write_reg_bits
+					    (data, chip,
+					     PROCESSOR_LINK,
+					     p_reg_top_hostb_mpeg_ser_mode,
+					     reg_top_hostb_mpeg_ser_mode_pos,
+					     reg_top_hostb_mpeg_ser_mode_len,
+					     0);
+				if (error)
+					goto exit;
+				/* Disable HostB parallel */
+				error =
+				    it9135_write_reg_bits
+				    (data, chip, PROCESSOR_LINK,
+				     p_reg_top_hostb_mpeg_par_mode,
+				     reg_top_hostb_mpeg_par_mode_pos,
+				     reg_top_hostb_mpeg_par_mode_len, 0);
+				if (error)
+					goto exit;
+			}
+		}
+	} else {
+		/* Power down case */
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, suspend_flag,
+				     1);
+		if (error)
+			goto exit;
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, trigger_ofsm,
+				     0);
+		if (error)
+			goto exit;
+
+		for (j = 0; j < 150; j++) {
+			error =
+			    it9135_read_reg(data, chip, PROCESSOR_OFDM,
+					    suspend_flag, &temp);
+			if (error)
+				goto exit;
+			if (!temp)
+				break;
+			mdelay(10);
+		}
+		/* power down demod adc */
+		error =
+		    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM,
+					  p_reg_afe_mem0, 3, 1, 1);
+		if (error)
+			goto exit;
+
+		/* Fixed current leakage */
+		if ((data->chip_num > 1) && (chip > 0)) {
+			/* Pictor & Orion & Omega */
+			if (data->tuner_desc.id ==
+			    0x35
+			    || data->tuner_desc.id ==
+			    0x39 || data->chip_type == 0x9135
+			    || data->chip_type == 0x9175) {
+				/* Enable HostB parallel */
+				error =
+				    it9135_write_reg_bits
+				    (data, chip, PROCESSOR_LINK,
+				     p_reg_top_hostb_mpeg_ser_mode,
+				     reg_top_hostb_mpeg_ser_mode_pos,
+				     reg_top_hostb_mpeg_ser_mode_len, 0);
+				if (error)
+					goto exit;
+				error =
+				    it9135_write_reg_bits
+				    (data, chip, PROCESSOR_LINK,
+				     p_reg_top_hostb_mpeg_par_mode,
+				     reg_top_hostb_mpeg_par_mode_pos,
+				     reg_top_hostb_mpeg_par_mode_len, 1);
+				if (error)
+					goto exit;
+			}
+		}
+	}
+
+exit:
+	return error;
+}
+
+unsigned long it9135_ctrl_tuner_leakage(struct it9135_data *data,
+					unsigned char chip,
+					unsigned char control)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char value[15] = { 0 };
+
+	if (control) {
+		/* Power up case */
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_reg_p_if_en,
+				     1);
+		if (error)
+			goto exit;
+	} else {
+		/* Fixed tuner current leakage */
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_reg_dyn0_clk,
+				     0);
+		if (error)
+			goto exit;
+		/* 0xec40 */
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_reg_p_if_en,
+				     0);
+		if (error)
+			goto exit;
+
+		value[1] = 0x0c;
+
+		error =
+		    it9135_write_regs(data, chip, PROCESSOR_OFDM, p_reg_pd_a,
+				      15, value);
+		if (error)
+			goto exit;
+
+		value[1] = 0;
+
+		/* 0xec12~0xec15 */
+		error =
+		    it9135_write_regs(data, chip, PROCESSOR_OFDM, p_reg_lna_g,
+				      4, value);
+		if (error)
+			goto exit;
+		/* oxec17~0xec1f */
+		error =
+		    it9135_write_regs(data, chip, PROCESSOR_OFDM, p_reg_pgc, 9,
+				      value);
+		if (error)
+			goto exit;
+		/* 0xec22~0xec2b */
+		error =
+		    it9135_write_regs(data, chip, PROCESSOR_OFDM,
+				      p_reg_clk_del_sel, 10, value);
+		if (error)
+			goto exit;
+		/* 0xec20 */
+		error = it9135_write_reg(data, chip, PROCESSOR_OFDM, 0xec20, 0);
+		if (error)
+			goto exit;
+		/* 0xec3f */
+		error = it9135_write_reg(data, chip, PROCESSOR_OFDM, 0xec3F, 1);
+		if (error)
+			goto exit;
+	}
+
+exit:
+	return error;
+}
+
+unsigned long it9135_ctrl_tuner_pw_saving(struct it9135_data *data,
+					  unsigned char chip,
+					  unsigned char control)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char value[15] = { 0 };
+
+	if (control) {
+		/* Power up case */
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_reg_p_if_en,
+				     1);
+		if (error)
+			goto exit;
+	} else {
+		/* tuner power down */
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_reg_dyn0_clk,
+				     0);
+		if (error)
+			goto exit;
+		/* 0xec40 */
+		error =
+		    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_reg_p_if_en,
+				     0);
+		if (error)
+			goto exit;
+
+		value[0] = 0x3F;	/* 0xec02 */
+		value[1] = 0x1F;	/* 0xec03 */
+		value[2] = 0x3F;	/* 0xec04 */
+		value[3] = 0x3E;	/* 0xec05 */
+
+		error =
+		    it9135_write_regs(data, chip, PROCESSOR_OFDM, p_reg_pd_a,
+				      15, value);
+		if (error)
+			goto exit;
+
+		value[0] = 0;
+		value[1] = 0;
+		value[2] = 0;
+		value[3] = 0;
+
+		/* 0xec12~0xec15 */
+		error =
+		    it9135_write_regs(data, chip, PROCESSOR_OFDM, p_reg_lna_g,
+				      4, value);
+		if (error)
+			goto exit;
+		/* oxec17~0xec1f */
+		error =
+		    it9135_write_regs(data, chip, PROCESSOR_OFDM, p_reg_pgc, 9,
+				      value);
+		if (error)
+			goto exit;
+		/* 0xec22~0xec2b */
+		error =
+		    it9135_write_regs(data, chip, PROCESSOR_OFDM,
+				      p_reg_clk_del_sel, 10, value);
+		if (error)
+			goto exit;
+		/* 0xec20 */
+		error = it9135_write_reg(data, chip, PROCESSOR_OFDM, 0xec20, 0);
+		if (error)
+			goto exit;
+		/* 0xec3f */
+		error = it9135_write_reg(data, chip, PROCESSOR_OFDM, 0xec3F, 1);
+		if (error)
+			goto exit;
+	}
+
+exit:
+	return error;
+}
+
+unsigned long it9135_ctrl_pid_filter(struct it9135_data *data,
+				     unsigned char chip, unsigned char control)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM,
+				  p_mp2if_pid_en, mp2if_pid_en_pos,
+				  mp2if_pid_en_len, control);
+
+	return error;
+}
+
+unsigned long it9135_reset_pid_filter(struct it9135_data *data,
+				      unsigned char chip)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM, p_mp2if_pid_rst,
+				  mp2if_pid_rst_pos, mp2if_pid_rst_len, 1);
+	if (error)
+		goto exit;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_add_pid_filter(struct it9135_data *data,
+				    unsigned char chip, unsigned char index,
+				    unsigned short pid)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char w_buff[2];
+
+	/* Enable pid filter */
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM, p_mp2if_pid_en,
+				  mp2if_pid_en_pos, mp2if_pid_en_len, 1);
+	if (error)
+		goto exit;
+
+	w_buff[0] = (unsigned char)pid;
+	w_buff[1] = (unsigned char)(pid >> 8);
+
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM, p_mp2if_pid_dat_l, 2,
+			      w_buff);
+	if (error)
+		goto exit;
+
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM,
+				  p_mp2if_pid_index_en, mp2if_pid_index_en_pos,
+				  mp2if_pid_index_en_len, 1);
+	if (error)
+		goto exit;
+
+	error =
+	    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_mp2if_pid_index,
+			     index);
+	if (error)
+		goto exit;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_get_snr(struct it9135_data *data, unsigned char chip,
+			     unsigned char *snr)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	struct it9135_ch_modulation ch_modulation;
+	unsigned long snr_value;
+
+	error = it9135_get_ch_modulation(data, chip, &ch_modulation);
+	if (error)
+		goto exit;
+
+	error = it9135_get_snr_val(data, chip, &snr_value);
+	if (error)
+		goto exit;
+
+	if (ch_modulation.trans_mode == TransmissionMode_2K)
+		snr_value = snr_value * 4;
+	else if (ch_modulation.trans_mode == TransmissionMode_4K)
+		snr_value = snr_value * 2;
+	else
+		snr_value = snr_value * 1;
+
+	if (ch_modulation.constellation == 0) {	/* CONSTELLATION_QPSK */
+		if (snr_value < 0xB4771)
+			*snr = 0;
+		else if (snr_value < 0xC1AED)
+			*snr = 1;
+		else if (snr_value < 0xD0D27)
+			*snr = 2;
+		else if (snr_value < 0xE4D19)
+			*snr = 3;
+		else if (snr_value < 0xE5DA8)
+			*snr = 4;
+		else if (snr_value < 0x107097)
+			*snr = 5;
+		else if (snr_value < 0x116975)
+			*snr = 6;
+		else if (snr_value < 0x1252D9)
+			*snr = 7;
+		else if (snr_value < 0x131FA4)
+			*snr = 8;
+		else if (snr_value < 0x13D5E1)
+			*snr = 9;
+		else if (snr_value < 0x148E53)
+			*snr = 10;
+		else if (snr_value < 0x15358B)
+			*snr = 11;
+		else if (snr_value < 0x15DD29)
+			*snr = 12;
+		else if (snr_value < 0x168112)
+			*snr = 13;
+		else if (snr_value < 0x170B61)
+			*snr = 14;
+		else if (snr_value < 0x17A532)
+			*snr = 15;
+		else if (snr_value < 0x180F94)
+			*snr = 16;
+		else if (snr_value < 0x186ED2)
+			*snr = 17;
+		else if (snr_value < 0x18B271)
+			*snr = 18;
+		else if (snr_value < 0x18E118)
+			*snr = 19;
+		else if (snr_value < 0x18FF4B)
+			*snr = 20;
+		else if (snr_value < 0x190AF1)
+			*snr = 21;
+		else if (snr_value < 0x191451)
+			*snr = 22;
+		else
+			*snr = 23;
+	} else if (ch_modulation.constellation == 1) {	/* CONSTELLATION_16QAM */
+		if (snr_value < 0x4F0D5)
+			*snr = 0;
+		else if (snr_value < 0x5387A)
+			*snr = 1;
+		else if (snr_value < 0x573A4)
+			*snr = 2;
+		else if (snr_value < 0x5A99E)
+			*snr = 3;
+		else if (snr_value < 0x5CC80)
+			*snr = 4;
+		else if (snr_value < 0x5EB62)
+			*snr = 5;
+		else if (snr_value < 0x5FECF)
+			*snr = 6;
+		else if (snr_value < 0x60B80)
+			*snr = 7;
+		else if (snr_value < 0x62501)
+			*snr = 8;
+		else if (snr_value < 0x64865)
+			*snr = 9;
+		else if (snr_value < 0x69604)
+			*snr = 10;
+		else if (snr_value < 0x6F356)
+			*snr = 11;
+		else if (snr_value < 0x7706A)
+			*snr = 12;
+		else if (snr_value < 0x804D3)
+			*snr = 13;
+		else if (snr_value < 0x89D1A)
+			*snr = 14;
+		else if (snr_value < 0x93E3D)
+			*snr = 15;
+		else if (snr_value < 0x9E35D)
+			*snr = 16;
+		else if (snr_value < 0xA7C3C)
+			*snr = 17;
+		else if (snr_value < 0xAFAF8)
+			*snr = 18;
+		else if (snr_value < 0xB719D)
+			*snr = 19;
+		else if (snr_value < 0xBDA6A)
+			*snr = 20;
+		else if (snr_value < 0xC0C75)
+			*snr = 21;
+		else if (snr_value < 0xC3F7D)
+			*snr = 22;
+		else if (snr_value < 0xC5E62)
+			*snr = 23;
+		else if (snr_value < 0xC6C31)
+			*snr = 24;
+		else if (snr_value < 0xC7925)
+			*snr = 25;
+		else
+			*snr = 26;
+	} else if (ch_modulation.constellation == 2) {	/* CONSTELLATION_64QAM */
+		if (snr_value < 0x256D0)
+			*snr = 0;
+		else if (snr_value < 0x27A65)
+			*snr = 1;
+		else if (snr_value < 0x29873)
+			*snr = 2;
+		else if (snr_value < 0x2B7FE)
+			*snr = 3;
+		else if (snr_value < 0x2CF1E)
+			*snr = 4;
+		else if (snr_value < 0x2E234)
+			*snr = 5;
+		else if (snr_value < 0x2F409)
+			*snr = 6;
+		else if (snr_value < 0x30046)
+			*snr = 7;
+		else if (snr_value < 0x30844)
+			*snr = 8;
+		else if (snr_value < 0x30A02)
+			*snr = 9;
+		else if (snr_value < 0x30CDE)
+			*snr = 10;
+		else if (snr_value < 0x31031)
+			*snr = 11;
+		else if (snr_value < 0x3144C)
+			*snr = 12;
+		else if (snr_value < 0x315DD)
+			*snr = 13;
+		else if (snr_value < 0x31920)
+			*snr = 14;
+		else if (snr_value < 0x322D0)
+			*snr = 15;
+		else if (snr_value < 0x339FC)
+			*snr = 16;
+		else if (snr_value < 0x364A1)
+			*snr = 17;
+		else if (snr_value < 0x38BCC)
+			*snr = 18;
+		else if (snr_value < 0x3C7D3)
+			*snr = 19;
+		else if (snr_value < 0x408CC)
+			*snr = 20;
+		else if (snr_value < 0x43BED)
+			*snr = 21;
+		else if (snr_value < 0x48061)
+			*snr = 22;
+		else if (snr_value < 0x4BE95)
+			*snr = 23;
+		else if (snr_value < 0x4FA7D)
+			*snr = 24;
+		else if (snr_value < 0x52405)
+			*snr = 25;
+		else if (snr_value < 0x5570D)
+			*snr = 26;
+		else if (snr_value < 0x59FEB)
+			*snr = 27;
+		else if (snr_value < 0x5BF38)
+			*snr = 28;
+		else if (snr_value < 0x5F78F)
+			*snr = 29;
+		else if (snr_value < 0x612C3)
+			*snr = 30;
+		else if (snr_value < 0x626BE)
+			*snr = 31;
+		else
+			*snr = 32;
+	} else
+		goto exit;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_get_snr_val(struct it9135_data *data, unsigned char chip,
+				 unsigned long *snr_value)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char super_frame_num = 0;
+	unsigned char snr_reg[3];
+
+	error = it9135_read_regs(data, chip, PROCESSOR_OFDM, 0x2c, 3, snr_reg);
+	if (error)
+		goto exit;
+
+	*snr_value = (snr_reg[2] << 16) + (snr_reg[1] << 8) + snr_reg[0];
+
+	/* gets superFrame num */
+	error =
+	    it9135_read_reg(data, chip, PROCESSOR_OFDM, 0xF78b,
+			    (unsigned char *)&super_frame_num);
+	if (error)
+		goto exit;
+
+	if (super_frame_num)
+		*snr_value /= super_frame_num;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_set_multiplier(struct it9135_data *data,
+				    unsigned char multiplier)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char new_adc_mul = 0;
+	unsigned char buffer[3];
+	long ctl_word;
+	unsigned char i;
+
+	if (multiplier == Multiplier_1X)
+		new_adc_mul = 0;
+	else
+		new_adc_mul = 1;
+
+	for (i = 0; i < data->chip_num; i++) {
+		/* Write ADC multiplier factor to firmware. */
+		error =
+		    it9135_write_reg(data, i, PROCESSOR_OFDM, adcx2,
+				     new_adc_mul);
+		if (error)
+			goto exit;
+	}
+
+	/* Compute FCW and load them to device */
+	if (data->fcw >= 0x00400000)
+		ctl_word = data->fcw - 0x00800000;
+	else
+		ctl_word = data->fcw;
+
+	if (new_adc_mul == 1)
+		ctl_word /= 2;
+	else
+		ctl_word *= 2;
+
+	data->fcw = 0x7FFFFF & ctl_word;
+
+	buffer[0] = (unsigned char)(data->fcw & 0x000000FF);
+	buffer[1] = (unsigned char)((data->fcw & 0x0000FF00) >> 8);
+	buffer[2] = (unsigned char)((data->fcw & 0x007F0000) >> 16);
+	for (i = 0; i < data->chip_num; i++)
+		error =
+		    it9135_write_regs(data, i, PROCESSOR_OFDM, bfs_fcw_7_0,
+				      bfs_fcw_22_16 - bfs_fcw_7_0 + 1, buffer);
+
+exit:
+	return error;
+}
+
+unsigned long it9135_reset_pid(struct it9135_data *data, unsigned char chip)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char i;
+
+	for (i = 0; i < 32; i++)
+		data->pid_info.pid_tab[chip].pid[i] = 0xFFFF;
+
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM, p_mp2if_pid_rst,
+				  mp2if_pid_rst_pos, mp2if_pid_rst_len, 1);
+	if (error)
+		goto exit;
+
+	data->pid_info.pid_cnt = 0;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_remove_pid_at(struct it9135_data *data, unsigned char chip,
+				   unsigned char index, unsigned short pid)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM,
+				  p_mp2if_pid_index_en, mp2if_pid_index_en_pos,
+				  mp2if_pid_index_en_len, 0);
+	if (error)
+		goto exit;
+
+	error =
+	    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_mp2if_pid_index,
+			     index);
+	if (error)
+		goto exit;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_get_ch_statistic(struct it9135_data *data,
+				      unsigned char chip,
+				      struct it9135_ch_statistic *ch_statistic)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long post_err_cnt;
+	unsigned long post_bit_cnt;
+	unsigned short rsd_abort_cnt;
+
+	/* Get BER if couter is ready, error = ERROR_RSD_COUNTER_NOT_READY if counter is not ready */
+	if (data->architecture == ARCHITECTURE_PIP) {
+		error =
+		    it9135_get_post_vitber(data, chip, &post_err_cnt,
+					   &post_bit_cnt, &rsd_abort_cnt);
+		if (error == ERROR_NO_ERROR) {
+			data->ch_statistic[chip].post_vit_err_cnt =
+			    post_err_cnt;
+			data->ch_statistic[chip].post_vitbit_cnt = post_bit_cnt;
+			data->ch_statistic[chip].abort_cnt = rsd_abort_cnt;
+		}
+	} else {
+		error =
+		    it9135_get_post_vitber(data, 0, &post_err_cnt,
+					   &post_bit_cnt, &rsd_abort_cnt);
+		if (error == ERROR_NO_ERROR) {
+			data->ch_statistic[chip].post_vit_err_cnt =
+			    post_err_cnt;
+			data->ch_statistic[chip].post_vitbit_cnt = post_bit_cnt;
+			data->ch_statistic[chip].abort_cnt = rsd_abort_cnt;
+		}
+	}
+
+	*ch_statistic = data->ch_statistic[chip];
+
+	return error;
+}
+
+static struct it9135_tuner_desc tuner_def_desc = {
+	NULL,
+	NULL,
+	0x38,			/* tuner id */
+};
+
+unsigned long it9135_set_bus_tuner(struct it9135_data *data,
+				   unsigned short busId,
+				   unsigned short tuner_id)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char support_type = OMEGA_NORMAL;
+
+	data->busId = busId;
+	memcpy(&data->tuner_desc, &tuner_def_desc, sizeof(data->tuner_desc));
+
+	switch (tuner_id) {
+	case IT9135_TUNER_ID:
+		support_type = OMEGA_NORMAL;
+		break;
+	case IT9135_TUNER_ID_LNA_CONFIG1:
+		support_type = OMEGA_LNA_CONFIG1;
+		break;
+	case IT9135_TUNER_ID_LNA_CONFIG2:
+		support_type = OMEGA_LNA_CONFIG2;
+		break;
+	case IT9135_TUNER_ID_V2:
+		support_type = OMEGA_NORMAL;
+		break;
+	case IT9135_TUNER_ID_V2_LNA_CONFIG1:
+		support_type = OMEGA_LNA_CONFIG1;
+		break;
+	case IT9135_TUNER_ID_V2_LNA_CONFIG2:
+		support_type = OMEGA_LNA_CONFIG2;
+		break;
+	default:
+		error = ERROR_INVALID_TUNER_TYPE;
+		goto exit;
+	}
+
+	if (data->chip_type == 0x9135 && data->chip_ver == 2) {
+		switch (support_type) {
+		case OMEGA_NORMAL:
+			data->tuner_desc.scripts = data->tuner_script_normal;
+			data->tuner_desc.script_sets =
+			    &data->tuner_script_sets_normal;
+			data->tuner_desc.id = IT9135_TUNER_ID_V2;
+			error = ERROR_NO_ERROR;
+			break;
+		case OMEGA_LNA_CONFIG1:
+			data->tuner_desc.scripts = data->tuner_script_lna1;
+			data->tuner_desc.script_sets =
+			    &data->tuner_script_sets_lna1;
+			data->tuner_desc.id = IT9135_TUNER_ID_V2_LNA_CONFIG1;
+			error = ERROR_NO_ERROR;
+			break;
+		case OMEGA_LNA_CONFIG2:
+			data->tuner_desc.scripts = data->tuner_script_lna2;
+			data->tuner_desc.script_sets =
+			    &data->tuner_script_sets_lna2;
+			data->tuner_desc.id = IT9135_TUNER_ID_V2_LNA_CONFIG2;
+			error = ERROR_NO_ERROR;
+			break;
+		default:
+			break;
+		}
+	} else {
+		switch (support_type) {
+		case OMEGA_NORMAL:
+			data->tuner_desc.scripts = data->tuner_script_normal;
+			data->tuner_desc.script_sets =
+			    &data->tuner_script_sets_normal;
+			data->tuner_desc.id = IT9135_TUNER_ID;
+			error = ERROR_NO_ERROR;
+			break;
+		case OMEGA_LNA_CONFIG1:
+			data->tuner_desc.scripts = data->tuner_script_lna1;
+			data->tuner_desc.script_sets =
+			    &data->tuner_script_sets_lna1;
+			data->tuner_desc.id = IT9135_TUNER_ID_LNA_CONFIG1;
+			error = ERROR_NO_ERROR;
+			break;
+		case OMEGA_LNA_CONFIG2:
+			data->tuner_desc.scripts = data->tuner_script_lna2;
+			data->tuner_desc.script_sets =
+			    &data->tuner_script_sets_lna2;
+			data->tuner_desc.id = IT9135_TUNER_ID_LNA_CONFIG2;
+			error = ERROR_NO_ERROR;
+			break;
+		default:
+
+			break;
+		}
+	}
+
+	if (data->tuner_desc.scripts == NULL) {
+		data->tuner_desc.scripts = NULL;
+		data->tuner_desc.script_sets = NULL;
+	}
+
+exit:
+	return error;
+}
+
+unsigned long it9135_add_pid(struct it9135_data *data, unsigned char chip,
+			     unsigned short pid)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char w_buff[2];
+	unsigned char i, j;
+	int found = 0;
+
+	if (!data->pid_info.pid_init) {
+		for (i = 0; i < data->chip_num; i++) {
+			for (j = 0; j < 32; j++)
+				data->pid_info.pid_tab[i].pid[j] = 0xFFFF;
+		}
+		data->pid_info.pid_init = 1;
+	}
+
+	/* Enable pid filter */
+	if (data->pid_info.pid_cnt == 0) {
+		error =
+		    it9135_write_reg_bits(data, chip,
+					  PROCESSOR_OFDM, p_mp2if_pid_en,
+					  mp2if_pid_en_pos, mp2if_pid_en_len,
+					  1);
+		if (error)
+			goto exit;
+	} else {
+		for (i = 0; i < 32; i++) {
+			if (data->pid_info.pid_tab[chip].pid[i] == pid) {
+				found = 1;
+				break;
+			}
+		}
+		if (found)
+			goto exit;
+	}
+
+	for (i = 0; i < 32; i++) {
+		if (data->pid_info.pid_tab[chip].pid[i] == 0xFFFF)
+			break;
+	}
+	if (i == 32) {
+		error = ERROR_PID_FILTER_FULL;
+		goto exit;
+	}
+
+	w_buff[0] = (unsigned char)pid;
+	w_buff[1] = (unsigned char)(pid >> 8);
+
+	error =
+	    it9135_write_regs(data, chip, PROCESSOR_OFDM, p_mp2if_pid_dat_l, 2,
+			      w_buff);
+	if (error)
+		goto exit;
+
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM,
+				  p_mp2if_pid_index_en, mp2if_pid_index_en_pos,
+				  mp2if_pid_index_en_len, 1);
+	if (error)
+		goto exit;
+
+	error =
+	    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_mp2if_pid_index, i);
+	if (error)
+		goto exit;
+
+	data->pid_info.pid_tab[chip].pid[i] = pid;
+	data->pid_info.pid_cnt++;
+
+exit:
+	return error;
+}
+
+unsigned long it9135_add_pid_at(struct it9135_data *data, unsigned char chip,
+				unsigned char index, unsigned short pid)
+{
+	return it9135_add_pid_filter(data, chip, index, pid);
+}
+
+unsigned long it9135_remove_pid(struct it9135_data *data, unsigned char chip,
+				unsigned short pid)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char i;
+	int found = 0;
+
+	for (i = 0; i < 32; i++) {
+		if (data->pid_info.pid_tab[chip].pid[i] == pid) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found)
+		goto exit;
+
+	error =
+	    it9135_write_reg_bits(data, chip, PROCESSOR_OFDM,
+				  p_mp2if_pid_index_en, mp2if_pid_index_en_pos,
+				  mp2if_pid_index_en_len, 0);
+	if (error)
+		goto exit;
+
+	error =
+	    it9135_write_reg(data, chip, PROCESSOR_OFDM, p_mp2if_pid_index, i);
+	if (error)
+		goto exit;
+
+	data->pid_info.pid_tab[chip].pid[i] = 0xFFFF;
+
+	/* Disable pid filter */
+	if (data->pid_info.pid_cnt == 1) {
+		error =
+		    it9135_write_reg_bits(data, chip,
+					  PROCESSOR_OFDM, p_mp2if_pid_en,
+					  mp2if_pid_en_pos, mp2if_pid_en_len,
+					  0);
+	}
+
+	data->pid_info.pid_cnt--;
+
+exit:
+	return error;
+}
diff --git a/drivers/media/dvb/dvb-usb/it9135-fe.h b/drivers/media/dvb/dvb-usb/it9135-fe.h
new file mode 100644
index 0000000..1744ba4
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/it9135-fe.h
@@ -0,0 +1,1632 @@
+/*
+ * DVB USB Linux driver for IT9135 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2011 ITE Technologies, INC.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ */
+
+#ifndef __IT9135_FE_H__
+#define __IT9135_FE_H__
+
+#define IT9135_API_VER_NUM	0x0203
+#define IT9135_API_DATE		0x20110426
+#define IT9135_API_BUILD	0x00
+
+/*
+ * Hardware register define
+ */
+#define    p_reg_pd_a				0xEC02
+#define	reg_pd_a_pos 0
+#define	reg_pd_a_len 6
+#define	reg_pd_a_lsb 0
+#define    p_reg_pd_c				0xEC04
+#define	reg_pd_c_pos 0
+#define	reg_pd_c_len 6
+#define	reg_pd_c_lsb 0
+#define    p_reg_pd_d				0xEC05
+#define	reg_pd_d_pos 0
+#define	reg_pd_d_len 6
+#define	reg_pd_d_lsb 0
+#define    p_reg_tst_a				0xEC06
+#define	reg_tst_a_pos 0
+#define	reg_tst_a_len 6
+#define	reg_tst_a_lsb 0
+#define    p_reg_tst_b				0xEC07
+#define	reg_tst_b_pos 0
+#define	reg_tst_b_len 2
+#define	reg_tst_b_lsb 0
+#define    p_reg_ctrl_a				0xEC08
+#define	reg_ctrl_a_pos 0
+#define	reg_ctrl_a_len 6
+#define	reg_ctrl_a_lsb 0
+#define    p_reg_ctrl_b				0xEC09
+#define	reg_ctrl_b_pos 0
+#define	reg_ctrl_b_len 2
+#define	reg_ctrl_b_lsb 0
+#define    p_reg_cal_freq_a			0xEC0A
+#define	reg_cal_freq_a_pos 0
+#define	reg_cal_freq_a_len 6
+#define	reg_cal_freq_a_lsb 0
+#define    p_reg_cal_freq_b			0xEC0B
+#define	reg_cal_freq_b_pos 0
+#define	reg_cal_freq_b_len 6
+#define	reg_cal_freq_b_lsb 0
+#define    p_reg_cal_freq_c			0xEC0C
+#define	reg_cal_freq_c_pos 0
+#define	reg_cal_freq_c_len 4
+#define	reg_cal_freq_c_lsb 0
+#define    p_reg_lo_freq_a			0xEC0D
+#define	reg_lo_freq_a_pos 0
+#define	reg_lo_freq_a_len 6
+#define	reg_lo_freq_a_lsb 0
+#define    p_reg_lo_freq_b			0xEC0E
+#define	reg_lo_freq_b_pos 0
+#define	reg_lo_freq_b_len 6
+#define	reg_lo_freq_b_lsb 0
+#define    p_reg_lo_freq_c			0xEC0F
+#define	reg_lo_freq_c_pos 0
+#define	reg_lo_freq_c_len 4
+#define	reg_lo_freq_c_lsb 0
+#define    p_reg_lo_cap				0xEC10
+#define	reg_lo_cap_pos 0
+#define	reg_lo_cap_len 6
+#define	reg_lo_cap_lsb 0
+#define    p_reg_clk02_select			0xEC11
+#define	reg_clk02_select_pos 0
+#define	reg_clk02_select_len 3
+#define	reg_clk02_select_lsb 0
+#define    p_reg_clk01_select			0xEC11
+#define	reg_clk01_select_pos 3
+#define	reg_clk01_select_len 3
+#define	reg_clk01_select_lsb 0
+#define    p_reg_lna_cap			0xEC13
+#define	reg_lna_cap_pos 0
+#define	reg_lna_cap_len 6
+#define	reg_lna_cap_lsb 0
+#define    p_reg_lna_g				0xEC12
+#define	reg_lna_g_pos 0
+#define	reg_lna_g_len 3
+#define	reg_lna_g_lsb 0
+#define    p_reg_lna_band			0xEC14
+#define	reg_lna_band_pos 0
+#define	reg_lna_band_len 3
+#define	reg_lna_band_lsb 0
+#define    p_reg_pga				0xEC15
+#define	reg_pga_pos 0
+#define	reg_pga_len 6
+#define	reg_pga_lsb 0
+#define    p_reg_pgc				0xEC17
+#define	reg_pgc_pos 0
+#define	reg_pgc_len 3
+#define	reg_pgc_lsb 0
+#define    p_reg_lpf_cap			0xEC18
+#define	reg_lpf_cap_pos 0
+#define	reg_lpf_cap_len 5
+#define	reg_lpf_cap_lsb 0
+#define    p_reg_lpf_bw				0xEC19
+#define	reg_lpf_bw_pos 0
+#define	reg_lpf_bw_len 3
+#define	reg_lpf_bw_lsb 0
+#define    p_reg_ofsi				0xEC1A
+#define	reg_ofsi_pos 0
+#define	reg_ofsi_len 6
+#define	reg_ofsi_lsb 0
+#define    p_reg_ofsq				0xEC1B
+#define	reg_ofsq_pos 0
+#define	reg_ofsq_len 6
+#define	reg_ofsq_lsb 0
+#define    p_reg_dcxo_a				0xEC1C
+#define	reg_dcxo_a_pos 0
+#define	reg_dcxo_a_len 6
+#define	reg_dcxo_a_lsb 0
+#define    p_reg_dcxo_b				0xEC1D
+#define	reg_dcxo_b_pos 0
+#define	reg_dcxo_b_len 4
+#define	reg_dcxo_b_lsb 0
+#define    p_reg_tddo				0xEC1E
+#define	reg_tddo_pos 0
+#define	reg_tddo_len 6
+#define	reg_tddo_lsb 0
+#define    p_reg_strength_setting		0xEC1F
+#define	reg_strength_setting_pos 0
+#define	reg_strength_setting_len 6
+#define	reg_strength_setting_lsb 0
+#define    p_reg_gi				0xEC22
+#define	reg_gi_pos 0
+#define	reg_gi_len 2
+#define	reg_gi_lsb 0
+#define    p_reg_clk_del_sel			0xEC22
+#define	reg_clk_del_sel_pos 2
+#define	reg_clk_del_sel_len 2
+#define	reg_clk_del_sel_lsb 0
+#define    p_reg_p2s_ck_sel			0xEC22
+#define	reg_p2s_ck_sel_pos 4
+#define	reg_p2s_ck_sel_len 1
+#define	reg_p2s_ck_sel_lsb 0
+#define    p_reg_rssi_sel			0xEC22
+#define	reg_rssi_sel_pos 5
+#define	reg_rssi_sel_len 1
+#define	reg_rssi_sel_lsb 0
+#define    p_reg_tst_sel			0xEC23
+#define	reg_tst_sel_pos 4
+#define	reg_tst_sel_len 2
+#define	reg_tst_sel_lsb 0
+#define    p_reg_ctrl_c				0xEC24
+#define	reg_ctrl_c_pos 0
+#define	reg_ctrl_c_len 6
+#define	reg_ctrl_c_lsb 0
+#define    p_reg_ctrl_d				0xEC25
+#define	reg_ctrl_d_pos 0
+#define	reg_ctrl_d_len 6
+#define	reg_ctrl_d_lsb 0
+#define    p_reg_ctrl_e				0xEC26
+#define	reg_ctrl_e_pos 0
+#define	reg_ctrl_e_len 6
+#define	reg_ctrl_e_lsb 0
+#define    p_reg_ctrl_f				0xEC27
+#define	reg_ctrl_f_pos 0
+#define	reg_ctrl_f_len 6
+#define	reg_ctrl_f_lsb 0
+#define    p_reg_lo_bias			0xEC28
+#define	reg_lo_bias_pos 0
+#define	reg_lo_bias_len 3
+#define	reg_lo_bias_lsb 0
+#define    p_reg_ext_lna_en			0xEC29
+#define	reg_ext_lna_en_pos 0
+#define	reg_ext_lna_en_len 1
+#define	reg_ext_lna_en_lsb 0
+#define    p_reg_pga_bak			0xEC2A
+#define	reg_pga_bak_pos 0
+#define	reg_pga_bak_len 3
+#define	reg_pga_bak_lsb 0
+#define    p_reg_cpll_cap			0xEC2B
+#define	reg_cpll_cap_pos 0
+#define	reg_cpll_cap_len 6
+#define	reg_cpll_cap_lsb 0
+#define    p_reg_p_if_en			0xEC40
+#define	reg_p_if_en_pos 0
+#define	reg_p_if_en_len 2
+#define	reg_p_if_en_lsb 0
+#define    p_reg_one_cycle_counter_tuner	0xF103
+#define	reg_one_cycle_counter_tuner_pos 0
+#define	reg_one_cycle_counter_tuner_len 8
+#define	reg_one_cycle_counter_tuner_lsb 0
+#define    p_reg_f_adc_7_0			0xF1CD
+#define	reg_f_adc_7_0_pos 0
+#define	reg_f_adc_7_0_len 8
+#define	reg_f_adc_7_0_lsb 0
+#define    p_reg_dvbt_en			0xF41A
+#define	reg_dvbt_en_pos 0
+#define	reg_dvbt_en_len 1
+#define	reg_dvbt_en_lsb 0
+#define    p_fd_tpsd_lock			0xF5A9
+#define	fd_tpsd_lock_pos 0
+#define	fd_tpsd_lock_len 1
+#define	fd_tpsd_lock_lsb 0
+#define    p_reg_feq_read_update		0xF5CA
+#define	reg_feq_read_update_pos 0
+#define	reg_feq_read_update_len 1
+#define	reg_feq_read_update_lsb 0
+#define    p_reg_link_ofsm_dummy_15_8		0xF641
+#define	reg_link_ofsm_dummy_15_8_pos 0
+#define	reg_link_ofsm_dummy_15_8_len 8
+#define	reg_link_ofsm_dummy_15_8_lsb 8
+#define    p_fec_vtb_rsd_mon_en			0xF715
+#define	fec_vtb_rsd_mon_en_pos 0
+#define	fec_vtb_rsd_mon_en_len 1
+#define	fec_vtb_rsd_mon_en_lsb 0
+#define    p_reg_dca_platch			0xF730
+#define	reg_dca_platch_pos 0
+#define	reg_dca_platch_len 1
+#define	reg_dca_platch_lsb 0
+#define    p_reg_dca_upper_chip			0xF731
+#define	reg_dca_upper_chip_pos 0
+#define	reg_dca_upper_chip_len 1
+#define	reg_dca_upper_chip_lsb 0
+#define    p_reg_dca_lower_chip			0xF732
+#define	reg_dca_lower_chip_pos 0
+#define	reg_dca_lower_chip_len 1
+#define	reg_dca_lower_chip_lsb 0
+#define    p_reg_dca_stand_alone		0xF73C
+#define	reg_dca_stand_alone_pos 0
+#define	reg_dca_stand_alone_len 1
+#define	reg_dca_stand_alone_lsb 0
+#define    p_reg_dca_upper_out_en		0xF73D
+#define	reg_dca_upper_out_en_pos 0
+#define	reg_dca_upper_out_en_len 1
+#define	reg_dca_upper_out_en_lsb 0
+#define    p_reg_dca_en				0xF776
+#define	reg_dca_en_pos 0
+#define	reg_dca_en_len 1
+#define	reg_dca_en_lsb 0
+#define    p_reg_dca_fpga_latch			0xF778
+#define	reg_dca_fpga_latch_pos 0
+#define	reg_dca_fpga_latch_len 8
+#define	reg_dca_fpga_latch_lsb 0
+#define    g_reg_tpsd_txmod			0xF900
+#define	reg_tpsd_txmod_pos 0
+#define	reg_tpsd_txmod_len 2
+#define	reg_tpsd_txmod_lsb 0
+#define    g_reg_tpsd_gi			0xF901
+#define	reg_tpsd_gi_pos 0
+#define	reg_tpsd_gi_len 2
+#define	reg_tpsd_gi_lsb 0
+#define    g_reg_tpsd_hier			0xF902
+#define	reg_tpsd_hier_pos 0
+#define	reg_tpsd_hier_len 3
+#define	reg_tpsd_hier_lsb 0
+#define    g_reg_tpsd_const			0xF903
+#define	reg_tpsd_const_pos 0
+#define	reg_tpsd_const_len 2
+#define	reg_tpsd_const_lsb 0
+#define    g_reg_bw				0xF904
+#define	reg_bw_pos 0
+#define	reg_bw_len 2
+#define	reg_bw_lsb 0
+#define    g_reg_dec_pri			0xF905
+#define	reg_dec_pri_pos 0
+#define	reg_dec_pri_len 1
+#define	reg_dec_pri_lsb 0
+#define    g_reg_tpsd_hpcr			0xF906
+#define	reg_tpsd_hpcr_pos 0
+#define	reg_tpsd_hpcr_len 3
+#define	reg_tpsd_hpcr_lsb 0
+#define    g_reg_tpsd_lpcr			0xF907
+#define	reg_tpsd_lpcr_pos 0
+#define	reg_tpsd_lpcr_len 3
+#define	reg_tpsd_lpcr_lsb 0
+#define    p_mp2if_mpeg_ser_mode		0xF985
+#define	mp2if_mpeg_ser_mode_pos 0
+#define	mp2if_mpeg_ser_mode_len 1
+#define	mp2if_mpeg_ser_mode_lsb 0
+#define    p_mp2if_mpeg_par_mode		0xF986
+#define	mp2if_mpeg_par_mode_pos 0
+#define	mp2if_mpeg_par_mode_len 1
+#define	mp2if_mpeg_par_mode_lsb 0
+#define    p_reg_mpeg_full_speed		0xF990
+#define	reg_mpeg_full_speed_pos 0
+#define	reg_mpeg_full_speed_len 1
+#define	reg_mpeg_full_speed_lsb 0
+#define    p_mp2if_pid_rst			0xF992
+#define	mp2if_pid_rst_pos 0
+#define	mp2if_pid_rst_len 1
+#define	mp2if_pid_rst_lsb 0
+#define    p_mp2if_pid_en			0xF993
+#define	mp2if_pid_en_pos 0
+#define	mp2if_pid_en_len 1
+#define	mp2if_pid_en_lsb 0
+#define    p_mp2if_pid_index_en			0xF994
+#define	mp2if_pid_index_en_pos 0
+#define	mp2if_pid_index_en_len 1
+#define	mp2if_pid_index_en_lsb 0
+#define    p_mp2if_pid_index			0xF995
+#define	mp2if_pid_index_pos 0
+#define	mp2if_pid_index_len 5
+#define	mp2if_pid_index_lsb 0
+#define    p_mp2if_pid_dat_l			0xF996
+#define	mp2if_pid_dat_l_pos 0
+#define	mp2if_pid_dat_l_len 8
+#define	mp2if_pid_dat_l_lsb 0
+#define    r_mp2if_sync_byte_locked		0xF999
+#define	mp2if_sync_byte_locked_pos 0
+#define	mp2if_sync_byte_locked_len 1
+#define	mp2if_sync_byte_locked_lsb 0
+#define    p_reg_mp2_sw_rst			0xF99D
+#define	reg_mp2_sw_rst_pos 0
+#define	reg_mp2_sw_rst_len 1
+#define	reg_mp2_sw_rst_lsb 0
+#define    p_reg_mp2if2_en			0xF9A3
+#define	reg_mp2if2_en_pos 0
+#define	reg_mp2if2_en_len 1
+#define	reg_mp2if2_en_lsb 0
+#define    p_reg_mp2if2_sw_rst			0xF9A4
+#define	reg_mp2if2_sw_rst_pos 0
+#define	reg_mp2if2_sw_rst_len 1
+#define	reg_mp2if2_sw_rst_lsb 0
+#define    p_reg_mp2if2_half_psb		0xF9A5
+#define	reg_mp2if2_half_psb_pos 0
+#define	reg_mp2if2_half_psb_len 1
+#define	reg_mp2if2_half_psb_lsb 0
+#define    p_reg_mp2if_stop_en			0xF9B5
+#define	reg_mp2if_stop_en_pos 0
+#define	reg_mp2if_stop_en_len 1
+#define	reg_mp2if_stop_en_lsb 0
+#define    p_reg_tsis_en			0xF9CD
+#define	reg_tsis_en_pos 0
+#define	reg_tsis_en_len 1
+#define	reg_tsis_en_lsb 0
+#define    p_reg_afe_mem0			0xFB24
+#define	reg_afe_mem0_pos 0
+#define	reg_afe_mem0_len 8
+#define	reg_afe_mem0_lsb 0
+#define    p_reg_dyn0_clk			0xFBA8
+#define	reg_dyn0_clk_pos 0
+#define	reg_dyn0_clk_len 1
+#define	reg_dyn0_clk_lsb 0
+#define    r_io_mux_pwron_clk_strap		0xD800
+#define	io_mux_pwron_clk_strap_pos 0
+#define	io_mux_pwron_clk_strap_len 4
+#define	io_mux_pwron_clk_strap_lsb 0
+#define    p_reg_top_pwrdw_hwen			0xD809
+#define	reg_top_pwrdw_hwen_pos 0
+#define	reg_top_pwrdw_hwen_len 1
+#define	reg_top_pwrdw_hwen_lsb 0
+#define    p_reg_top_pwrdw			0xD80B
+#define	reg_top_pwrdw_pos 0
+#define	reg_top_pwrdw_len 1
+#define	reg_top_pwrdw_lsb 0
+#define    p_reg_top_padodpu			0xD827
+#define	reg_top_padodpu_pos 0
+#define	reg_top_padodpu_len 1
+#define	reg_top_padodpu_lsb 0
+#define    p_reg_top_agc_od			0xD829
+#define	reg_top_agc_od_pos 0
+#define	reg_top_agc_od_len 1
+#define	reg_top_agc_od_lsb 0
+#define    p_reg_top_padmiscdr2			0xD830
+#define	reg_top_padmiscdr2_pos 0
+#define	reg_top_padmiscdr2_len 1
+#define	reg_top_padmiscdr2_lsb 0
+#define    p_reg_top_padmiscdr4			0xD831
+#define	reg_top_padmiscdr4_pos 0
+#define	reg_top_padmiscdr4_len 1
+#define	reg_top_padmiscdr4_lsb 0
+#define    p_reg_top_padmiscdr8			0xD832
+#define	reg_top_padmiscdr8_pos 0
+#define	reg_top_padmiscdr8_len 1
+#define	reg_top_padmiscdr8_lsb 0
+#define    p_reg_top_padmiscdrsr		0xD833
+#define	reg_top_padmiscdrsr_pos 0
+#define	reg_top_padmiscdrsr_len 1
+#define	reg_top_padmiscdrsr_lsb 0
+#define    p_reg_top_gpioh1_o			0xD8AF
+#define	reg_top_gpioh1_o_pos 0
+#define	reg_top_gpioh1_o_len 1
+#define	reg_top_gpioh1_o_lsb 0
+#define    p_reg_top_gpioh1_en			0xD8B0
+#define	reg_top_gpioh1_en_pos 0
+#define	reg_top_gpioh1_en_len 1
+#define	reg_top_gpioh1_en_lsb 0
+#define    p_reg_top_gpioh1_on			0xD8B1
+#define	reg_top_gpioh1_on_pos 0
+#define	reg_top_gpioh1_on_len 1
+#define	reg_top_gpioh1_on_lsb 0
+#define    p_reg_top_gpioh3_o			0xD8B3
+#define	reg_top_gpioh3_o_pos 0
+#define	reg_top_gpioh3_o_len 1
+#define	reg_top_gpioh3_o_lsb 0
+#define    p_reg_top_gpioh3_en			0xD8B4
+#define	reg_top_gpioh3_en_pos 0
+#define	reg_top_gpioh3_en_len 1
+#define	reg_top_gpioh3_en_lsb 0
+#define    p_reg_top_gpioh3_on			0xD8B5
+#define	reg_top_gpioh3_on_pos 0
+#define	reg_top_gpioh3_on_len 1
+#define	reg_top_gpioh3_on_lsb 0
+#define    p_reg_top_gpioh5_o			0xD8BB
+#define	reg_top_gpioh5_o_pos 0
+#define	reg_top_gpioh5_o_len 1
+#define	reg_top_gpioh5_o_lsb 0
+#define    p_reg_top_gpioh5_en			0xD8BC
+#define	reg_top_gpioh5_en_pos 0
+#define	reg_top_gpioh5_en_len 1
+#define	reg_top_gpioh5_en_lsb 0
+#define    p_reg_top_gpioh5_on			0xD8BD
+#define	reg_top_gpioh5_on_pos 0
+#define	reg_top_gpioh5_on_len 1
+#define	reg_top_gpioh5_on_lsb 0
+#define    p_reg_top_gpioh7_en			0xD8C4
+#define	reg_top_gpioh7_en_pos 0
+#define	reg_top_gpioh7_en_len 1
+#define	reg_top_gpioh7_en_lsb 0
+#define    p_reg_top_gpioh7_on			0xD8C5
+#define	reg_top_gpioh7_on_pos 0
+#define	reg_top_gpioh7_on_len 1
+#define	reg_top_gpioh7_on_lsb 0
+#define    p_reg_top_lock3_out			0xD8FD
+#define	reg_top_lock3_out_pos 0
+#define	reg_top_lock3_out_len 1
+#define	reg_top_lock3_out_lsb 0
+#define    p_reg_top_hostb_mpeg_par_mode	0xD91B
+#define	reg_top_hostb_mpeg_par_mode_pos 0
+#define	reg_top_hostb_mpeg_par_mode_len 1
+#define	reg_top_hostb_mpeg_par_mode_lsb 0
+#define    p_reg_top_hostb_mpeg_ser_mode	0xD91C
+#define	reg_top_hostb_mpeg_ser_mode_pos 0
+#define	reg_top_hostb_mpeg_ser_mode_len 1
+#define	reg_top_hostb_mpeg_ser_mode_lsb 0
+#define    p_reg_top_hostb_dca_upper		0xD91E
+#define	reg_top_hostb_dca_upper_pos 0
+#define	reg_top_hostb_dca_upper_len 1
+#define	reg_top_hostb_dca_upper_lsb 0
+#define    p_reg_top_hostb_dca_lower		0xD91F
+#define	reg_top_hostb_dca_lower_pos 0
+#define	reg_top_hostb_dca_lower_len 1
+#define	reg_top_hostb_dca_lower_lsb 0
+#define    p_reg_ep4_max_pkt			0xDD0C
+#define	reg_ep4_max_pkt_pos 0
+#define	reg_ep4_max_pkt_len 8
+#define	reg_ep4_max_pkt_lsb 0
+#define    p_reg_ep5_max_pkt			0xDD0D
+#define	reg_ep5_max_pkt_pos 0
+#define	reg_ep5_max_pkt_len 8
+#define	reg_ep5_max_pkt_lsb 0
+#define    p_reg_ep4_tx_en			0xDD11
+#define	reg_ep4_tx_en_pos 5
+#define	reg_ep4_tx_en_len 1
+#define	reg_ep4_tx_en_lsb 0
+#define    p_reg_ep5_tx_en			0xDD11
+#define	reg_ep5_tx_en_pos 6
+#define	reg_ep5_tx_en_len 1
+#define	reg_ep5_tx_en_lsb 0
+#define    p_reg_ep4_tx_nak			0xDD13
+#define	reg_ep4_tx_nak_pos 5
+#define	reg_ep4_tx_nak_len 1
+#define	reg_ep4_tx_nak_lsb 0
+#define    p_reg_ep5_tx_nak			0xDD13
+#define	reg_ep5_tx_nak_pos 6
+#define	reg_ep5_tx_nak_len 1
+#define	reg_ep5_tx_nak_lsb 0
+#define    p_reg_ep4_tx_len_7_0			0xDD88
+#define	reg_ep4_tx_len_7_0_pos 0
+#define	reg_ep4_tx_len_7_0_len 8
+#define	reg_ep4_tx_len_7_0_lsb 0
+#define    p_reg_ep4_tx_len_15_8		0xDD89
+#define	reg_ep4_tx_len_15_8_pos 0
+#define	reg_ep4_tx_len_15_8_len 8
+#define	reg_ep4_tx_len_15_8_lsb 8
+#define    p_reg_ep5_tx_len_7_0			0xDD8A
+#define	reg_ep5_tx_len_7_0_pos 0
+#define	reg_ep5_tx_len_7_0_len 8
+#define	reg_ep5_tx_len_7_0_lsb 0
+#define    p_reg_ep5_tx_len_15_8		0xDD8B
+#define	reg_ep5_tx_len_15_8_pos 0
+#define	reg_ep5_tx_len_15_8_len 8
+#define	reg_ep5_tx_len_15_8_lsb 8
+#define    r_reg_aagc_rf_gain			0xCFFF
+#define	reg_aagc_rf_gain_pos 0
+#define	reg_aagc_rf_gain_len 8
+#define	reg_aagc_rf_gain_lsb 0
+#define    r_reg_aagc_if_gain			0xCFFF
+#define	reg_aagc_if_gain_pos 0
+#define	reg_aagc_if_gain_len 8
+#define	reg_aagc_if_gain_lsb 0
+#define    p_reg_top_clkoen			0xCFFF
+#define reg_top_clkoen_pos 0
+#define reg_top_clkoen_len 1
+#define reg_top_clkoen_lsb 0
+#define    p_reg_top_hosta_mpeg_ser_mode	0xCFFF
+#define reg_top_hosta_mpeg_ser_mode_pos 0
+#define reg_top_hosta_mpeg_ser_mode_len 1
+#define reg_top_hosta_mpeg_ser_mode_lsb 0
+#define    p_reg_top_hosta_mpeg_par_mode	0xCFFF
+#define reg_top_hosta_mpeg_par_mode_pos 0
+#define reg_top_hosta_mpeg_par_mode_len 1
+#define reg_top_hosta_mpeg_par_mode_lsb 0
+#define    p_reg_top_hosta_dca_upper		0xCFFF
+#define reg_top_hosta_dca_upper_pos 0
+#define reg_top_hosta_dca_upper_len 1
+#define reg_top_hosta_dca_upper_lsb 0
+#define    p_reg_top_hosta_dca_lower		0xCFFF
+#define reg_top_hosta_dca_lower_pos 0
+#define reg_top_hosta_dca_lower_len 1
+#define reg_top_hosta_dca_lower_lsb 0
+
+/*
+ * IT9135 variable defines
+ */
+/* ----- LL variables ----- */
+#define OVA_BASE			0x4C00	/* omega variable address base */
+#define OVA_LINK_VERSION		(OVA_BASE-4)	/* 4 bytes */
+#define OVA_LINK_VERSION_31_24		(OVA_LINK_VERSION+0)
+#define OVA_LINK_VERSION_23_16		(OVA_LINK_VERSION+1)
+#define OVA_LINK_VERSION_15_8		(OVA_LINK_VERSION+2)
+#define OVA_LINK_VERSION_7_0		(OVA_LINK_VERSION+3)
+#define OVA_SECOND_DEMOD_I2C_ADDR	(OVA_BASE-5)
+#define OVA_EEPROM_CFG			(OVA_BASE-620)	/* 256 bytes */
+#define OVA_IR_TABLE_ADDR		(OVA_BASE-363)	/* 2 bytes pointer point to IR_TABLE */
+#define OVA_IR_TABLE_ADDR_15_18		(OVA_IR_TABLE_ADDR+0)
+#define OVA_IR_TABLE_ADDR_7_0		(OVA_IR_TABLE_ADDR+1)
+
+/* For API variable name, not use in firmware */
+#define second_i2c_address		OVA_SECOND_DEMOD_I2C_ADDR
+#define ir_table_start_15_8		OVA_IR_TABLE_ADDR_15_18
+#define ir_table_start_7_0		OVA_IR_TABLE_ADDR_7_0
+#define prechip_version_7_0		0x384F
+#define chip_version_7_0		0x1222
+#define link_version_31_24		OVA_LINK_VERSION_31_24
+#define link_version_23_16		OVA_LINK_VERSION_23_16
+#define link_version_15_8		OVA_LINK_VERSION_15_8
+#define link_version_7_0		OVA_LINK_VERSION_7_0
+
+/* ----- OFDM variables ----- */
+/* 2k */
+#define var_addr_base			0x418b
+#define log_addr_base			0x418d
+#define log_data_base			0x418f
+#define LowerLocalRetra			0x43bb
+
+#define trigger_ofsm			0x0000
+#define cfoe_NS_2048_coeff1_25_24	0x0001
+#define cfoe_NS_2048_coeff1_23_16	0x0002
+#define cfoe_NS_2048_coeff1_15_8	0x0003
+#define cfoe_NS_2048_coeff1_7_0		0x0004
+#define cfoe_NS_2k_coeff2_24		0x0005
+#define cfoe_NS_2k_coeff2_23_16		0x0006
+#define cfoe_NS_2k_coeff2_15_8		0x0007
+#define cfoe_NS_2k_coeff2_7_0		0x0008
+
+/* 8k */
+#define cfoe_NS_8191_coeff1_25_24	0x0009
+#define cfoe_NS_8191_coeff1_23_16	0x000a
+#define cfoe_NS_8191_coeff1_15_8	0x000b
+#define cfoe_NS_8191_coeff1_7_0		0x000c
+#define cfoe_NS_8192_coeff1_25_24	0x000d
+#define cfoe_NS_8192_coeff1_23_16	0x000e
+#define cfoe_NS_8192_coeff1_15_8	0x000f
+#define cfoe_NS_8192_coeff1_7_0		0x0010
+#define cfoe_NS_8193_coeff1_25_24	0x0011
+#define cfoe_NS_8193_coeff1_23_16	0x0012
+#define cfoe_NS_8193_coeff1_15_8	0x0013
+#define cfoe_NS_8193_coeff1_7_0		0x0014
+
+#define cfoe_NS_8k_coeff2_24		0x0015
+#define cfoe_NS_8k_coeff2_23_16		0x0016
+#define cfoe_NS_8k_coeff2_15_8		0x0017
+#define cfoe_NS_8k_coeff2_7_0		0x0018
+
+/* 4k */
+#define cfoe_NS_4096_coeff1_25_24	0x0019
+#define cfoe_NS_4096_coeff1_23_16	0x001a
+#define cfoe_NS_4096_coeff1_15_8	0x001b
+#define cfoe_NS_4096_coeff1_7_0		0x001c
+#define cfoe_NS_4k_coeff2_24		0x001d
+#define cfoe_NS_4k_coeff2_23_16		0x001e
+#define cfoe_NS_4k_coeff2_15_8		0x001f
+#define cfoe_NS_4k_coeff2_7_0		0x0020
+
+#define bfsfcw_fftindex_ratio_7_0	0x0021
+#define bfsfcw_fftindex_ratio_15_8	0x0022
+#define fftindex_bfsfcw_ratio_7_0	0x0023
+#define fftindex_bfsfcw_ratio_15_8	0x0024
+
+#define crystal_clk_7_0			0x0025
+#define crystal_clk_15_8		0x0026
+#define crystal_clk_23_16		0x0027
+#define crystal_clk_31_24		0x0028
+
+#define bfs_fcw_7_0			0x0029
+#define bfs_fcw_15_8			0x002a
+#define bfs_fcw_22_16			0x002b
+
+#define rsd_abort_packet_cnt_7_0	0x0032
+#define rsd_abort_packet_cnt_15_8	0x0033
+#define rsd_bit_err_cnt_7_0		0x0034
+#define rsd_bit_err_cnt_15_8		0x0035
+#define rsd_bit_err_cnt_23_16		0x0036
+#define r_rsd_packet_unit_7_0		0x0037
+#define r_rsd_packet_unit_15_8		0x0038
+
+#define tpsd_lock			0x003c
+#define mpeg_lock			0x003d
+
+#define Training_Mode			0x0040
+
+#define adcx2				0x0045
+
+#define empty_channel_status		0x0047
+#define signal_quality			0x0049
+
+#define FreBand				0x004b
+#define suspend_flag			0x004c
+
+#define var_p_inband			0x00f7
+
+#define var_pre_lo_freq_7_0		0x011e
+#define var_pre_lo_freq_15_8		0x011f
+#define var_pre_lna_cap_sel		0x0120
+
+#define ofdm_version_31_24		0x4191
+#define ofdm_version_23_16		0x4192
+#define ofdm_version_15_8		0x4193
+#define ofdm_version_7_0		0x4194
+
+/*
+ * Error code
+ */
+enum it9135_err_code {
+	ERROR_NO_ERROR = 0x00000000ul,
+	ERROR_RESET_TIMEOUT = 0x00000001ul,
+	ERROR_WRITE_REG_TIMEOUT = 0x00000002ul,
+	ERROR_WRITE_TUNER_TIMEOUT = 0x00000003ul,
+	ERROR_WRITE_TUNER_FAIL = 0x00000004ul,
+	ERROR_RSD_COUNTER_NOT_READY = 0x00000005ul,
+	ERROR_VTB_COUNTER_NOT_READY = 0x00000006ul,
+	ERROR_FEC_MON_NOT_ENABLED = 0x00000007ul,
+	ERROR_INVALID_DEV_TYPE = 0x00000008ul,
+	ERROR_INVALID_TUNER_TYPE = 0x00000009ul,
+	ERROR_OPEN_FILE_FAIL = 0x0000000Aul,
+	ERROR_WRITEFILE_FAIL = 0x0000000Bul,
+	ERROR_READFILE_FAIL = 0x0000000Cul,
+	ERROR_CREATEFILE_FAIL = 0x0000000Dul,
+	ERROR_MALLOC_FAIL = 0x0000000Eul,
+	ERROR_INVALID_FILE_SIZE = 0x0000000Ful,
+	ERROR_INVALID_READ_SIZE = 0x00000010ul,
+	ERROR_LOAD_FW_DONE_BUT_FAIL = 0x00000011ul,
+	ERROR_NOT_IMPLEMENTED = 0x00000012ul,
+	ERROR_NOT_SUPPORT = 0x00000013ul,
+	ERROR_WRITE_MBX_TUNER_TIMEOUT = 0x00000014ul,
+	ERROR_DIV_MORE_THAN_8_CHIPS = 0x00000015ul,
+	ERROR_DIV_NO_CHIPS = 0x00000016ul,
+	ERROR_SUPER_FRAME_CNT_0 = 0x00000017ul,
+	ERROR_INVALID_FFT_MODE = 0x00000018ul,
+	ERROR_INVALID_CONSTELLATION_MODE = 0x00000019ul,
+	ERROR_RSD_PKT_CNT_0 = 0x0000001Aul,
+	ERROR_FFT_SHIFT_TIMEOUT = 0x0000001Bul,
+	ERROR_WAIT_TPS_TIMEOUT = 0x0000001Cul,
+	ERROR_INVALID_BW = 0x0000001Dul,
+	ERROR_INVALID_BUF_LEN = 0x0000001Eul,
+	ERROR_NULL_PTR = 0x0000001Ful,
+	ERROR_INVALID_AGC_VOLT = 0x00000020ul,
+	ERROR_MT_OPEN_FAIL = 0x00000021ul,
+	ERROR_MT_TUNE_FAIL = 0x00000022ul,
+	ERROR_CMD_NOT_SUPPORTED = 0x00000023ul,
+	ERROR_CE_NOT_READY = 0x00000024ul,
+	ERROR_EMBX_INT_NOT_CLEARED = 0x00000025ul,
+	ERROR_INV_PULLUP_VOLT = 0x00000026ul,
+	ERROR_FREQ_OUT_OF_RANGE = 0x00000027ul,
+	ERROR_INDEX_OUT_OF_RANGE = 0x00000028ul,
+	ERROR_NULL_SETTUNER_PTR = 0x00000029ul,
+	ERROR_NULL_INITSCRIPT_PTR = 0x0000002Aul,
+	ERROR_INVALID_INITSCRIPT_LEN = 0x0000002Bul,
+	ERROR_INVALID_POS = 0x0000002Cul,
+	ERROR_BACK_TO_BOOTCODE_FAIL = 0x0000002Dul,
+	ERROR_GET_BUFFER_VALUE_FAIL = 0x0000002Eul,
+	ERROR_INVALID_REG_VALUE = 0x0000002Ful,
+	ERROR_INVALID_INDEX = 0x00000030ul,
+	ERROR_READ_TUNER_TIMEOUT = 0x00000031ul,
+	ERROR_READ_TUNER_FAIL = 0x00000032ul,
+	ERROR_UNDEFINED_SAW_BW = 0x00000033ul,
+	ERROR_MT_NOT_AVAILABLE = 0x00000034ul,
+	ERROR_NO_SUCH_TABLE = 0x00000035ul,
+	ERROR_WRONG_CHECKSUM = 0x00000036ul,
+	ERROR_INVALID_XTAL_FREQ = 0x00000037ul,
+	ERROR_COUNTER_NOT_AVAILABLE = 0x00000038ul,
+	ERROR_INVALID_DATA_LENGTH = 0x00000039ul,
+	ERROR_BOOT_FAIL = 0x0000003Aul,
+	ERROR_BUFFER_INSUFFICIENT = 0x0000003Bul,
+	ERROR_NOT_READY = 0x0000003Cul,
+	ERROR_DRIVER_INVALID = 0x0000003Dul,
+	ERROR_INTERFACE_FAIL = 0x0000003Eul,
+	ERROR_PID_FILTER_FULL = 0x0000003Ful,
+	ERROR_OPERATION_TIMEOUT = 0x00000040ul,
+	ERROR_LOADFIRMWARE_SKIPPED = 0x00000041ul,
+	ERROR_REBOOT_FAIL = 0x00000042ul,
+	ERROR_PROTOCOL_FORMAT_INVALID = 0x00000043ul,
+	ERROR_ACTIVESYNC_ERROR = 0x00000044ul,
+	ERROR_CE_READWRITEBUS_ERROR = 0x00000045ul,
+	ERROR_CE_NODATA_ERROR = 0x00000046ul,
+	ERROR_NULL_FW_SCRIPT = 0x00000047ul,
+	ERROR_NULL_TUNER_SCRIPT = 0x00000048ul,
+	ERROR_INVALID_CHIP_TYPE = 0x00000049ul,
+	ERROR_TUNER_TYPE_NOT_COMPATIBLE = 0x0000004Aul,
+	/* Error Code of Gemini System */
+	ERROR_INVALID_INDICATOR_TYPE = 0x00000101ul,
+	ERROR_INVALID_SC_NUMBER = 0x00000102ul,
+	ERROR_INVALID_SC_INFO = 0x00000103ul,
+	ERROR_FIGBYPASS_FAIL = 0x00000104ul,
+	/* Error Code of Firmware */
+	ERROR_FIRMWARE_STATUS = 0x01000000ul,
+	/* Error Code of I2C Module */
+	ERROR_I2C_DATA_HIGH_FAIL = 0x02001000ul,
+	ERROR_I2C_CLK_HIGH_FAIL = 0x02002000ul,
+	ERROR_I2C_WRITE_NO_ACK = 0x02003000ul,
+	ERROR_I2C_DATA_LOW_FAIL = 0x02004000ul,
+	/* Error Code of USB Module */
+	ERROR_USB_NULL_HANDLE = 0x03010001ul,
+	ERROR_USB_WRITEFILE_FAIL = 0x03000002ul,
+	ERROR_USB_READFILE_FAIL = 0x03000003ul,
+	ERROR_USB_INVALID_READ_SIZE = 0x03000004ul,
+	ERROR_USB_INVALID_STATUS = 0x03000005ul,
+	ERROR_USB_INVALID_SN = 0x03000006ul,
+	ERROR_USB_INVALID_PKT_SIZE = 0x03000007ul,
+	ERROR_USB_INVALID_HEADER = 0x03000008ul,
+	ERROR_USB_NO_IR_PKT = 0x03000009ul,
+	ERROR_USB_INVALID_IR_PKT = 0x0300000Aul,
+	ERROR_USB_INVALID_DATA_LEN = 0x0300000Bul,
+	ERROR_USB_EP4_READFILE_FAIL = 0x0300000Cul,
+	ERROR_USB_EP$_INVALID_READ_SIZE = 0x0300000Dul,
+	ERROR_USB_BOOT_INVALID_PKT_TYPE = 0x0300000Eul,
+	ERROR_USB_BOOT_BAD_CONFIG_HEADER = 0x0300000Ful,
+	ERROR_USB_BOOT_BAD_CONFIG_SIZE = 0x03000010ul,
+	ERROR_USB_BOOT_BAD_CONFIG_SN = 0x03000011ul,
+	ERROR_USB_BOOT_BAD_CONFIG_SUBTYPE = 0x03000012ul,
+	ERROR_USB_BOOT_BAD_CONFIG_VALUE = 0x03000013ul,
+	ERROR_USB_BOOT_BAD_CONFIG_CHKSUM = 0x03000014ul,
+	ERROR_USB_BOOT_BAD_CONFIRM_HEADER = 0x03000015ul,
+	ERROR_USB_BOOT_BAD_CONFIRM_SIZE = 0x03000016ul,
+	ERROR_USB_BOOT_BAD_CONFIRM_SN = 0x03000017ul,
+	ERROR_USB_BOOT_BAD_CONFIRM_SUBTYPE = 0x03000018ul,
+	ERROR_USB_BOOT_BAD_CONFIRM_VALUE = 0x03000019ul,
+	ERROR_USB_BOOT_BAD_CONFIRM_CHKSUM = 0x03000020ul,
+	ERROR_USB_BOOT_BAD_BOOT_HEADER = 0x03000021ul,
+	ERROR_USB_BOOT_BAD_BOOT_SIZE = 0x03000022ul,
+	ERROR_USB_BOOT_BAD_BOOT_SN = 0x03000023ul,
+	ERROR_USB_BOOT_BAD_BOOT_PATTERN_01 = 0x03000024ul,
+	ERROR_USB_BOOT_BAD_BOOT_PATTERN_10 = 0x03000025ul,
+	ERROR_USB_BOOT_BAD_BOOT_CHKSUM = 0x03000026ul,
+	ERROR_USB_INVALID_BOOT_PKT_TYPE = 0x03000027ul,
+	ERROR_USB_BOOT_BAD_CONFIG_VAlUE = 0x03000028ul,
+	ERROR_USB_COINITIALIZEEX_FAIL = 0x03000029ul,
+	ERROR_USB_COCREATEINSTANCE_FAIL = 0x0300003Aul,
+	ERROR_USB_COCREATCLSEENUMERATOR_FAIL = 0x0300002Bul,
+	ERROR_USB_QUERY_INTERFACE_FAIL = 0x0300002Cul,
+	ERROR_USB_PKSCTRL_NULL = 0x0300002Dul,
+	ERROR_USB_INVALID_REGMODE = 0x0300002Eul,
+	ERROR_USB_INVALID_REG_COUNT = 0x0300002Ful,
+	ERROR_USB_INVALID_HANDLE = 0x03000100ul,
+	ERROR_USB_WRITE_FAIL = 0x03000200ul,
+	ERROR_USB_UNEXPECTED_WRITE_LEN = 0x03000300ul,
+	ERROR_USB_READ_FAIL = 0x03000400ul,
+	/* Error code of Omega */
+	ERROR_TUNER_INIT_FAIL = 0x05000000ul
+};
+
+enum it9135_tuner_id {
+	/* 0x50~0x5f reserved for OMEGA use */
+	IT9135_TUNER_ID = 0x38,
+	IT9135_TUNER_ID_LNA_CONFIG1 = 0x51,
+	IT9135_TUNER_ID_LNA_CONFIG2 = 0x52,
+	/* 0x60~0x6f reserved for OMEGA V2 use */
+	IT9135_TUNER_ID_V2 = 0x60,
+	IT9135_TUNER_ID_V2_LNA_CONFIG1 = 0x61,
+	IT9135_TUNER_ID_V2_LNA_CONFIG2 = 0x62
+};
+
+enum it9135_tuner_lna {
+	OMEGA_NORMAL = 0x00,
+	OMEGA_LNA_CONFIG1 = 0x01,
+	OMEGA_LNA_CONFIG2 = 0x02,
+};
+
+struct it9135_val_set {
+	unsigned long address;	/* The address of target register */
+	unsigned char value;	/* The value of target register   */
+};
+
+struct it9135_tuner_desc {
+	struct it9135_val_set *scripts;
+	unsigned short *script_sets;
+	unsigned short id;
+};
+
+/*
+ * The type defination of clock table.
+ */
+struct it9135_freq_clk {
+	unsigned long crystal_Freq;	/* The frequency of crystal. */
+	unsigned long adc_freq;	/* The frequency of ADC.     */
+};
+
+#define IT9135_MAX_PKT_SIZE	255
+
+/* Define commands */
+enum it9135_cmd {
+	CMD_REG_DEMOD_READ = 0x0000,
+	CMD_REG_DEMOD_WRITE = 0x0001,
+	CMD_REG_EEPROM_READ = 0x0004,
+	CMD_REG_EEPROM_WRITE = 0x0005,
+	CMD_IR_GET = 0x0018,
+	CMD_FW_DOWNLOAD = 0x0021,
+	CMD_QUERYINFO = 0x0022,
+	CMD_BOOT = 0x0023,
+	CMD_REBOOT = 0x0023,
+	CMD_FW_DOWNLOAD_BEGIN = 0x0024,
+	CMD_FW_DOWNLOAD_END = 0x0025,
+	CMD_SCATTER_WRITE = 0x0029,
+	CMD_GENERIC_READ = 0x002A,
+	CMD_GENERIC_WRITE = 0x002B
+};
+
+#define it9135_build_command(command, processor, chip) \
+		(command + (unsigned short) (processor << 12) + (unsigned short) (chip << 12))
+
+/*
+ * The type defination of channel Statistic.
+ */
+struct it9135_ch_statistic {
+	unsigned short abort_cnt;
+	unsigned long post_vitbit_cnt;
+	unsigned long post_vit_err_cnt;
+};
+
+/*
+ * The type defination of Segment
+ */
+struct it9135_segment {
+	unsigned char type;	/* 0:Firmware download 1:Rom copy 2:Direct command */
+	unsigned long length;
+};
+
+/*
+ * The type defination of TransmissionMode.
+ */
+enum it9135_transmission_modes {
+	TransmissionMode_2K = 0,	/* OFDM frame consists of 2048 different carriers (2K FFT mode) */
+	TransmissionMode_8K,	/* OFDM frame consists of 8192 different carriers (8K FFT mode) */
+	TransmissionMode_4K	/* OFDM frame consists of 4096 different carriers (4K FFT mode) */
+};
+
+/*
+ * The type defination of Priority.
+ */
+enum it9135_priority {
+	PRIORITY_HIGH = 0,	/* DVB-T and DVB-H - identifies high-priority stream */
+	PRIORITY_LOW		/* DVB-T and DVB-H - identifies low-priority stream  */
+};
+
+/*
+ * The type defination of CodeRate.
+ */
+enum it9135_code_rate {
+	CodeRate_1_OVER_2 = 0,	/* Signal uses FEC coding ratio of 1/2 */
+	CodeRate_2_OVER_3,	/* Signal uses FEC coding ratio of 2/3 */
+	CodeRate_3_OVER_4,	/* Signal uses FEC coding ratio of 3/4 */
+	CodeRate_5_OVER_6,	/* Signal uses FEC coding ratio of 5/6 */
+	CodeRate_7_OVER_8,	/* Signal uses FEC coding ratio of 7/8 */
+	CodeRate_NONE		/* None, NXT doesn't have this one     */
+};
+
+/*
+ * TPS Hierarchy and Alpha value.
+ */
+enum it9135_hierarchy {
+	Hierarchy_NONE = 0,	/* Signal is non-hierarchical        */
+	Hierarchy_ALPHA_1,	/* Signalling format uses alpha of 1 */
+	Hierarchy_ALPHA_2,	/* Signalling format uses alpha of 2 */
+	Hierarchy_ALPHA_4	/* Signalling format uses alpha of 4 */
+};
+
+/*
+ * The type defination of Multiplier.
+ */
+enum it9135_multiplier {
+	Multiplier_1X = 0,
+	Multiplier_2X
+};
+
+/*
+ * The type defination of StreamType.
+ */
+enum it9135_stream_type {
+	STREAM_TYPE_NONE = 0,	/* Invalid (Null) StreamType                */
+	STREAM_TYPE_DVBT_DATAGRAM = 3,	/* DVB-T mode, store data in device buffer  */
+	STREAM_TYPE_DVBT_PARALLEL,	/* DVB-T mode, output via paralle interface */
+	STREAM_TYPE_DVBT_SERIAL,	/* DVB-T mode, output via serial interface  */
+};
+
+/*
+ * The type defination of Architecture.
+ */
+enum it9135_architecture {
+	ARCHITECTURE_NONE = 0,	/* Inavalid (Null) Architecture.                                    */
+	ARCHITECTURE_DCA,	/* Diversity combine architecture. Only valid when chip number > 1. */
+	ARCHITECTURE_PIP	/* Picture in picture. Only valid when chip number > 1.             */
+};
+
+/*
+ * The type defination of processor.
+ */
+enum it9135_processor {
+	PROCESSOR_LINK = 0,
+	PROCESSOR_OFDM = 8
+};
+
+/*
+ * The type defination of Constellation.
+ */
+enum Constellation {
+	CONSTELLATION_QPSK = 0,	/* Signal uses QPSK constellation  */
+	CONSTELLATION_16QAM,	/* Signal uses 16QAM constellation */
+	CONSTELLATION_64QAM	/* Signal uses 64QAM constellation */
+};
+
+/*
+ * The defination of ChannelModulation.
+ */
+struct it9135_ch_modulation {
+	unsigned long frequency;	/* Channel frequency in KHz.                                */
+	unsigned char trans_mode;	/* Number of carriers used for OFDM signal                  */
+	unsigned char constellation;	/* Constellation scheme (FFT mode) in use           */
+	unsigned char interval;	/* Fraction of symbol length used as guard (Guard Interval) */
+	unsigned char priority;	/* The priority of stream                                   */
+	unsigned char h_code_rate;	/* FEC coding ratio of high-priority stream                 */
+	unsigned char l_code_rate;	/* FEC coding ratio of low-priority stream                  */
+	unsigned char hierarchy;	/* Hierarchy levels of OFDM signal                          */
+	unsigned char bandwidth;
+};
+
+/*
+ * The type defination of Statistic.
+ */
+struct it9135_statistic {
+	int presented;		/* Signal is presented.                           */
+	int locked;		/* Signal is locked.                              */
+	unsigned char quality;	/* Signal quality, from 0 (poor) to 100 (good).   */
+	unsigned char strength;	/* Signal strength from 0 (weak) to 100 (strong). */
+};
+
+/*
+ * The type defination of PidTable
+ */
+struct it9135_pid_tab {
+	unsigned short pid[32];
+};
+
+struct it9135_pid_info {
+	struct it9135_pid_tab pid_tab[2];
+	unsigned char pid_cnt;
+	int pid_init;
+};
+
+/*
+ * The data structure of IT9135
+ */
+struct it9135_data {
+	/* Basic structure */
+	void *driver;
+
+/* Bus types */
+#define IT9135_BUS_USB20	2
+#define IT9135_BUS_USB11           5
+	unsigned short busId;
+
+	unsigned short tuner_id;
+	struct it9135_tuner_desc tuner_desc;
+
+	unsigned char *fw_codes;
+	struct it9135_segment *fw_segs;	/* FW seqments */
+	unsigned char fw_parts;	/* FW partitions */
+	unsigned short *script_sets;
+	struct it9135_val_set *scripts;
+	unsigned short *tuner_script_sets;
+	struct it9135_val_set *tuner_scripts;
+
+	const struct firmware *it9135_fw;
+	unsigned char chip_ver;
+	unsigned long chip_type;
+	unsigned char chip_num;
+	unsigned char streamType;
+	unsigned char architecture;
+	unsigned long crystal_Freq;
+	unsigned long adc_freq;
+	unsigned short bandwidth[2];
+	unsigned long frequency[2];
+	unsigned long fcw;
+	struct it9135_statistic statistic[2];
+	struct it9135_ch_statistic ch_statistic[2];	/* releaseExternalRemove */
+	unsigned char host_if[2];	/* Host Interface */
+	unsigned char cmd_seq;	/* command sequence */
+	struct it9135_pid_info pid_info;
+	unsigned char pre_sqi;
+
+	int booted;
+	int inited;
+
+	unsigned char clock_mode;
+	unsigned int fxtal_khz;
+	unsigned int fdiv;
+
+	/* for linux kernel driver */
+	struct it9135_val_set *tuner_script_normal;
+	unsigned short tuner_script_sets_normal;
+	struct it9135_val_set *tuner_script_lna1;
+	unsigned short tuner_script_sets_lna1;
+	struct it9135_val_set *tuner_script_lna2;
+	unsigned short tuner_script_sets_lna2;
+};
+
+#define REG_MASK(mask, pos, len)		(mask[len-1] << pos)
+#define REG_CLEAR(mask, temp, pos, len)		(temp & (~REG_MASK(mask, pos, len)))
+#define REG_CREATE(mask, val, temp, pos, len)	((val << pos) | (REG_CLEAR(mask, temp, pos, len)))
+#define REG_GET(mask, value, pos, len)		((value & REG_MASK(mask, pos, len)) >> pos)
+#define LOWBYTE(w)				((unsigned char)((w) & 0xff))
+#define HIGHBYTE(w)				((unsigned char)((w >> 8) & 0xff))
+
+struct it9135_coeff_param {
+	unsigned long adc_freq;
+	unsigned short bandwidth;
+	unsigned long coeff1_2048Nu;
+	unsigned long coeff1_4096Nu;
+	unsigned long coeff1_8191Nu;
+	unsigned long coeff1_8192Nu;
+	unsigned long coeff1_8193Nu;
+	unsigned long coeff2_2k;
+	unsigned long coeff2_4k;
+	unsigned long coeff2_8k;
+	unsigned short bfsfcw_fftindex_ratio;
+	unsigned short fftindex_bfsfcw_ratio;
+};
+
+/*
+ * Write one unsigned char (8 bits) to a specific register in IT9135.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param processor: The processor of specified register. Because each chip
+ *        has two processor so user have to specify the processor. The
+ *        possible values are PROCESSOR_LINK and PROCESSOR_OFDM.
+ * @param reg_addr: the address of the register to be written.
+ * @param value: the value to be written.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_write_reg(struct it9135_data *data, unsigned char chip,
+			       unsigned char processor, unsigned long reg_addr,
+			       unsigned char value);
+
+/*
+ * Write a sequence of unsigned chars to the contiguous registers in IT9135.
+ * The maximum burst size is restricted by the capacity of bus. If bus
+ * could transfer N unsigned chars in one cycle, then the maximum value of
+ * post_err_cnt would be N - 5.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param processor: The processor of specified register. Because each chip
+ *        has two processor so user have to specify the processor. The
+ *        possible values are PROCESSOR_LINK and PROCESSOR_OFDM.
+ * @param reg_addr: the start address of the registers to be written.
+ * @param post_err_cnt: the number of registers to be written.
+ * @param buffer: a unsigned char array which is used to store values to be written.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_write_regs(struct it9135_data *data, unsigned char chip,
+				unsigned char processor, unsigned long reg_addr,
+				unsigned long w_buff_len,
+				unsigned char *w_buff);
+
+/*
+ * Write a sequence of unsigned chars to the contiguous registers in slave device
+ * through specified interface (1, 2, 3).
+ * The maximum burst size is restricted by the capacity of bus. If bus
+ * could transfer N unsigned chars in one cycle, then the maximum value of
+ * post_err_cnt would be N - 6 (one more unsigned char to specify tuner address).
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param interfaceIndex: the index of interface. The possible values are 1~3.
+ * @param slaveAddress: the I2c address of slave device.
+ * @param post_err_cnt: the number of registers to be read.
+ * @param buffer: a unsigned char array which is used to store values to be read.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_write_gen_regs(struct it9135_data *data,
+				    unsigned char chip,
+				    unsigned char interfaceIndex,
+				    unsigned char slaveAddress,
+				    unsigned char post_err_cnt,
+				    unsigned char *buffer);
+
+/*
+ * Write a sequence of unsigned chars to the contiguous cells in the EEPROM.
+ * The maximum burst size is restricted by the capacity of bus. If bus
+ * could transfer N unsigned chars in one cycle, then the maximum value of
+ * post_err_cnt would be N - 5 (firmware will detect EEPROM address).
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param reg_addr: the start address of the cells to be written.
+ * @param post_err_cnt: the number of cells to be written.
+ * @param buffer: a unsigned char array which is used to store values to be written.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_write_ee_vals(struct it9135_data *data, unsigned char chip,
+				   unsigned short reg_addr,
+				   unsigned char w_buff_len,
+				   unsigned char *w_buff);
+
+/*
+ * Modify bits in the specific register.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param processor: The processor of specified register. Because each chip
+ *        has two processor so user have to specify the processor. The
+ *        possible values are PROCESSOR_LINK and PROCESSOR_OFDM.
+ * @param reg_addr: the address of the register to be written.
+ * @param position: the start position of bits to be modified (0 means the
+ *        LSB of the specifyed register).
+ * @param length: the length of bits.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_write_reg_bits(struct it9135_data *data,
+				    unsigned char chip, unsigned char processor,
+				    unsigned long reg_addr,
+				    unsigned char position,
+				    unsigned char length, unsigned char value);
+
+/*
+ * Read one unsigned char (8 bits) from a specific register in IT9135.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param processor: The processor of specified register. Because each chip
+ *        has two processor so user have to specify the processor. The
+ *        possible values are PROCESSOR_LINK and PROCESSOR_OFDM.
+ * @param reg_addr: the address of the register to be read.
+ * @param value: the pointer used to store the value read from IT9135 register.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_read_reg(struct it9135_data *data, unsigned char chip,
+			      unsigned char processor, unsigned long reg_addr,
+			      unsigned char *value);
+
+/*
+ * Read a sequence of unsigned chars from the contiguous registers in IT9135.
+ * The maximum burst size is restricted by the capacity of bus. If bus
+ * could transfer N unsigned chars in one cycle, then the maximum value of
+ * post_err_cnt would be N - 5.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param processor: The processor of specified register. Because each chip
+ *        has two processor so user have to specify the processor. The
+ *        possible values are PROCESSOR_LINK and PROCESSOR_OFDM.
+ * @param reg_addr: the address of the register to be read.
+ * @param post_err_cnt: the number of registers to be read.
+ * @param buffer: a unsigned char array which is used to store values to be read.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_read_regs(struct it9135_data *data, unsigned char chip,
+			       unsigned char processor, unsigned long reg_addr,
+			       unsigned long r_buff_len, unsigned char *r_buff);
+
+/*
+ * Read a sequence of unsigned chars from the contiguous registers in slave device
+ * through specified interface (1, 2, 3).
+ * The maximum burst size is restricted by the capacity of bus. If bus
+ * could transfer N unsigned chars in one cycle, then the maximum value of
+ * post_err_cnt would be N - 6 (one more unsigned char to specify tuner address).
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param interfaceIndex: the index of interface. The possible values are 1~3.
+ * @param slaveAddress: the I2c address of slave device.
+ * @param post_err_cnt: the number of registers to be read.
+ * @param buffer: a unsigned char array which is used to store values to be read.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_read_gen_regs(struct it9135_data *data,
+				   unsigned char chip,
+				   unsigned char interfaceIndex,
+				   unsigned char slaveAddress,
+				   unsigned char post_err_cnt,
+				   unsigned char *buffer);
+
+/*
+ * Read a sequence of unsigned chars from the contiguous cells in the EEPROM.
+ * The maximum burst size is restricted by the capacity of bus. If bus
+ * could transfer N unsigned chars in one cycle, then the maximum value of
+ * post_err_cnt would be N - 5 (firmware will detect EEPROM address).
+ *
+ * @param struct it9135_data the handle of IT9135.
+ * @param chip The index of IT9135. The possible values are 0~7.
+ * @param reg_addr the start address of the cells to be read.
+ * @param registerAddressLength the valid unsigned chars of reg_addr.
+ * @param post_err_cnt the number of cells to be read.
+ * @param buffer a unsigned char array which is used to store values to be read.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_read_ee_vals(struct it9135_data *data, unsigned char chip,
+				  unsigned short reg_addr,
+				  unsigned char r_buff_len,
+				  unsigned char *r_buff);
+
+/*
+ * Read bits of the specified register.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param processor: The processor of specified register. Because each chip
+ *        has two processor so user have to specify the processor. The
+ *        possible values are PROCESSOR_LINK and PROCESSOR_OFDM.
+ * @param reg_addr: the address of the register to be read.
+ * @param position: the start position of bits to be read (0 means the
+ *        LSB of the specifyed register).
+ * @param length: the length of bits.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_read_reg_bits(struct it9135_data *data,
+				   unsigned char chip, unsigned char processor,
+				   unsigned long reg_addr,
+				   unsigned char position, unsigned char length,
+				   unsigned char *value);
+
+/*
+ * Get the version of firmware.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param version: the version of firmware.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_get_fw_ver(struct it9135_data *data,
+				unsigned char processor,
+				unsigned long *version);
+
+/*
+ * Get siganl strength Indication.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ *        NOTE: When the architecture is set to ARCHITECTURE_DCA
+ *        this parameter is regard as don't care.
+ * @param strength: The value of signal strength that calculations of "score mapping" from the signal strength (dBm) to the "0-100" scoring.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_get_strength(struct it9135_data *data, unsigned char chip,
+				  unsigned char *strength);
+
+/*
+ * Get signal strength in dbm
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param rfpullUpVolt_X10: the pullup voltag of RF multiply 10.
+ * @param ifpullUpVolt_X10: the pullup voltag of IF multiply 10.
+ * @param strengthDbm: The value of signal strength in DBm.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_get_strength_dbm(struct it9135_data *data,
+				      unsigned char chip, long *strength_dbm);
+
+/*
+ * Load the IR table for USB device.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param tab_len: The length of IR table.
+ * @param table: The content of IR table.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_load_ir_tab(struct it9135_data *data,
+				 unsigned short tab_len, unsigned char *table);
+
+/*
+ * First, download firmware from host to IT9135. Actually, firmware is
+ * put in firmware.h as a part of source code. Therefore, in order to
+ * update firmware the host have to re-compile the source code.
+ * Second, setting all parameters which will be need at the beginning.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip_num: The total number of IT9135s.
+ * @param saw_band: SAW filter bandwidth in MHz. The possible values
+ *        are 6000, 7000, and 8000 (KHz).
+ * @param streamType: The format of output stream.
+ * @param architecture: the architecture of IT9135.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_dev_init(struct it9135_data *data, unsigned char chip_num,
+			      unsigned short saw_band, unsigned char streamType,
+			      unsigned char architecture);
+
+/*
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_tps_locked(struct it9135_data *data, unsigned char chip,
+				int *locked);
+
+/*
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_mp2_locked(struct it9135_data *data, unsigned char chip,
+				int *locked);
+
+/*
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ *        NOTE: When the architecture is set to ARCHITECTURE_DCA
+ *        this parameter is regard as don't care.
+ * @param locked: the result of frequency tuning. 1 if there is
+ *        IT9135 can lock signal, 0 otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_freq_locked(struct it9135_data *data, unsigned char chip,
+				 int *locked);
+
+/*
+ * Get channel modulation related information.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param ch_modul: The modulation of channel.
+ * @return ERROR_NO_ERROR: successful, other non-zero error code otherwise.
+ */
+unsigned long it9135_get_ch_modulation(struct it9135_data *data,
+				       unsigned char chip,
+				       struct it9135_ch_modulation *ch_modul);
+
+/*
+ * Specify the bandwidth of channel and tune the channel to the specific
+ * frequency. Afterwards, host could use output parameter dvbH to determine
+ * if there is a DVB-H signal.
+ * In DVB-T mode, after calling this function the output parameter dvbH
+ * should return 0 and host could use output parameter "locked" to check
+ * if the channel has correct TS output.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ *        NOTE: When the architecture is set to ARCHITECTURE_DCA
+ *        this parameter is regard as don't care.
+ * @param bandwidth: The channel bandwidth.
+ *        DVB-T: 5000, 6000, 7000, and 8000 (KHz).
+ * @param frequency: the channel frequency in KHz.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_acquire_ch(struct it9135_data *data, unsigned char chip,
+				unsigned short bandwidth,
+				unsigned long frequency);
+
+/*
+ * Set the output stream type of chip. Because the device could output in
+ * many stream type, therefore host have to choose one type before receive data.
+ *
+ * Note: Please refer to the example of Standard_acquireChannel when host want
+ *       to detect the available channels.
+ * Note: After host know all the available channels, and want to change to
+ *       specific channel, host have to choose output mode before receive
+ *       data. Please refer the example of it9135_set_stream_type.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param streamType: the possible values are
+ *        DVB-T:    STREAM_TYPE_DVBT_DATAGRAM
+ *                  STREAM_TYPE_DVBT_PARALLEL
+ *                  STREAM_TYPE_DVBT_SERIAL
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_set_stream_type(struct it9135_data *data,
+				     unsigned char streamType);
+
+/*
+ * Set the architecture of chip. When two of our device are using, they could
+ * be operated in Diversity Combine Architecture (DCA) or (PIP). Therefore,
+ * host could decide which mode to be operated.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param architecture: the possible values are
+ *        ARCHITECTURE_DCA
+ *        ARCHITECTURE_PIP
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_set_arch(struct it9135_data *data,
+			      unsigned char architecture);
+
+/*
+ * Get the statistic values of IT9135, it includes Pre-Viterbi BER,
+ * Post-Viterbi BER, Abort Count, Signal Presented Flag, Signal Locked Flag,
+ * Signal Quality, Signal Strength, Delta-T for DVB-H time slicing.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param statistic: the structure that store all statistic values.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_get_statistic(struct it9135_data *data, unsigned char chip,
+				   struct it9135_statistic *statistic);
+
+/*
+ * @param it9135_data: the handle of IT9135.
+ * @param code: the value of IR raw code, the size should be 4 or 6,
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_get_ir_code(struct it9135_data *data, unsigned long *code);
+
+/*
+ * Return to boot code
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_dev_reboot(struct it9135_data *data);
+
+/*
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param contorl: 1: Power up, 0: Power down;
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_ctrl_pw_saving(struct it9135_data *data,
+				    unsigned char chip, unsigned char control);
+
+/*
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param contorl: 1: Power up, 0: Power down;
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_ctrl_tuner_leakage(struct it9135_data *data,
+					unsigned char chip,
+					unsigned char control);
+
+/*
+ * @param it9135_data: the handle of IT9135.
+ * @param contorl: 1: Power up, 0: Power down;
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_ctrl_tuner_pw_saving(struct it9135_data *data,
+					  unsigned char chip,
+					  unsigned char control);
+
+/*
+ * Control PID fileter
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param contorl: 0: Disable, 1: Enable.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_ctrl_pid_filter(struct it9135_data *data,
+				     unsigned char chip, unsigned char control);
+
+/*
+ * Reset PID filter.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_reset_pid_filter(struct it9135_data *data,
+				      unsigned char chip);
+
+/*
+ * Add PID to PID filter.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param pid: the PID that will be add to PID filter.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_add_pid_filter(struct it9135_data *data,
+				    unsigned char chip, unsigned char index,
+				    unsigned short pid);
+
+/*
+ * get SNR .
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param snr (db).
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_get_snr(struct it9135_data *data, unsigned char chip,
+			     unsigned char *snr);
+
+/*
+ * get SNR data .
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param snr_value (hex).
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_get_snr_val(struct it9135_data *IT9135, unsigned char chip,
+				 unsigned long *snr_value);
+
+/*
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param multiplier: ADC frequency multiplier;
+ * @return ERROR_NO_ERROR: successful, other non-zero error code otherwise.
+ * @example <pre>
+ * </pre>
+ */
+unsigned long it9135_set_multiplier(struct it9135_data *data,
+				    unsigned char multiplier);
+
+/*
+ * Reset PID filter.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_reset_pid(struct it9135_data *data, unsigned char chip);
+
+/*
+ * Remove PID from PID filter by index.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param index: the index of PID filter.
+ * @param pid: the PID that will be remove from PID filter.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_remove_pid_at(struct it9135_data *data, unsigned char chip,
+				   unsigned char index, unsigned short pid);
+
+/*
+ * Get the statistic values of IT9135, it includes Pre-Viterbi BER,
+ * Post-Viterbi BER, Abort Count, Signal Presented Flag, Signal Locked Flag,
+ * Signal Quality, Signal Strength, Delta-T for DVB-H time slicing.
+ *
+ * @param struct it9135_data the handle of IT9135.
+ * @param chip The index of IT9135. The possible values are 0~7.
+ * @param statistic the structure that store all statistic values.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_get_ch_statistic(struct it9135_data *data,
+				      unsigned char chip,
+				      struct it9135_ch_statistic *ch_statistic);
+
+/*
+ * Set control bus and tuner.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param busId: The ID of bus.
+ * @param tuner_id: The ID of tuner.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_set_bus_tuner(struct it9135_data *data,
+				   unsigned short busId,
+				   unsigned short tuner_id);
+
+/*
+ * Add PID to PID filter.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param pid: the PID that will be add to PID filter.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_add_pid(struct it9135_data *data, unsigned char chip,
+			     unsigned short pid);
+
+/*
+ * Add PID to PID filter by index.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param index: the index of PID filter.
+ * @param pid: the PID that will be add to PID filter.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_add_pid_at(struct it9135_data *data, unsigned char chip,
+				unsigned char index, unsigned short pid);
+
+/*
+ * Remove PID from PID filter.
+ *
+ * @param it9135_data: the handle of IT9135.
+ * @param chip: The index of IT9135. The possible values are 0~7.
+ * @param pid: the PID that will be remove from PID filter.
+ * @return ERROR_NO_ERROR: successful, non-zero error code otherwise.
+ */
+unsigned long it9135_remove_pid(struct it9135_data *data, unsigned char chip,
+				unsigned short pid);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/it9135.c b/drivers/media/dvb/dvb-usb/it9135.c
new file mode 100644
index 0000000..7fa21c7
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/it9135.c
@@ -0,0 +1,2492 @@
+/*
+ * DVB USB Linux driver for IT9135 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2011 ITE Technologies, INC.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ */
+
+#include "it9135.h"
+
+int dvb_usb_it9135_debug;
+module_param_named(debug, dvb_usb_it9135_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+		 "set debugging level.(func=1,info=2,warning=4)"
+		 DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct dvb_usb_device_properties it9135_properties[];
+
+static unsigned long it9135_drv_nim_reset(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	/* Set AF0350 GPIOH1 to 0 to reset AF0351 */
+	error =
+	    it9135_write_reg_bits(&dev->data, 0,
+				  PROCESSOR_LINK, p_reg_top_gpioh1_en,
+				  reg_top_gpioh1_en_pos, reg_top_gpioh1_en_len,
+				  1);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0, PROCESSOR_LINK,
+				  p_reg_top_gpioh1_on, reg_top_gpioh1_on_pos,
+				  reg_top_gpioh1_on_len, 1);
+
+	error =
+	    it9135_write_reg_bits(&dev->data, 0,
+				  PROCESSOR_LINK, p_reg_top_gpioh1_o,
+				  reg_top_gpioh1_o_pos, reg_top_gpioh1_o_len,
+				  1);
+	mdelay(50);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0,
+				  PROCESSOR_LINK, p_reg_top_gpioh1_o,
+				  reg_top_gpioh1_o_pos, reg_top_gpioh1_o_len,
+				  0);
+	mdelay(50);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0,
+				  PROCESSOR_LINK, p_reg_top_gpioh1_o,
+				  reg_top_gpioh1_o_pos, reg_top_gpioh1_o_len,
+				  1);
+
+	return error;
+}
+
+/* Write NIMSuspend Register */
+static unsigned long it9135_drv_init_nim_suspend_regs(struct it9135_dev_ctx
+						      *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	error =
+	    it9135_write_reg_bits(&dev->data, 0,
+				  PROCESSOR_LINK, p_reg_top_gpioh5_en,
+				  reg_top_gpioh5_en_pos, reg_top_gpioh5_en_len,
+				  1);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0, PROCESSOR_LINK,
+				  p_reg_top_gpioh5_on, reg_top_gpioh5_on_pos,
+				  reg_top_gpioh5_on_len, 1);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0, PROCESSOR_LINK,
+				  p_reg_top_gpioh5_o, reg_top_gpioh5_o_pos,
+				  reg_top_gpioh5_o_len, 0);
+	mdelay(10);
+	error =
+	    it9135_write_reg_bits(&dev->data, 1, PROCESSOR_LINK,
+				  p_reg_top_pwrdw, reg_top_pwrdw_pos,
+				  reg_top_pwrdw_len, 1);
+	error =
+	    it9135_write_reg_bits(&dev->data, 1, PROCESSOR_LINK,
+				  p_reg_top_pwrdw_hwen, reg_top_pwrdw_hwen_pos,
+				  reg_top_pwrdw_hwen_len, 1);
+
+	return error;
+}
+
+/* Get OFDM /LINK Firmware version */
+static unsigned long it9135_drv_get_firmware_version_from_file(struct
+							       it9135_dev_ctx
+							       *dev,
+							       unsigned char
+							       processor,
+							       unsigned long
+							       *version)
+{
+	if (processor == PROCESSOR_OFDM) {
+		*version = dev->ofdm_ver;
+	} else {		/* LINK */
+		*version = dev->link_ver;
+	}
+
+	return *version;
+}
+
+static unsigned long it9135_drv_disable_gpio_pins(struct it9135_dev_ctx *dev)
+{
+	/* For strapping, gpioh1/gpioh5/ghioh7 have been program, just IT9135; */
+	unsigned long error = ERROR_NO_ERROR;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	error =
+	    it9135_write_reg_bits(&dev->data, 0,
+				  PROCESSOR_LINK, p_reg_top_gpioh1_en,
+				  reg_top_gpioh1_en_pos, reg_top_gpioh1_en_len,
+				  0);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0, PROCESSOR_LINK,
+				  p_reg_top_gpioh1_on, reg_top_gpioh1_on_pos,
+				  reg_top_gpioh1_on_len, 0);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0, PROCESSOR_LINK,
+				  p_reg_top_gpioh5_en, reg_top_gpioh5_en_pos,
+				  reg_top_gpioh5_en_len, 0);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0, PROCESSOR_LINK,
+				  p_reg_top_gpioh5_on, reg_top_gpioh5_on_pos,
+				  reg_top_gpioh5_on_len, 0);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0, PROCESSOR_LINK,
+				  p_reg_top_gpioh7_en, reg_top_gpioh7_en_pos,
+				  reg_top_gpioh7_en_len, 0);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0, PROCESSOR_LINK,
+				  p_reg_top_gpioh7_on, reg_top_gpioh7_on_pos,
+				  reg_top_gpioh7_on_len, 0);
+
+	if (error)
+		err("it9135_drv_disable_gpio_pins failed !!!\n");
+
+	return error;
+}
+
+/* Device initialize or not */
+static unsigned long it9135_drv_initialize(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long file_ver, cmd_ver = 0;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	if (dev->data.booted) {
+		error =
+		    it9135_drv_get_firmware_version_from_file(dev,
+							      PROCESSOR_OFDM,
+							      &file_ver);
+
+		/* Use "Command_QUERYINFO" to get fw version */
+		error = it9135_get_fw_ver(&dev->data, PROCESSOR_OFDM, &cmd_ver);
+		if (error)
+			err("it9135_drv_initialize : it9135_get_fw_ver : error = 0x%08lx", (long unsigned int)error);
+
+		if (cmd_ver != file_ver) {
+			deb_info
+			    ("Reboot: Outside Fw = 0x%lX, Inside Fw = 0x%lX",
+			     (long unsigned int)file_ver,
+			     (long unsigned int)cmd_ver);
+
+			/* Patch for 2 chips reboot; */
+			if (dev->data.chip_num == 2)
+				it9135_drv_disable_gpio_pins(dev);
+
+			error = it9135_dev_reboot(&dev->data);
+			dev->boot_code = 1;
+			if (error) {
+				err("it9135_dev_reboot : error = 0x%08lx",
+				    (long unsigned int)error);
+				return error;
+			} else {
+				return ERROR_NOT_READY;
+			}
+		} else {
+			deb_info("Fw version is the same!\n");
+			error = ERROR_NO_ERROR;
+		}
+	}
+
+	error =
+	    it9135_dev_init(&dev->data, dev->data.chip_num, 8000,
+			    dev->stream_type, dev->architecture);
+	if (error)
+		err("it9135_drv_initialize fail : 0x%08lx",
+		    (long unsigned int)error);
+	else
+		deb_info("it9135_drv_initialize Ok!!");
+
+	it9135_get_fw_ver(&dev->data, PROCESSOR_OFDM, &cmd_ver);
+	deb_info("FwVer OFDM = 0x%lX,", (long unsigned int)cmd_ver);
+	it9135_get_fw_ver(&dev->data, PROCESSOR_LINK, &cmd_ver);
+	deb_info("FwVer LINK = 0x%lX\n", (long unsigned int)cmd_ver);
+
+	return error;
+}
+
+static unsigned long it9135_nim_reset_seq(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char bootbuffer[6];
+
+	/* checksum = 0xFEDC */
+	bootbuffer[0] = 0x05;
+	bootbuffer[1] = 0x00;
+	bootbuffer[2] = 0x23;
+	bootbuffer[3] = 0x01;
+	bootbuffer[4] = 0xFE;
+	bootbuffer[5] = 0xDC;
+
+	/* GPIOH5 init */
+	error =
+	    it9135_write_reg_bits(&dev->data, 0,
+				  PROCESSOR_LINK, p_reg_top_gpioh5_en,
+				  reg_top_gpioh5_en_pos, reg_top_gpioh5_en_len,
+				  0);
+	error =
+	    it9135_write_reg_bits(&dev->data, 0, PROCESSOR_LINK,
+				  p_reg_top_gpioh5_on, reg_top_gpioh5_on_pos,
+				  reg_top_gpioh5_on_len, 0);
+
+	error = it9135_drv_nim_reset(dev);
+	error = it9135_drv_init_nim_suspend_regs(dev);
+	error =
+	    it9135_write_gen_regs(&dev->data, 0, 0x01, 0x3a, 0x06, bootbuffer);
+	error =
+	    it9135_read_gen_regs(&dev->data, 0, 0x01, 0x3a, 0x05, bootbuffer);
+
+	mdelay(50);		/* Delay for Fw boot */
+
+	/* Demod & Tuner init */
+	error = it9135_drv_initialize(dev);
+
+	return error;
+}
+
+/************** DRV_ *************/
+static unsigned long it9135_drv_ir_table_download(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	struct file *filp;
+	unsigned char buff[512];
+	int file_sz;
+	mm_segment_t oldfs;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	filp = filp_open("/lib/firmware/af35irtbl.bin", O_RDWR, 0644);
+
+	if (IS_ERR(filp)) {
+		deb_warning("LoadIrTable : Can't open file\n");
+		goto exit;
+	}
+
+	if ((filp->f_op) == NULL) {
+		deb_warning("LoadIrTable : File Operation Method Error!!\n");
+		goto exit;
+	}
+
+	filp->f_pos = 0x00;
+	file_sz = filp->f_op->read(filp, buff, sizeof(buff), &filp->f_pos);
+
+	error =
+	    it9135_load_ir_tab((struct it9135_data *)&dev->data,
+			       (unsigned short)file_sz, buff);
+	if (error) {
+		err("it9135_load_ir_tab fail");
+		goto exit;
+	}
+
+	filp_close(filp, NULL);
+	set_fs(oldfs);
+
+	return error;
+
+exit:
+	deb_warning("LoadIrTable fail!\n");
+	return error;
+}
+
+/* Set tuner Frequency and BandWidth */
+static unsigned long it9135_drv_set_freq_bw(struct it9135_dev_ctx *dev,
+					    unsigned char chip,
+					    unsigned long freq,
+					    unsigned short bw)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long temp_freq = freq;
+	unsigned short temp_bw = bw;
+
+	deb_func("Enter %s Function -\n ", __func__);
+	deb_info("chip = %d, Freq= %ld, BW=%d\n", chip, (long int)freq, bw);
+
+	if (dev->fc[chip].en_pid) {
+		/* Disable PID filter */
+		it9135_write_reg_bits(&dev->data, chip, PROCESSOR_OFDM,
+				      p_mp2if_pid_en, mp2if_pid_en_pos,
+				      mp2if_pid_en_len, 0);
+		dev->fc[chip].en_pid = 0;
+	}
+
+	/* Before acquireChannel, it is 1; otherwise, it is 0 */
+	dev->fc[chip].tuner_info.setting_freq = 1;
+
+	if (freq)
+		dev->fc[chip].desired_freq = freq;
+	else
+		freq = dev->fc[chip].desired_freq;
+
+	if (bw)
+		dev->fc[chip].desired_bw = bw * 1000;
+	else
+		bw = dev->fc[chip].desired_bw;
+
+	deb_info("Real Freq= %ld, BW=%d\n",
+		 (long int)dev->fc[chip].desired_freq,
+		 dev->fc[chip].desired_bw);
+
+	if (!dev->fc[chip].tuner_info.inited) {
+		deb_warning("Skip SetFreq - Tuner is still off!\n");
+		goto exit;
+	}
+
+	dev->fc[chip].tuner_info.set = 0;
+	if (dev->fc[chip].desired_freq != 0 && dev->fc[chip].desired_bw != 0) {
+		deb_info("it9135_acquire_ch: Real Freq= %ld, BW=%d\n",
+			 (long int)dev->fc[chip].desired_freq,
+			 dev->fc[chip].desired_bw);
+		error =
+		    it9135_acquire_ch(&dev->data, chip,
+				      dev->fc[chip].desired_bw,
+				      dev->fc[chip].desired_freq);
+		/* dev->fc[chip].tuner_info.setting_freq = 0; */
+		if (error) {
+			err("it9135_acquire_ch fail! 0x%08lx",
+			    (long unsigned int)error);
+			goto exit;
+		} else {	/* when success acquireChannel, record currentFreq/currentBW. */
+			dev->fc[chip].curr_freq = dev->fc[chip].desired_freq;
+			dev->fc[chip].curr_bw = dev->fc[chip].desired_bw;
+		}
+	}
+
+	if (dev->stream_type == STREAM_TYPE_DVBT_DATAGRAM)
+		dev->fc[chip].ovr_flw_chk = 5;
+
+	dev->fc[chip].tuner_info.set = 1;
+
+	/* [OMEGA] if only 1 on, set the other to the same freq. */
+	if (dev->architecture == ARCHITECTURE_PIP) {
+		if (!dev->fc[0].timer_on && !dev->fc[1].timer_on) {
+			/* case: when 1st open; */
+			error =
+			    it9135_acquire_ch(&dev->data, (!chip),
+					      dev->fc[chip].curr_bw,
+					      dev->fc[chip].curr_freq);
+		} else if ((!dev->fc[0].timer_on || !dev->fc[1].timer_on)
+			   && !dev->fc[!chip].tuner_info.locked) {
+			/* case: when only 1 active, and change freq; (the other need to change to same freq too) */
+			error =
+			    it9135_acquire_ch(&dev->data, (!chip),
+					      dev->fc[chip].curr_bw,
+					      dev->fc[chip].curr_freq);
+		}
+	}
+
+exit:
+	dev->fc[chip].tuner_info.setting_freq = 0;
+
+	if (dev->chip_ver == 1) {
+		if (error && (!dev->already_nim_reset_seq)
+		    && (chip == 1)) {
+			dev->already_nim_reset_seq = 1;
+			it9135_nim_reset_seq(dev);
+			it9135_drv_set_freq_bw(dev, chip, temp_freq, temp_bw);
+			dev->already_nim_reset_seq = 0;
+		}
+	}
+	return error;
+}
+
+/* Tuner lock signal or not */
+static unsigned long it9135_drv_is_locked(struct it9135_dev_ctx *dev,
+					  unsigned char chip, int *locked)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	*locked = 0;
+
+	error = it9135_freq_locked(&dev->data, chip, locked);
+	if (error) {
+		err("Standard_isLocked is failed!");
+	} else {
+		if (!*locked)
+			deb_info("The chip=%d signal is %s Lock\n", chip,
+				 *locked ? "" : "not");
+	}
+
+	return error;
+}
+
+unsigned long it9135_drv_get_snr_value(struct it9135_dev_ctx *dev,
+				       unsigned long *snr_value)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char snr_reg_23_16, snr_reg_15_8, snr_reg_7_0;
+
+	deb_func("Enter %s Function\n ", __func__);
+
+	error =
+	    it9135_read_reg(&dev->data, 0, PROCESSOR_OFDM, 0x2e,
+			    (unsigned char *)&snr_reg_23_16);
+	if (error)
+		err("it9135_get_snr snr_reg_23_16 is failed!");
+
+	error =
+	    it9135_read_reg(&dev->data, 0, PROCESSOR_OFDM, 0x2d,
+			    (unsigned char *)&snr_reg_15_8);
+	if (error)
+		err("it9135_get_snr snr_reg_15_8 is failed!");
+
+	error =
+	    it9135_read_reg(&dev->data, 0, PROCESSOR_OFDM, 0x2c,
+			    (unsigned char *)&snr_reg_7_0);
+	if (error)
+		err("it9135_get_snr snr_reg_7_0 is failed!");
+
+	*snr_value =
+	    (snr_reg_23_16 & 0xff) * 256 * 256 + (snr_reg_15_8 & 0xff) * 256 +
+	    (snr_reg_7_0 & 0xff);
+
+	return error;
+}
+
+unsigned long it9135_drv_get_statistic(struct it9135_dev_ctx *dev,
+				       unsigned char chip,
+				       struct it9135_statistic *statistic)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	if (dev->fc[chip].tuner_info.set) {
+		error = it9135_get_statistic(&dev->data, chip, statistic);
+	} else {
+		(*statistic).presented = 0;
+		(*statistic).locked = 0;
+		(*statistic).quality = 0;
+		(*statistic).strength = 0;
+	}
+
+	return error;
+}
+
+static unsigned long it9135_drv_init_dev_info(struct it9135_dev_ctx *dev,
+					      unsigned char chip)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	dev->fc[chip].curr_freq = 0;
+	dev->fc[chip].curr_bw = 0;
+	dev->fc[chip].desired_freq = 0;
+	dev->fc[chip].desired_bw = 6000;
+
+	/* For PID Filter Setting */
+	dev->fc[chip].en_pid = 0;
+	dev->fc[chip].ap_on = 0;
+	dev->fc[chip].reset_ts = 0;
+	dev->fc[chip].tuner_info.set = 0;
+	dev->fc[chip].tuner_info.setting_freq = 0;
+
+	return error;
+}
+
+/* Get EEPROM_IRMODE/ir_tab_load/bRAWIr/architecture config from EEPROM */
+static unsigned long it9135_drv_get_eeprom_config(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char chip_ver = 0;
+	unsigned long chip_type;
+	unsigned char var[2];
+	/* ir_tab_load option */
+	unsigned char tmp = 0;
+	int chip;
+
+	deb_func("Enter %s Function", __func__);
+
+	/* Patch for read eeprom valid bit */
+	error =
+	    it9135_read_reg(&dev->data, 0, PROCESSOR_LINK, chip_version_7_0,
+			    &chip_ver);
+	error =
+	    it9135_read_regs(&dev->data, 0, PROCESSOR_LINK,
+			     chip_version_7_0 + 1, 2, var);
+
+	if (error)
+		err("it9135_drv_get_eeprom_config fail---cannot read chip version");
+
+	chip_type = var[1] << 8 | var[0];
+	if (chip_type == 0x9135 && chip_ver == 2) {	/* Om2 */
+		dev->chip_ver = 2;
+		error =
+		    it9135_read_regs(&dev->data, 0, PROCESSOR_LINK, 0x461d, 1,
+				     &tmp);
+		deb_info
+		    ("Chip Version is %d---and Read 461d---valid bit = 0x%02X",
+		     chip_ver, tmp);
+	} else {
+		dev->chip_ver = 1;	/* Om1 */
+		error =
+		    it9135_read_regs(&dev->data, 0, PROCESSOR_LINK, 0x461b, 1,
+				     &tmp);
+		deb_info
+		    ("Chip Version is %d---and Read 461b---valid bit = 0x%02X",
+		     chip_ver, tmp);
+	}
+	deb_info("*** Chip Version = %d ***", chip_ver);
+	if (error) {
+		err("0x461D eeprom valid bit read fail!");
+		goto exit;
+	}
+
+	if (tmp == 0) {
+		deb_info("No need read eeprom\n");
+		dev->ir_tab_load = 0;
+		dev->proprietary_ir = 0;
+		dev->dual_ts = 0;
+		dev->architecture = ARCHITECTURE_DCA;
+		dev->data.chip_num = 1;
+		dev->dca_pip = 0;
+		dev->fc[0].tuner_info.id = 0x38;
+	} else {
+		deb_info("Need read eeprom\n");
+		error =
+		    it9135_read_regs(&dev->data, 0, PROCESSOR_LINK,
+				     EEPROM_IRMODE, 1, &tmp);
+		if (error)
+			goto exit;
+
+		dev->ir_tab_load = tmp ? 1 : 0;
+		deb_info("EEPROM_IRMODE = 0x%02X, ", tmp);
+		deb_info("ir_tab_load %s\n", dev->ir_tab_load ? "ON" : "OFF");
+
+		dev->proprietary_ir = (tmp == 0x05) ? 1 : 0;
+		deb_info("proprietary_ir - %s\n",
+			 dev->proprietary_ir ? "ON" : "OFF");
+		if (dev->proprietary_ir)
+			deb_info("IT9135 propriety (raw) mode\n");
+		else
+			deb_info("IT9135 HID (keyboard) mode\n");
+
+		/* EE chose NEC RC5 RC6 threshhold table */
+		if (dev->ir_tab_load) {
+			error =
+			    it9135_read_regs(&dev->data, 0, PROCESSOR_LINK,
+					     EEPROM_IRTYPE, 1, &tmp);
+			if (error)
+				goto exit;
+			dev->ir_type = tmp;
+			deb_info("ir_type %d", dev->ir_type);
+		}
+
+		/* dual_ts option */
+		dev->dual_ts = 0;
+		dev->architecture = ARCHITECTURE_DCA;
+		dev->data.chip_num = 1;
+		dev->dca_pip = 0;
+
+		error =
+		    it9135_read_regs(&dev->data, 0, PROCESSOR_LINK,
+				     EEPROM_TSMODE, 1, &tmp);
+		if (error)
+			goto exit;
+		deb_info("EEPROM_TSMODE = 0x%02X", tmp);
+
+		if (tmp == 0) {
+			deb_info("TSMode = TS1 mode\n");
+		} else if (tmp == 1) {
+			deb_info("TSMode = DCA+PIP mode\n");
+			dev->architecture = ARCHITECTURE_DCA;
+			dev->data.chip_num = 2;
+			dev->dual_ts = 1;
+			dev->dca_pip = 1;
+		} else if (tmp == 2) {
+			deb_info("TSMode = DCA mode\n");
+			dev->data.chip_num = 2;
+		} else if (tmp == 3) {
+			deb_info("TSMode = PIP mode\n");
+			dev->architecture = ARCHITECTURE_PIP;
+			dev->data.chip_num = 2;
+			dev->dual_ts = 1;
+		}
+
+		/* tunerID option, Omega, not need to read register, just assign 0x38; */
+		error =
+		    it9135_read_regs(&dev->data, 0, PROCESSOR_LINK,
+				     EEPROM_TUNERID, 1, &tmp);
+		if (tmp == 0x51)
+			dev->fc[0].tuner_info.id = 0x51;
+		else if (tmp == 0x52)
+			dev->fc[0].tuner_info.id = 0x52;
+		else if (tmp == 0x60)
+			dev->fc[0].tuner_info.id = 0x60;
+		else if (tmp == 0x61)
+			dev->fc[0].tuner_info.id = 0x61;
+		else if (tmp == 0x62)
+			dev->fc[0].tuner_info.id = 0x62;
+		else
+			dev->fc[0].tuner_info.id = 0x38;
+
+		deb_info("dev->fc[0].tuner_info.id = 0x%x",
+			 dev->fc[0].tuner_info.id);
+		if (dev->dual_ts) {
+			dev->fc[1].tuner_info.id = dev->fc[0].tuner_info.id;
+			deb_info("dev->fc[1].tuner_info.id = 0x%x",
+				 dev->fc[1].tuner_info.id);
+		}
+		error =
+		    it9135_read_regs(&dev->data, 0, PROCESSOR_LINK,
+				     EEPROM_SUSPEND, 1, &tmp);
+		deb_info("EEPROM susped mode=%d", tmp);
+
+	}
+
+	for (chip = 0; chip <= (unsigned char)dev->dual_ts; chip++)
+		error = it9135_drv_init_dev_info(dev, chip);
+
+exit:
+	return error;
+}
+
+static unsigned long it9135_drv_set_bus_tuner(struct it9135_dev_ctx *dev,
+					      unsigned short busId,
+					      unsigned short tuner_id)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long version = 0;
+
+	deb_func("Enter %s Function", __func__);
+	deb_info("busId = 0x%x, tuner_id =0x%x\n", busId, tuner_id);
+
+	if ((dev->usb_mode == 0x0110) && (busId == IT9135_BUS_USB20))
+		busId = IT9135_BUS_USB11;
+
+	error = it9135_set_bus_tuner(&dev->data, busId, tuner_id);
+	if (error) {
+		err("it9135_set_bus_tuner error");
+		return error;
+	}
+
+	error = it9135_get_fw_ver(&dev->data, PROCESSOR_LINK, &version);
+	if (version != 0)
+		dev->data.booted = 1;
+	else
+		dev->data.booted = 0;
+
+	if (error)
+		err("it9135_get_fw_ver error");
+
+	return error;
+}
+
+/* suspend 1 --> sleep / suspend not 1 --> resume */
+static unsigned long it9135_drv_nim_suspend(struct it9135_dev_ctx *dev,
+					    int suspend)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	deb_func("Enter %s Function\n", __func__);
+	deb_info("suspend = %s\n", suspend ? "ON" : "OFF");
+
+	if (dev->data.chip_num == 1)
+		return ERROR_NO_ERROR;
+
+	if (suspend) {		/* Sleep */
+		error =
+		    it9135_write_reg_bits(&dev->data,
+					  0, PROCESSOR_LINK, p_reg_top_gpioh5_o,
+					  reg_top_gpioh5_o_pos,
+					  reg_top_gpioh5_o_len, 1);
+		mdelay(20);
+	} else {		/* Resume */
+		error =
+		    it9135_write_reg_bits(&dev->data,
+					  0, PROCESSOR_LINK, p_reg_top_gpioh5_o,
+					  reg_top_gpioh5_o_pos,
+					  reg_top_gpioh5_o_len, 0);
+		mdelay(100);
+	}
+
+	return error;
+}
+
+/* Set tuner power saving and control */
+static unsigned long it9135_drv_ap_ctrl(struct it9135_dev_ctx *dev,
+					unsigned char chip, int onoff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned long version = 0;
+	int i;
+
+	deb_func("Enter %s Function\n", __func__);
+	deb_info("chip = %d, onoff = %s\n", chip, onoff ? "ON" : "OFF");
+
+	if (onoff) {
+		dev->fc[chip].tuner_info.inited = 1;
+		if (dev->architecture == ARCHITECTURE_PIP) {
+			if (dev->fc[0].timer_on || dev->fc[1].timer_on) {
+				deb_info("Already all power on !!");
+				return 0;
+			}
+		}
+	} else {
+		dev->fc[chip].tuner_info.inited = 0;
+		dev->fc[chip].tuner_info.locked = 0;
+
+		/* [OMEGA] if other one still alive, do not pwr down, just need to set freq; */
+		if (dev->architecture == ARCHITECTURE_PIP) {
+			if (dev->fc[0].timer_on || dev->fc[1].timer_on) {
+				deb_info("CLOSE 1");
+				it9135_acquire_ch(&dev->data, chip,
+						  dev->fc[!chip].curr_bw,
+						  dev->fc[!chip].curr_freq);
+				return 0;
+			}
+		}
+	}
+	/*[OMEGA] clock from tuner, so close sequence demod->tuner, and 9133->9137. vice versa.
+	 * BUT! demod->tuner:57mADC, tuner->demod:37mADC
+	 */
+	if (onoff) {		/* pwr on */
+		if (dev->chip_ver == 1) {
+			if (chip == 1) {
+				error = it9135_nim_reset_seq(dev);
+				if (error)
+					it9135_nim_reset_seq(dev);
+			} else {
+				dev->usb_ctrl_timeOut = 1;
+				for (i = 0; i < 5; i++) {
+					deb_info
+					    ("it9135_drv_ap_ctrl - DummyCmd %d",
+					     i);
+					error =
+					    it9135_get_fw_ver(&dev->data,
+							      PROCESSOR_LINK,
+							      &version);
+					mdelay(1);
+				}
+				dev->usb_ctrl_timeOut = 5;
+
+				error =
+				    it9135_ctrl_tuner_pw_saving(&dev->data,
+								chip, onoff);
+				if (error)
+					err("it9135_drv_ap_ctrl::it9135_ctrl_tuner_pw_saving error = %x", (unsigned int)error);
+
+				error =
+				    it9135_ctrl_pw_saving(&dev->data, chip,
+							  onoff);
+				if (error)
+					err("it9135_drv_ap_ctrl::it9135_ctrl_pw_saving error = %x", (unsigned int)error);
+			}
+		} else {
+			if (chip == 1) {
+				error = it9135_drv_nim_suspend(dev, 0);
+			} else {
+				/* DummyCmd */
+				dev->usb_ctrl_timeOut = 1;
+				for (i = 0; i < 5; i++) {
+					deb_info
+					    ("it9135_drv_ap_ctrl - DummyCmd %d",
+					     i);
+					error =
+					    it9135_get_fw_ver(&dev->data,
+							      PROCESSOR_LINK,
+							      &version);
+					mdelay(1);
+				}
+				dev->usb_ctrl_timeOut = 5;
+			}
+
+			error =
+			    it9135_ctrl_tuner_pw_saving(&dev->data, chip,
+							onoff);
+			if (error)
+				err("it9135_drv_ap_ctrl - it9135_ctrl_tuner_pw_saving error = %x", (unsigned int)error);
+
+			error = it9135_ctrl_pw_saving(&dev->data, chip, onoff);
+			mdelay(50);
+			if (error)
+				err("it9135_drv_ap_ctrl - it9135_ctrl_pw_saving error = %x", (unsigned int)error);
+		}
+	} else {		/* pwr down:  DCA DUT: 36(all) -> 47-159(no GPIOH5, sequence change) */
+		if ((chip == 0) && (dev->data.chip_num == 2)) {
+			error = it9135_ctrl_tuner_leakage(&dev->data, 1, onoff);
+			if (error)
+				err("it9135_drv_ap_ctrl::it9135_ctrl_tuner_leakage error = %x", (unsigned int)error);
+			error = it9135_drv_nim_suspend(dev, 1);
+		}
+
+		error = it9135_ctrl_pw_saving(&dev->data, chip, onoff);
+		if (error)
+			err("it9135_drv_ap_ctrl::it9135_ctrl_pw_saving error = %x", (unsigned int)error);
+
+		error = it9135_ctrl_tuner_pw_saving(&dev->data, chip, onoff);
+		if (error)
+			err("it9135_drv_ap_ctrl::it9135_ctrl_tuner_pw_saving error = %x", (unsigned int)error);
+	}
+
+	return error;
+}
+
+static unsigned long it9135_drv_ap_reset(struct it9135_dev_ctx *dev,
+					 unsigned char chip, int onoff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	dev->fc[chip].curr_freq = 0;
+	dev->fc[chip].curr_bw = 6000;	/* For BDAUtil */
+	dev->fc[chip].ap_on = 0;
+
+	if (!onoff) {		/* Only for stop */
+		dev->fc[chip].en_pid = 0;
+	}
+
+	/* Init Tuner info */
+	dev->fc[chip].tuner_info.setting_freq = 0;
+
+	error = it9135_drv_ap_ctrl(dev, chip, onoff);
+	if (error)
+		err("it9135_drv_ap_ctrl Fail!");
+
+	return error;
+}
+
+static unsigned long it9135_drv_dummy_cmd(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	int i;
+
+	deb_info("it9135_drv_dummy_cmd:: patch for KJS/EEPC\n");
+	for (i = 0; i < 5; i++) {
+		error =
+		    it9135_drv_set_bus_tuner(dev, IT9135_BUS_USB20,
+					     IT9135_TUNER_ID);
+		mdelay(1);
+	}
+	if (error)
+		deb_warning("it9135_drv_dummy_cmd failed - %d\n", i);
+
+	return error;
+}
+
+/************** DL_ *************/
+
+static unsigned long it9135_dl_dummy_cmd(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_dummy_cmd(dev);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+static unsigned long it9135_dl_nim_reset(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_nim_reset(dev);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+static unsigned long it9135_dl_init_nim_suspend_regs(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_init_nim_suspend_regs(dev);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+static unsigned long it9135_dl_initialize(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_initialize(dev);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+static unsigned long it9135_dl_set_bus_tuner(struct it9135_dev_ctx *dev,
+					     unsigned short busId,
+					     unsigned short tuner_id)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_set_bus_tuner(dev, busId, tuner_id);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+static unsigned long it9135_dl_get_eeprom_config(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_get_eeprom_config(dev);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+/* Load Ir Table */
+static unsigned long it9135_dl_ir_table_download(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_ir_table_download(dev);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_reset_pid(struct it9135_dev_ctx *dev,
+				  unsigned char chip)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	/* Reset and Clear pidTable */
+	error = it9135_reset_pid(&dev->data, chip);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_add_pid(struct it9135_dev_ctx *dev, unsigned char chip,
+				unsigned char index, unsigned short pid)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function - index: %d, pid: %x\n", __func__, index,
+		 pid);
+
+	error = it9135_add_pid_filter(&dev->data, chip, index, pid);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_remove_pid(struct it9135_dev_ctx *dev,
+				   unsigned char chip, unsigned char index,
+				   unsigned short pid)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function - index: %d, pid: %x\n", __func__, index,
+		 pid);
+
+	error = it9135_remove_pid_at(&dev->data, chip, index, pid);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_pid_on_off(struct it9135_dev_ctx *dev,
+				   unsigned char chip, int onoff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char ctrl = 0;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function - onoff: %d\n ", __func__, onoff);
+
+	if (onoff)
+		ctrl = 1;
+	else
+		ctrl = 0;
+
+	error = it9135_ctrl_pid_filter(&dev->data, chip, 0);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_ap_ctrl(struct it9135_dev_ctx *dev, unsigned char chip,
+				int onoff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	deb_func("Enter %s Function\n", __func__);
+	deb_info("chip = %d, onoff = %s\n", chip, onoff ? "ON" : "OFF");
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_ap_ctrl(dev, chip, onoff);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_ap_reset(struct it9135_dev_ctx *dev, unsigned char chip,
+				 int on)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_ap_reset(dev, chip, on);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_tuner_set_freq_bw(struct it9135_dev_ctx *dev,
+					  unsigned char chip,
+					  unsigned long freq, unsigned short bw)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function\n", __func__);
+
+	if (dev->fc[chip].desired_freq != freq
+	    || dev->fc[chip].desired_bw != bw * 1000)
+		error = it9135_drv_set_freq_bw(dev, chip, freq, bw);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_set_architecture(struct it9135_dev_ctx *dev,
+					 unsigned char architecture)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function\n", __func__);
+	error = it9135_set_arch(&dev->data, architecture);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_is_locked(struct it9135_dev_ctx *dev,
+				  unsigned char chip, int *locked)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	error = it9135_drv_is_locked(dev, chip, locked);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_get_signal_strength(struct it9135_dev_ctx *dev,
+					    unsigned char chip,
+					    unsigned char *strength)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function\n", __func__);
+
+	error = it9135_get_strength(&dev->data, chip, strength);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_get_signal_strength_Dbm(struct it9135_dev_ctx *dev,
+						unsigned char chip,
+						long *strength_dbm)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function\n", __func__);
+
+	error = it9135_get_strength_dbm(&dev->data, chip, strength_dbm);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_get_channel_statistic(struct it9135_dev_ctx *dev,
+					      unsigned char chip,
+					      struct it9135_ch_statistic
+					      *ch_statistic)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function\n", __func__);
+
+	error = it9135_get_ch_statistic(&dev->data, chip, ch_statistic);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_get_channel_modulation(struct it9135_dev_ctx *dev,
+					       unsigned char chip,
+					       struct it9135_ch_modulation
+					       *ch_modulation)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function\n", __func__);
+
+	error = it9135_get_ch_modulation(&dev->data, chip, ch_modulation);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_get_snr(struct it9135_dev_ctx *dev,
+				unsigned char chip,
+				unsigned char *constellation,
+				unsigned char *snr)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function\n", __func__);
+
+	error = it9135_get_snr(&dev->data, chip, snr);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_reboot(struct it9135_dev_ctx *dev)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	deb_func("Enter %s Function\n", __func__);
+
+	error = it9135_dev_reboot(&dev->data);
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+unsigned long it9135_dl_read_raw_ir(struct it9135_dev_ctx *dev,
+				    unsigned long *read_buff)
+{
+	unsigned long error = ERROR_NO_ERROR;
+
+	mutex_lock(&dev->it9135_mutex);
+
+	if (dev->proprietary_ir)
+		error = it9135_get_ir_code(&dev->data, read_buff);
+	else
+		deb_warning("RAWIr can't be used!!\n");
+
+	mutex_unlock(&dev->it9135_mutex);
+
+	return error;
+}
+
+/* Set device driver init */
+unsigned long it9135_device_init(struct usb_device *udev,
+				 struct it9135_dev_ctx *dev, int boot)
+{
+	unsigned long error = ERROR_NO_ERROR;
+	int err_cnt = 0;
+	int i;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	dev_set_drvdata(&udev->dev, dev);
+
+	info("=========================================");
+	info("DRIVER_RELEASE_VERSION:    %s", DRIVER_RELEASE_VERSION);
+	info("FW_RELEASE_VERSION:        %s", dev->fw_ver);
+	info("API_RELEASE_VERSION:       %X.%X.%X", IT9135_API_VER_NUM,
+	     IT9135_API_DATE, IT9135_API_BUILD);
+	info("=========================================");
+
+#ifdef DVB_USB_ADAP_NEED_PID_FILTER
+	deb_info("DVB_USB_ADAP_NEED_PID_FILTERING\n");
+#else
+	deb_info("DVB_USB_ADAP_NOT_NEED_PID_FILTERING\n");
+#endif
+
+	/************* Set Device init Info *************/
+	dev->enter_suspend = 0;
+	dev->surprise_removal = 0;
+	dev->dev_not_resp = 0;
+	dev->selective_suspend = 0;
+	dev->tuner_pw_off = 0;
+	dev->already_nim_reset_seq = 0;
+
+	if (boot) {
+		dev->data.chip_num = 1;
+		dev->architecture = ARCHITECTURE_DCA;
+		dev->data.frequency[0] = 666000;
+		dev->data.bandwidth[0] = 8000;
+		dev->ir_tab_load = 0;
+		dev->fc[0].tuner_info.id = 0;
+		dev->fc[1].tuner_info.id = 0;
+		dev->fc[0].timer_on = 0;
+		dev->fc[1].timer_on = 0;
+		dev->dual_ts = 0;
+		dev->filter_cnt = 0;
+		dev->filter_index = 0;
+		dev->stream_type = STREAM_TYPE_DVBT_DATAGRAM;
+		dev->usb_ctrl_timeOut = 1;
+		dev->disconnect = 0;
+		if (udev->speed == USB_SPEED_FULL)
+			dev->max_packet_sz = 0x0110;
+		else
+			dev->max_packet_sz = 0x0200;
+	} else {
+		dev->usb_ctrl_timeOut = 5;
+	}
+
+	error = it9135_dl_dummy_cmd(dev);
+
+	if (boot) {
+		/************* Set USB Info *************/
+		dev->usb_mode = (dev->max_packet_sz == 0x200) ? 0x0200 : 0x0110;
+		deb_info("USB mode = 0x%x\n", dev->usb_mode);
+
+		dev->ts_packet_cnt =
+		    (dev->usb_mode ==
+		     0x200) ? IT9135_TS_PACKET_COUNT_HI :
+		    IT9135_TS_PACKET_COUNT_FU;
+		dev->ts_frames =
+		    (dev->usb_mode ==
+		     0x200) ? IT9135_TS_FRAMES_HI : IT9135_TS_FRAMES_FU;
+		dev->ts_frame_sz = IT9135_TS_PACKET_SIZE * dev->ts_packet_cnt;
+		dev->ts_frame_sz_dw = dev->ts_frame_sz / 4;
+	}
+	dev->ep12_err = 0;
+	dev->ep45_err = 0;
+	dev->active_filter = 0;
+
+	if (boot) {
+		error =
+		    it9135_dl_set_bus_tuner(dev, IT9135_BUS_USB20,
+					    IT9135_TUNER_ID);
+		if (error) {
+			err("First it9135_dl_set_bus_tuner fail : 0x%08lx",
+			    (long unsigned int)error);
+			err_cnt++;
+			goto Exit;
+		}
+
+		error = it9135_dl_get_eeprom_config(dev);
+		if (error) {
+			err("it9135_dl_get_eeprom_config fail : 0x%08lx",
+			    (long unsigned int)error);
+			err_cnt++;
+			goto Exit;
+		}
+	}
+
+	error =
+	    it9135_dl_set_bus_tuner(dev, IT9135_BUS_USB20,
+				    dev->fc[0].tuner_info.id);
+	if (error) {
+		err("it9135_dl_set_bus_tuner fail!");
+		err_cnt++;
+		goto Exit;
+	}
+
+	if (dev->data.chip_num == 2 && !dev->data.booted) {	/* plug/cold-boot/S4 */
+		error = it9135_dl_nim_reset(dev);
+	} else if (dev->data.chip_num == 2 && dev->data.booted) {	/* warm-boot/(S1) */
+		/* pwr on for init. */
+		for (i = 0; i < dev->data.chip_num; i++)
+			error = it9135_dl_ap_ctrl(dev, i, 1);
+	} else if (dev->data.chip_num == 1 && dev->data.booted) {	/* warm-boot/(S1) */
+		/* pwr on for init, but seems not necessary. */
+		error = it9135_dl_ap_ctrl(dev, 0, 1);
+	}
+
+	if (error)
+		err("it9135_dl_nim_reset or dl_nim_suspend fail!");
+
+	error = it9135_dl_initialize(dev);
+	if (error) {
+		err("it9135_dl_initialize fail! 0x%08lx",
+		    (long unsigned int)error);
+		err_cnt++;
+		goto Exit;
+	}
+
+	if (dev->ir_tab_load) {
+		error = it9135_dl_ir_table_download(dev);
+		if (error) {
+			err("it9135_dl_ir_table_download fail");
+			err_cnt++;
+		}
+	}
+
+	if (dev->data.chip_num == 2) {
+		error = it9135_dl_init_nim_suspend_regs(dev);
+		if (error)
+			err("it9135_dl_init_nim_suspend_regs fail!");
+	}
+
+	for (i = dev->data.chip_num; i > 0; i--) {
+		error = it9135_dl_ap_ctrl(dev, (i - 1), 0);
+		if (error)
+			err("%d: it9135_dl_ap_ctrl Fail!", i);
+
+	}
+
+	info("%s success!!", __func__);
+
+Exit:
+	if (err_cnt)
+		err("[Device_init] Error %d\n", err_cnt);
+	return error;
+}
+
+int dca_to_pip(struct it9135_dev_ctx *dev)
+{
+	dev->filter_index = dev->filter_cnt;
+
+	deb_info("dca_to_pip - %d\n", dev->filter_cnt);
+
+	if (dev->filter_cnt == 1) {
+		/* Do nothing, stay in DCA. */
+		it9135_dl_set_architecture(dev, ARCHITECTURE_DCA);
+		mdelay(50);
+	} else if (dev->filter_cnt == 2) {
+		it9135_dl_set_architecture(dev, ARCHITECTURE_PIP);
+		mdelay(50);
+	}
+
+	return 0;
+}
+
+int pip_to_dca(struct it9135_dev_ctx *dev)
+{
+	deb_info("pip_to_dca - %d, %d\n", dev->filter_cnt, dev->filter_index);
+
+	if (dev->filter_cnt == 1) {
+		if (dev->filter_index == 0) {	/*Close filter 0. */
+			dev->swap_filter = 1;
+			it9135_dl_set_architecture(dev, ARCHITECTURE_DCA);
+			it9135_dl_tuner_set_freq_bw(dev, 0,
+						    dev->fc[1].curr_freq, 0);
+			dev->swap_filter = 0;
+		} else {	/* Close filter 1. */
+
+			it9135_dl_set_architecture(dev, ARCHITECTURE_DCA);
+			it9135_dl_tuner_set_freq_bw(dev, 0,
+						    dev->fc[0].curr_freq, 0);
+		}
+
+		dev->fc[1].timer_on = 0;
+		dev->fc[0].timer_on = 1;
+	} else if (dev->filter_cnt == 0) {
+		dev->fc[1].timer_on = 0;
+		dev->fc[0].timer_on = 0;
+	}
+	return 0;
+}
+
+/* IT9135 device tuner on init */
+static int it9135_init(struct dvb_frontend *demod)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)demod->demodulator_priv;
+	unsigned long error = ERROR_NO_ERROR;
+	int i;
+
+	deb_func("Enter %s Function - chip=%d\n", __func__, demod->dvb->num);
+
+	if (dev->disconnect)
+		return 0;
+
+	dev->filter_cnt++;
+
+	if (dev->dca_pip) {
+		for (i = 0; i < dev->data.chip_num; i++)
+			error = it9135_dl_ap_ctrl(dev, i, 1);
+
+		error = dca_to_pip(dev);
+	}
+
+	if (error)
+		return -EREMOTEIO;
+
+	if ((dev->architecture == ARCHITECTURE_PIP) && (dev->filter_cnt == 2)) {
+		/* Do nothging, MODE = DCA+PIP, because 2 tuners have turn on from DCA. */
+	} else if (dev->architecture == ARCHITECTURE_DCA) {	/* Single or DCA */
+		for (i = 0; i < dev->data.chip_num; i++)
+			error = it9135_dl_ap_ctrl(dev, i, 1);
+	} else {
+		/* PIP */
+		/* pwr on 2 chips directly; */
+		for (i = 0; i < dev->data.chip_num; i++)
+			error = it9135_dl_ap_ctrl(dev, i, 1);
+	}
+
+	if (error)
+		return -EREMOTEIO;
+
+	dev->fc[demod->dvb->num].timer_on = 1;
+
+	return 0;
+}
+
+/* IT9135 device tuner off sleep */
+static int it9135_sleep(struct dvb_frontend *demod)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)demod->demodulator_priv;
+	unsigned long error = ERROR_NO_ERROR;
+	int i;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	if (dev->disconnect)
+		return 0;
+
+	dev->filter_cnt--;
+	dev->fc[demod->dvb->num].timer_on = 0;
+
+	if (dev->dca_pip)
+		error = pip_to_dca(dev);
+
+	if (dev->filter_cnt == 1) {
+		/* Do nothing, Mode = DCA+PIP, because from PIP to DCA */
+		deb_info("ARCHITECTURE_DCA - %d\n", dev->filter_cnt);
+	} else {		/* Single or DCA */
+		deb_info("ARCHITECTURE_DCA2 - %d\n", dev->filter_cnt);
+
+		for (i = dev->data.chip_num; i > 0; i--)
+			error = it9135_dl_ap_reset(dev, i - 1, 0);
+
+	}
+
+	if (error)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int it9135_get_frontend(struct dvb_frontend *fe,
+			       struct dvb_frontend_parameters *fep)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)fe->demodulator_priv;
+
+	if (dev->data.chip_num != 2)
+		deb_func("Enter %s Function\n", __func__);
+	else
+		deb_func("Enter %s Function - chip=%d\n", __func__,
+			 fe->dvb->num);
+
+	fep->inversion = INVERSION_AUTO;
+	return 0;
+}
+
+/* Set OFDM bandwidth and tuner frequency */
+static int it9135_set_frontend(struct dvb_frontend *fe,
+			       struct dvb_frontend_parameters *fep)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)fe->demodulator_priv;
+	struct it9135_ofdm_channel ch;
+	unsigned long error = ERROR_NO_ERROR;
+
+	ch.rf_khz = 0;
+	ch.bw = 0;
+
+	if (dev->disconnect)
+		return 0;
+
+	if (dev->data.chip_num != 2)
+		deb_func("Enter %s Function\n", __func__);
+	else
+		deb_func("Enter %s Function - chip=%d RF=%d, BW=%d\n", __func__,
+			 fe->dvb->num, ch.rf_khz, ch.bw);
+
+	if (fep->u.ofdm.bandwidth == 0)
+		fep->u.ofdm.bandwidth = 8;
+	if (fep->u.ofdm.bandwidth == 1)
+		fep->u.ofdm.bandwidth = 7;
+	if (fep->u.ofdm.bandwidth == 2)
+		fep->u.ofdm.bandwidth = 6;
+
+	ch.rf_khz = fep->frequency / 1000;
+	ch.bw = fep->u.ofdm.bandwidth;
+
+	if (ch.rf_khz < 177000 || ch.rf_khz > 8585000)
+		ch.rf_khz = 950000;
+
+	if (dev->data.chip_num != 2)
+		error = it9135_dl_tuner_set_freq_bw(dev, 0, ch.rf_khz, ch.bw);
+	else
+		error =
+		    it9135_dl_tuner_set_freq_bw(dev, fe->dvb->num, ch.rf_khz,
+						ch.bw);
+
+	if (error)
+		err("it9135_set_frontend return error");
+
+	return 0;
+}
+
+/* Tuner signal lock frequency */
+static int it9135_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)fe->demodulator_priv;
+	unsigned long error = ERROR_NO_ERROR;
+	int locked;
+
+	if (dev->disconnect)
+		return 0;
+
+	*stat = 0;
+
+	if (dev->data.chip_num != 2)
+		error = it9135_dl_is_locked(dev, 0, &locked);
+	else
+		error = it9135_dl_is_locked(dev, fe->dvb->num, &locked);
+
+	if (error)
+		return 0;
+
+	if (locked) {
+		/* It's seems ok that always return lock to AP */
+		*stat |= FE_HAS_SIGNAL;
+		*stat |= FE_HAS_CARRIER;
+		*stat |= FE_HAS_LOCK;
+		*stat |= FE_HAS_VITERBI;
+		*stat |= FE_HAS_SYNC;
+	} else
+		*stat |= FE_TIMEDOUT;
+
+	return 0;
+}
+
+/* Get it9135_ch_statistic and calculate ber value */
+static int it9135_read_ber(struct dvb_frontend *fe, u32 * ber)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)fe->demodulator_priv;
+	unsigned long error = ERROR_NO_ERROR;
+	struct it9135_ch_statistic ch_statistic;
+
+	if (dev->disconnect)
+		return 0;
+
+	if (dev->data.chip_num != 2)
+		error = it9135_dl_get_channel_statistic(dev, 0, &ch_statistic);
+	else
+		error =
+		    it9135_dl_get_channel_statistic(dev, fe->dvb->num,
+						    &ch_statistic);
+	if (error)
+		return error;
+
+	deb_info
+	    ("it9135_read_ber post_vit_err_cnt: %ld, post_vitbit_cnt: %ld\n",
+	     (long int)ch_statistic.post_vit_err_cnt,
+	     (long int)ch_statistic.post_vitbit_cnt);
+
+	*ber =
+	    ch_statistic.post_vit_err_cnt * (0xFFFFFFFF /
+					     ch_statistic.post_vitbit_cnt);
+
+	return 0;
+}
+
+/* Calculate SNR value */
+static int it9135_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)fe->demodulator_priv;
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char constellation;
+	unsigned char SignalSnr = 0;
+
+	if (dev->disconnect)
+		return 0;
+
+	if (dev->data.chip_num != 2)
+		error = it9135_dl_get_snr(dev, 0, &constellation, &SignalSnr);
+	else
+		error =
+		    it9135_dl_get_snr(dev, fe->dvb->num, &constellation,
+				      &SignalSnr);
+	if (error)
+		return error;
+
+	deb_info("it9135_read_snr constellation: %d, SignalSnr: %d\n",
+		 constellation, SignalSnr);
+
+	if (constellation == 0) {
+		*snr = (u16)SignalSnr * (0xFFFF / 23);
+	} else if (constellation == 1) {
+		*snr = (u16)SignalSnr * (0xFFFF / 26);
+	} else if (constellation == 2) {
+		*snr = (u16)SignalSnr * (0xFFFF / 29);
+	} else {
+		deb_warning("Get constellation is failed!\n");
+	}
+
+	return 0;
+}
+
+static int it9135_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
+{
+	*unc = 0;
+	return 0;
+}
+
+/* Read signal strength and calculate strength value */
+static int it9135_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)fe->demodulator_priv;
+	unsigned long error = ERROR_NO_ERROR;
+	unsigned char st = 0;
+
+	if (dev->disconnect)
+		return 0;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	if (dev->data.chip_num != 2)
+		error = it9135_dl_get_signal_strength(dev, 0, &st);
+	else
+		error = it9135_dl_get_signal_strength(dev, fe->dvb->num, &st);
+	if (error)
+		return error;
+
+	deb_info("%s is %d\n", __func__, st);
+	*strength = (u16)st * (0xFFFF / 100);
+
+	return 0;
+}
+
+static void it9135_release(struct dvb_frontend *fe)
+{
+	deb_func("%s:\n", __func__);
+	kfree(fe);
+}
+
+static struct dvb_frontend_ops it9135_ops;
+struct dvb_frontend *it9135_attach(struct dvb_usb_adapter *adap)
+{
+	struct dvb_frontend *frontend;
+	struct it9135_dev_ctx *dev = dev_get_drvdata(&adap->dev->udev->dev);
+
+	frontend = kzalloc(sizeof(*frontend), GFP_KERNEL);
+	if (frontend == NULL)
+		goto error;
+
+	frontend->demodulator_priv = dev;
+	memcpy(&frontend->ops, &it9135_ops, sizeof(it9135_ops));
+
+	return frontend;
+
+error:
+	kfree(frontend);
+	return NULL;
+}
+
+static struct dvb_frontend_ops it9135_ops = {
+	.info = {
+		 .name = "IT9135 USB DVB-T",
+		 .type = FE_OFDM,
+		 .frequency_min = 44250000,
+		 .frequency_max = 867250000,
+		 .frequency_stepsize = 62500,
+		 .caps = FE_CAN_INVERSION_AUTO |
+		 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+		 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+		 FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
+		 },
+
+	.release = it9135_release,
+
+	.init = it9135_init,
+	.sleep = it9135_sleep,
+
+	.set_frontend = it9135_set_frontend,
+	.get_frontend = it9135_get_frontend,
+
+	.read_status = it9135_read_status,
+	.read_ber = it9135_read_ber,
+	.read_signal_strength = it9135_read_signal_strength,
+	.read_snr = it9135_read_snr,
+	.read_ucblocks = it9135_read_unc_blocks,
+};
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * init it9135 properties
+ */
+
+static int it9135_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)adap->fe->demodulator_priv;
+	int ret = 0;
+
+	deb_info("%s: onoff:%d\n", __func__, onoff);
+
+	if (!onoff) {
+		deb_info("Reset PID Table\n");
+
+		if (dev->data.chip_num != 2)
+			it9135_dl_reset_pid(dev, 0);
+		else
+			it9135_dl_reset_pid(dev, (unsigned char)adap->id);
+	}
+
+	dev->fc[adap->id].en_pid = onoff;
+
+	if (dev->data.chip_num != 2)
+		ret = it9135_dl_pid_on_off(dev, 0, dev->fc[adap->id].en_pid);
+	else
+		ret =
+		    it9135_dl_pid_on_off(dev, (unsigned char)adap->id,
+					 dev->fc[adap->id].en_pid);
+
+	deb_info("Set pid onoff ok\n");
+
+	return ret;
+}
+
+static int it9135_pid_filter(struct dvb_usb_adapter *adap, int index,
+			     u16 pidnum, int onoff)
+{
+	struct it9135_dev_ctx *dev =
+	    (struct it9135_dev_ctx *)adap->fe->demodulator_priv;
+	unsigned short pid;
+	int ret = 0;
+
+	deb_info
+	    ("%s: set pid filter, feedcount %d, index %d, pid %x, onoff %d.\n",
+	     __func__, adap->feedcount, index, pidnum, onoff);
+
+	if (onoff) {
+		/* Cannot use it as pid_filter_ctrl since it has to be done before setting the first pid */
+		if (adap->feedcount == 1) {
+			deb_info("first pid set, enable pid table\n");
+			ret = it9135_pid_filter_ctrl(adap, onoff);
+			if (ret)
+				return ret;
+		}
+
+		pid = (unsigned short)pidnum;
+		if (dev->data.chip_num != 2)
+			ret = it9135_dl_add_pid(dev, 0, index, pid);
+		else
+			ret =
+			    it9135_dl_add_pid(dev, (unsigned char)adap->id,
+					      index, pid);
+		if (ret)
+			return ret;
+	} else {
+		pid = (unsigned short)pidnum;
+		if (dev->data.chip_num != 2)
+			ret = it9135_dl_remove_pid(dev, 0, index, pid);
+		else
+			ret =
+			    it9135_dl_remove_pid(dev, (unsigned char)adap->id,
+						 index, pid);
+		if (ret)
+			return ret;
+
+		if (adap->feedcount == 0) {
+			deb_info("last pid unset, disable pid table\n");
+			ret = it9135_pid_filter_ctrl(adap, onoff);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+struct it9135_val_set *script_parser(const struct firmware *fw,
+				     int *fw_file_pos, u16 * script_sets)
+{
+	int pos = *fw_file_pos;
+	struct it9135_val_set *scripts_temp = NULL;
+	int j = 0;
+	int i = 0;
+
+	/* fw_file_pos+0 ~ +3 == VERSION1 VERSION2 VERSION3 VERSION4 */
+	pos += 4;
+
+	/* OMEGA_ADDRESS */
+	pos += 1;
+
+	/* OMEGA_SCRIPTSETLENGTH */
+	if (fw->data[pos] != 1) {
+		err("OMEGA_SCRIPTSETLENGTH != 1 !!");
+		return NULL;
+	}
+	pos += 4;
+
+	/* scriptSets */
+	*script_sets = fw->data[pos] + (fw->data[pos + 1] << 8);
+	pos += 2;
+
+	/* OMEGA_LNA_Config_2_scripts */
+	scripts_temp =
+	    kzalloc((*script_sets) * sizeof(*scripts_temp), GFP_KERNEL);
+	for (i = 0; i < (*script_sets); i++) {
+		scripts_temp[i].address = fw->data[pos + j] +
+		    (fw->data[pos + j + 1] << 8) +
+		    (fw->data[pos + j + 2] << 16) +
+		    (fw->data[pos + j + 3] << 24);
+
+		scripts_temp[i].value = fw->data[pos + j + 4];
+		j += 5;
+	}
+
+	pos += j;
+	*fw_file_pos = pos;
+
+	return scripts_temp;
+}
+
+static int it9135_download_firmware(struct usb_device *udev,
+				    const struct firmware *fw)
+{
+	int retval = -ENOMEM;
+	struct it9135_dev_ctx *dev = NULL;
+	struct it9135_segment *segs = NULL;
+	u8 *fw_codes;
+	u16 *script_sets;
+	struct it9135_val_set *scripts = NULL;
+	int fw_file_pos = 0;
+	unsigned int fw_code_len = 0;
+	unsigned char var[2];
+	u32 fw_script_len_v1 = 0;
+	u32 fw_script_len_v2 = 0;
+	u32 partition_len_v1 = 0;
+	u32 partition_len_v2 = 0;
+	int chip_v2 = 0;
+	int i = 0;
+	int j = 0;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		err("Alloc dev out of memory");
+		return -ENOTTY;
+	}
+
+	/* init mutex */
+	mutex_init(&dev->it9135_mutex);
+	dev->data.it9135_fw = fw;
+
+	dev->data.driver = (void *)udev;
+
+	/* check device chip version */
+	retval =
+	    it9135_read_reg(&dev->data, 0, PROCESSOR_LINK, chip_version_7_0,
+			    &dev->data.chip_ver);
+	retval =
+	    it9135_read_regs(&dev->data, 0, PROCESSOR_LINK,
+			     chip_version_7_0 + 1, 2, var);
+	if (retval)
+		info("Cannot read chip version");
+
+	dev->data.chip_type = var[1] << 8 | var[0];
+
+	if ((dev->data.chip_type == 0x9135) && (dev->data.chip_ver == 2)) {
+		chip_v2 = 1;
+		info("This is IT9135 chip v2");
+	} else {
+		info("This is IT9135 chip v1");
+	}
+
+	/* byte 0~7 = OMEGA1 */
+	if ((fw->data[0] != 'I') || (fw->data[1] != 'T') || (fw->data[2] != '9')
+	    || (fw->data[3] != '1') || (fw->data[4] != '3')
+	    || (fw->data[5] != '5') || (fw->data[6] != 'A')
+	    || (fw->data[7] != 'X')) {
+		err("IT9135 chip v1 FW format Error");
+		return -ENOENT;
+	}
+	fw_file_pos += 8;
+
+	/* byte 8~11 = OMEGA1 fw & script length */
+	fw_script_len_v1 =
+	    (fw->data[fw_file_pos]) + (fw->data[fw_file_pos + 1] << 8) +
+	    (fw->data[fw_file_pos + 2] << 16) +
+	    (fw->data[fw_file_pos + 3] << 24);
+	fw_file_pos += 4;
+	partition_len_v1 = 8 + 4 + fw_script_len_v1;
+
+	if (chip_v2) {
+		fw_file_pos += fw_script_len_v1;
+		if ((fw->data[fw_file_pos] != 'I')
+		    || (fw->data[fw_file_pos + 1] != 'T')
+		    || (fw->data[fw_file_pos + 2] != '9')
+		    || (fw->data[fw_file_pos + 3] != '1')
+		    || (fw->data[fw_file_pos + 4] != '3')
+		    || (fw->data[fw_file_pos + 5] != '5')
+		    || (fw->data[fw_file_pos + 6] != 'B')
+		    || (fw->data[fw_file_pos + 7] != 'X')) {
+			err("IT9135 chip v2 FW format Error");
+			return -ENOENT;
+		}
+		fw_file_pos += 8;
+
+		fw_script_len_v2 =
+		    (fw->data[fw_file_pos]) + (fw->data[fw_file_pos + 1] << 8) +
+		    (fw->data[fw_file_pos + 2] << 16) +
+		    (fw->data[fw_file_pos + 3] << 24);
+		fw_file_pos += 4;
+
+		partition_len_v2 = 8 + 4 + fw_script_len_v2;
+
+		if (fw->size != (partition_len_v1 + partition_len_v2)) {
+			err("FW file size error!!");
+			return -ENOENT;
+		}
+	}
+
+	/* 32 byte Fw version */
+	for (i = 0; i < 32; i++)
+		dev->fw_ver[i] = fw->data[fw_file_pos + i];
+
+	dev->fw_ver[31] = '\0';
+	fw_file_pos += 32;
+
+	/*------------------------ Parsing Firmware ------------------------*/
+
+	/* byte fw_file_pos+0 ~ +7 = OFDM & LINK version */
+	dev->link_ver =
+	    (fw->data[fw_file_pos] << 24) + (fw->data[fw_file_pos + 1] << 16) +
+	    (fw->data[fw_file_pos + 2] << 8) + (fw->data[fw_file_pos + 3]);
+	fw_file_pos += 4;
+
+	dev->ofdm_ver =
+	    (fw->data[fw_file_pos] << 24) + (fw->data[fw_file_pos + 1] << 16) +
+	    (fw->data[fw_file_pos + 2] << 8) + (fw->data[fw_file_pos + 3]);
+	fw_file_pos += 4;
+
+	deb_info("@@@@@@@@@@@@@ Omega 1or2_OFDM ver = 0x%x, LINK ver = 0x%x",
+		 (unsigned int)dev->link_ver, (unsigned int)dev->ofdm_ver);
+
+	/* byte fw_file_pos+0 ~ +3 = FirmwareV2_CODELENGTH */
+	fw_code_len = fw->data[fw_file_pos] + (fw->data[fw_file_pos + 1] << 8) +
+	    (fw->data[fw_file_pos + 2] << 16) +
+	    (fw->data[fw_file_pos + 3] << 24);
+
+	fw_file_pos += 4;
+	/* byte fw_file_pos+0 ~ +3 = FirmwareV2_SEGMENTLENGTH, only first one byte has value */
+	dev->data.fw_parts = fw->data[fw_file_pos];
+	fw_file_pos += 4;
+
+	/* byte fw_file_pos+0 ~ +3 = FirmwareV2_PARTITIONLENGTH */
+	if (fw->data[fw_file_pos] != 1) {
+		err("FirmwareV2_PARTITIONLENGTH != 1 !!");
+		return -EPERM;
+	}
+	fw_file_pos += 4;
+
+	/* byte fw_file_pos+0 ~ +(fw_code_len-1) == Fw code */
+	fw_codes = kzalloc(fw_code_len * sizeof(*fw_codes), GFP_KERNEL);
+	for (i = 0; i < fw_code_len; i++) {
+		fw_codes[i] = (unsigned char)fw->data[fw_file_pos + i];
+	}	
+	dev->data.fw_codes = fw_codes;
+
+	fw_file_pos += fw_code_len;
+
+	/* FirmwareV2_segments */
+	segs = kzalloc(dev->data.fw_parts * sizeof(*segs), GFP_KERNEL);
+	for (i = 0; i < dev->data.fw_parts; i++) {
+		segs[i].type = fw->data[fw_file_pos + j];
+		segs[i].length =
+		    fw->data[fw_file_pos + j + 1] +
+		    (fw->data[fw_file_pos + j + 2] << 8) +
+		    (fw->data[fw_file_pos + j + 3] << 16) +
+		    (fw->data[fw_file_pos + j + 4] << 24);
+		j += 5;
+	}
+	dev->data.fw_segs = segs;
+
+	fw_file_pos += j;
+
+	/* FirmwareV2_partitions */
+	if (dev->data.fw_parts != fw->data[fw_file_pos]) {
+		err("FirmwareV2_SEGMENTLENGTH != FirmwareV2_partitions[0], parsing error!!!");
+		return -EPERM;
+	}
+
+	fw_file_pos += 1;
+
+	/* FirmwareV2_SCRIPTSETLENGTH == 1 */
+	if (fw->data[fw_file_pos] != 1) {
+		err("FirmwareV2_SCRIPTSETLENGTH != 1 !!");
+		return -EPERM;
+	}
+
+	fw_file_pos += 4;
+
+	/* Word FirmwareV2_scriptSets */
+	script_sets = kzalloc(sizeof(u16), GFP_KERNEL);
+	*script_sets = fw->data[fw_file_pos] + (fw->data[fw_file_pos + 1] << 8);
+	dev->data.script_sets = script_sets;
+
+	fw_file_pos += 2;
+
+	/* FirmwareV2_scripts */
+	j = 0;
+	scripts = kzalloc(*script_sets * sizeof(*scripts), GFP_KERNEL);
+	for (i = 0; i < *script_sets; i++) {
+		scripts[i].address = fw->data[fw_file_pos + j] +
+		    (fw->data[fw_file_pos + j + 1] << 8) +
+		    (fw->data[fw_file_pos + j + 2] << 16) +
+		    (fw->data[fw_file_pos + j + 3] << 24);
+
+		scripts[i].value = fw->data[fw_file_pos + j + 4];
+		j += 5;
+	}
+
+	dev->data.scripts = scripts;
+	fw_file_pos += j;
+
+	if (chip_v2 && (fw_file_pos == fw->size)) {
+		info("FW file only include IT9135 v2 firmware");
+		goto end_of_fw;
+	} else if (!chip_v2 && (fw_file_pos == partition_len_v1)) {
+		info("FW file only include IT9135 v1 firmware!");
+		goto end_of_fw;
+	}
+
+	/*--- Parsing Firmware_Afa_Omega_Script ---*/
+
+	dev->data.tuner_script_normal = script_parser(fw, &fw_file_pos,
+						      &(dev->data.
+							tuner_script_sets_normal));
+
+	if (dev->data.tuner_script_normal == NULL)
+		return -EPERM;
+
+	if (chip_v2 && (fw_file_pos == fw->size)) {
+		info("~~~ .Fw file only include Omega2 firmware&Omega_Script!!");
+		goto end_of_fw;
+	} else if (!chip_v2 && (fw_file_pos == partition_len_v1)) {
+		info("~~~ .Fw file only include Omega1 firmware&Omega_Script!!");
+		goto end_of_fw;
+	}
+
+	/*--- Parsing Firmware_Afa_Omega_LNA_Config_1_Script ---*/
+
+	dev->data.tuner_script_lna1 =
+	    script_parser(fw, &fw_file_pos,
+			  &(dev->data.tuner_script_sets_lna1));
+
+	if (dev->data.tuner_script_lna1 == NULL)
+		return -EPERM;
+	if (chip_v2 && (fw_file_pos == fw->size)) {
+		info("~~~ .Fw file only include Omega2 firmware Script1!!");
+		goto end_of_fw;
+	} else if (!chip_v2 && (fw_file_pos == partition_len_v1)) {
+		info("~~~ .Fw file only include Omega1 firmware, Script1!!");
+		goto end_of_fw;
+	}
+
+	/*--- Parsing Firmware_Afa_Omega_LNA_Config_2_Script_V2 ---*/
+	dev->data.tuner_script_lna2 =
+	    script_parser(fw, &fw_file_pos,
+			  &(dev->data.tuner_script_sets_lna2));
+
+	if (dev->data.tuner_script_lna2 == NULL)
+		return -EPERM;
+
+	if (chip_v2 && (fw_file_pos == fw->size)) {
+		info("~~~ .Fw file only include Omega2 firmware, Scripts1&2!!");
+		goto end_of_fw;
+	} else if (!chip_v2 && (fw_file_pos == partition_len_v1)) {
+		info("~~~ .Fw file only include Omega1 firmware, Scripts1&2!!");
+		goto end_of_fw;
+	}
+
+end_of_fw:
+
+	/**** Init Device first ****/
+	retval = it9135_device_init(udev, dev, true);
+	if (retval) {
+		if (retval)
+			err("device_init Fail: 0x%08x\n", retval);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < it9135_device_count; i++) {
+		if (dev->architecture == ARCHITECTURE_PIP) {
+			deb_info("@@@@@@@ adapter == 2");
+			it9135_properties[i].num_adapters = 2;
+			it9135_properties[i].caps = DVB_USB_IS_AN_I2C_ADAPTER;
+		} else {
+			deb_info("@@@@@@@ adapter == 1");
+			it9135_properties[i].caps = 0;
+			it9135_properties[i].num_adapters = 1;
+		}
+
+		/* USB1.1 set smaller buffersize and disable 2nd adapter */
+		if (udev->speed == USB_SPEED_FULL) {
+			it9135_properties[i].adapter[0].stream.u.bulk.buffersize
+			    = (188 * 21);
+		} else {
+			it9135_properties[i].adapter[0].stream.u.bulk.buffersize
+			    = (188 * 348);
+		}
+
+	}
+
+	return 0;
+}
+
+static int it9135_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	return 0;
+}
+
+static int it9135_identify_state(struct usb_device *udev,
+				 struct dvb_usb_device_properties *props,
+				 struct dvb_usb_device_description **desc,
+				 int *cold)
+{
+	/* *cold = 0; */
+	return 0;
+}
+
+static int it9135_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+			   int num)
+{
+	return 0;
+}
+
+static u32 it9135_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm it9135_i2c_algo = {
+	.master_xfer = it9135_i2c_xfer,
+	.functionality = it9135_i2c_func,
+};
+
+/* Called to attach the possible frontends */
+static int it9135_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	deb_func("Enter %s Function - chip=%d\n", __func__, adap->id);
+
+	adap->fe = it9135_attach(adap);
+
+	return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static int it9135_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	deb_func("Enter %s Function - (%s) streaming state for chip=%d\n",
+		 __func__, onoff ? "ON" : "OFF", adap->id);
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* ******* IT9135 DVB USB DEVICE ******* */
+
+/* Table of devices that work with this driver */
+struct usb_device_id it9135_usb_id_table[] = {
+	{USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135)},
+	{USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005)},
+	{USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006)},
+	{0},			/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, it9135_usb_id_table);
+
+struct dvb_usb_device_properties it9135_properties[] = {
+	{
+	 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	 .download_firmware = it9135_download_firmware,
+	 .firmware = "dvb-usb-it9135.fw",
+
+	 .size_of_priv = sizeof(struct it9135_state),
+	 .i2c_algo = &it9135_i2c_algo,
+
+	 .usb_ctrl = DEVICE_SPECIFIC,
+
+	 .no_reconnect = 1,
+	 .power_ctrl = it9135_power_ctrl,
+	 .identify_state = it9135_identify_state,
+	 .num_adapters = 2,
+	 .adapter = {
+		     {
+		      .caps =
+		      DVB_USB_ADAP_HAS_PID_FILTER |
+		      DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+		      .pid_filter_count = 32,
+		      .pid_filter = it9135_pid_filter,
+		      .pid_filter_ctrl = it9135_pid_filter_ctrl,
+		      .frontend_attach = it9135_frontend_attach,
+		      .streaming_ctrl = it9135_streaming_ctrl,
+		      .stream = {
+				 .type = USB_BULK,
+				 .count = 4,
+				 .endpoint = 0x84,
+				 .u = {
+				       .bulk = {
+						.buffersize = (188 * 348),
+						}
+				       }
+				 }
+		      },
+		     {
+		      .caps =
+		      DVB_USB_ADAP_HAS_PID_FILTER |
+		      DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+		      .pid_filter_count = 32,
+		      .pid_filter = it9135_pid_filter,
+		      .pid_filter_ctrl = it9135_pid_filter_ctrl,
+		      .frontend_attach = it9135_frontend_attach,
+		      .streaming_ctrl = it9135_streaming_ctrl,
+		      .stream = {
+				 .type = USB_BULK,
+				 .count = 4,
+				 .endpoint = 0x85,
+				 .u = {
+				       .bulk = {
+						.buffersize = (188 * 348),
+						}
+				       }
+				 }
+		      },
+		     },
+	 .num_device_descs = 1,
+	 .devices = {
+		     {"ITEtech USB2.0 DVB-T Recevier",
+		      {&it9135_usb_id_table[0], &it9135_usb_id_table[1],
+		       &it9135_usb_id_table[2], NULL},
+		      {NULL},
+		      },
+		     {NULL},
+
+		     }
+	 }
+};
+
+int it9135_device_count = ARRAY_SIZE(it9135_properties);
+
+/* Register a DVB_USB device and a USB device node end */
+static int it9135_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	int retval = -ENOMEM;
+	int i;
+	struct dvb_usb_device *d = NULL;
+
+	if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+
+		if (it9135_device_count > 2)
+			it9135_device_count = 2;
+
+		for (i = 0; i < it9135_device_count; i++) {
+			retval =
+			    dvb_usb_device_init(intf, &it9135_properties[i],
+						THIS_MODULE, &d, adapter_nr);
+
+			if (!retval) {
+				deb_info("dvb_usb_device_init success!!\n");
+				break;
+			}
+			if (retval != -ENODEV)
+				return retval;
+		}
+		if (retval)
+			return retval;
+	}
+
+	return retval;
+}
+
+static int it9135_suspend(struct usb_interface *intf, pm_message_t state)
+{
+	deb_func("Enter %s Function\n", __func__);
+	return 0;
+}
+
+static int it9135_resume(struct usb_interface *intf)
+{
+	deb_func("Enter %s Function\n", __func__);
+	return 0;
+}
+
+static int it9135_reset_resume(struct usb_interface *intf)
+{
+	int retval = -ENOMEM;
+	int i;
+	struct it9135_dev_ctx *dev = NULL;
+	struct usb_device *udev;
+
+	deb_func("Enter %s Function\n", __func__);
+
+	udev = interface_to_usbdev(intf);
+	dev = dev_get_drvdata(&udev->dev);
+
+	retval = it9135_device_init(udev, dev, 1);
+	if (retval) {
+		if (retval)
+			err("device_init Fail: 0x%08x", retval);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < dev->data.chip_num; i++)
+		it9135_dl_ap_ctrl(dev, i, 1);
+
+	return 0;
+}
+
+static void it9135_i2c_exit(struct dvb_usb_device *d)
+{
+	struct it9135_state *state = d->priv;
+
+	deb_func("%s:\n", __func__);
+
+	/* remove 2nd I2C adapter */
+	if (d->state & DVB_USB_STATE_I2C) {
+		try_module_get(THIS_MODULE);
+		i2c_del_adapter(&state->i2c_adap);
+	}
+}
+
+static void it9135_disconnect(struct usb_interface *intf)
+{
+	struct it9135_dev_ctx *dev;
+	struct usb_device *udev;
+	int minor = intf->minor;
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+
+	deb_func("%s:\n", __func__);
+
+	udev = interface_to_usbdev(intf);
+	dev = dev_get_drvdata(&udev->dev);
+	dev->disconnect = 1;
+
+	kfree(dev->data.script_sets);
+	kfree(dev->data.scripts);
+	kfree(dev->data.fw_codes);
+	kfree(dev->data.fw_segs);
+	kfree(dev->data.tuner_script_normal);
+	kfree(dev->data.tuner_script_lna1);
+	kfree(dev->data.tuner_script_lna2);
+	kfree(dev);
+
+	/* remove 2nd I2C adapter */
+	if (d != NULL && d->desc != NULL)
+		it9135_i2c_exit(d);
+
+	try_module_get(THIS_MODULE);
+	dvb_usb_device_exit(intf);
+
+	deb_info("ITEtech USB #%d now disconnected", minor);
+}
+
+static struct usb_driver it9135_driver = {
+	.name = "dvb_usb_it9135",
+	.probe = it9135_probe,
+	.disconnect = it9135_disconnect,
+	.id_table = it9135_usb_id_table,
+	.suspend = it9135_suspend,
+	.resume = it9135_resume,
+	.reset_resume = it9135_reset_resume,
+};
+
+/* Insert it9135 module and prepare to register it9135 driver */
+static int __init it9135_module_init(void)
+{
+	int ret;
+
+	deb_info("dvb_usb_it9135 Module is loaded\n");
+
+	ret = usb_register(&it9135_driver);
+
+	if (ret) {
+		err("usb_register failed. Error number %d", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* Deregister this driver with the USB subsystem */
+static void __exit it9135_module_exit(void)
+{
+	deb_info("dvb_usb_it9135 Module is unloaded!\n");
+	usb_deregister(&it9135_driver);
+}
+
+module_init(it9135_module_init);
+module_exit(it9135_module_exit);
+
+MODULE_AUTHOR("Jason Dong <jason.dong@ite.com.tw>");
+MODULE_DESCRIPTION("Driver for devices based on ITEtech IT9135");
+MODULE_VERSION(DRIVER_RELEASE_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/it9135.h b/drivers/media/dvb/dvb-usb/it9135.h
new file mode 100644
index 0000000..d1cf54c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/it9135.h
@@ -0,0 +1,155 @@
+/*
+ * DVB USB Linux driver for IT9135 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2011 ITE Technologies, INC.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ */
+
+#ifndef _IT9135_H_
+#define _IT9135_H_
+
+#define DVB_USB_LOG_PREFIX "IT9135"
+
+#include <linux/version.h>
+
+#include "dvb-usb.h"
+#include "it9135-fe.h"
+
+#define DRIVER_RELEASE_VERSION	"v11.08.02.1"
+/* **************** customization **************** */
+extern int dvb_usb_it9135_debug;
+
+#ifdef CONFIG_DVB_USB_IT9135_DEBUG
+#define deb_func(args...)	printk(KERN_INFO args)
+#define deb_info(args...)	printk(KERN_INFO args)
+#define deb_warning(args...)	printk(KERN_INFO args)
+#define dmg(format, arg...)	printk(KERN_ERR DVB_USB_LOG_PREFIX "::" "%s: " format "\n" , __func__, ## arg)
+#else
+#define deb_func(args...)	dprintk(dvb_usb_it9135_debug, 0x01, args)
+#define deb_info(args...)	dprintk(dvb_usb_it9135_debug, 0x02, args)
+#define deb_warning(args...)	dprintk(dvb_usb_it9135_debug, 0x04, args)
+#define dmg(format, arg...)	printk(KERN_ERR DVB_USB_LOG_PREFIX "::" "%s: " format "\n" , __func__, ## arg)
+#endif
+/* **************** from device.h **************** */
+#define IT9135_TS_PACKET_SIZE		188
+#define IT9135_TS_PACKET_COUNT_HI	348
+#define IT9135_TS_PACKET_COUNT_FU	21
+
+/* **************** from driver.h **************** */
+#define IT9135_TS_FRAMES_HI		128
+#define IT9135_TS_FRAMES_FU		128
+#define IT9135_MAX_USB20_IRP_NUM	5
+#define IT9135_MAX_USB11_IRP_NUM	2
+
+/* **************** from afdrv.h **************** */
+#define EEPROM_FLB_OFS		8
+
+#define EEPROM_IRMODE       (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x10)	/* 00:disabled, 01:HID */
+#define EEPROM_SELSUSPEND   (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x28)	/* Selective Suspend Mode */
+#define EEPROM_TSMODE       (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x28+1)	/* 0:one ts, 1:dual ts */
+#define EEPROM_2WIREADDR    (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x28+2)	/* MPEG2 2WireAddr */
+#define EEPROM_SUSPEND      (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x28+3)	/* Suspend Mode */
+#define EEPROM_IRTYPE       (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x28+4)	/* 0:NEC, 1:RC6 */
+#define EEPROM_SAWBW1       (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x28+5)
+#define EEPROM_XTAL1        (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x28+6)	/* 0:28800, 1:20480 */
+#define EEPROM_SPECINV1     (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x28+7)
+#define EEPROM_TUNERID      (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x30+4)
+#define EEPROM_IFFREQL      (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x30)
+#define EEPROM_IFFREQH      (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x30+1)
+#define EEPROM_IF1L         (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x30+2)
+#define EEPROM_IF1H         (OVA_EEPROM_CFG+EEPROM_FLB_OFS+0x30+3)
+#define EEPROM_SHIFT        (0x10)	/* EEPROM Addr Shift for slave front end */
+
+/* **************** from device.h **************** */
+struct it9135_state {
+	struct i2c_adapter i2c_adap;	/* I2C adapter for 2nd FE */
+	u8 rc_repeat;
+	u32 rc_keycode;
+};
+
+struct it9135_tuner_info {
+	int inited;
+	int setting_freq;
+	unsigned short id;
+	int set;
+	int locked;
+};
+
+struct it9135_filter_ctx_hw {
+	struct it9135_tuner_info tuner_info;
+	unsigned long curr_freq;
+	unsigned short curr_bw;
+	unsigned long desired_freq;
+	unsigned short desired_bw;
+	int timer_on;
+	int en_pid;
+	int ap_on;
+	int reset_ts;
+	unsigned char ovr_flw_chk;
+};
+
+/* IT9135 device context */
+struct it9135_dev_ctx {
+	struct it9135_filter_ctx_hw fc[2];
+	struct mutex it9135_mutex;
+	int boot_code;
+	int ep12_err;
+	int ep45_err;
+	int dual_ts;
+	int ir_tab_load;
+	int proprietary_ir;
+	u8 ir_type;		/* EE chose NEC RC5 RC6 table */
+	int surprise_removal;
+	int dev_not_resp;
+	int enter_suspend;
+	u16 usb_mode;
+	u16 max_packet_sz;
+	u32 ts_frames;
+	u32 ts_frame_sz;
+	u32 ts_frame_sz_dw;
+	u32 ts_packet_cnt;
+	int selective_suspend;
+	u32 active_filter;
+	unsigned char architecture;
+	unsigned char stream_type;
+	int dca_pip;
+	int swap_filter;
+	u8 filter_cnt;
+	u8 filter_index;
+	int tuner_pw_off;
+	u8 usb_ctrl_timeOut;
+	struct it9135_data data;
+	int disconnect;
+	/* patch for Om1 Om2 EE */
+	unsigned char chip_ver;
+	int already_nim_reset_seq;
+	/* Fw versiion */
+	u32 ofdm_ver;
+	u32 link_ver;
+	u8 fw_ver[32];
+
+};
+
+struct it9135_ofdm_channel {
+	u32 rf_khz;
+	u8 bw;
+	s16 nfft;
+	s16 guard;
+	s16 nqam;
+	s16 vit_hrch;
+	s16 vit_select_hp;
+	s16 vit_alpha;
+	s16 vit_code_rate_hp;
+	s16 vit_code_rate_lp;
+	u8 intlv_native;
+};
+
+/**********************************************/
+
+extern int it9135_device_count;
+
+#endif
-- 
1.7.1




             reply	other threads:[~2011-08-05 10:32 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-05 10:24 jasondong [this message]
2011-08-06  9:51 ` [PATCH 1/2] IT9135 Add support for KWORLD_UB499_2T_T09 (id 1b80:e409) Malcolm Priestley
2011-08-06  9:52 ` [PATCH 2/2] IT9135 add MFE support to driver Malcolm Priestley
2011-08-24 18:08 ` [PATCH 1/1] Add driver support for ITE IT9135 device Arkadiusz Miskiewicz
2011-08-24 20:27   ` Arkadiusz Miskiewicz
2011-09-03 13:44 ` Mauro Carvalho Chehab

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1312539895.2763.33.camel@Jason-Linux \
    --to=jason.dong@ite.com.tw \
    --cc=linux-media@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).