Przeglądaj źródła

add FCI FC2580 tuner support

Signed-off-by: Steve Markgraf <steve@steve-m.de>
Steve Markgraf 13 lat temu
rodzic
commit
b5e4b76885
6 zmienionych plików z 641 dodań i 17 usunięć
  1. 1 1
      include/Makefile.am
  2. 127 0
      include/tuner_fc2580.h
  3. 1 0
      src/CMakeLists.txt
  4. 1 1
      src/Makefile.am
  5. 17 15
      src/rtl-sdr.c
  6. 494 0
      src/tuner_fc2580.c

+ 1 - 1
include/Makefile.am

@@ -1,5 +1,5 @@
 rtlsdr_HEADERS = rtl-sdr.h
 rtlsdr_HEADERS = rtl-sdr.h
 
 
-noinst_HEADERS = rtlsdr_i2c.h tuner_e4000.h tuner_fc0012.h tuner_fc0013.h
+noinst_HEADERS = rtlsdr_i2c.h tuner_e4000.h tuner_fc0012.h tuner_fc0013.h tuner_fc2580.h
 
 
 rtlsdrdir = $(includedir)
 rtlsdrdir = $(includedir)

+ 127 - 0
include/tuner_fc2580.h

@@ -0,0 +1,127 @@
+#ifndef __TUNER_FC2580_H
+#define __TUNER_FC2580_H
+
+#define	BORDER_FREQ	2600000	//2.6GHz : The border frequency which determines whether Low VCO or High VCO is used
+#define USE_EXT_CLK	0	//0 : Use internal XTAL Oscillator / 1 : Use External Clock input
+#define OFS_RSSI 57
+
+#define FC2580_I2C_ADDR		0xac
+#define FC2580_CHECK_ADDR	0x01
+#define FC2580_CHECK_VAL	0x56
+
+typedef enum {
+	FC2580_UHF_BAND,
+	FC2580_L_BAND,
+	FC2580_VHF_BAND,
+	FC2580_NO_BAND
+} fc2580_band_type;
+
+typedef enum {
+	FC2580_FCI_FAIL,
+	FC2580_FCI_SUCCESS
+} fc2580_fci_result_type;
+
+enum FUNCTION_STATUS
+{
+	FUNCTION_SUCCESS,
+	FUNCTION_ERROR,
+};
+
+extern void fc2580_wait_msec(void *pTuner, int a);
+
+fc2580_fci_result_type fc2580_i2c_write(void *pTuner, unsigned char reg, unsigned char val);
+fc2580_fci_result_type fc2580_i2c_read(void *pTuner, unsigned char reg, unsigned char *read_data);
+
+/*==============================================================================
+       fc2580 initial setting
+
+  This function is a generic function which gets called to initialize
+
+  fc2580 in DVB-H mode or L-Band TDMB mode
+
+  <input parameter>
+
+  ifagc_mode
+    type : integer
+	1 : Internal AGC
+	2 : Voltage Control Mode
+
+==============================================================================*/
+fc2580_fci_result_type fc2580_set_init(void *pTuner, int ifagc_mode, unsigned int freq_xtal );
+
+/*==============================================================================
+       fc2580 frequency setting
+
+  This function is a generic function which gets called to change LO Frequency
+
+  of fc2580 in DVB-H mode or L-Band TDMB mode
+
+  <input parameter>
+
+  f_lo
+	Value of target LO Frequency in 'kHz' unit
+	ex) 2.6GHz = 2600000
+
+==============================================================================*/
+fc2580_fci_result_type fc2580_set_freq(void *pTuner, unsigned int f_lo, unsigned int freq_xtal );
+
+
+/*==============================================================================
+       fc2580 filter BW setting
+
+  This function is a generic function which gets called to change Bandwidth
+
+  frequency of fc2580's channel selection filter
+
+  <input parameter>
+
+  filter_bw
+    1 : 1.53MHz(TDMB)
+	6 : 6MHz
+	7 : 7MHz
+	8 : 7.8MHz
+
+
+==============================================================================*/
+fc2580_fci_result_type fc2580_set_filter( void *pTuner, unsigned char filter_bw, unsigned int freq_xtal );
+
+// The following context is FC2580 tuner API source code
+// Definitions
+
+// AGC mode
+enum FC2580_AGC_MODE
+{
+	FC2580_AGC_INTERNAL = 1,
+	FC2580_AGC_EXTERNAL = 2,
+};
+
+
+// Bandwidth mode
+enum FC2580_BANDWIDTH_MODE
+{
+	FC2580_BANDWIDTH_1530000HZ = 1,
+	FC2580_BANDWIDTH_6000000HZ = 6,
+	FC2580_BANDWIDTH_7000000HZ = 7,
+	FC2580_BANDWIDTH_8000000HZ = 8,
+};
+
+// Manipulaing functions
+int
+fc2580_Initialize(
+	void *pTuner
+	);
+
+int
+fc2580_SetRfFreqHz(
+	void *pTuner,
+	unsigned long RfFreqHz
+	);
+
+// Extra manipulaing functions
+int
+fc2580_SetBandwidthMode(
+	void *pTuner,
+	int BandwidthMode
+	);
+
+#endif

