From patchwork Fri Aug 5 10:24:55 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: jasondong X-Patchwork-Id: 1038212 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p75AWS4E030842 for ; Fri, 5 Aug 2011 10:32:28 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756617Ab1HEKcY (ORCPT ); Fri, 5 Aug 2011 06:32:24 -0400 Received: from itemail.ite.com.tw ([210.208.198.203]:7661 "EHLO ironport.internal.ite.com.tw" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754774Ab1HEKcU convert rfc822-to-8bit (ORCPT ); Fri, 5 Aug 2011 06:32:20 -0400 X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 05 Aug 2011 10:32:30 +0000 (UTC) X-Greylist: delayed 594 seconds by postgrey-1.27 at vger.kernel.org; Fri, 05 Aug 2011 06:32:16 EDT Received: from unknown (HELO mse.ite.com.tw) ([192.168.35.30]) by ironport.internal.ite.com.tw with ESMTP; 05 Aug 2011 18:22:21 +0800 Received: from hscmail.internal.ite.com.tw (hscmail.internal.ite.com.tw [192.168.35.14]) by mse.ite.com.tw with ESMTP id p75AMJtU086999 for ; Fri, 5 Aug 2011 18:22:19 +0800 (CST) (envelope-from Jason.Dong@ite.com.tw) Received: from tpemail.internal.ite.com.tw ([192.168.15.3]) by hscmail.internal.ite.com.tw with Microsoft SMTPSVC(6.0.3790.4675); Fri, 5 Aug 2011 18:21:55 +0800 Received: from 192.168.14.156 ([192.168.14.156]) by tpemail.internal.ite.com.tw ([192.168.15.3]) with Microsoft Exchange Server HTTP-DAV ; Fri, 5 Aug 2011 10:21:54 +0000 Received: from Jason-Linux by tpemail.internal.ite.com.tw; 05 Aug 2011 18:24:55 +0800 Subject: [PATCH 1/1] Add driver support for ITE IT9135 device From: jasondong To: linux-media@vger.kernel.org Date: Fri, 05 Aug 2011 18:24:55 +0800 Message-ID: <1312539895.2763.33.camel@Jason-Linux> Mime-Version: 1.0 X-Mailer: Evolution 2.28.3 X-OriginalArrivalTime: 05 Aug 2011 10:21:55.0600 (UTC) FILETIME=[80437100:01CC5359] X-TM-AS-Product-Ver: SMEX-8.0.0.4125-6.500.1024-18302.000 X-TM-AS-Result: No--0.033100-8.000000-31 X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-MAIL: mse.ite.com.tw p75AMJtU086999 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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 --- 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 + +#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
+ * 
+ */ +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
+ * 
+ */ +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
+ * 
+ */ +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
+ * 
+ */ +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
+ * 
+ */ +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
+ * 
+ */ +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
+ * 
+ */ +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
+ * 
+ */ +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
+ * 
+ */ +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
+ * 
+ */ +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 "); +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 + +#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