+ 1 - 0
src/CMakeLists.txt

@@ -25,6 +25,7 @@ add_library(rtlsdr SHARED
     tuner_e4000.c
     tuner_e4000.c
     tuner_fc0012.c
     tuner_fc0012.c
     tuner_fc0013.c
     tuner_fc0013.c
+    tuner_fc2580.c
 )
 )
 
 
 target_link_libraries(rtlsdr
 target_link_libraries(rtlsdr

+ 1 - 1
src/Makefile.am

@@ -7,7 +7,7 @@ AM_CFLAGS = -fPIC -Wall
 
 
 lib_LTLIBRARIES = librtlsdr.la
 lib_LTLIBRARIES = librtlsdr.la
 
 
-librtlsdr_la_SOURCES = rtl-sdr.c tuner_e4000.c tuner_fc0012.c tuner_fc0013.c
+librtlsdr_la_SOURCES = rtl-sdr.c tuner_e4000.c tuner_fc0012.c tuner_fc0013.c tuner_fc2580.c
 librtlsdr_la_LDFALGS = -version-info $(LIBVERSION)
 librtlsdr_la_LDFALGS = -version-info $(LIBVERSION)
 
 
 bin_PROGRAMS         = rtl_sdr
 bin_PROGRAMS         = rtl_sdr

+ 17 - 15
src/rtl-sdr.c

@@ -29,6 +29,7 @@
 #include "tuner_e4000.h"
 #include "tuner_e4000.h"
 #include "tuner_fc0012.h"
 #include "tuner_fc0012.h"
 #include "tuner_fc0013.h"
 #include "tuner_fc0013.h"
+#include "tuner_fc2580.h"
 
 
 typedef struct rtlsdr_tuner {
 typedef struct rtlsdr_tuner {
 	int(*init)(void *);
 	int(*init)(void *);
@@ -73,16 +74,24 @@ int fc0013_set_bw(void *dev, int bw) {
 }
 }
 int fc0013_set_gain(void *dev, int gain) { return 0; }
 int fc0013_set_gain(void *dev, int gain) { return 0; }
 
 
+int fc2580_init(void *dev) { return fc2580_Initialize(dev); }
+int fc2580_exit(void *dev) { return 0; }
+int fc2580_tune(void *dev, int freq) { return fc2580_SetRfFreqHz(dev, freq); }
+int fc2580_set_bw(void *dev, int bw) { return fc2580_SetBandwidthMode(dev, 1); }
+int fc2580_set_gain(void *dev, int gain) { return 0; }
+
 enum rtlsdr_tuners {
 enum rtlsdr_tuners {
 	RTLSDR_TUNER_E4000,
 	RTLSDR_TUNER_E4000,
 	RTLSDR_TUNER_FC0012,
 	RTLSDR_TUNER_FC0012,
 	RTLSDR_TUNER_FC0013,
 	RTLSDR_TUNER_FC0013,
+	RTLSDR_TUNER_FC2580
 };
 };
 
 
 static rtlsdr_tuner_t tuners[] = {
 static rtlsdr_tuner_t tuners[] = {
 	{ e4k_init, e4k_exit, e4k_tune, e4k_set_bw, e4k_set_gain, 0, 0, 0 },
 	{ e4k_init, e4k_exit, e4k_tune, e4k_set_bw, e4k_set_gain, 0, 0, 0 },
 	{ fc0012_init, fc0012_exit, fc0012_tune, fc0012_set_bw, fc0012_set_gain, 0, 0, 0 },
 	{ fc0012_init, fc0012_exit, fc0012_tune, fc0012_set_bw, fc0012_set_gain, 0, 0, 0 },
 	{ fc0013_init, fc0013_exit, fc0013_tune, fc0013_set_bw, fc0013_set_gain, 0, 0, 0 },
 	{ fc0013_init, fc0013_exit, fc0013_tune, fc0013_set_bw, fc0013_set_gain, 0, 0, 0 },
+	{ fc2580_init, fc2580_exit, fc2580_tune, fc2580_set_bw, fc2580_set_gain, 0, 0, 0 },
 };
 };
 
 
 typedef struct rtlsdr_device {
 typedef struct rtlsdr_device {
@@ -570,12 +579,6 @@ const char *rtlsdr_get_device_name(uint32_t index)
 		return "";
 		return "";
 }
 }
 
 
-/* TODO: put those defines in the tuner header once the drivers are added */
-
-#define FC2580_I2C_ADDR		0xac
-#define FC2580_CHECK_ADDR	0x01
-#define FC2580_CHECK_VAL	0x56
-
 rtlsdr_dev_t *rtlsdr_open(int index)
 rtlsdr_dev_t *rtlsdr_open(int index)
 {
 {
 	int r;
 	int r;
@@ -651,21 +654,20 @@ rtlsdr_dev_t *rtlsdr_open(int index)
 		goto found;
 		goto found;
 	}
 	}
 
 
+	/* initialise GPIOs */
+	rtlsdr_set_gpio_output(dev, 5);
+
+	/* reset tuner before probing */
+	rtlsdr_set_gpio_bit(dev, 5, 1);
+	rtlsdr_set_gpio_bit(dev, 5, 0);
+
 	reg = rtlsdr_i2c_read_reg(dev, FC2580_I2C_ADDR, FC2580_CHECK_ADDR);
 	reg = rtlsdr_i2c_read_reg(dev, FC2580_I2C_ADDR, FC2580_CHECK_ADDR);
 	if ((reg & 0x7f) == FC2580_CHECK_VAL) {
 	if ((reg & 0x7f) == FC2580_CHECK_VAL) {
 		fprintf(stderr, "Found FCI 2580 tuner\n");
 		fprintf(stderr, "Found FCI 2580 tuner\n");
-		//dev->tuner = &tuners[RTLSDR_TUNER_FC2580];
-		// TODO: set GPIO5 low
+		dev->tuner = &tuners[RTLSDR_TUNER_FC2580];
 		goto found;
 		goto found;
 	}
 	}
 
 
-	/* initialise GPIOs (only needed for the FC0012 so far */
-	rtlsdr_set_gpio_output(dev, 5);
-
-	/* reset FC0012 before probing */
-	rtlsdr_set_gpio_bit(dev, 5, 1);
-	rtlsdr_set_gpio_bit(dev, 5, 0);
-
 	reg = rtlsdr_i2c_read_reg(dev, FC0012_I2C_ADDR, FC0012_CHECK_ADDR);
 	reg = rtlsdr_i2c_read_reg(dev, FC0012_I2C_ADDR, FC0012_CHECK_ADDR);
 	if (reg == FC0012_CHECK_VAL) {
 	if (reg == FC0012_CHECK_VAL) {
 		fprintf(stderr, "Found Fitipower FC0012 tuner\n");
 		fprintf(stderr, "Found Fitipower FC0012 tuner\n");

+ 494 - 0
src/tuner_fc2580.c

@@ -0,0 +1,494 @@
+/*
+ * FCI FC2580 tuner driver, taken from the kernel driver that can be found
+ * on http://linux.terratec.de/tv_en.html
+ *
+ * This driver is a mess, and should be cleaned up/rewritten.
+ *
+ */
+
+#include <stdint.h>
+
+#include "rtlsdr_i2c.h"
+#include "tuner_fc2580.h"
+
+/* 16.384 MHz (at least on the Logilink VG0002A) */
+#define CRYSTAL_FREQ		16384000
+
+/* glue functions to rtl-sdr code */
+
+fc2580_fci_result_type fc2580_i2c_write(void *pTuner, unsigned char reg, unsigned char val)
+{
+	uint8_t data[2];
+
+	data[0] = reg;
+	data[1] = val;
+
+	if (rtlsdr_i2c_write((rtlsdr_dev_t *)pTuner, FC2580_I2C_ADDR, data, 2) < 0)
+		return FC2580_FCI_FAIL;
+
+	return FC2580_FCI_SUCCESS;
+}
+
+fc2580_fci_result_type fc2580_i2c_read(void *pTuner, unsigned char reg, unsigned char *read_data)
+{
+	uint8_t data = reg;
+
+	if (rtlsdr_i2c_write((rtlsdr_dev_t *)pTuner, FC2580_I2C_ADDR, &data, 1) < 0)
+		return FC2580_FCI_FAIL;
+
+	if (rtlsdr_i2c_read((rtlsdr_dev_t *)pTuner, FC2580_I2C_ADDR, &data, 1) < 0)
+		return FC2580_FCI_FAIL;
+
+	*read_data = data;
+
+	return FC2580_FCI_SUCCESS;
+}
+
+int
+fc2580_Initialize(
+	void *pTuner
+	)
+{
+	int AgcMode;
+	unsigned int CrystalFreqKhz;
+
+	//TODO set AGC mode
+	AgcMode = FC2580_AGC_EXTERNAL;
+
+	// Initialize tuner with AGC mode.
+	// Note: CrystalFreqKhz = round(CrystalFreqHz / 1000)
+	CrystalFreqKhz = (unsigned int)((CRYSTAL_FREQ + 500) / 1000);
+
+	if(fc2580_set_init(pTuner, AgcMode, CrystalFreqKhz) != FC2580_FCI_SUCCESS)
+		goto error_status_initialize_tuner;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_initialize_tuner:
+	return FUNCTION_ERROR;
+}
+
+int
+fc2580_SetRfFreqHz(
+	void *pTuner,
+	unsigned long RfFreqHz
+	)
+{
+	unsigned int RfFreqKhz;
+	unsigned int CrystalFreqKhz;
+
+	// Set tuner RF frequency in KHz.
+	// Note: RfFreqKhz = round(RfFreqHz / 1000)
+	//       CrystalFreqKhz = round(CrystalFreqHz / 1000)
+	RfFreqKhz = (unsigned int)((RfFreqHz + 500) / 1000);
+	CrystalFreqKhz = (unsigned int)((CRYSTAL_FREQ + 500) / 1000);
+
+	if(fc2580_set_freq(pTuner, RfFreqKhz, CrystalFreqKhz) != FC2580_FCI_SUCCESS)
+		goto error_status_set_tuner_rf_frequency;
+
+	return FUNCTION_SUCCESS;
+
+error_status_set_tuner_rf_frequency:
+	return FUNCTION_ERROR;
+}
+
+/**
+
+@brief   Set FC2580 tuner bandwidth mode.
+
+*/
+int
+fc2580_SetBandwidthMode(
+	void *pTuner,
+	int BandwidthMode
+	)
+{
+	unsigned int CrystalFreqKhz;
+
+	// Set tuner bandwidth mode.
+	// Note: CrystalFreqKhz = round(CrystalFreqHz / 1000)
+	CrystalFreqKhz = (unsigned int)((CRYSTAL_FREQ + 500) / 1000);
+
+	if(fc2580_set_filter(pTuner, (unsigned char)BandwidthMode, CrystalFreqKhz) != FC2580_FCI_SUCCESS)
+		goto error_status_set_tuner_bandwidth_mode;
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_tuner_bandwidth_mode:
+	return FUNCTION_ERROR;
+}
+
+void fc2580_wait_msec(void *pTuner, int a)
+{
+	/* USB latency is enough for now ;) */
+//	usleep(a * 1000);
+	return;
+}
+
+/*==============================================================================
+       fc2580 initial setting
+
+  This function is a generic function which gets called to initialize
+
+  fc2580 in DVB-H mode or L-Band TDMB mode
+
+  <input parameter>
+
+  ifagc_mode
+    type : integer
+	1 : Internal AGC
+	2 : Voltage Control Mode
+
+==============================================================================*/
+fc2580_fci_result_type fc2580_set_init( void *pTuner, int ifagc_mode, unsigned int freq_xtal )
+{
+	fc2580_fci_result_type result = FC2580_FCI_SUCCESS;
+
+	result &= fc2580_i2c_write(pTuner, 0x00, 0x00);	/*** Confidential ***/
+	result &= fc2580_i2c_write(pTuner, 0x12, 0x86);
+	result &= fc2580_i2c_write(pTuner, 0x14, 0x5C);
+	result &= fc2580_i2c_write(pTuner, 0x16, 0x3C);
+	result &= fc2580_i2c_write(pTuner, 0x1F, 0xD2);
+	result &= fc2580_i2c_write(pTuner, 0x09, 0xD7);
+	result &= fc2580_i2c_write(pTuner, 0x0B, 0xD5);
+	result &= fc2580_i2c_write(pTuner, 0x0C, 0x32);
+	result &= fc2580_i2c_write(pTuner, 0x0E, 0x43);
+	result &= fc2580_i2c_write(pTuner, 0x21, 0x0A);
+	result &= fc2580_i2c_write(pTuner, 0x22, 0x82);
+	if( ifagc_mode == 1 )
+	{
+		result &= fc2580_i2c_write(pTuner, 0x45, 0x10);	//internal AGC
+		result &= fc2580_i2c_write(pTuner, 0x4C, 0x00);	//HOLD_AGC polarity
+	}
+	else if( ifagc_mode == 2 )
+	{
+		result &= fc2580_i2c_write(pTuner, 0x45, 0x20);	//Voltage Control Mode
+		result &= fc2580_i2c_write(pTuner, 0x4C, 0x02);	//HOLD_AGC polarity
+	}
+	result &= fc2580_i2c_write(pTuner, 0x3F, 0x88);
+	result &= fc2580_i2c_write(pTuner, 0x02, 0x0E);
+	result &= fc2580_i2c_write(pTuner, 0x58, 0x14);
+	result &= fc2580_set_filter(pTuner, 8, freq_xtal);	//BW = 7.8MHz
+
+	return result;
+}
+
+
+/*==============================================================================
+       fc2580 frequency setting
+
+  This function is a generic function which gets called to change LO Frequency
+
+  of fc2580 in DVB-H mode or L-Band TDMB mode
+
+  <input parameter>
+  freq_xtal: kHz
+
+  f_lo
+	Value of target LO Frequency in 'kHz' unit
+	ex) 2.6GHz = 2600000
+
+==============================================================================*/
+fc2580_fci_result_type fc2580_set_freq( void *pTuner, unsigned int f_lo, unsigned int freq_xtal )
+{
+	unsigned int f_diff, f_diff_shifted, n_val, k_val;
+	unsigned int f_vco, r_val, f_comp;
+	unsigned char pre_shift_bits = 4;// number of preshift to prevent overflow in shifting f_diff to f_diff_shifted
+	unsigned char data_0x18;
+	unsigned char data_0x02 = (USE_EXT_CLK<<5)|0x0E;
+	
+	fc2580_band_type band = ( f_lo > 1000000 )? FC2580_L_BAND : ( f_lo > 400000 )? FC2580_UHF_BAND : FC2580_VHF_BAND;
+
+	fc2580_fci_result_type result = FC2580_FCI_SUCCESS;
+
+	f_vco = ( band == FC2580_UHF_BAND )? f_lo * 4 : (( band == FC2580_L_BAND )? f_lo * 2 : f_lo * 12);
+	r_val = ( f_vco >= 2*76*freq_xtal )? 1 : ( f_vco >= 76*freq_xtal )? 2 : 4;
+	f_comp = freq_xtal/r_val;
+	n_val =	( f_vco / 2 ) / f_comp;
+	
+	f_diff = f_vco - 2* f_comp * n_val;
+	f_diff_shifted = f_diff << ( 20 - pre_shift_bits );
+	k_val = f_diff_shifted / ( ( 2* f_comp ) >> pre_shift_bits );
+	
+	if( f_diff_shifted - k_val * ( ( 2* f_comp ) >> pre_shift_bits ) >= ( f_comp >> pre_shift_bits ) )
+	k_val = k_val + 1;
+	
+	if( f_vco >= BORDER_FREQ )	//Select VCO Band
+		data_0x02 = data_0x02 | 0x08;	//0x02[3] = 1;
+	else
+		data_0x02 = data_0x02 & 0xF7;	//0x02[3] = 0;
+	
+//	if( band != curr_band ) {
+		switch(band)
+		{
+			case FC2580_UHF_BAND:
+				data_0x02 = (data_0x02 & 0x3F);
+
+				result &= fc2580_i2c_write(pTuner, 0x25, 0xF0);
+				result &= fc2580_i2c_write(pTuner, 0x27, 0x77);
+				result &= fc2580_i2c_write(pTuner, 0x28, 0x53);
+				result &= fc2580_i2c_write(pTuner, 0x29, 0x60);
+				result &= fc2580_i2c_write(pTuner, 0x30, 0x09);
+				result &= fc2580_i2c_write(pTuner, 0x50, 0x8C);
+				result &= fc2580_i2c_write(pTuner, 0x53, 0x50);
+
+				if( f_lo < 538000 )
+					result &= fc2580_i2c_write(pTuner, 0x5F, 0x13);
+				else					
+					result &= fc2580_i2c_write(pTuner, 0x5F, 0x15);
+
+				if( f_lo < 538000 )
+				{
+					result &= fc2580_i2c_write(pTuner, 0x61, 0x07);
+					result &= fc2580_i2c_write(pTuner, 0x62, 0x06);
+					result &= fc2580_i2c_write(pTuner, 0x67, 0x06);
+					result &= fc2580_i2c_write(pTuner, 0x68, 0x08);
+					result &= fc2580_i2c_write(pTuner, 0x69, 0x10);
+					result &= fc2580_i2c_write(pTuner, 0x6A, 0x12);
+				}
+				else if( f_lo < 794000 )
+				{
+					result &= fc2580_i2c_write(pTuner, 0x61, 0x03);
+					result &= fc2580_i2c_write(pTuner, 0x62, 0x03);
+					result &= fc2580_i2c_write(pTuner, 0x67, 0x03);  //ACI improve
+					result &= fc2580_i2c_write(pTuner, 0x68, 0x05);  //ACI improve
+					result &= fc2580_i2c_write(pTuner, 0x69, 0x0C);
+					result &= fc2580_i2c_write(pTuner, 0x6A, 0x0E);
+				}
+				else
+				{
+					result &= fc2580_i2c_write(pTuner, 0x61, 0x07);
+					result &= fc2580_i2c_write(pTuner, 0x62, 0x06);
+					result &= fc2580_i2c_write(pTuner, 0x67, 0x07);
+					result &= fc2580_i2c_write(pTuner, 0x68, 0x09);
+					result &= fc2580_i2c_write(pTuner, 0x69, 0x10);
+					result &= fc2580_i2c_write(pTuner, 0x6A, 0x12);
+				}
+
+				result &= fc2580_i2c_write(pTuner, 0x63, 0x15);
+
+				result &= fc2580_i2c_write(pTuner, 0x6B, 0x0B);
+				result &= fc2580_i2c_write(pTuner, 0x6C, 0x0C);
+				result &= fc2580_i2c_write(pTuner, 0x6D, 0x78);
+				result &= fc2580_i2c_write(pTuner, 0x6E, 0x32);
+				result &= fc2580_i2c_write(pTuner, 0x6F, 0x14);
+				result &= fc2580_set_filter(pTuner, 8, freq_xtal);	//BW = 7.8MHz
+				break;
+			case FC2580_VHF_BAND:
+				data_0x02 = (data_0x02 & 0x3F) | 0x80;
+				result &= fc2580_i2c_write(pTuner, 0x27, 0x77);
+				result &= fc2580_i2c_write(pTuner, 0x28, 0x33);
+				result &= fc2580_i2c_write(pTuner, 0x29, 0x40);
+				result &= fc2580_i2c_write(pTuner, 0x30, 0x09);
+				result &= fc2580_i2c_write(pTuner, 0x50, 0x8C);
+				result &= fc2580_i2c_write(pTuner, 0x53, 0x50);
+				result &= fc2580_i2c_write(pTuner, 0x5F, 0x0F);
+				result &= fc2580_i2c_write(pTuner, 0x61, 0x07);
+				result &= fc2580_i2c_write(pTuner, 0x62, 0x00);
+				result &= fc2580_i2c_write(pTuner, 0x63, 0x15);
+				result &= fc2580_i2c_write(pTuner, 0x67, 0x03);
+				result &= fc2580_i2c_write(pTuner, 0x68, 0x05);
+				result &= fc2580_i2c_write(pTuner, 0x69, 0x10);
+				result &= fc2580_i2c_write(pTuner, 0x6A, 0x12);
+				result &= fc2580_i2c_write(pTuner, 0x6B, 0x08);
+				result &= fc2580_i2c_write(pTuner, 0x6C, 0x0A);
+				result &= fc2580_i2c_write(pTuner, 0x6D, 0x78);
+				result &= fc2580_i2c_write(pTuner, 0x6E, 0x32);
+				result &= fc2580_i2c_write(pTuner, 0x6F, 0x54);
+				result &= fc2580_set_filter(pTuner, 7, freq_xtal);	//BW = 6.8MHz
+				break;
+			case FC2580_L_BAND:
+				data_0x02 = (data_0x02 & 0x3F) | 0x40;
+				result &= fc2580_i2c_write(pTuner, 0x2B, 0x70);
+				result &= fc2580_i2c_write(pTuner, 0x2C, 0x37);
+				result &= fc2580_i2c_write(pTuner, 0x2D, 0xE7);
+				result &= fc2580_i2c_write(pTuner, 0x30, 0x09);
+				result &= fc2580_i2c_write(pTuner, 0x44, 0x20);
+				result &= fc2580_i2c_write(pTuner, 0x50, 0x8C);
+				result &= fc2580_i2c_write(pTuner, 0x53, 0x50);
+				result &= fc2580_i2c_write(pTuner, 0x5F, 0x0F);
+				result &= fc2580_i2c_write(pTuner, 0x61, 0x0F);
+				result &= fc2580_i2c_write(pTuner, 0x62, 0x00);
+				result &= fc2580_i2c_write(pTuner, 0x63, 0x13);
+				result &= fc2580_i2c_write(pTuner, 0x67, 0x00);
+				result &= fc2580_i2c_write(pTuner, 0x68, 0x02);
+				result &= fc2580_i2c_write(pTuner, 0x69, 0x0C);
+				result &= fc2580_i2c_write(pTuner, 0x6A, 0x0E);
+				result &= fc2580_i2c_write(pTuner, 0x6B, 0x08);
+				result &= fc2580_i2c_write(pTuner, 0x6C, 0x0A);
+				result &= fc2580_i2c_write(pTuner, 0x6D, 0xA0);
+				result &= fc2580_i2c_write(pTuner, 0x6E, 0x50);
+				result &= fc2580_i2c_write(pTuner, 0x6F, 0x14);
+				result &= fc2580_set_filter(pTuner, 1, freq_xtal);	//BW = 1.53MHz
+				break;
+			default:
+				break;
+		}
+//		curr_band = band;
+//	}
+
+	//A command about AGC clock's pre-divide ratio
+	if( freq_xtal >= 28000 )
+		result &= fc2580_i2c_write(pTuner, 0x4B, 0x22 );
+
+	//Commands about VCO Band and PLL setting.
+	result &= fc2580_i2c_write(pTuner, 0x02, data_0x02);
+	data_0x18 = ( ( r_val == 1 )? 0x00 : ( ( r_val == 2 )? 0x10 : 0x20 ) ) + (unsigned char)(k_val >> 16);
+	result &= fc2580_i2c_write(pTuner, 0x18, data_0x18);						//Load 'R' value and high part of 'K' values
+	result &= fc2580_i2c_write(pTuner, 0x1A, (unsigned char)( k_val >> 8 ) );	//Load middle part of 'K' value
+	result &= fc2580_i2c_write(pTuner, 0x1B, (unsigned char)( k_val ) );		//Load lower part of 'K' value
+	result &= fc2580_i2c_write(pTuner, 0x1C, (unsigned char)( n_val ) );		//Load 'N' value
+
+	//A command about UHF LNA Load Cap
+	if( band == FC2580_UHF_BAND )
+		result &= fc2580_i2c_write(pTuner, 0x2D, ( f_lo <= (unsigned int)794000 )? 0x9F : 0x8F );	//LNA_OUT_CAP
+	
+
+	return result;
+}
+
+
+/*==============================================================================
+       fc2580 filter BW setting
+
+  This function is a generic function which gets called to change Bandwidth
+
+  frequency of fc2580's channel selection filter
+
+  <input parameter>
+  freq_xtal: kHz
+
+  filter_bw
+    1 : 1.53MHz(TDMB)
+	6 : 6MHz   (Bandwidth 6MHz)
+	7 : 6.8MHz (Bandwidth 7MHz)
+	8 : 7.8MHz (Bandwidth 8MHz)
+	
+
+==============================================================================*/
+fc2580_fci_result_type fc2580_set_filter( void *pTuner, unsigned char filter_bw, unsigned int freq_xtal )
+{
+	unsigned char	cal_mon, i;
+	fc2580_fci_result_type result = FC2580_FCI_SUCCESS;
+
+	if(filter_bw == 1)
+	{
+		result &= fc2580_i2c_write(pTuner, 0x36, 0x1C);
+		result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(4151*freq_xtal/1000000) );
+		result &= fc2580_i2c_write(pTuner, 0x39, 0x00);
+		result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+	}
+	if(filter_bw == 6)
+	{
+		result &= fc2580_i2c_write(pTuner, 0x36, 0x18);
+		result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(4400*freq_xtal/1000000) );
+		result &= fc2580_i2c_write(pTuner, 0x39, 0x00);
+		result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+	}
+	else if(filter_bw == 7)
+	{
+		result &= fc2580_i2c_write(pTuner, 0x36, 0x18);
+		result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(3910*freq_xtal/1000000) );
+		result &= fc2580_i2c_write(pTuner, 0x39, 0x80);
+		result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+	}
+	else if(filter_bw == 8)
+	{
+		result &= fc2580_i2c_write(pTuner, 0x36, 0x18);
+		result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(3300*freq_xtal/1000000) );
+		result &= fc2580_i2c_write(pTuner, 0x39, 0x80);
+		result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+	}
+
+	
+	for(i=0; i<5; i++)
+	{
+		fc2580_wait_msec(pTuner, 5);//wait 5ms
+		result &= fc2580_i2c_read(pTuner, 0x2F, &cal_mon);
+		if( (cal_mon & 0xC0) != 0xC0)
+		{
+			result &= fc2580_i2c_write(pTuner, 0x2E, 0x01);
+			result &= fc2580_i2c_write(pTuner, 0x2E, 0x09);
+		}
+		else
+			break;
+	}
+
+	result &= fc2580_i2c_write(pTuner, 0x2E, 0x01);
+
+	return result;
+}
+
+/*==============================================================================
+       fc2580 RSSI function
+
+  This function is a generic function which returns fc2580's
+  
+  current RSSI value.
+
+  <input parameter>
+	none
+
+  <return value>
+  int
+  	rssi : estimated input power.
+
+==============================================================================*/
+//int fc2580_get_rssi(void) {
+//	
+//	unsigned char s_lna, s_rfvga, s_cfs, s_ifvga;
+//	int ofs_lna, ofs_rfvga, ofs_csf, ofs_ifvga, rssi;
+//
+//	fc2580_i2c_read(0x71, &s_lna );
+//	fc2580_i2c_read(0x72, &s_rfvga );
+//	fc2580_i2c_read(0x73, &s_cfs );
+//	fc2580_i2c_read(0x74, &s_ifvga );
+//	
+//
+//	ofs_lna = 
+//			(curr_band==FC2580_UHF_BAND)?
+//				(s_lna==0)? 0 :
+//				(s_lna==1)? -6 :
+//				(s_lna==2)? -17 :
+//				(s_lna==3)? -22 : -30 :
+//			(curr_band==FC2580_VHF_BAND)?
+//				(s_lna==0)? 0 :
+//				(s_lna==1)? -6 :
+//				(s_lna==2)? -19 :
+//				(s_lna==3)? -24 : -32 :
+//			(curr_band==FC2580_L_BAND)?
+//				(s_lna==0)? 0 :
+//				(s_lna==1)? -6 :
+//				(s_lna==2)? -11 :
+//				(s_lna==3)? -16 : -34 :
+//			0;//FC2580_NO_BAND
+//	ofs_rfvga = -s_rfvga+((s_rfvga>=11)? 1 : 0) + ((s_rfvga>=18)? 1 : 0);
+//	ofs_csf = -6*s_cfs;
+//	ofs_ifvga = s_ifvga/4;
+//
+//	return rssi = ofs_lna+ofs_rfvga+ofs_csf+ofs_ifvga+OFS_RSSI;
+//				
+//}
+
+/*==============================================================================
+       fc2580 Xtal frequency Setting
+
+  This function is a generic function which sets 
+  
+  the frequency of xtal.
+  
+  <input parameter>
+  
+  frequency
+  	frequency value of internal(external) Xtal(clock) in kHz unit.
+
+==============================================================================*/
+//void fc2580_set_freq_xtal(unsigned int frequency) {
+//
+//	freq_xtal = frequency;
+//
+//}
+