driver for rtl28xx devices;

it supports several demodulators (RTL2832, RTL2836, RTL2840)
and 11 different tuners;

this version is based on the new sources released by Realtek on 03/09/2012
and adds support for the new Rafael Micro R820T tuner, support for FM radio
(untested) and many enhancements;

many thanks to Ambrosa who got the old driver from Realtek and
ported it on kernels 3.0.x and 3.1.x;

thanks to Hans-Frieder Vogt for the patch to support the 3.2 kernel;

this patch supports kernel 3.8 and beyond and can be applied also
to the current media_build tree;
the directory structure of media drivers has been reorganized
in kernel 3.8, so this patch will not apply to older kernels.

added define to manage refactored RC code on recent v4l
versions together with old kernels (2.6.x);
modified frontend driver to work directly with the DVBv5
data structure, as required in new kernels >= 3.3 as well as the
current media_build tree;
disabled the custom ioctls for the rtl2832 demod, as the fe_ioctl_override()
method is deprecated in kernel 3.8 as it was designed for the old DVBv3 API;
fixed GetSignalStrength function so that the signal strength is not
capped anymore to about 39%;
implemented the .get_frontend() method properly, so now it is possible
to retrieve the tuning parameters from the demodulator;

added definition of a new Leadteck USB stick:
- Leadtek WinFast DTV Dongle Mini [ID 0413:6a03]
(thanks to djnice);

added definition of 3 new Terratec USB sticks:
- TERRATEC Cinergy T Stick RC (Rev.3) [ID 0ccd:00d3]
- TERRATEC Cinergy T Stick BLACK (Rev.2) [ID 0ccd:00d4]
- TERRATEC NOXON DAB Stick (Rev.2) [ID 0ccd:00e0]
(thanks to CyBoardR);

From: Gianluca Gennari <gennarone@gmail.com>
---
 drivers/media/usb/dvb-usb/Kconfig                |     7 +
 drivers/media/usb/dvb-usb/Makefile               |    12 +
 drivers/media/usb/dvb-usb/demod_rtl2832.c        |  2872 +++
 drivers/media/usb/dvb-usb/demod_rtl2832.h        |   466 +
 drivers/media/usb/dvb-usb/demod_rtl2836.c        |  2049 ++
 drivers/media/usb/dvb-usb/demod_rtl2836.h        |   376 +
 drivers/media/usb/dvb-usb/demod_rtl2840.c        |  2437 +++
 drivers/media/usb/dvb-usb/demod_rtl2840.h        |   386 +
 drivers/media/usb/dvb-usb/dtmb_demod_base.c      |  1566 ++
 drivers/media/usb/dvb-usb/dtmb_demod_base.h      |  2505 +++
 drivers/media/usb/dvb-usb/dtmb_nim_base.c        |   545 +
 drivers/media/usb/dvb-usb/dtmb_nim_base.h        |   967 +
 drivers/media/usb/dvb-usb/dvbt_demod_base.c      |   816 +
 drivers/media/usb/dvb-usb/dvbt_demod_base.h      |  2722 +++
 drivers/media/usb/dvb-usb/dvbt_nim_base.c        |   531 +
 drivers/media/usb/dvb-usb/dvbt_nim_base.h        |   964 +
 drivers/media/usb/dvb-usb/foundation.c           |   352 +
 drivers/media/usb/dvb-usb/foundation.h           |  1026 +
 drivers/media/usb/dvb-usb/i2c_bridge.h           |   122 +
 drivers/media/usb/dvb-usb/math_mpi.c             |  1054 +
 drivers/media/usb/dvb-usb/math_mpi.h             |   201 +
 drivers/media/usb/dvb-usb/nim_rtl2832_e4000.c    |  1001 +
 drivers/media/usb/dvb-usb/nim_rtl2832_e4000.h    |   226 +
 drivers/media/usb/dvb-usb/nim_rtl2832_fc0012.c   |   840 +
 drivers/media/usb/dvb-usb/nim_rtl2832_fc0012.h   |   168 +
 drivers/media/usb/dvb-usb/nim_rtl2832_fc0013.c   |  1053 +
 drivers/media/usb/dvb-usb/nim_rtl2832_fc0013.h   |   170 +
 drivers/media/usb/dvb-usb/nim_rtl2832_fc2580.c   |   343 +
 drivers/media/usb/dvb-usb/nim_rtl2832_fc2580.h   |   141 +
 drivers/media/usb/dvb-usb/nim_rtl2832_max3543.c  |   346 +
 drivers/media/usb/dvb-usb/nim_rtl2832_max3543.h  |   145 +
 drivers/media/usb/dvb-usb/nim_rtl2832_mt2063.c   |   360 +
 drivers/media/usb/dvb-usb/nim_rtl2832_mt2063.h   |   160 +
 drivers/media/usb/dvb-usb/nim_rtl2832_mt2266.c   |  1082 ++
 drivers/media/usb/dvb-usb/nim_rtl2832_mt2266.h   |   264 +
 drivers/media/usb/dvb-usb/nim_rtl2832_mxl5007t.c |   517 +
 drivers/media/usb/dvb-usb/nim_rtl2832_mxl5007t.h |   165 +
 drivers/media/usb/dvb-usb/nim_rtl2832_r820t.c    |   356 +
 drivers/media/usb/dvb-usb/nim_rtl2832_r820t.h    |   143 +
 drivers/media/usb/dvb-usb/nim_rtl2832_tda18272.c |   408 +
 drivers/media/usb/dvb-usb/nim_rtl2832_tda18272.h |   148 +
 drivers/media/usb/dvb-usb/nim_rtl2832_tua9001.c  |   340 +
 drivers/media/usb/dvb-usb/nim_rtl2832_tua9001.h  |   137 +
 drivers/media/usb/dvb-usb/nim_rtl2836_fc2580.c   |   308 +
 drivers/media/usb/dvb-usb/nim_rtl2836_fc2580.h   |   140 +
 drivers/media/usb/dvb-usb/nim_rtl2836_mxl5007t.c |   319 +
 drivers/media/usb/dvb-usb/nim_rtl2836_mxl5007t.h |   150 +
 drivers/media/usb/dvb-usb/nim_rtl2840_max3543.c  |   341 +
 drivers/media/usb/dvb-usb/nim_rtl2840_max3543.h  |   146 +
 drivers/media/usb/dvb-usb/nim_rtl2840_mt2063.c   |   307 +
 drivers/media/usb/dvb-usb/nim_rtl2840_mt2063.h   |   163 +
 drivers/media/usb/dvb-usb/qam_demod_base.c       |  1289 ++
 drivers/media/usb/dvb-usb/qam_demod_base.h       |  2818 +++
 drivers/media/usb/dvb-usb/qam_nim_base.c         |   496 +
 drivers/media/usb/dvb-usb/qam_nim_base.h         |   879 +
 drivers/media/usb/dvb-usb/rtl2832u.c             |  1745 ++
 drivers/media/usb/dvb-usb/rtl2832u.h             |   277 +
 drivers/media/usb/dvb-usb/rtl2832u_audio.c       |   926 +
 drivers/media/usb/dvb-usb/rtl2832u_audio.h       |    67 +
 drivers/media/usb/dvb-usb/rtl2832u_fe.c          |  4746 +++++
 drivers/media/usb/dvb-usb/rtl2832u_fe.h          |   336 +
 drivers/media/usb/dvb-usb/rtl2832u_io.c          |   912 +
 drivers/media/usb/dvb-usb/rtl2832u_io.h          |   276 +
 drivers/media/usb/dvb-usb/tuner_base.h           |  1913 ++
 drivers/media/usb/dvb-usb/tuner_e4000.c          |  2482 +++
 drivers/media/usb/dvb-usb/tuner_e4000.h          |   295 +
 drivers/media/usb/dvb-usb/tuner_fc0012.c         |  1056 +
 drivers/media/usb/dvb-usb/tuner_fc0012.h         |   292 +
 drivers/media/usb/dvb-usb/tuner_fc0013.c         |  1261 ++
 drivers/media/usb/dvb-usb/tuner_fc0013.h         |   307 +
 drivers/media/usb/dvb-usb/tuner_fc2580.c         |   932 +
 drivers/media/usb/dvb-usb/tuner_fc2580.h         |   461 +
 drivers/media/usb/dvb-usb/tuner_max3543.c        |  1441 ++
 drivers/media/usb/dvb-usb/tuner_max3543.h        |   572 +
 drivers/media/usb/dvb-usb/tuner_mt2063.c         |  5264 +++++
 drivers/media/usb/dvb-usb/tuner_mt2063.h         |  2206 +++
 drivers/media/usb/dvb-usb/tuner_mt2266.c         |  3278 ++++
 drivers/media/usb/dvb-usb/tuner_mt2266.h         |  1534 ++
 drivers/media/usb/dvb-usb/tuner_mxl5007t.c       |  1267 ++
 drivers/media/usb/dvb-usb/tuner_mxl5007t.h       |   788 +
 drivers/media/usb/dvb-usb/tuner_r820t.c          |  3453 ++++
 drivers/media/usb/dvb-usb/tuner_r820t.h          |   263 +
 drivers/media/usb/dvb-usb/tuner_tda18272.c       | 21631 +++++++++++++++++++++
 drivers/media/usb/dvb-usb/tuner_tda18272.h       |  7412 +++++++
 drivers/media/usb/dvb-usb/tuner_tua9001.c        |  1245 ++
 drivers/media/usb/dvb-usb/tuner_tua9001.h        |   493 +
 86 files changed, 106976 insertions(+)

diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
index c423eb8..23505fa 100644
--- a/drivers/media/usb/dvb-usb/Kconfig
+++ b/drivers/media/usb/dvb-usb/Kconfig
@@ -313,3 +313,10 @@ config DVB_USB_TECHNISAT_USB2
 	select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
 	help
 	  Say Y here to support the Technisat USB2 DVB-S/S2 device
+
+config DVB_USB_RTL2832
+	tristate "Realtek RTL2832 DVB-T USB2.0 support"
+	depends on DVB_USB
+	default m
+	help
+	  Say Y or M to support the Realtek RTL2832 DVB-T receiver
diff --git a/drivers/media/usb/dvb-usb/Makefile b/drivers/media/usb/dvb-usb/Makefile
index acdd1ef..cd05c7b 100644
--- a/drivers/media/usb/dvb-usb/Makefile
+++ b/drivers/media/usb/dvb-usb/Makefile
@@ -76,6 +76,18 @@ obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
 dvb-usb-technisat-usb2-objs := technisat-usb2.o
 obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
 
+dvb-usb-rtl2832-objs := demod_rtl2832.o	dvbt_demod_base.o dvbt_nim_base.o foundation.o \
+                        math_mpi.o nim_rtl2832_mxl5007t.o nim_rtl2832_fc2580.o nim_rtl2832_mt2266.o \
+                        rtl2832u.o rtl2832u_fe.o rtl2832u_io.o tuner_mxl5007t.o tuner_fc2580.o \
+                        tuner_mt2266.o tuner_tua9001.o nim_rtl2832_tua9001.o tuner_fc0012.o \
+                        nim_rtl2832_fc0012.o demod_rtl2836.o dtmb_demod_base.o dtmb_nim_base.o \
+                        nim_rtl2836_fc2580.o nim_rtl2836_mxl5007t.o tuner_e4000.o nim_rtl2832_e4000.o \
+                        tuner_mt2063.o demod_rtl2840.o tuner_max3543.o nim_rtl2832_mt2063.o \
+                        nim_rtl2832_max3543.o nim_rtl2840_mt2063.o nim_rtl2840_max3543.o \
+                        qam_demod_base.o qam_nim_base.o tuner_tda18272.o nim_rtl2832_tda18272.o \
+                        nim_rtl2832_fc0013.o tuner_fc0013.o rtl2832u_audio.o tuner_r820t.o nim_rtl2832_r820t.o
+obj-$(CONFIG_DVB_USB_RTL2832) += dvb-usb-rtl2832.o
+
 ccflags-y += -I$(srctree)/drivers/media/dvb-core
 ccflags-y += -I$(srctree)/drivers/media/dvb-frontends/
 # due to tuner-xc3028
diff --git a/drivers/media/usb/dvb-usb/demod_rtl2832.c b/drivers/media/usb/dvb-usb/demod_rtl2832.c
new file mode 100644
index 0000000..dcb57f4
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/demod_rtl2832.c
@@ -0,0 +1,2872 @@
+/**
+
+@file
+
+@brief   RTL2832 demod module definition
+
+One can manipulate RTL2832 demod through RTL2832 module.
+RTL2832 module is derived from DVB-T demod module.
+
+*/
+
+
+#include "demod_rtl2832.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 demod module builder
+
+Use BuildRtl2832Module() to build RTL2832 module, set all module function pointers with the corresponding
+functions, and initialize module private variables.
+
+
+@param [in]   ppDemod                      Pointer to RTL2832 demod module pointer
+@param [in]   pDvbtDemodModuleMemory       Pointer to an allocated DVB-T demod module memory
+@param [in]   pBaseInterfaceModuleMemory   Pointer to an allocated base interface module memory
+@param [in]   pI2cBridgeModuleMemory       Pointer to an allocated I2C bridge module memory
+@param [in]   DeviceAddr                   RTL2832 I2C device address
+@param [in]   CrystalFreqHz                RTL2832 crystal frequency in Hz
+@param [in]   TsInterfaceMode              RTL2832 TS interface mode for setting
+@param [in]   AppMode                      RTL2832 application mode for setting
+@param [in]   UpdateFuncRefPeriodMs        RTL2832 update function reference period in millisecond for setting
+@param [in]   IsFunc1Enabled               RTL2832 Function 1 enabling status for setting
+
+
+@note
+	-# One should call BuildRtl2832Module() to build RTL2832 module before using it.
+
+*/
+void
+BuildRtl2832Module(
+	DVBT_DEMOD_MODULE **ppDemod,
+	DVBT_DEMOD_MODULE *pDvbtDemodModuleMemory,
+	BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory,
+	I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory,
+	unsigned char DeviceAddr,
+	unsigned long CrystalFreqHz,
+	int TsInterfaceMode,
+	int AppMode,
+	unsigned long UpdateFuncRefPeriodMs,
+	int IsFunc1Enabled
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	RTL2832_EXTRA_MODULE *pExtra;
+
+
+
+	// Set demod module pointer, 
+	*ppDemod = pDvbtDemodModuleMemory;
+
+	// Get demod module.
+	pDemod = *ppDemod;
+
+	// Set base interface module pointer and I2C bridge module pointer.
+	pDemod->pBaseInterface = pBaseInterfaceModuleMemory;
+	pDemod->pI2cBridge     = pI2cBridgeModuleMemory;
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+
+	// Set demod type.
+	pDemod->DemodType = DVBT_DEMOD_TYPE_RTL2832;
+
+	// Set demod I2C device address.
+	pDemod->DeviceAddr = DeviceAddr;
+
+	// Set demod crystal frequency in Hz.
+	pDemod->CrystalFreqHz = CrystalFreqHz;
+
+	// Set demod TS interface mode.
+	pDemod->TsInterfaceMode = TsInterfaceMode;
+
+
+	// Initialize demod parameter setting status
+	pDemod->IsBandwidthModeSet = NO;
+	pDemod->IsIfFreqHzSet      = NO;
+	pDemod->IsSpectrumModeSet  = NO;
+
+
+	// Initialize demod register table.
+	rtl2832_InitRegTable(pDemod);
+
+	
+	// Build I2C birdge module.
+	rtl2832_BuildI2cBridgeModule(pDemod);
+
+
+	// Set demod module I2C function pointers with default functions.
+	pDemod->SetRegPage         = dvbt_demod_default_SetRegPage;
+	pDemod->SetRegBytes        = dvbt_demod_default_SetRegBytes;
+	pDemod->GetRegBytes        = dvbt_demod_default_GetRegBytes;
+	pDemod->SetRegMaskBits     = dvbt_demod_default_SetRegMaskBits;
+	pDemod->GetRegMaskBits     = dvbt_demod_default_GetRegMaskBits;
+	pDemod->SetRegBits         = dvbt_demod_default_SetRegBits;
+	pDemod->GetRegBits         = dvbt_demod_default_GetRegBits;
+	pDemod->SetRegBitsWithPage = dvbt_demod_default_SetRegBitsWithPage;
+	pDemod->GetRegBitsWithPage = dvbt_demod_default_GetRegBitsWithPage;
+
+
+	// Set demod module manipulating function pointers with default functions.
+	pDemod->GetDemodType     = dvbt_demod_default_GetDemodType;
+	pDemod->GetDeviceAddr    = dvbt_demod_default_GetDeviceAddr;
+	pDemod->GetCrystalFreqHz = dvbt_demod_default_GetCrystalFreqHz;
+
+	pDemod->GetBandwidthMode = dvbt_demod_default_GetBandwidthMode;
+	pDemod->GetIfFreqHz      = dvbt_demod_default_GetIfFreqHz;
+	pDemod->GetSpectrumMode  = dvbt_demod_default_GetSpectrumMode;
+
+
+	// Set demod module manipulating function pointers with particular functions.
+	pDemod->IsConnectedToI2c  = rtl2832_IsConnectedToI2c;
+	pDemod->SoftwareReset     = rtl2832_SoftwareReset;
+	pDemod->Initialize        = rtl2832_Initialize;
+	pDemod->SetBandwidthMode  = rtl2832_SetBandwidthMode;
+	pDemod->SetIfFreqHz       = rtl2832_SetIfFreqHz;
+	pDemod->SetSpectrumMode   = rtl2832_SetSpectrumMode;
+
+	pDemod->IsTpsLocked       = rtl2832_IsTpsLocked;
+	pDemod->IsSignalLocked    = rtl2832_IsSignalLocked;
+
+	pDemod->GetSignalStrength = rtl2832_GetSignalStrength;
+	pDemod->GetSignalQuality  = rtl2832_GetSignalQuality;
+
+	pDemod->GetBer            = rtl2832_GetBer;
+	pDemod->GetSnrDb          = rtl2832_GetSnrDb;
+
+	pDemod->GetRfAgc          = rtl2832_GetRfAgc;
+	pDemod->GetIfAgc          = rtl2832_GetIfAgc;
+	pDemod->GetDiAgc          = rtl2832_GetDiAgc;
+
+	pDemod->GetTrOffsetPpm    = rtl2832_GetTrOffsetPpm;
+	pDemod->GetCrOffsetHz     = rtl2832_GetCrOffsetHz;
+
+	pDemod->GetConstellation  = rtl2832_GetConstellation;
+	pDemod->GetHierarchy      = rtl2832_GetHierarchy;
+	pDemod->GetCodeRateLp     = rtl2832_GetCodeRateLp;
+	pDemod->GetCodeRateHp     = rtl2832_GetCodeRateHp;
+	pDemod->GetGuardInterval  = rtl2832_GetGuardInterval;
+	pDemod->GetFftMode        = rtl2832_GetFftMode;
+
+	pDemod->UpdateFunction    = rtl2832_UpdateFunction;
+	pDemod->ResetFunction     = rtl2832_ResetFunction;
+
+
+	// Initialize demod extra module variables.
+	pExtra->AppMode = AppMode;
+
+
+	// Initialize demod Function 1 variables.
+	pExtra->Func1State = RTL2832_FUNC1_STATE_NORMAL;
+
+	pExtra->IsFunc1Enabled = IsFunc1Enabled;
+
+	pExtra->Func1WaitTimeMax        = DivideWithCeiling(RTL2832_FUNC1_WAIT_TIME_MS, UpdateFuncRefPeriodMs);
+	pExtra->Func1GettingTimeMax     = DivideWithCeiling(RTL2832_FUNC1_GETTING_TIME_MS, UpdateFuncRefPeriodMs);
+	pExtra->Func1GettingNumEachTime = DivideWithCeiling(RTL2832_FUNC1_GETTING_NUM_MIN, pExtra->Func1GettingTimeMax + 1);
+
+	pExtra->Func1QamBak  = 0xff;
+	pExtra->Func1HierBak = 0xff;
+	pExtra->Func1LpCrBak = 0xff;
+	pExtra->Func1HpCrBak = 0xff;
+	pExtra->Func1GiBak   = 0xff;
+	pExtra->Func1FftBak  = 0xff;
+
+
+	// Set demod extra module function pointers.
+	pExtra->GetAppMode = rtl2832_GetAppMode;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_IS_CONNECTED_TO_I2C
+
+*/
+void
+rtl2832_IsConnectedToI2c(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned char Nothing;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Send read command.
+	// Note: The number of reading bytes must be greater than 0.
+	if(pBaseInterface->I2cRead(pBaseInterface, pDemod->DeviceAddr, &Nothing, LEN_1_BYTE) == FUNCTION_ERROR)
+		goto error_status_i2c_read;
+
+
+	// Set I2cConnectionStatus with YES.
+	*pAnswer = YES;
+
+
+	return;
+
+
+error_status_i2c_read:
+
+	// Set I2cConnectionStatus with NO.
+	*pAnswer = NO;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_SOFTWARE_RESET
+
+*/
+int
+rtl2832_SoftwareReset(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	// Set SOFT_RST with 1. Then, set SOFT_RST with 0.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_SOFT_RST, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_SOFT_RST, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_INITIALIZE
+
+*/
+int
+rtl2832_Initialize(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	// Initializing table entry only used in Initialize()
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long WritingValue;
+	}
+	INIT_TABLE_ENTRY;
+
+	// TS interface initializing table entry only used in Initialize()
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long WritingValue[TS_INTERFACE_MODE_NUM];
+	}
+	TS_INTERFACE_INIT_TABLE_ENTRY;
+
+	// Application initializing table entry only used in Initialize()
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long WritingValue[RTL2832_APPLICATION_MODE_NUM];
+	}
+	APP_INIT_TABLE_ENTRY;
+
+
+
+	static const INIT_TABLE_ENTRY InitTable[RTL2832_INIT_TABLE_LEN] =
+	{
+		// RegBitName,				WritingValue
+		{DVBT_AD_EN_REG,			0x1		},
+		{DVBT_AD_EN_REG1,			0x1		},
+		{DVBT_RSD_BER_FAIL_VAL,		0x2800	},
+		{DVBT_MGD_THD0,				0x10	},
+		{DVBT_MGD_THD1,				0x20	},
+		{DVBT_MGD_THD2,				0x20	},
+		{DVBT_MGD_THD3,				0x40	},
+		{DVBT_MGD_THD4,				0x22	},
+		{DVBT_MGD_THD5,				0x32	},
+		{DVBT_MGD_THD6,				0x37	},
+		{DVBT_MGD_THD7,				0x39	},
+		{DVBT_EN_BK_TRK,			0x0		},
+		{DVBT_EN_CACQ_NOTCH,		0x0		},
+		{DVBT_AD_AV_REF,			0x2a	},
+		{DVBT_REG_PI,				0x6		},
+		{DVBT_PIP_ON,				0x0		},
+		{DVBT_CDIV_PH0,				0x8		},
+		{DVBT_CDIV_PH1,				0x8		},
+		{DVBT_SCALE1_B92,			0x4		},
+		{DVBT_SCALE1_B93,			0xb0	},
+		{DVBT_SCALE1_BA7,			0x78	},
+		{DVBT_SCALE1_BA9,			0x28	},
+		{DVBT_SCALE1_BAA,			0x59	},
+		{DVBT_SCALE1_BAB,			0x83	},
+		{DVBT_SCALE1_BAC,			0xd4	},
+		{DVBT_SCALE1_BB0,			0x65	},
+		{DVBT_SCALE1_BB1,			0x43	},
+		{DVBT_KB_P1,				0x1		},
+		{DVBT_KB_P2,				0x4		},
+		{DVBT_KB_P3,				0x7		},
+		{DVBT_K1_CR_STEP12,			0xa		},
+		{DVBT_REG_GPE,				0x1		},
+	};
+
+	static const TS_INTERFACE_INIT_TABLE_ENTRY TsInterfaceInitTable[RTL2832_TS_INTERFACE_INIT_TABLE_LEN] =
+	{
+		// RegBitName,				WritingValue for {Parallel, Serial}
+		{DVBT_SERIAL,				{0x0,	0x1}},
+		{DVBT_CDIV_PH0,				{0x9,	0x1}},
+		{DVBT_CDIV_PH1,				{0x9,	0x2}},
+		{DVBT_MPEG_IO_OPT_2_2,		{0x0,	0x0}},
+		{DVBT_MPEG_IO_OPT_1_0,		{0x0,	0x1}},
+	};
+
+	static const APP_INIT_TABLE_ENTRY AppInitTable[RTL2832_APP_INIT_TABLE_LEN] =
+	{
+		// RegBitName,				WritingValue for {Dongle, STB}
+		{DVBT_TRK_KS_P2,			{0x4,	0x4}},
+		{DVBT_TRK_KS_I2,			{0x7,	0x7}},
+		{DVBT_TR_THD_SET2,			{0x6,	0x6}},
+		{DVBT_TRK_KC_I2,			{0x5,	0x6}},
+		{DVBT_CR_THD_SET2,			{0x1,	0x1}},
+	};
+
+
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	RTL2832_EXTRA_MODULE *pExtra;
+
+	int i;
+
+	int TsInterfaceMode;
+	int AppMode;
+
+
+
+	// Get base interface and demod extra module.
+	pBaseInterface = pDemod->pBaseInterface;
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+	// Get TS interface mode.
+	TsInterfaceMode = pDemod->TsInterfaceMode;
+
+	// Get application mode.
+	pExtra->GetAppMode(pDemod, &AppMode);
+
+
+	// Initialize demod registers according to the initializing table.
+	for(i = 0; i < RTL2832_INIT_TABLE_LEN; i++)
+	{
+		if(pDemod->SetRegBitsWithPage(pDemod, InitTable[i].RegBitName, InitTable[i].WritingValue)
+			!= FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	// Initialize demod registers according to the TS interface initializing table.
+	for(i = 0; i < RTL2832_TS_INTERFACE_INIT_TABLE_LEN; i++)
+	{
+		if(pDemod->SetRegBitsWithPage(pDemod, TsInterfaceInitTable[i].RegBitName,
+			TsInterfaceInitTable[i].WritingValue[TsInterfaceMode]) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	// Initialize demod registers according to the application initializing table.
+	for(i = 0; i < RTL2832_APP_INIT_TABLE_LEN; i++)
+	{
+		if(pDemod->SetRegBitsWithPage(pDemod, AppInitTable[i].RegBitName,
+			AppInitTable[i].WritingValue[AppMode]) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_SET_BANDWIDTH_MODE
+
+*/
+int
+rtl2832_SetBandwidthMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int BandwidthMode
+	)
+{
+	static const unsigned char HlpfxTable[DVBT_BANDWIDTH_MODE_NUM][RTL2832_H_LPF_X_LEN] =
+	{
+		// H_LPF_X writing value for 6 MHz bandwidth
+		{
+			0xf5,	0xff,	0x15,	0x38,	0x5d,	0x6d,	0x52,	0x07,	0xfa,	0x2f,
+			0x53,	0xf5,	0x3f,	0xca,	0x0b,	0x91,	0xea,	0x30,	0x63,	0xb2,
+			0x13,	0xda,	0x0b,	0xc4,	0x18,	0x7e,	0x16,	0x66,	0x08,	0x67,
+			0x19,	0xe0,
+		},
+
+		// H_LPF_X writing value for 7 MHz bandwidth
+		{
+			0xe7,	0xcc,	0xb5,	0xba,	0xe8,	0x2f,	0x67,	0x61,	0x00,	0xaf,
+			0x86,	0xf2,	0xbf,	0x59,	0x04,	0x11,	0xb6,	0x33,	0xa4,	0x30,
+			0x15,	0x10,	0x0a,	0x42,	0x18,	0xf8,	0x17,	0xd9,	0x07,	0x22,
+			0x19,	0x10,
+		},
+
+		// H_LPF_X writing value for 8 MHz bandwidth
+		{
+			0x09,	0xf6,	0xd2,	0xa7,	0x9a,	0xc9,	0x27,	0x77,	0x06,	0xbf,
+			0xec,	0xf4,	0x4f,	0x0b,	0xfc,	0x01,	0x63,	0x35,	0x54,	0xa7,
+			0x16,	0x66,	0x08,	0xb4,	0x19,	0x6e,	0x19,	0x65,	0x05,	0xc8,
+			0x19,	0xe0,
+		},
+	};
+
+
+	unsigned long CrystalFreqHz;
+
+	long ConstWithBandwidthMode;
+
+	MPI MpiCrystalFreqHz;
+	MPI MpiConst, MpiVar0, MpiVar1, MpiNone;
+
+	unsigned long RsampRatio;
+
+	long CfreqOffRatioInt;
+	unsigned long CfreqOffRatioBinary;
+
+
+
+	// Get demod crystal frequency in Hz.
+	pDemod->GetCrystalFreqHz(pDemod, &CrystalFreqHz);
+
+
+	// Set H_LPF_X registers with HlpfxTable according to BandwidthMode.
+	if(pDemod->SetRegPage(pDemod, RTL2832_H_LPF_X_PAGE) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->SetRegBytes(pDemod, RTL2832_H_LPF_X_ADDR, HlpfxTable[BandwidthMode], RTL2832_H_LPF_X_LEN) !=
+		FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Determine constant value with bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:	ConstWithBandwidthMode = 48000000;		break;
+		case DVBT_BANDWIDTH_7MHZ:	ConstWithBandwidthMode = 56000000;		break;
+		case DVBT_BANDWIDTH_8MHZ:	ConstWithBandwidthMode = 64000000;		break;
+	}
+
+
+	// Calculate RSAMP_RATIO value.
+	// Note: RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22) / ConstWithBandwidthMode)
+	MpiSetValue(&MpiCrystalFreqHz, CrystalFreqHz);
+	MpiSetValue(&MpiVar1,          ConstWithBandwidthMode);
+	MpiSetValue(&MpiConst,         7);
+
+	MpiMul(&MpiVar0, MpiCrystalFreqHz, MpiConst);
+	MpiLeftShift(&MpiVar0, MpiVar0, 22);
+	MpiDiv(&MpiVar0, &MpiNone, MpiVar0, MpiVar1);
+
+	MpiGetValue(MpiVar0, (long *)&RsampRatio);
+
+
+	// Set RSAMP_RATIO with calculated value.
+	// Note: Use SetRegBitsWithPage() to set register bits with page setting.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_RSAMP_RATIO, RsampRatio) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Calculate CFREQ_OFF_RATIO value.
+	// Note: CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20) / (CrystalFreqHz * 7))
+	MpiSetValue(&MpiCrystalFreqHz, CrystalFreqHz);
+	MpiSetValue(&MpiVar0,          ConstWithBandwidthMode);
+	MpiSetValue(&MpiConst,         7);
+
+	MpiLeftShift(&MpiVar0, MpiVar0, 20);
+	MpiMul(&MpiVar1, MpiCrystalFreqHz, MpiConst);
+	MpiDiv(&MpiVar0, &MpiNone, MpiVar0, MpiVar1);
+
+	MpiGetValue(MpiVar0, &CfreqOffRatioInt);
+	CfreqOffRatioInt = - CfreqOffRatioInt;
+
+	CfreqOffRatioBinary = SignedIntToBin(CfreqOffRatioInt, RTL2832_CFREQ_OFF_RATIO_BIT_NUM);
+
+
+	// Set CFREQ_OFF_RATIO with calculated value.
+	// Note: Use SetRegBitsWithPage() to set register bits with page setting.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_CFREQ_OFF_RATIO, CfreqOffRatioBinary) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+
+	// Set demod bandwidth mode parameter.
+	pDemod->BandwidthMode      = BandwidthMode;
+	pDemod->IsBandwidthModeSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_SET_IF_FREQ_HZ
+
+*/
+int
+rtl2832_SetIfFreqHz(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long IfFreqHz
+	)
+{
+	unsigned long CrystalFreqHz;
+
+	unsigned long EnBbin;
+
+	MPI MpiCrystalFreqHz, MpiVar, MpiNone;
+
+	long PsetIffreqInt;
+	unsigned long PsetIffreqBinary;
+
+
+
+	// Get demod crystal frequency in Hz.
+	pDemod->GetCrystalFreqHz(pDemod, &CrystalFreqHz);
+
+
+	// Determine and set EN_BBIN value.
+	EnBbin = (IfFreqHz == IF_FREQ_0HZ) ? 0x1 : 0x0;
+
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_EN_BBIN, EnBbin) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Calculate PSET_IFFREQ value.
+	// Note: PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22) / CrystalFreqHz)
+	MpiSetValue(&MpiCrystalFreqHz, CrystalFreqHz);
+
+	MpiSetValue(&MpiVar, (IfFreqHz % CrystalFreqHz));
+	MpiLeftShift(&MpiVar, MpiVar, RTL2832_PSET_IFFREQ_BIT_NUM);
+	MpiDiv(&MpiVar, &MpiNone, MpiVar, MpiCrystalFreqHz);
+
+	MpiGetValue(MpiVar, &PsetIffreqInt);
+	PsetIffreqInt = - PsetIffreqInt;
+
+	PsetIffreqBinary = SignedIntToBin(PsetIffreqInt, RTL2832_PSET_IFFREQ_BIT_NUM);
+
+
+	// Set PSET_IFFREQ with calculated value.
+	// Note: Use SetRegBitsWithPage() to set register bits with page setting.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_PSET_IFFREQ, PsetIffreqBinary) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod IF frequnecy parameter.
+	pDemod->IfFreqHz      = IfFreqHz;
+	pDemod->IsIfFreqHzSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_SET_SPECTRUM_MODE
+
+*/
+int
+rtl2832_SetSpectrumMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int SpectrumMode
+	)
+{
+	unsigned long SpecInv;
+
+
+
+	// Determine SpecInv according to spectrum mode.
+	switch(SpectrumMode)
+	{
+		default:
+		case SPECTRUM_NORMAL:		SpecInv = 0;		break;
+		case SPECTRUM_INVERSE:		SpecInv = 1;		break;
+	}
+
+
+	// Set SPEC_INV with SpecInv.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_SPEC_INV, SpecInv) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod spectrum mode parameter.
+	pDemod->SpectrumMode      = SpectrumMode;
+	pDemod->IsSpectrumModeSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_IS_TPS_LOCKED
+
+*/
+int
+rtl2832_IsTpsLocked(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	unsigned long FsmStage;
+
+
+
+	// Get FSM stage from FSM_STAGE.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_FSM_STAGE, &FsmStage) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Determine answer according to FSM stage.
+	if(FsmStage > 9)
+		*pAnswer = YES;
+	else
+		*pAnswer = NO;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_IS_SIGNAL_LOCKED
+
+*/
+int
+rtl2832_IsSignalLocked(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	unsigned long FsmStage;
+
+
+
+	// Get FSM stage from FSM_STAGE.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_FSM_STAGE, &FsmStage) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Determine answer according to FSM stage.
+	if(FsmStage == 11)
+		*pAnswer = YES;
+	else
+		*pAnswer = NO;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_SIGNAL_STRENGTH
+
+*/
+int
+rtl2832_GetSignalStrength(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalStrength
+	)
+{
+	unsigned long FsmStage;
+	long IfAgc;
+
+
+
+	// Get FSM stage and IF AGC value.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_FSM_STAGE, &FsmStage) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->GetIfAgc(pDemod, &IfAgc) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	//  Determine signal strength according to FSM stage and IF AGC value.
+	if(FsmStage < 10)
+		*pSignalStrength = 0;
+	else
+		*pSignalStrength = 55 - IfAgc / 182;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_SIGNAL_QUALITY
+
+*/
+int
+rtl2832_GetSignalQuality(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalQuality
+	)
+{
+	unsigned long FsmStage, RsdBerEst;
+
+	MPI MpiVar;
+	long Var;
+
+
+
+	// Get FSM_STAGE and RSD_BER_EST.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_FSM_STAGE, &FsmStage) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RSD_BER_EST, &RsdBerEst) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// If demod is not signal-locked, set signal quality with zero.
+	if(FsmStage < 10)
+	{
+		*pSignalQuality = 0;
+		goto success_status_non_signal_lock;
+	}
+
+	// Determine signal quality according to RSD_BER_EST.
+	// Note: Map RSD_BER_EST value 8192 ~ 128 to 10 ~ 100
+	//       Original formula: SignalQuality = 205 - 15 * log2(RSD_BER_EST)
+	//       Adjusted formula: SignalQuality = ((205 << 5) - 15 * (log2(RSD_BER_EST) << 5)) >> 5
+	//       If RSD_BER_EST > 8192, signal quality is 10.
+	//       If RSD_BER_EST < 128, signal quality is 100.
+	if(RsdBerEst > 8192)
+	{
+		*pSignalQuality = 10;
+	}
+	else if(RsdBerEst < 128)
+	{
+		*pSignalQuality = 100;
+	}
+	else
+	{
+		MpiSetValue(&MpiVar, RsdBerEst);
+		MpiLog2(&MpiVar, MpiVar, RTL2832_SQ_FRAC_BIT_NUM);
+		MpiGetValue(MpiVar, &Var);
+
+		*pSignalQuality = ((205 << RTL2832_SQ_FRAC_BIT_NUM) - 15 * Var) >> RTL2832_SQ_FRAC_BIT_NUM;
+	}
+
+
+success_status_non_signal_lock:
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_BER
+
+*/
+int
+rtl2832_GetBer(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	)
+{
+	unsigned long RsdBerEst;
+
+
+
+	// Get RSD_BER_EST.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RSD_BER_EST, &RsdBerEst) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Set BER numerator according to RSD_BER_EST.
+	*pBerNum = RsdBerEst;
+
+	// Set BER denominator.
+	*pBerDen = RTL2832_BER_DEN_VALUE;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_SNR_DB
+
+*/
+int
+rtl2832_GetSnrDb(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	)
+{
+	unsigned long FsmStage;
+	unsigned long CeEstEvm;
+	int Constellation, Hierarchy;
+
+	static const long SnrDbNumConst[DVBT_CONSTELLATION_NUM][DVBT_HIERARCHY_NUM] =
+	{
+		{122880,	122880,		122880,		122880,		},
+		{146657,	146657,		156897,		171013,		},
+		{167857,	167857,		173127,		181810,		},
+	};
+
+	long Var;
+	MPI MpiCeEstEvm, MpiVar;
+
+
+
+	// Get FSM stage, CE_EST_EVM, constellation, and hierarchy.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_FSM_STAGE, &FsmStage) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_CE_EST_EVM, &CeEstEvm) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->GetConstellation(pDemod, &Constellation) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->GetHierarchy(pDemod, &Hierarchy) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+
+	// SNR dB formula
+	// Original formula: SNR_dB = 10 * log10(Norm * pow(2, 11) / CeEstEvm)
+	// Adjusted formula: SNR_dB = (SNR_DB_NUM_CONST - 10 * log2(CeEstEvm) * pow(2, SNR_FRAC_BIT_NUM)) / SNR_DB_DEN
+	//                   SNR_DB_NUM_CONST = 10 * log2(Norm * pow(2, 11)) * pow(2, SNR_FRAC_BIT_NUM)
+	//                   SNR_DB_DEN       = log2(10) * pow(2, SNR_FRAC_BIT_NUM)
+	// Norm:
+	//	                 None      Alpha=1   Alpha=2   Alpha=4
+	//        4-QAM      2         2         2         2
+	//       16-QAM      10        10        20        52
+	//       64-QAM      42        42        60        108
+
+
+	// If FSM stage < 10, set CE_EST_EVM with max value.
+	if(FsmStage < 10)
+		CeEstEvm = RTL2832_CE_EST_EVM_MAX_VALUE;
+
+
+	// Calculate SNR dB numerator.
+	MpiSetValue(&MpiCeEstEvm, CeEstEvm);
+
+	MpiLog2(&MpiVar, MpiCeEstEvm, RTL2832_SNR_FRAC_BIT_NUM);
+
+	MpiGetValue(MpiVar, &Var);
+
+	*pSnrDbNum = SnrDbNumConst[Constellation][Hierarchy] - 10 * Var;
+
+	
+	// Set SNR dB denominator.
+	*pSnrDbDen = RTL2832_SNR_DB_DEN;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_RF_AGC
+
+*/
+int
+rtl2832_GetRfAgc(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pRfAgc
+	)
+{
+	unsigned long Value;
+
+
+
+	// Get RF_AGC_VAL to Value.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RF_AGC_VAL, &Value) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Convert Value to signed integer and store the signed integer to RfAgc.
+	*pRfAgc = (int)BinToSignedInt(Value, RTL2832_RF_AGC_REG_BIT_NUM);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_IF_AGC
+
+*/
+int
+rtl2832_GetIfAgc(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pIfAgc
+	)
+{
+	unsigned long Value;
+
+
+
+	// Get IF_AGC_VAL to Value.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_IF_AGC_VAL, &Value) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Convert Value to signed integer and store the signed integer to IfAgc.
+	*pIfAgc = (int)BinToSignedInt(Value, RTL2832_IF_AGC_REG_BIT_NUM);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_DI_AGC
+
+*/
+int
+rtl2832_GetDiAgc(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char *pDiAgc
+	)
+{
+	unsigned long Value;
+
+
+
+	// Get DAGC_VAL to DiAgc.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_DAGC_VAL, &Value) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	*pDiAgc = (unsigned char)Value;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_TR_OFFSET_PPM
+
+*/
+int
+rtl2832_GetTrOffsetPpm(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pTrOffsetPpm
+	)
+{
+	unsigned long SfreqOffBinary;
+	long SfreqOffInt;
+
+	MPI MpiSfreqOffInt;
+	MPI MpiConst, MpiVar;
+
+
+	// Get SfreqOff binary value from SFREQ_OFF register bits.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_SFREQ_OFF, &SfreqOffBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+	// Convert SfreqOff binary value to signed integer.
+	SfreqOffInt = BinToSignedInt(SfreqOffBinary, RTL2832_SFREQ_OFF_BIT_NUM);
+
+	
+	// Get TR offset in ppm.
+	// Note: Original formula:   TrOffsetPpm = (SfreqOffInt * 1000000) / pow(2, 24)
+	//       Adjusted formula:   TrOffsetPpm = (SfreqOffInt * 1000000) >> 24
+	MpiSetValue(&MpiSfreqOffInt, SfreqOffInt);
+	MpiSetValue(&MpiConst,       1000000);
+
+	MpiMul(&MpiVar, MpiSfreqOffInt, MpiConst);
+	MpiRightShift(&MpiVar, MpiVar, 24);
+
+	MpiGetValue(MpiVar, pTrOffsetPpm);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_CR_OFFSET_HZ
+
+*/
+int
+rtl2832_GetCrOffsetHz(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pCrOffsetHz
+	)
+{
+	int BandwidthMode;
+	int FftMode;
+
+	unsigned long CfreqOffBinary;
+	long CfreqOffInt;
+
+	long ConstWithBandwidthMode, ConstWithFftMode;
+
+	MPI MpiCfreqOffInt;
+	MPI MpiConstWithBandwidthMode, MpiConstWithFftMode;
+	MPI MpiConst, MpiVar0, MpiVar1, MpiNone;
+
+
+
+	// Get demod bandwidth mode.
+	if(pDemod->GetBandwidthMode(pDemod, &BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_bandwidth_mode;
+
+
+	// Get demod FFT mode.
+	if(pDemod->GetFftMode(pDemod, &FftMode) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Get CfreqOff binary value from CFREQ_OFF register bits.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_CFREQ_OFF, &CfreqOffBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+	// Convert CfreqOff binary value to signed integer.
+	CfreqOffInt = BinToSignedInt(CfreqOffBinary, RTL2832_CFREQ_OFF_BIT_NUM);
+
+
+	// Determine constant value with bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:	ConstWithBandwidthMode = 48000000;		break;
+		case DVBT_BANDWIDTH_7MHZ:	ConstWithBandwidthMode = 56000000;		break;
+		case DVBT_BANDWIDTH_8MHZ:	ConstWithBandwidthMode = 64000000;		break;
+	}
+
+
+	// Determine constant value with FFT mode.
+	switch(FftMode)
+	{
+		default:
+		case DVBT_FFT_MODE_2K:		ConstWithFftMode = 2048;		break;
+		case DVBT_FFT_MODE_8K:		ConstWithFftMode = 8192;		break;
+	}
+
+
+	// Get Cr offset in Hz.
+	// Note: Original formula:   CrOffsetHz = (CfreqOffInt * ConstWithBandwidthMode) / (ConstWithFftMode * 7 * 128)
+	//       Adjusted formula:   CrOffsetHz = (CfreqOffInt * ConstWithBandwidthMode) / ((ConstWithFftMode * 7) << 7)
+	MpiSetValue(&MpiCfreqOffInt,            CfreqOffInt);
+	MpiSetValue(&MpiConstWithBandwidthMode, ConstWithBandwidthMode);
+	MpiSetValue(&MpiConstWithFftMode,       ConstWithFftMode);
+	MpiSetValue(&MpiConst,                  7);
+
+	MpiMul(&MpiVar0, MpiCfreqOffInt, MpiConstWithBandwidthMode);
+	MpiMul(&MpiVar1, MpiConstWithFftMode, MpiConst);
+	MpiLeftShift(&MpiVar1, MpiVar1, 7);
+	MpiDiv(&MpiVar0, &MpiNone, MpiVar0, MpiVar1);
+
+	MpiGetValue(MpiVar0, pCrOffsetHz);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_get_demod_bandwidth_mode:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_CONSTELLATION
+
+*/
+int
+rtl2832_GetConstellation(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pConstellation
+	)
+{
+	unsigned long ReadingValue;
+
+
+	// Get TPS constellation information from RX_CONSTEL.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RX_CONSTEL, &ReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(ReadingValue)
+	{
+		default:
+		case 0:		*pConstellation = DVBT_CONSTELLATION_QPSK;			break;
+		case 1:		*pConstellation = DVBT_CONSTELLATION_16QAM;			break;
+		case 2:		*pConstellation = DVBT_CONSTELLATION_64QAM;			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_HIERARCHY
+
+*/
+int
+rtl2832_GetHierarchy(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pHierarchy
+	)
+{
+	unsigned long ReadingValue;
+
+
+	// Get TPS hierarchy infromation from RX_HIER.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RX_HIER, &ReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(ReadingValue)
+	{
+		default:
+		case 0:		*pHierarchy = DVBT_HIERARCHY_NONE;				break;
+		case 1:		*pHierarchy = DVBT_HIERARCHY_ALPHA_1;			break;
+		case 2:		*pHierarchy = DVBT_HIERARCHY_ALPHA_2;			break;
+		case 3:		*pHierarchy = DVBT_HIERARCHY_ALPHA_4;			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_CODE_RATE_LP
+
+*/
+int
+rtl2832_GetCodeRateLp(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pCodeRateLp
+	)
+{
+	unsigned long ReadingValue;
+
+
+	// Get TPS low-priority code rate infromation from RX_C_RATE_LP.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RX_C_RATE_LP, &ReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(ReadingValue)
+	{
+		default:
+		case 0:		*pCodeRateLp = DVBT_CODE_RATE_1_OVER_2;			break;
+		case 1:		*pCodeRateLp = DVBT_CODE_RATE_2_OVER_3;			break;
+		case 2:		*pCodeRateLp = DVBT_CODE_RATE_3_OVER_4;			break;
+		case 3:		*pCodeRateLp = DVBT_CODE_RATE_5_OVER_6;			break;
+		case 4:		*pCodeRateLp = DVBT_CODE_RATE_7_OVER_8;			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_CODE_RATE_HP
+
+*/
+int
+rtl2832_GetCodeRateHp(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pCodeRateHp
+	)
+{
+	unsigned long ReadingValue;
+
+
+	// Get TPS high-priority code rate infromation from RX_C_RATE_HP.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RX_C_RATE_HP, &ReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(ReadingValue)
+	{
+		default:
+		case 0:		*pCodeRateHp = DVBT_CODE_RATE_1_OVER_2;			break;
+		case 1:		*pCodeRateHp = DVBT_CODE_RATE_2_OVER_3;			break;
+		case 2:		*pCodeRateHp = DVBT_CODE_RATE_3_OVER_4;			break;
+		case 3:		*pCodeRateHp = DVBT_CODE_RATE_5_OVER_6;			break;
+		case 4:		*pCodeRateHp = DVBT_CODE_RATE_7_OVER_8;			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_GUARD_INTERVAL
+
+*/
+int
+rtl2832_GetGuardInterval(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pGuardInterval
+	)
+{
+	unsigned long ReadingValue;
+
+
+	// Get TPS guard interval infromation from GI_IDX.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_GI_IDX, &ReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(ReadingValue)
+	{
+		default:
+		case 0:		*pGuardInterval = DVBT_GUARD_INTERVAL_1_OVER_32;			break;
+		case 1:		*pGuardInterval = DVBT_GUARD_INTERVAL_1_OVER_16;			break;
+		case 2:		*pGuardInterval = DVBT_GUARD_INTERVAL_1_OVER_8;				break;
+		case 3:		*pGuardInterval = DVBT_GUARD_INTERVAL_1_OVER_4;				break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_FFT_MODE
+
+*/
+int
+rtl2832_GetFftMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pFftMode
+	)
+{
+	unsigned long ReadingValue;
+
+
+	// Get TPS FFT mode infromation from FFT_MODE_IDX.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_FFT_MODE_IDX, &ReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(ReadingValue)
+	{
+		default:
+		case 0:		*pFftMode = DVBT_FFT_MODE_2K;			break;
+		case 1:		*pFftMode = DVBT_FFT_MODE_8K;			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_UPDATE_FUNCTION
+
+*/
+int
+rtl2832_UpdateFunction(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	RTL2832_EXTRA_MODULE *pExtra;
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+
+	// Execute Function 1 according to Function 1 enabling status
+	if(pExtra->IsFunc1Enabled == YES)
+	{
+		if(rtl2832_func1_Update(pDemod) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_RESET_FUNCTION
+
+*/
+int
+rtl2832_ResetFunction(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	RTL2832_EXTRA_MODULE *pExtra;
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+
+	// Reset Function 1 settings according to Function 1 enabling status.
+	if(pExtra->IsFunc1Enabled == YES)
+	{
+		if(rtl2832_func1_Reset(pDemod) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   I2C_BRIDGE_FP_FORWARD_I2C_READING_CMD
+
+*/
+int
+rtl2832_ForwardI2cReadingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+
+
+	// Get demod module.
+	pDemod = (DVBT_DEMOD_MODULE *)pI2cBridge->pPrivateData;
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Send I2C reading command.
+	if(pBaseInterface->I2cRead(pBaseInterface, DeviceAddr, pReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_send_i2c_reading_command;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_send_i2c_reading_command:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   I2C_BRIDGE_FP_FORWARD_I2C_WRITING_CMD
+
+*/
+int
+rtl2832_ForwardI2cWritingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+
+
+	// Get demod module.
+	pDemod = (DVBT_DEMOD_MODULE *)pI2cBridge->pPrivateData;
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Send I2C writing command.
+	if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, pWritingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_send_i2c_writing_command;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_send_i2c_writing_command:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Initialize RTL2832 register table.
+
+Use rtl2832_InitRegTable() to initialize RTL2832 register table.
+
+
+@param [in]   pDemod   RTL2832 demod module pointer
+
+
+@note
+	-# The rtl2832_InitRegTable() function will be called by BuildRtl2832Module().
+
+*/
+void
+rtl2832_InitRegTable(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	static const DVBT_PRIMARY_REG_ENTRY PrimaryRegTable[RTL2832_REG_TABLE_LEN] =
+	{
+		// Software reset register
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_SOFT_RST,						0x1,		0x1,			2,		2},
+
+		// Tuner I2C forwording register
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_IIC_REPEAT,					0x1,		0x1,			3,		3},
+
+		// Registers for initialization
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_TR_WAIT_MIN_8K,				0x1,		0x88,			11,		2},
+		{DVBT_RSD_BER_FAIL_VAL,				0x1,		0x8f,			15,		0},
+		{DVBT_EN_BK_TRK,					0x1,		0xa6,			7,		7},
+		{DVBT_AD_EN_REG,					0x0,		0x8,			7,		7},
+		{DVBT_AD_EN_REG1,					0x0,		0x8,			6,		6},
+		{DVBT_EN_BBIN,						0x1,		0xb1,			0,		0},
+		{DVBT_MGD_THD0,						0x1,		0x95,			7,		0},
+		{DVBT_MGD_THD1,						0x1,		0x96,			7,		0},
+		{DVBT_MGD_THD2,						0x1,		0x97,			7,		0},
+		{DVBT_MGD_THD3,						0x1,		0x98,			7,		0},
+		{DVBT_MGD_THD4,						0x1,		0x99,			7,		0},
+		{DVBT_MGD_THD5,						0x1,		0x9a,			7,		0},
+		{DVBT_MGD_THD6,						0x1,		0x9b,			7,		0},
+		{DVBT_MGD_THD7,						0x1,		0x9c,			7,		0},
+		{DVBT_EN_CACQ_NOTCH,				0x1,		0x61,			4,		4},
+		{DVBT_AD_AV_REF,					0x0,		0x9,			6,		0},
+		{DVBT_REG_PI,						0x0,		0xa,			2,		0},
+		{DVBT_PIP_ON,						0x0,		0x21,			3,		3},
+		{DVBT_SCALE1_B92,					0x2,		0x92,			7,		0},
+		{DVBT_SCALE1_B93,					0x2,		0x93,			7,		0},
+		{DVBT_SCALE1_BA7,					0x2,		0xa7,			7,		0},
+		{DVBT_SCALE1_BA9,					0x2,		0xa9,			7,		0},
+		{DVBT_SCALE1_BAA,					0x2,		0xaa,			7,		0},
+		{DVBT_SCALE1_BAB,					0x2,		0xab,			7,		0},
+		{DVBT_SCALE1_BAC,					0x2,		0xac,			7,		0},
+		{DVBT_SCALE1_BB0,					0x2,		0xb0,			7,		0},
+		{DVBT_SCALE1_BB1,					0x2,		0xb1,			7,		0},
+		{DVBT_KB_P1,						0x1,		0x64,			3,		1},
+		{DVBT_KB_P2,						0x1,		0x64,			6,		4},
+		{DVBT_KB_P3,						0x1,		0x65,			2,		0},
+		{DVBT_OPT_ADC_IQ,					0x0,		0x6,			5,		4},
+		{DVBT_AD_AVI,						0x0,		0x9,			1,		0},
+		{DVBT_AD_AVQ,						0x0,		0x9,			3,		2},
+		{DVBT_K1_CR_STEP12,					0x2,		0xad,			9,		4},
+
+		// Registers for initialization according to mode
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_TRK_KS_P2,					0x1,		0x6f,			2,		0},
+		{DVBT_TRK_KS_I2,					0x1,		0x70,			5,		3},
+		{DVBT_TR_THD_SET2,					0x1,		0x72,			3,		0},
+		{DVBT_TRK_KC_P2,					0x1,		0x73,			5,		3},
+		{DVBT_TRK_KC_I2,					0x1,		0x75,			2,		0},
+		{DVBT_CR_THD_SET2,					0x1,		0x76,			7,		6},
+
+		// Registers for IF setting
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_PSET_IFFREQ,					0x1,		0x19,			21,		0},
+		{DVBT_SPEC_INV,						0x1,		0x15,			0,		0},
+
+		// Registers for bandwidth programming
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_RSAMP_RATIO,					0x1,		0x9f,			27,		2},
+		{DVBT_CFREQ_OFF_RATIO,				0x1,		0x9d,			23,		4},
+
+		// FSM stage register
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_FSM_STAGE,					0x3,		0x51,			6,		3},
+
+		// TPS content registers
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_RX_CONSTEL,					0x3,		0x3c,			3,		2},
+		{DVBT_RX_HIER,						0x3,		0x3c,			6,		4},
+		{DVBT_RX_C_RATE_LP,					0x3,		0x3d,			2,		0},
+		{DVBT_RX_C_RATE_HP,					0x3,		0x3d,			5,		3},
+		{DVBT_GI_IDX,						0x3,		0x51,			1,		0},
+		{DVBT_FFT_MODE_IDX,					0x3,		0x51,			2,		2},
+
+		// Performance measurement registers
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_RSD_BER_EST,					0x3,		0x4e,			15,		0},
+		{DVBT_CE_EST_EVM,					0x4,		0xc,			15,		0},
+
+		// AGC registers
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_RF_AGC_VAL,					0x3,		0x5b,			13,		0},
+		{DVBT_IF_AGC_VAL,					0x3,		0x59,			13,		0},
+		{DVBT_DAGC_VAL,						0x3,		0x5,			7,		0},
+
+		// TR offset and CR offset registers
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_SFREQ_OFF,					0x3,		0x18,			13,		0},
+		{DVBT_CFREQ_OFF,					0x3,		0x5f,			17,		0},
+
+		// AGC relative registers
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_POLAR_RF_AGC,					0x0,		0xe,			1,		1},
+		{DVBT_POLAR_IF_AGC,					0x0,		0xe,			0,		0},
+		{DVBT_AAGC_HOLD,					0x1,		0x4,			5,		5},
+		{DVBT_EN_RF_AGC,					0x1,		0x4,			6,		6},
+		{DVBT_EN_IF_AGC,					0x1,		0x4,			7,		7},
+		{DVBT_IF_AGC_MIN,					0x1,		0x8,			7,		0},
+		{DVBT_IF_AGC_MAX,					0x1,		0x9,			7,		0},
+		{DVBT_RF_AGC_MIN,					0x1,		0xa,			7,		0},
+		{DVBT_RF_AGC_MAX,					0x1,		0xb,			7,		0},
+		{DVBT_IF_AGC_MAN,					0x1,		0xc,			6,		6},
+		{DVBT_IF_AGC_MAN_VAL,				0x1,		0xc,			13,		0},
+		{DVBT_RF_AGC_MAN,					0x1,		0xe,			6,		6},
+		{DVBT_RF_AGC_MAN_VAL,				0x1,		0xe,			13,		0},
+		{DVBT_DAGC_TRG_VAL,					0x1,		0x12,			7,		0},
+		{DVBT_AGC_TARG_VAL_0,				0x1,		0x2,			0,		0},
+		{DVBT_AGC_TARG_VAL_8_1,				0x1,		0x3,			7,		0},
+		{DVBT_AAGC_LOOP_GAIN,				0x1,		0xc7,			5,		1},
+		{DVBT_LOOP_GAIN2_3_0,				0x1,		0x4,			4,		1},
+		{DVBT_LOOP_GAIN2_4,					0x1,		0x5,			7,		7},
+		{DVBT_LOOP_GAIN3,					0x1,		0xc8,			4,		0},
+		{DVBT_VTOP1,						0x1,		0x6,			5,		0},
+		{DVBT_VTOP2,						0x1,		0xc9,			5,		0},
+		{DVBT_VTOP3,						0x1,		0xca,			5,		0},
+		{DVBT_KRF1,							0x1,		0xcb,			7,		0},
+		{DVBT_KRF2,							0x1,		0x7,			7,		0},
+		{DVBT_KRF3,							0x1,		0xcd,			7,		0},
+		{DVBT_KRF4,							0x1,		0xce,			7,		0},
+		{DVBT_EN_GI_PGA,					0x1,		0xe5,			0,		0},
+		{DVBT_THD_LOCK_UP,					0x1,		0xd9,			8,		0},
+		{DVBT_THD_LOCK_DW,					0x1,		0xdb,			8,		0},
+		{DVBT_THD_UP1,						0x1,		0xdd,			7,		0},
+		{DVBT_THD_DW1,						0x1,		0xde,			7,		0},
+		{DVBT_INTER_CNT_LEN,				0x1,		0xd8,			3,		0},
+		{DVBT_GI_PGA_STATE,					0x1,		0xe6,			3,		3},
+		{DVBT_EN_AGC_PGA,					0x1,		0xd7,			0,		0},
+
+		// TS interface registers
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_CKOUTPAR,						0x1,		0x7b,			5,		5},
+		{DVBT_CKOUT_PWR,					0x1,		0x7b,			6,		6},
+		{DVBT_SYNC_DUR,						0x1,		0x7b,			7,		7},
+		{DVBT_ERR_DUR,						0x1,		0x7c,			0,		0},
+		{DVBT_SYNC_LVL,						0x1,		0x7c,			1,		1},
+		{DVBT_ERR_LVL,						0x1,		0x7c,			2,		2},
+		{DVBT_VAL_LVL,						0x1,		0x7c,			3,		3},
+		{DVBT_SERIAL,						0x1,		0x7c,			4,		4},
+		{DVBT_SER_LSB,						0x1,		0x7c,			5,		5},
+		{DVBT_CDIV_PH0,						0x1,		0x7d,			3,		0},
+		{DVBT_CDIV_PH1,						0x1,		0x7d,			7,		4},
+		{DVBT_MPEG_IO_OPT_2_2,				0x0,		0x6,			7,		7},
+		{DVBT_MPEG_IO_OPT_1_0,				0x0,		0x7,			7,		6},
+		{DVBT_CKOUTPAR_PIP,					0x0,		0xb7,			4,		4},
+		{DVBT_CKOUT_PWR_PIP,				0x0,		0xb7,			3,		3},
+		{DVBT_SYNC_LVL_PIP,					0x0,		0xb7,			2,		2},
+		{DVBT_ERR_LVL_PIP,					0x0,		0xb7,			1,		1},
+		{DVBT_VAL_LVL_PIP,					0x0,		0xb7,			0,		0},
+		{DVBT_CKOUTPAR_PID,					0x0,		0xb9,			4,		4},
+		{DVBT_CKOUT_PWR_PID,				0x0,		0xb9,			3,		3},
+		{DVBT_SYNC_LVL_PID,					0x0,		0xb9,			2,		2},
+		{DVBT_ERR_LVL_PID,					0x0,		0xb9,			1,		1},
+		{DVBT_VAL_LVL_PID,					0x0,		0xb9,			0,		0},
+
+		// FSM state-holding register
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_SM_PASS,						0x1,		0x93,			11,		0},
+
+		// AD7 registers
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_AD7_SETTING,					0x0,		0x11,			15,		0},
+		{DVBT_RSSI_R,						0x3,		0x1,			6,		0},
+
+		// ACI detection registers
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_ACI_DET_IND,					0x3,		0x12,			0,		0},
+
+		// Clock output registers
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DVBT_REG_MON,						0x0,		0xd,			1,		0},
+		{DVBT_REG_MONSEL,					0x0,		0xd,			2,		2},
+		{DVBT_REG_GPE,						0x0,		0xd,			7,		7},
+		{DVBT_REG_GPO,						0x0,		0x10,			0,		0},
+		{DVBT_REG_4MSEL,					0x0,		0x13,			0,		0},
+	};
+
+
+	int i;
+	int RegBitName;
+
+
+
+	// Initialize register table according to primary register table.
+	// Note: 1. Register table rows are sorted by register bit name key.
+	//       2. The default value of the IsAvailable variable is "NO".
+	for(i = 0; i < DVBT_REG_TABLE_LEN_MAX; i++)
+		pDemod->RegTable[i].IsAvailable  = NO;
+
+	for(i = 0; i < RTL2832_REG_TABLE_LEN; i++)
+	{
+		RegBitName = PrimaryRegTable[i].RegBitName;
+
+		pDemod->RegTable[RegBitName].IsAvailable  = YES;
+		pDemod->RegTable[RegBitName].PageNo       = PrimaryRegTable[i].PageNo;
+		pDemod->RegTable[RegBitName].RegStartAddr = PrimaryRegTable[i].RegStartAddr;
+		pDemod->RegTable[RegBitName].Msb          = PrimaryRegTable[i].Msb;
+		pDemod->RegTable[RegBitName].Lsb          = PrimaryRegTable[i].Lsb;
+	}
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Set I2C bridge module demod arguments.
+
+RTL2832 builder will use rtl2832_BuildI2cBridgeModule() to set I2C bridge module demod arguments.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@see   BuildRtl2832Module()
+
+*/
+void
+rtl2832_BuildI2cBridgeModule(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	I2C_BRIDGE_MODULE *pI2cBridge;
+
+
+
+	// Get I2C bridge module.
+	pI2cBridge = pDemod->pI2cBridge;
+
+	// Set I2C bridge module demod arguments.
+	pI2cBridge->pPrivateData = (void *)pDemod;
+	pI2cBridge->ForwardI2cReadingCmd = rtl2832_ForwardI2cReadingCmd;
+	pI2cBridge->ForwardI2cWritingCmd = rtl2832_ForwardI2cWritingCmd;
+
+
+	return;
+}
+
+
+
+
+
+/*
+
+@see   RTL2832_FP_GET_APP_MODE
+
+*/
+void
+rtl2832_GetAppMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAppMode
+	)
+{
+	RTL2832_EXTRA_MODULE *pExtra;
+
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+
+	// Get demod type from demod module.
+	*pAppMode = pExtra->AppMode;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Reset Function 1 variables and registers.
+
+One can use rtl2832_func1_Reset() to reset Function 1 variables and registers.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset Function 1 variables and registers successfully.
+@retval   FUNCTION_ERROR     Reset Function 1 variables and registers unsuccessfully.
+
+
+@note
+	-# Need to execute Function 1 reset function when change tuner RF frequency or demod parameters.
+	-# Function 1 update flow also employs Function 1 reset function.
+
+*/
+int
+rtl2832_func1_Reset(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	RTL2832_EXTRA_MODULE *pExtra;
+
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+	// Reset demod Function 1 variables.
+	pExtra->Func1State               = RTL2832_FUNC1_STATE_NORMAL;
+	pExtra->Func1WaitTime            = 0;
+	pExtra->Func1GettingTime         = 0;
+	pExtra->Func1RsdBerEstSumNormal  = 0;
+	pExtra->Func1RsdBerEstSumConfig1 = 0;
+	pExtra->Func1RsdBerEstSumConfig2 = 0;
+	pExtra->Func1RsdBerEstSumConfig3 = 0;
+
+
+	// Reset demod Function 1 registers.
+    if(rtl2832_func1_ResetReg(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Update demod registers with Function 1.
+
+One can use rtl2832_func1_Update() to update demod registers with Function 1.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update demod registers with Function 1 successfully.
+@retval   FUNCTION_ERROR     Update demod registers with Function 1 unsuccessfully.
+
+*/
+int
+rtl2832_func1_Update(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	RTL2832_EXTRA_MODULE *pExtra;
+
+	int Answer;
+	int MinWeightedBerConfigMode;
+
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+
+	// Run FSM.
+	switch(pExtra->Func1State)
+	{
+		case RTL2832_FUNC1_STATE_NORMAL:
+
+			// Ask if criterion is matched.
+			if(rtl2832_func1_IsCriterionMatched(pDemod, &Answer) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			if(Answer == YES)
+			{
+				// Accumulate RSD_BER_EST for normal case.
+				if(rtl2832_func1_AccumulateRsdBerEst(pDemod, &pExtra->Func1RsdBerEstSumNormal) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset getting time counter.
+				pExtra->Func1GettingTime = 0;
+
+				// Go to RTL2832_FUNC1_STATE_NORMAL_GET_BER state.
+				pExtra->Func1State = RTL2832_FUNC1_STATE_NORMAL_GET_BER;
+			}
+
+			break;
+
+
+		case RTL2832_FUNC1_STATE_NORMAL_GET_BER:
+
+			// Accumulate RSD_BER_EST for normal case.
+			if(rtl2832_func1_AccumulateRsdBerEst(pDemod, &pExtra->Func1RsdBerEstSumNormal) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			// Use getting time counter to hold RTL2832_FUNC1_STATE_NORMAL_GET_BER state several times.
+			pExtra->Func1GettingTime += 1;
+
+			if(pExtra->Func1GettingTime >= pExtra->Func1GettingTimeMax)
+			{
+				// Set common registers for configuration 1, 2, and 3 case.
+				if(rtl2832_func1_SetCommonReg(pDemod) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Set registers with FFT mode for configuration 1, 2, and 3 case.
+				if(rtl2832_func1_SetRegWithFftMode(pDemod, pExtra->Func1FftBak) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Set registers for configuration 1 case.
+				if(rtl2832_func1_SetRegWithConfigMode(pDemod, RTL2832_FUNC1_CONFIG_1) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset demod by software reset.
+				if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset wait time counter.
+				pExtra->Func1WaitTime = 0;
+
+				// Go to RTL2832_FUNC1_STATE_CONFIG_1_WAIT state.
+				pExtra->Func1State = RTL2832_FUNC1_STATE_CONFIG_1_WAIT;
+			}
+
+			break;
+
+
+		case RTL2832_FUNC1_STATE_CONFIG_1_WAIT:
+
+			// Use wait time counter to hold RTL2832_FUNC1_STATE_CONFIG_1_WAIT state several times.
+			pExtra->Func1WaitTime += 1;
+
+			if(pExtra->Func1WaitTime >= pExtra->Func1WaitTimeMax)
+			{
+				// Accumulate RSD_BER_EST for configuration 1 case.
+				if(rtl2832_func1_AccumulateRsdBerEst(pDemod, &pExtra->Func1RsdBerEstSumConfig1) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset getting time counter.
+				pExtra->Func1GettingTime = 0;
+
+				// Go to RTL2832_FUNC1_STATE_CONFIG_1_GET_BER state.
+				pExtra->Func1State = RTL2832_FUNC1_STATE_CONFIG_1_GET_BER;
+			}
+
+			break;
+
+
+		case RTL2832_FUNC1_STATE_CONFIG_1_GET_BER:
+
+			// Accumulate RSD_BER_EST for configuration 1 case.
+			if(rtl2832_func1_AccumulateRsdBerEst(pDemod, &pExtra->Func1RsdBerEstSumConfig1) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			// Use getting time counter to hold RTL2832_FUNC1_STATE_CONFIG_1_GET_BER state several times.
+			pExtra->Func1GettingTime += 1;
+
+			if(pExtra->Func1GettingTime >= pExtra->Func1GettingTimeMax)
+			{
+				// Set registers for configuration 2 case.
+				if(rtl2832_func1_SetRegWithConfigMode(pDemod, RTL2832_FUNC1_CONFIG_2) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset demod by software reset.
+				if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset wait time counter.
+				pExtra->Func1WaitTime = 0;
+
+				// Go to RTL2832_FUNC1_STATE_CONFIG_2_WAIT state.
+				pExtra->Func1State = RTL2832_FUNC1_STATE_CONFIG_2_WAIT;
+			}
+
+			break;
+
+
+		case RTL2832_FUNC1_STATE_CONFIG_2_WAIT:
+
+			// Use wait time counter to hold RTL2832_FUNC1_STATE_CONFIG_2_WAIT state several times.
+			pExtra->Func1WaitTime += 1;
+
+			if(pExtra->Func1WaitTime >= pExtra->Func1WaitTimeMax)
+			{
+				// Accumulate RSD_BER_EST for configuration 2 case.
+				if(rtl2832_func1_AccumulateRsdBerEst(pDemod, &pExtra->Func1RsdBerEstSumConfig2) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset getting time counter.
+				pExtra->Func1GettingTime = 0;
+
+				// Go to RTL2832_FUNC1_STATE_CONFIG_2_GET_BER state.
+				pExtra->Func1State = RTL2832_FUNC1_STATE_CONFIG_2_GET_BER;
+			}
+
+			break;
+
+
+		case RTL2832_FUNC1_STATE_CONFIG_2_GET_BER:
+
+			// Accumulate RSD_BER_EST for configuration 2 case.
+			if(rtl2832_func1_AccumulateRsdBerEst(pDemod, &pExtra->Func1RsdBerEstSumConfig2) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			// Use getting time counter to hold RTL2832_FUNC1_STATE_CONFIG_2_GET_BER state several times.
+			pExtra->Func1GettingTime += 1;
+
+			if(pExtra->Func1GettingTime >= pExtra->Func1GettingTimeMax)
+			{
+				// Set registers for configuration 3 case.
+				if(rtl2832_func1_SetRegWithConfigMode(pDemod, RTL2832_FUNC1_CONFIG_3) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset demod by software reset.
+				if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset wait time counter.
+				pExtra->Func1WaitTime = 0;
+
+				// Go to RTL2832_FUNC1_STATE_CONFIG_3_WAIT state.
+				pExtra->Func1State = RTL2832_FUNC1_STATE_CONFIG_3_WAIT;
+			}
+
+			break;
+
+
+		case RTL2832_FUNC1_STATE_CONFIG_3_WAIT:
+
+			// Use wait time counter to hold RTL2832_FUNC1_STATE_CONFIG_3_WAIT state several times.
+			pExtra->Func1WaitTime += 1;
+
+			if(pExtra->Func1WaitTime >= pExtra->Func1WaitTimeMax)
+			{
+				// Accumulate RSD_BER_EST for configuration 3 case.
+				if(rtl2832_func1_AccumulateRsdBerEst(pDemod, &pExtra->Func1RsdBerEstSumConfig3) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset getting time counter.
+				pExtra->Func1GettingTime = 0;
+
+				// Go to RTL2832_FUNC1_STATE_CONFIG_3_GET_BER state.
+				pExtra->Func1State = RTL2832_FUNC1_STATE_CONFIG_3_GET_BER;
+			}
+
+			break;
+
+
+		case RTL2832_FUNC1_STATE_CONFIG_3_GET_BER:
+
+			// Accumulate RSD_BER_EST for configuration 3 case.
+			if(rtl2832_func1_AccumulateRsdBerEst(pDemod, &pExtra->Func1RsdBerEstSumConfig3) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			// Use getting time counter to hold RTL2832_FUNC1_STATE_CONFIG_3_GET_BER state several times.
+			pExtra->Func1GettingTime += 1;
+
+			if(pExtra->Func1GettingTime >= pExtra->Func1GettingTimeMax)
+			{
+				// Determine minimum-weighted-BER configuration mode.
+				rtl2832_func1_GetMinWeightedBerConfigMode(pDemod, &MinWeightedBerConfigMode);
+
+				// Set registers with minimum-weighted-BER configuration mode.
+				switch(MinWeightedBerConfigMode)
+				{
+					case RTL2832_FUNC1_CONFIG_NORMAL:
+
+						// Reset registers for normal configuration.
+						if(rtl2832_func1_ResetReg(pDemod) != FUNCTION_SUCCESS)
+							goto error_status_execute_function;
+
+						break;
+
+
+					case RTL2832_FUNC1_CONFIG_1:
+					case RTL2832_FUNC1_CONFIG_2:
+					case RTL2832_FUNC1_CONFIG_3:
+
+						// Set registers for minimum-weighted-BER configuration.
+						if(rtl2832_func1_SetRegWithConfigMode(pDemod, MinWeightedBerConfigMode) != FUNCTION_SUCCESS)
+							goto error_status_execute_function;
+
+						break;
+
+
+					default:
+
+						// Get error configuration mode, reset registers.
+						if(rtl2832_func1_ResetReg(pDemod) != FUNCTION_SUCCESS)
+							goto error_status_execute_function;
+
+						break;
+				}
+
+				// Reset demod by software reset.
+				if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+
+				// Reset wait time counter.
+				pExtra->Func1WaitTime = 0;
+
+				// Go to RTL2832_FUNC1_STATE_DETERMINED_WAIT state.
+				pExtra->Func1State = RTL2832_FUNC1_STATE_DETERMINED_WAIT;
+			}
+
+			break;
+
+
+		case RTL2832_FUNC1_STATE_DETERMINED_WAIT:
+
+			// Use wait time counter to hold RTL2832_FUNC1_STATE_CONFIG_3_WAIT state several times.
+			pExtra->Func1WaitTime += 1;
+
+			if(pExtra->Func1WaitTime >= pExtra->Func1WaitTimeMax)
+			{
+				// Go to RTL2832_FUNC1_STATE_DETERMINED state.
+				pExtra->Func1State = RTL2832_FUNC1_STATE_DETERMINED;
+			}
+
+			break;
+
+
+		case RTL2832_FUNC1_STATE_DETERMINED:
+
+			// Ask if criterion is matched.
+			if(rtl2832_func1_IsCriterionMatched(pDemod, &Answer) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			if(Answer == NO)
+			{
+				// Reset FSM.
+				// Note: rtl2832_func1_Reset() will set FSM state with RTL2832_FUNC1_STATE_NORMAL.
+				if(rtl2832_func1_Reset(pDemod) != FUNCTION_SUCCESS)
+					goto error_status_execute_function;
+			}
+
+			break;
+
+
+		default:
+
+			// Get error state, reset FSM.
+			// Note: rtl2832_func1_Reset() will set FSM state with RTL2832_FUNC1_STATE_NORMAL.
+			if(rtl2832_func1_Reset(pDemod) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			break;
+	}
+
+
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Ask if criterion is matched for Function 1.
+
+One can use rtl2832_func1_IsCriterionMatched() to ask if criterion is matched for Function 1.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Ask if criterion is matched for Function 1 successfully.
+@retval   FUNCTION_ERROR     Ask if criterion is matched for Function 1 unsuccessfully.
+
+*/
+int
+rtl2832_func1_IsCriterionMatched(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	RTL2832_EXTRA_MODULE *pExtra;
+
+	unsigned long FsmStage;
+
+	int Qam;
+	int Hier;
+	int LpCr;
+	int HpCr;
+	int Gi;
+	int Fft;
+
+	unsigned long Reg0, Reg1;
+
+	int BandwidthMode;
+
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+
+	// Get FSM_STAGE.
+    if(pDemod->GetRegBitsWithPage(pDemod, DVBT_FSM_STAGE, &FsmStage) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Get QAM.
+	if(pDemod->GetConstellation(pDemod, &Qam) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get hierarchy.
+	if(pDemod->GetHierarchy(pDemod, &Hier) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get low-priority code rate.
+	if(pDemod->GetCodeRateLp(pDemod, &LpCr) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get high-priority code rate.
+	if(pDemod->GetCodeRateHp(pDemod, &HpCr) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get guard interval.
+	if(pDemod->GetGuardInterval(pDemod, &Gi) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get FFT mode.
+	if(pDemod->GetFftMode(pDemod, &Fft) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Get REG_0 and REG_1.
+	if(pDemod->SetRegPage(pDemod, 0x3) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->GetRegMaskBits(pDemod, 0x22, 0, 0, &Reg0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->GetRegMaskBits(pDemod, 0x1a, 15, 3, &Reg1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Get bandwidth mode.
+	if(pDemod->GetBandwidthMode(pDemod, &BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Determine criterion answer.
+	*pAnswer = 
+		(FsmStage == 11) && 
+
+		(Qam  == pExtra->Func1QamBak) &&
+		(Hier == pExtra->Func1HierBak) &&
+		(LpCr == pExtra->Func1LpCrBak) &&
+		(HpCr == pExtra->Func1HpCrBak) &&
+		(Gi   == pExtra->Func1GiBak) &&
+		(Fft  == pExtra->Func1FftBak) &&
+
+		(Reg0 == 0x1) &&
+
+		((BandwidthMode == DVBT_BANDWIDTH_8MHZ) &&
+		 ( ((Fft == DVBT_FFT_MODE_2K) && (Reg1 > 1424) && (Reg1 < 1440)) ||
+		   ((Fft == DVBT_FFT_MODE_8K) && (Reg1 > 5696) && (Reg1 < 5760))    ) );
+
+
+	// Backup TPS information.
+	pExtra->Func1QamBak  = Qam;
+	pExtra->Func1HierBak = Hier;
+	pExtra->Func1LpCrBak = LpCr;
+	pExtra->Func1HpCrBak = HpCr;
+	pExtra->Func1GiBak   = Gi;
+	pExtra->Func1FftBak  = Fft;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+error_status_execute_function:
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Accumulate RSD_BER_EST value for Function 1.
+
+One can use rtl2832_func1_AccumulateRsdBerEst() to accumulate RSD_BER_EST for Function 1.
+
+
+@param [in]   pDemod               The demod module pointer
+@param [in]   pAccumulativeValue   Accumulative RSD_BER_EST value
+
+
+@retval   FUNCTION_SUCCESS   Accumulate RSD_BER_EST for Function 1 successfully.
+@retval   FUNCTION_ERROR     Accumulate RSD_BER_EST for Function 1 unsuccessfully.
+
+*/
+int
+rtl2832_func1_AccumulateRsdBerEst(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pAccumulativeValue
+	)
+{
+	RTL2832_EXTRA_MODULE *pExtra;
+
+	int i;
+	unsigned long RsdBerEst;
+
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+
+	// Get RSD_BER_EST with assigned times.
+	for(i = 0; i < pExtra->Func1GettingNumEachTime; i++)
+	{
+		// Get RSD_BER_EST.
+		if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RSD_BER_EST, &RsdBerEst) != FUNCTION_SUCCESS)
+			goto error_status_get_registers;
+
+		// Accumulate RSD_BER_EST to accumulative value.
+		*pAccumulativeValue += RsdBerEst;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Reset registers for Function 1.
+
+One can use rtl2832_func1_ResetReg() to reset registers for Function 1.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset registers for Function 1 successfully.
+@retval   FUNCTION_ERROR     Reset registers for Function 1 unsuccessfully.
+
+*/
+int
+rtl2832_func1_ResetReg(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	// Reset Function 1 registers.
+    if(pDemod->SetRegPage(pDemod, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x65, 2, 0, 0x7) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x68, 5, 4, 0x3) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x5b, 2, 0, 0x5) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x5b, 5, 3, 0x5) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x5c, 2, 0, 0x5) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x5c, 5, 3, 0x5) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd0, 3, 2, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd1, 14, 0, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd3, 14, 0, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd5, 14, 0, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegPage(pDemod, 0x2) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x1, 0, 0, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xb4, 7, 6, 0x3) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd2, 1, 1, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xb5, 7, 7, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Set common registers for Function 1.
+
+One can use rtl2832_func1_SetCommonReg() to set common registers for Function 1.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Set common registers for Function 1 successfully.
+@retval   FUNCTION_ERROR     Set common registers for Function 1 unsuccessfully.
+
+*/
+int
+rtl2832_func1_SetCommonReg(
+	DVBT_DEMOD_MODULE *pDemod
+	)
+{
+	// Set common registers for Function 1.
+    if(pDemod->SetRegPage(pDemod, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x65, 2, 0, 0x5) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x68, 5, 4, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegPage(pDemod, 0x2) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd2, 1, 1, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xb5, 7, 7, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Set registers with FFT mode for Function 1.
+
+One can use rtl2832_func1_SetRegWithConfigMode() to set registers with FFT mode for Function 1.
+
+
+@param [in]   pDemod    The demod module pointer
+@param [in]   FftMode   FFT mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set registers with FFT mode for Function 1 successfully.
+@retval   FUNCTION_ERROR     Set registers with FFT mode for Function 1 unsuccessfully.
+
+*/
+int
+rtl2832_func1_SetRegWithFftMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int FftMode
+	)
+{
+	typedef struct
+	{
+		unsigned long Reg0[DVBT_FFT_MODE_NUM];
+		unsigned long Reg1[DVBT_FFT_MODE_NUM];
+	}
+	FFT_REF_ENTRY;
+
+
+
+	static const FFT_REF_ENTRY FftRefTable =
+	{
+		// 2K mode,   8K mode
+		{0x0,         0x1    },
+		{0x3,         0x0    },
+	};
+
+
+
+	// Set registers with FFT mode for Function 1.
+    if(pDemod->SetRegPage(pDemod, 0x2) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x1, 0, 0, FftRefTable.Reg0[FftMode]) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xb4, 7, 6, FftRefTable.Reg1[FftMode]) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Set registers with configuration mode for Function 1.
+
+One can use rtl2832_func1_SetRegWithConfigMode() to set registers with configuration mode for Function 1.
+
+
+@param [in]   pDemod       The demod module pointer
+@param [in]   ConfigMode   Configuration mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set registers with configuration mode for Function 1 successfully.
+@retval   FUNCTION_ERROR     Set registers with configuration mode for Function 1 unsuccessfully.
+
+
+@note
+	-# This function can not set RTL2832_FUNC1_CONFIG_NORMAL configuration mode.
+
+*/
+int
+rtl2832_func1_SetRegWithConfigMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int ConfigMode
+	)
+{
+	typedef struct
+	{
+		unsigned long Reg0[RTL2832_FUNC1_CONFIG_MODE_NUM];
+		unsigned long Reg1[RTL2832_FUNC1_CONFIG_MODE_NUM];
+		unsigned long Reg2[RTL2832_FUNC1_CONFIG_MODE_NUM];
+		unsigned long Reg3[RTL2832_FUNC1_CONFIG_MODE_NUM];
+		unsigned long Reg4[RTL2832_FUNC1_CONFIG_MODE_NUM];
+
+		unsigned long Reg5Ref[RTL2832_FUNC1_CONFIG_MODE_NUM];
+		unsigned long Reg6Ref[RTL2832_FUNC1_CONFIG_MODE_NUM];
+		unsigned long Reg7Ref[RTL2832_FUNC1_CONFIG_MODE_NUM];
+	}
+	CONFIG_REF_ENTRY;
+
+
+
+	static const CONFIG_REF_ENTRY ConfigRefTable =
+	{
+		// Config 1,   Config 2,   Config 3
+		{0x5,          0x4,        0x5     },
+		{0x5,          0x4,        0x7     },
+		{0x5,          0x4,        0x7     },
+		{0x7,          0x6,        0x5     },
+		{0x3,          0x3,        0x2     },
+
+		{4437,         4437,       4325    },
+		{6000,         5500,       6500    },
+		{6552,         5800,       5850    },
+	};
+
+	int BandwidthMode;
+
+	static const unsigned long Const[DVBT_BANDWIDTH_MODE_NUM] =
+	{
+		// 6Mhz, 7Mhz, 8Mhz
+		48,      56,   64,
+	};
+
+	unsigned long Reg5, Reg6, Reg7;
+
+
+
+	// Get bandwidth mode.
+	if(pDemod->GetBandwidthMode(pDemod, &BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Calculate REG_5, REG_6, and REG_7 with bandwidth mode and configuration mode.
+	Reg5 = (ConfigRefTable.Reg5Ref[ConfigMode] * 7 * 2048 * 8) / (1000 * Const[BandwidthMode]);
+	Reg6 = (ConfigRefTable.Reg6Ref[ConfigMode] * 7 * 2048 * 8) / (1000 * Const[BandwidthMode]);
+	Reg7 = (ConfigRefTable.Reg7Ref[ConfigMode] * 7 * 2048 * 8) / (1000 * Const[BandwidthMode]);
+
+
+	// Set registers with bandwidth mode and configuration mode.
+    if(pDemod->SetRegPage(pDemod, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x5b, 2, 0, ConfigRefTable.Reg0[ConfigMode]) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x5b, 5, 3, ConfigRefTable.Reg1[ConfigMode]) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x5c, 2, 0, ConfigRefTable.Reg2[ConfigMode]) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0x5c, 5, 3, ConfigRefTable.Reg3[ConfigMode]) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd0, 3, 2, ConfigRefTable.Reg4[ConfigMode]) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd1, 14, 0, Reg5) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd3, 14, 0, Reg6) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+    if(pDemod->SetRegMaskBits(pDemod, 0xd5, 14, 0, Reg7) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Get minimum-weighted-BER configuration mode for Function 1.
+
+One can use rtl2832_func1_GetMinWeightedBerConfigMode() to get minimum-weighted-BER configuration mode for Function 1.
+
+
+@param [in]    pDemod        The demod module pointer
+@param [out]   pConfigMode   Pointer to an allocated memory for storing configuration mode answer
+
+
+@retval   FUNCTION_SUCCESS   Get minimum-weighted-BER configuration mode for Function 1 successfully.
+@retval   FUNCTION_ERROR     Get minimum-weighted-BER configuration mode for Function 1 unsuccessfully.
+
+*/
+void
+rtl2832_func1_GetMinWeightedBerConfigMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pConfigMode
+	)
+{
+	RTL2832_EXTRA_MODULE *pExtra;
+
+	unsigned long WeightedBerNormal;
+	unsigned long WeightedBerConfig1;
+	unsigned long WeightedBerConfig2;
+	unsigned long WeightedBerConfig3;
+
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2832);
+
+
+	// Calculate weighted BER for all configuration mode
+	WeightedBerNormal  = pExtra->Func1RsdBerEstSumNormal * 2;
+	WeightedBerConfig1 = pExtra->Func1RsdBerEstSumConfig1;
+	WeightedBerConfig2 = pExtra->Func1RsdBerEstSumConfig2;
+	WeightedBerConfig3 = pExtra->Func1RsdBerEstSumConfig3;
+
+
+	// Determine minimum-weighted-BER configuration mode.
+	if(WeightedBerNormal <= WeightedBerConfig1 &&
+		WeightedBerNormal <= WeightedBerConfig2 &&
+		WeightedBerNormal <= WeightedBerConfig3)
+	{
+		*pConfigMode = RTL2832_FUNC1_CONFIG_NORMAL;
+	}
+	else if(WeightedBerConfig1 <= WeightedBerNormal &&
+		WeightedBerConfig1 <= WeightedBerConfig2 &&
+		WeightedBerConfig1 <= WeightedBerConfig3)
+	{
+		*pConfigMode = RTL2832_FUNC1_CONFIG_1;
+	}
+	else if(WeightedBerConfig2 <= WeightedBerNormal &&
+		WeightedBerConfig2 <= WeightedBerConfig1 &&
+		WeightedBerConfig2 <= WeightedBerConfig3)
+	{
+		*pConfigMode = RTL2832_FUNC1_CONFIG_2;
+	}
+	else if(WeightedBerConfig3 <= WeightedBerNormal &&
+		WeightedBerConfig3 <= WeightedBerConfig1 &&
+		WeightedBerConfig3 <= WeightedBerConfig2)
+	{
+		*pConfigMode = RTL2832_FUNC1_CONFIG_3;
+	}
+
+
+	return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/demod_rtl2832.h b/drivers/media/usb/dvb-usb/demod_rtl2832.h
new file mode 100644
index 0000000..0c3674a
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/demod_rtl2832.h
@@ -0,0 +1,466 @@
+#ifndef __DEMOD_RTL2832_H
+#define __DEMOD_RTL2832_H
+
+/**
+
+@file
+
+@brief   RTL2832 demod module declaration
+
+One can manipulate RTL2832 demod through RTL2832 module.
+RTL2832 module is derived from DVB-T demod module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the DVB-T demod example in dvbt_demod_base.h except the listed lines.
+
+
+
+#include "demod_rtl2832.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+	DVBT_DEMOD_MODULE     DvbtDemodModuleMemory;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+	I2C_BRIDGE_MODULE     I2cBridgeModuleMemory;
+
+
+	...
+
+
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pDemod,
+		&DvbtDemodModuleMemory,
+		&BaseInterfaceModuleMemory,
+		&I2cBridgeModuleMemory,
+		0x20,								// I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,			// Crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,				// TS interface mode is serial.
+		RTL2832_APPLICATION_STB,			// Application mode is STB.
+		200,								// Update function reference period is 200 millisecond
+		YES									// Function 1 enabling status is YES.
+		);
+
+
+
+	// See the example for other DVB-T demod functions in dvbt_demod_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "dvbt_demod_base.h"
+
+
+extern int dvb_usb_rtl2832u_snrdb;
+
+
+// Definitions
+
+// Initializing
+#define RTL2832_INIT_TABLE_LEN						32
+#define RTL2832_TS_INTERFACE_INIT_TABLE_LEN			5
+#define RTL2832_APP_INIT_TABLE_LEN					5
+
+
+// Bandwidth setting
+#define RTL2832_H_LPF_X_PAGE		1
+#define RTL2832_H_LPF_X_ADDR		0x1c
+#define RTL2832_H_LPF_X_LEN			32
+#define RTL2832_RATIO_PAGE			1
+#define RTL2832_RATIO_ADDR			0x9d
+#define RTL2832_RATIO_LEN			6
+
+
+// Bandwidth setting
+#define RTL2832_CFREQ_OFF_RATIO_BIT_NUM		20
+
+
+// IF frequency setting
+#define RTL2832_PSET_IFFREQ_BIT_NUM		22
+
+
+// Signal quality
+#define RTL2832_SQ_FRAC_BIT_NUM			5
+
+
+// BER
+#define RTL2832_BER_DEN_VALUE				1000000
+
+
+// SNR
+#define RTL2832_CE_EST_EVM_MAX_VALUE		65535
+#define RTL2832_SNR_FRAC_BIT_NUM			10
+#define RTL2832_SNR_DB_DEN					3402
+
+
+// AGC
+#define RTL2832_RF_AGC_REG_BIT_NUM		14
+#define RTL2832_IF_AGC_REG_BIT_NUM		14
+
+
+// TR offset and CR offset
+#define RTL2832_SFREQ_OFF_BIT_NUM		14
+#define RTL2832_CFREQ_OFF_BIT_NUM		18
+
+
+// Register table length
+#define RTL2832_REG_TABLE_LEN			127
+
+
+// Function 1
+#define RTL2832_FUNC1_WAIT_TIME_MS			500
+#define RTL2832_FUNC1_GETTING_TIME_MS		200
+#define RTL2832_FUNC1_GETTING_NUM_MIN		20
+
+
+
+/// Demod application modes
+enum RTL2832_APPLICATION_MODE
+{
+	RTL2832_APPLICATION_DONGLE,
+	RTL2832_APPLICATION_STB,
+};
+#define RTL2832_APPLICATION_MODE_NUM		2
+
+
+// Function 1
+enum RTL2832_FUNC1_CONFIG_MODE
+{
+	RTL2832_FUNC1_CONFIG_1,
+	RTL2832_FUNC1_CONFIG_2,
+	RTL2832_FUNC1_CONFIG_3,
+};
+#define RTL2832_FUNC1_CONFIG_MODE_NUM		3
+#define RTL2832_FUNC1_CONFIG_NORMAL			-1
+
+
+enum RTL2832_FUNC1_STATE
+{
+	RTL2832_FUNC1_STATE_NORMAL,
+	RTL2832_FUNC1_STATE_NORMAL_GET_BER,
+	RTL2832_FUNC1_STATE_CONFIG_1_WAIT,
+	RTL2832_FUNC1_STATE_CONFIG_1_GET_BER,
+	RTL2832_FUNC1_STATE_CONFIG_2_WAIT,
+	RTL2832_FUNC1_STATE_CONFIG_2_GET_BER,
+	RTL2832_FUNC1_STATE_CONFIG_3_WAIT,
+	RTL2832_FUNC1_STATE_CONFIG_3_GET_BER,
+	RTL2832_FUNC1_STATE_DETERMINED_WAIT,
+	RTL2832_FUNC1_STATE_DETERMINED,
+};
+
+
+
+
+
+// Demod module builder
+void
+BuildRtl2832Module(
+	DVBT_DEMOD_MODULE **ppDemod,
+	DVBT_DEMOD_MODULE *pDvbtDemodModuleMemory,
+	BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory,
+	I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory,
+	unsigned char DeviceAddr,
+	unsigned long CrystalFreqHz,
+	int TsInterfaceMode,
+	int AppMode,
+	unsigned long UpdateFuncRefPeriodMs,
+	int IsFunc1Enabled
+	);
+
+
+
+
+
+// Manipulating functions
+void
+rtl2832_IsConnectedToI2c(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+);
+
+int
+rtl2832_SoftwareReset(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2832_Initialize(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2832_SetBandwidthMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int BandwidthMode
+	);
+
+int
+rtl2832_SetIfFreqHz(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long IfFreqHz
+	);
+
+int
+rtl2832_SetSpectrumMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int SpectrumMode
+	);
+
+int
+rtl2832_IsTpsLocked(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+int
+rtl2832_IsSignalLocked(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+int
+rtl2832_GetSignalStrength(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalStrength
+	);
+
+int
+rtl2832_GetSignalQuality(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalQuality
+	);
+
+int
+rtl2832_GetBer(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	);
+
+int
+rtl2832_GetSnrDb(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+int
+rtl2832_GetRfAgc(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pRfAgc
+	);
+
+int
+rtl2832_GetIfAgc(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pIfAgc
+	);
+
+int
+rtl2832_GetDiAgc(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char *pDiAgc
+	);
+
+int
+rtl2832_GetTrOffsetPpm(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pTrOffsetPpm
+	);
+
+int
+rtl2832_GetCrOffsetHz(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pCrOffsetHz
+	);
+
+int
+rtl2832_GetConstellation(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pConstellation
+	);
+
+int
+rtl2832_GetHierarchy(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pHierarchy
+	);
+
+int
+rtl2832_GetCodeRateLp(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pCodeRateLp
+	);
+
+int
+rtl2832_GetCodeRateHp(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pCodeRateHp
+	);
+
+int
+rtl2832_GetGuardInterval(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pGuardInterval
+	);
+
+int
+rtl2832_GetFftMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pFftMode
+	);
+
+int
+rtl2832_UpdateFunction(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2832_ResetFunction(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+// I2C command forwarding functions
+int
+rtl2832_ForwardI2cReadingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+int
+rtl2832_ForwardI2cWritingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+// Register table initializing
+void
+rtl2832_InitRegTable(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+// I2C birdge module builder
+void
+rtl2832_BuildI2cBridgeModule(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+// RTL2832 extra functions
+void
+rtl2832_GetAppMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAppMode
+	);
+
+
+
+
+
+// RTL2832 dependence
+int
+rtl2832_func1_Reset(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2832_func1_Update(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2832_func1_IsCriterionMatched(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+int
+rtl2832_func1_AccumulateRsdBerEst(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pAccumulativeValue
+	);
+
+int
+rtl2832_func1_ResetReg(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2832_func1_SetCommonReg(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2832_func1_SetRegWithFftMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int FftMode
+	);
+
+int
+rtl2832_func1_SetRegWithConfigMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int ConfigMode
+	);
+
+void
+rtl2832_func1_GetMinWeightedBerConfigMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pConfigMode
+	);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/demod_rtl2836.c b/drivers/media/usb/dvb-usb/demod_rtl2836.c
new file mode 100644
index 0000000..90fae89
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/demod_rtl2836.c
@@ -0,0 +1,2049 @@
+/**
+
+@file
+
+@brief   RTL2836 demod module definition
+
+One can manipulate RTL2836 demod through RTL2836 module.
+RTL2836 module is derived from DTMB demod module.
+
+*/
+
+
+#include "demod_rtl2836.h"
+
+
+
+
+
+/**
+
+@brief   RTL2836 demod module builder
+
+Use BuildRtl2836Module() to build RTL2836 module, set all module function pointers with the corresponding
+functions, and initialize module private variables.
+
+
+@param [in]   ppDemod                      Pointer to RTL2836 demod module pointer
+@param [in]   pDtmbDemodModuleMemory       Pointer to an allocated DTMB demod module memory
+@param [in]   pBaseInterfaceModuleMemory   Pointer to an allocated base interface module memory
+@param [in]   pI2cBridgeModuleMemory       Pointer to an allocated I2C bridge module memory
+@param [in]   DeviceAddr                   RTL2836 I2C device address
+@param [in]   CrystalFreqHz                RTL2836 crystal frequency in Hz
+@param [in]   TsInterfaceMode              RTL2836 TS interface mode for setting
+@param [in]   UpdateFuncRefPeriodMs        RTL2836 update function reference period in millisecond
+@param [in]   IsFunc1Enabled               RTL2836 Function 1 enabling status for setting
+@param [in]   IsFunc2Enabled               RTL2836 Function 2 enabling status for setting
+
+
+@note
+	-# One should call BuildRtl2836Module() to build RTL2836 module before using it.
+
+*/
+void
+BuildRtl2836Module(
+	DTMB_DEMOD_MODULE **ppDemod,
+	DTMB_DEMOD_MODULE *pDtmbDemodModuleMemory,
+	BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory,
+	I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory,
+	unsigned char DeviceAddr,
+	unsigned long CrystalFreqHz,
+	int TsInterfaceMode,
+	unsigned long UpdateFuncRefPeriodMs,
+	int IsFunc1Enabled,
+	int IsFunc2Enabled
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	RTL2836_EXTRA_MODULE *pExtra;
+
+
+
+	// Set demod module pointer, 
+	*ppDemod = pDtmbDemodModuleMemory;
+
+	// Get demod module.
+	pDemod = *ppDemod;
+
+	// Set base interface module pointer and I2C bridge module pointer.
+	pDemod->pBaseInterface = pBaseInterfaceModuleMemory;
+	pDemod->pI2cBridge     = pI2cBridgeModuleMemory;
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2836);
+
+
+	// Set demod type.
+	pDemod->DemodType = DTMB_DEMOD_TYPE_RTL2836;
+
+	// Set demod I2C device address.
+	pDemod->DeviceAddr = DeviceAddr;
+
+	// Set demod crystal frequency in Hz.
+	pDemod->CrystalFreqHz = CrystalFreqHz;
+
+	// Set demod TS interface mode.
+	pDemod->TsInterfaceMode = TsInterfaceMode;
+
+
+	// Initialize demod parameter setting status
+	pDemod->IsIfFreqHzSet      = NO;
+	pDemod->IsSpectrumModeSet  = NO;
+
+
+	// Initialize demod register table.
+	rtl2836_InitRegTable(pDemod);
+
+	
+	// Build I2C birdge module.
+	rtl2836_BuildI2cBridgeModule(pDemod);
+
+
+	// Set demod module I2C function pointers with 8-bit address default functions.
+	pDemod->RegAccess.Addr8Bit.SetRegPage         = dtmb_demod_addr_8bit_default_SetRegPage;
+	pDemod->RegAccess.Addr8Bit.SetRegBytes        = dtmb_demod_addr_8bit_default_SetRegBytes;
+	pDemod->RegAccess.Addr8Bit.GetRegBytes        = dtmb_demod_addr_8bit_default_GetRegBytes;
+	pDemod->RegAccess.Addr8Bit.SetRegMaskBits     = dtmb_demod_addr_8bit_default_SetRegMaskBits;
+	pDemod->RegAccess.Addr8Bit.GetRegMaskBits     = dtmb_demod_addr_8bit_default_GetRegMaskBits;
+	pDemod->RegAccess.Addr8Bit.SetRegBits         = dtmb_demod_addr_8bit_default_SetRegBits;
+	pDemod->RegAccess.Addr8Bit.GetRegBits         = dtmb_demod_addr_8bit_default_GetRegBits;
+	pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage = dtmb_demod_addr_8bit_default_SetRegBitsWithPage;
+	pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage = dtmb_demod_addr_8bit_default_GetRegBitsWithPage;
+
+
+	// Set demod module manipulating function pointers with default functions.
+	pDemod->GetDemodType     = dtmb_demod_default_GetDemodType;
+	pDemod->GetDeviceAddr    = dtmb_demod_default_GetDeviceAddr;
+	pDemod->GetCrystalFreqHz = dtmb_demod_default_GetCrystalFreqHz;
+
+	pDemod->GetIfFreqHz      = dtmb_demod_default_GetIfFreqHz;
+	pDemod->GetSpectrumMode  = dtmb_demod_default_GetSpectrumMode;
+
+
+	// Set demod module manipulating function pointers with particular functions.
+	pDemod->IsConnectedToI2c       = rtl2836_IsConnectedToI2c;
+	pDemod->SoftwareReset          = rtl2836_SoftwareReset;
+	pDemod->Initialize             = rtl2836_Initialize;
+	pDemod->SetIfFreqHz            = rtl2836_SetIfFreqHz;
+	pDemod->SetSpectrumMode        = rtl2836_SetSpectrumMode;
+
+	pDemod->IsSignalLocked         = rtl2836_IsSignalLocked;
+
+	pDemod->GetSignalStrength      = rtl2836_GetSignalStrength;
+	pDemod->GetSignalQuality       = rtl2836_GetSignalQuality;
+
+	pDemod->GetBer                 = rtl2836_GetBer;
+	pDemod->GetPer                 = rtl2836_GetPer;
+	pDemod->GetSnrDb               = rtl2836_GetSnrDb;
+
+	pDemod->GetRfAgc               = rtl2836_GetRfAgc;
+	pDemod->GetIfAgc               = rtl2836_GetIfAgc;
+	pDemod->GetDiAgc               = rtl2836_GetDiAgc;
+
+	pDemod->GetTrOffsetPpm         = rtl2836_GetTrOffsetPpm;
+	pDemod->GetCrOffsetHz          = rtl2836_GetCrOffsetHz;
+
+	pDemod->GetCarrierMode         = rtl2836_GetCarrierMode;
+	pDemod->GetPnMode              = rtl2836_GetPnMode;
+	pDemod->GetQamMode             = rtl2836_GetQamMode;
+	pDemod->GetCodeRateMode        = rtl2836_GetCodeRateMode;
+	pDemod->GetTimeInterleaverMode = rtl2836_GetTimeInterleaverMode;
+
+	pDemod->UpdateFunction         = rtl2836_UpdateFunction;
+	pDemod->ResetFunction          = rtl2836_ResetFunction;
+
+
+	// Initialize demod Function 1 variables.
+	pExtra->IsFunc1Enabled = IsFunc1Enabled;
+	pExtra->Func1CntThd = DivideWithCeiling(RTL2836_FUNC1_CHECK_TIME_MS, UpdateFuncRefPeriodMs);
+	pExtra->Func1Cnt = 0;
+
+	// Initialize demod Function 2 variables.
+	pExtra->IsFunc2Enabled = IsFunc2Enabled;
+	pExtra->Func2SignalModePrevious = RTL2836_FUNC2_SIGNAL_NORMAL;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_IS_CONNECTED_TO_I2C
+
+*/
+void
+rtl2836_IsConnectedToI2c(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	unsigned long ChipId;
+
+
+
+	// Get CHIP_ID.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_CHIP_ID, &ChipId) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Check chip ID value.
+	if(ChipId != RTL2836_CHIP_ID_VALUE)
+		goto error_status_check_value;
+
+
+	// Set I2cConnectionStatus with YES.
+	*pAnswer = YES;
+
+
+	return;
+
+
+error_status_check_value:
+error_status_get_registers:
+
+	// Set I2cConnectionStatus with NO.
+	*pAnswer = NO;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SOFTWARE_RESET
+
+*/
+int
+rtl2836_SoftwareReset(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	// Set SOFT_RST with 0x0. Then, set SOFT_RST with 0x1.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_SOFT_RST_N, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_SOFT_RST_N, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_INITIALIZE
+
+*/
+int
+rtl2836_Initialize(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	// Initializing table entry only used in Initialize()
+	typedef struct
+	{
+		unsigned char PageNo;
+		unsigned char RegStartAddr;
+		unsigned char Msb;
+		unsigned char Lsb;
+		unsigned long WritingValue;
+	}
+	INIT_TABLE_ENTRY;
+
+	// TS interface initializing table entry only used in Initialize()
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long WritingValue[TS_INTERFACE_MODE_NUM];
+	}
+	TS_INTERFACE_INIT_TABLE_ENTRY;
+
+
+
+	static const INIT_TABLE_ENTRY InitRegTable[RTL2836_INIT_REG_TABLE_LEN] =
+	{
+		// PageNo,	RegStartAddr,	Msb,	Lsb,	WritingValue
+		{0x0,		0x1,			0,		0,		0x1			},
+		{0x0,		0x2,			4,		4,		0x0			},
+		{0x0,		0x3,			2,		0,		0x0			},
+		{0x0,		0xe,			5,		5,		0x1			},
+		{0x0,		0x11,			3,		3,		0x0			},
+		{0x0,		0x12,			1,		0,		0x1			},
+		{0x0,		0x16,			2,		0,		0x3			},
+		{0x0,		0x19,			7,		0,		0x19		},
+		{0x0,		0x1b,			7,		0,		0xcc		},
+		{0x0,		0x1f,			7,		0,		0x5			},
+		{0x0,		0x20,			2,		2,		0x1			},
+		{0x0,		0x20,			3,		3,		0x0			},
+		{0x1,		0x3,			7,		0,		0x38		},
+		{0x1,		0x31,			1,		1,		0x0			},
+		{0x1,		0x67,			7,		0,		0x30		},
+		{0x1,		0x68,			7,		0,		0x10		},
+		{0x1,		0x7f,			3,		2,		0x1			},
+		{0x1,		0xda,			7,		7,		0x1			},
+		{0x1,		0xdb,			7,		0,		0x5			},
+		{0x2,		0x9,			7,		0,		0xa			},
+		{0x2,		0x10,			7,		0,		0x31		},
+		{0x2,		0x11,			7,		0,		0x31		},
+		{0x2,		0x1b,			7,		0,		0x1e		},
+		{0x2,		0x1e,			7,		0,		0x3a		},
+		{0x2,		0x1f,			5,		3,		0x3			},
+		{0x2,		0x21,			7,		0,		0x3f		},
+		{0x2,		0x24,			6,		5,		0x0			},
+		{0x2,		0x27,			7,		0,		0x17		},
+		{0x2,		0x31,			7,		0,		0x35		},
+		{0x2,		0x32,			7,		0,		0x3f		},
+		{0x2,		0x4f,			3,		2,		0x2			},
+		{0x2,		0x5a,			7,		0,		0x5			},
+		{0x2,		0x5b,			7,		0,		0x8			},
+		{0x2,		0x5c,			7,		0,		0x8			},
+		{0x2,		0x5e,			7,		5,		0x5			},
+		{0x2,		0x70,			0,		0,		0x0			},
+		{0x2,		0x77,			0,		0,		0x1			},
+		{0x2,		0x7a,			7,		0,		0x2f		},
+		{0x2,		0x81,			3,		2,		0x2			},
+		{0x2,		0x8d,			7,		0,		0x77		},
+		{0x2,		0x8e,			7,		4,		0x8			},
+		{0x2,		0x93,			7,		0,		0xff		},
+		{0x2,		0x94,			7,		0,		0x3			},
+		{0x2,		0x9d,			7,		0,		0xff		},
+		{0x2,		0x9e,			7,		0,		0x3			},
+		{0x2,		0xa8,			7,		0,		0xff		},
+		{0x2,		0xa9,			7,		0,		0x3			},
+		{0x2,		0xa3,			2,		2,		0x1			},
+		{0x3,		0x1,			7,		0,		0x0			},
+		{0x3,		0x4,			7,		0,		0x20		},
+		{0x3,		0x9,			7,		0,		0x10		},
+		{0x3,		0x14,			7,		0,		0xe4		},
+		{0x3,		0x15,			7,		0,		0x62		},
+		{0x3,		0x16,			7,		0,		0x8c		},
+		{0x3,		0x17,			7,		0,		0x11		},
+		{0x3,		0x1b,			7,		0,		0x40		},
+		{0x3,		0x1c,			7,		0,		0x14		},
+		{0x3,		0x23,			7,		0,		0x40		},
+		{0x3,		0x24,			7,		0,		0xd6		},
+		{0x3,		0x2b,			7,		0,		0x60		},
+		{0x3,		0x2c,			7,		0,		0x16		},
+		{0x3,		0x33,			7,		0,		0x40		},
+		{0x3,		0x3b,			7,		0,		0x44		},
+		{0x3,		0x43,			7,		0,		0x41		},
+		{0x3,		0x4b,			7,		0,		0x40		},
+		{0x3,		0x53,			7,		0,		0x4a		},
+		{0x3,		0x58,			7,		0,		0x1c		},
+		{0x3,		0x5b,			7,		0,		0x5a		},
+		{0x3,		0x5f,			7,		0,		0xe0		},
+		{0x4,		0x2,			7,		0,		0x7			},
+		{0x4,		0x3,			5,		0,		0x9			},
+		{0x4,		0x4,			5,		0,		0xb			},
+		{0x4,		0x5,			5,		0,		0xd			},
+		{0x4,		0x7,			2,		1,		0x3			},
+		{0x4,		0x7,			4,		3,		0x3			},
+		{0x4,		0xe,			4,		0,		0x18		},
+		{0x4,		0x10,			4,		0,		0x1c		},
+		{0x4,		0x12,			4,		0,		0x1c		},
+		{0x4,		0x2f,			7,		0,		0x0			},
+		{0x4,		0x30,			7,		0,		0x20		},
+		{0x4,		0x31,			7,		0,		0x40		},
+		{0x4,		0x3e,			0,		0,		0x0			},
+		{0x4,		0x3e,			1,		1,		0x1			},
+		{0x4,		0x3e,			5,		2,		0x0			},
+		{0x4,		0x3f,			5,		0,		0x10		},
+		{0x4,		0x4a,			0,		0,		0x1			},
+	};
+
+	static const TS_INTERFACE_INIT_TABLE_ENTRY TsInterfaceInitTable[RTL2836_TS_INTERFACE_INIT_TABLE_LEN] =
+	{
+		// RegBitName,				WritingValue for {Parallel, Serial}
+		{DTMB_SERIAL,				{0x0,	0x1}},
+		{DTMB_CDIV_PH0,				{0xf,	0x1}},
+		{DTMB_CDIV_PH1,				{0xf,	0x1}},
+	};
+
+	int i;
+
+	int TsInterfaceMode;
+
+	unsigned char PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+	unsigned long WritingValue;
+
+
+
+	// Get TS interface mode.
+	TsInterfaceMode = pDemod->TsInterfaceMode;
+
+	// Initialize demod registers according to the initializing table.
+	for(i = 0; i < RTL2836_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get all information from each register initializing entry.
+		PageNo       = InitRegTable[i].PageNo;
+		RegStartAddr = InitRegTable[i].RegStartAddr;
+		Msb          = InitRegTable[i].Msb;
+		Lsb          = InitRegTable[i].Lsb;
+		WritingValue = InitRegTable[i].WritingValue;
+
+		// Set register page number.
+		if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+
+		// Set register mask bits.
+		if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, WritingValue) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+	// Initialize demod registers according to the TS interface initializing table.
+	for(i = 0; i < RTL2836_TS_INTERFACE_INIT_TABLE_LEN; i++)
+	{
+		if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, TsInterfaceInitTable[i].RegBitName,
+			TsInterfaceInitTable[i].WritingValue[TsInterfaceMode]) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_IF_FREQ_HZ
+
+*/
+int
+rtl2836_SetIfFreqHz(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long IfFreqHz
+	)
+{
+
+	unsigned long BbinEn, EnDcr;
+
+	unsigned long IfFreqHzAdj;
+
+	MPI MpiVar, MpiNone, MpiConst;
+
+	long IffreqInt;
+	unsigned long IffreqBinary;
+
+
+
+	// Determine and set BBIN_EN and EN_DCR value.
+	BbinEn = (IfFreqHz == IF_FREQ_0HZ) ? 0x1 : 0x0;
+	EnDcr  = (IfFreqHz == IF_FREQ_0HZ) ? 0x1 : 0x0;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_BBIN_EN, BbinEn) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_EN_DCR, EnDcr) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Calculate IFFREQ value.
+	// Note: Case 1: IfFreqHz < 24000000,  IfFreqHzAdj = IfFreqHz;
+	//       Case 2: IfFreqHz >= 24000000, IfFreqHzAdj = 48000000 - IfFreqHz; 
+	//       IFFREQ = - round( IfFreqHzAdj * pow(2, 10) / 48000000 )
+	//              = - floor( (IfFreqHzAdj * pow(2, 10) + 24000000) / 48000000 )
+	//       RTL2836_ADC_FREQ_HZ = 48 MHz
+	//       IFFREQ_BIT_NUM = 10
+	IfFreqHzAdj = (IfFreqHz < (RTL2836_ADC_FREQ_HZ / 2)) ? IfFreqHz : (RTL2836_ADC_FREQ_HZ - IfFreqHz);
+
+	MpiSetValue(&MpiVar, IfFreqHzAdj);
+	MpiLeftShift(&MpiVar, MpiVar, RTL2836_IFFREQ_BIT_NUM);
+
+	MpiSetValue(&MpiConst, (RTL2836_ADC_FREQ_HZ / 2));
+	MpiAdd(&MpiVar, MpiVar, MpiConst);
+
+	MpiSetValue(&MpiConst, RTL2836_ADC_FREQ_HZ);
+	MpiDiv(&MpiVar, &MpiNone, MpiVar, MpiConst);
+
+	MpiGetValue(MpiVar, &IffreqInt);
+	IffreqInt = - IffreqInt;
+
+	IffreqBinary = SignedIntToBin(IffreqInt, RTL2836_IFFREQ_BIT_NUM);
+
+
+	// Set IFFREQ with calculated value.
+	// Note: Use SetRegBitsWithPage() to set register bits with page setting.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_IFFREQ, IffreqBinary) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod IF frequnecy parameter.
+	pDemod->IfFreqHz      = IfFreqHz;
+	pDemod->IsIfFreqHzSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_SPECTRUM_MODE
+
+*/
+int
+rtl2836_SetSpectrumMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int SpectrumMode
+	)
+{
+	unsigned long EnSpInv;
+
+
+
+	// Determine SpecInv according to spectrum mode.
+	switch(SpectrumMode)
+	{
+		case SPECTRUM_NORMAL:		EnSpInv = 0;		break;
+		case SPECTRUM_INVERSE:		EnSpInv = 1;		break;
+
+		default:	goto error_status_get_undefined_value;
+	}
+
+
+	// Set SPEC_INV with SpecInv.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_EN_SP_INV, EnSpInv) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod spectrum mode parameter.
+	pDemod->SpectrumMode      = SpectrumMode;
+	pDemod->IsSpectrumModeSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+error_status_get_undefined_value:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_IS_SIGNAL_LOCKED
+
+*/
+int
+rtl2836_IsSignalLocked(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	long SnrDbNum;
+	long SnrDbDen;
+	long SnrDbInt;
+
+	unsigned long PerNum;
+	unsigned long PerDen;
+
+
+
+	// Get SNR integer part.
+	if(pDemod->GetSnrDb(pDemod, &SnrDbNum, &SnrDbDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	SnrDbInt = SnrDbNum / SnrDbDen;
+
+
+	// Get PER.
+	if(pDemod->GetPer(pDemod, &PerNum, &PerDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Determine answer according to SNR and PER.
+	// Note: The criterion is "(0 < SNR_in_Db < 40) && (PER < 1)"
+	if((SnrDbInt > 0) && (SnrDbInt < 40) && (PerNum < PerDen))
+		*pAnswer = YES;
+	else
+		*pAnswer = NO;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_SIGNAL_STRENGTH
+
+*/
+int
+rtl2836_GetSignalStrength(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalStrength
+	)
+{
+	int SignalLockStatus;
+	long IfAgc;
+
+
+
+	// Get signal lock status.
+	if(pDemod->IsSignalLocked(pDemod, &SignalLockStatus) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Get IF AGC value.
+	if(pDemod->GetIfAgc(pDemod, &IfAgc) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// If demod is not signal-locked, set signal strength with zero.
+	if(SignalLockStatus != YES)
+	{
+		*pSignalStrength = 0;
+		goto success_status_signal_is_not_locked;
+	}
+
+	//  Determine signal strength according to signal lock status and IF AGC value.
+	// Note: Map IfAgc value 8191 ~ -8192 to 10 ~ 99
+	//       Formula: SignalStrength = 54 - IfAgc / 183
+	*pSignalStrength = 54 - IfAgc / 183;
+
+
+success_status_signal_is_not_locked:
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_SIGNAL_QUALITY
+
+*/
+int
+rtl2836_GetSignalQuality(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalQuality
+	)
+{
+	int SignalLockStatus;
+	long SnrDbNum, SnrDbDen;
+
+
+
+	// Get signal lock status.
+	if(pDemod->IsSignalLocked(pDemod, &SignalLockStatus) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->GetSnrDb(pDemod, &SnrDbNum, &SnrDbDen) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// If demod is not signal-locked, set signal quality with zero.
+	if(SignalLockStatus != YES)
+	{
+		*pSignalQuality = 0;
+		goto success_status_signal_is_not_locked;
+	}
+
+	// Determine signal quality according to SnrDbNum.
+	// Note: Map SnrDbNum value 12 ~ 100 to 12 ~ 100
+	//       Formula: SignalQuality = SnrDbNum
+	//       If SnrDbNum < 12, signal quality is 10.
+	//       If SnrDbNum > 100, signal quality is 100.
+	if(SnrDbNum < 12)
+	{
+		*pSignalQuality = 10;
+	}
+	else if(SnrDbNum > 100)
+	{
+		*pSignalQuality = 100;
+	}
+	else
+	{
+		*pSignalQuality = SnrDbNum;
+	}
+
+
+success_status_signal_is_not_locked:
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_BER
+
+*/
+int
+rtl2836_GetBer(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	)
+{
+/*
+	unsigned long RsdBerEst;
+
+
+
+	// Get RSD_BER_EST.
+	if(pDemod->GetRegBitsWithPage(pDemod, DTMB_RSD_BER_EST, &RsdBerEst) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Set BER numerator according to RSD_BER_EST.
+	*pBerNum = RsdBerEst;
+
+	// Set BER denominator.
+	*pBerDen = RTL2836_BER_DEN_VALUE;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+*/
+	return FUNCTION_SUCCESS;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_PER
+
+*/
+int
+rtl2836_GetPer(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	)
+{
+	unsigned long RoPktErrRate;
+
+
+
+	// Get RO_PKT_ERR_RATE.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_RO_PKT_ERR_RATE, &RoPktErrRate) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Set PER numerator according to RO_PKT_ERR_RATE.
+	*pPerNum = RoPktErrRate;
+
+	// Set PER denominator.
+	*pPerDen = RTL2836_PER_DEN_VALUE;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_SNR_DB
+
+*/
+int
+rtl2836_GetSnrDb(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	)
+{
+	unsigned long EstSnr;
+
+
+
+	// Get EST_SNR.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_EST_SNR, &EstSnr) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Set SNR dB numerator according to EST_SNR.
+	*pSnrDbNum = BinToSignedInt(EstSnr, RTL2836_EST_SNR_BIT_NUM);
+
+	// Set SNR dB denominator.
+	*pSnrDbDen = RTL2836_SNR_DB_DEN_VALUE;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_RF_AGC
+
+*/
+int
+rtl2836_GetRfAgc(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pRfAgc
+	)
+{
+	unsigned long RfAgcVal;
+
+
+
+	// Get RF AGC binary value from RF_AGC_VAL.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_RF_AGC_VAL, &RfAgcVal) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Convert RF AGC binary value to signed integer.
+	*pRfAgc = (long)BinToSignedInt(RfAgcVal, RTL2836_RF_AGC_REG_BIT_NUM);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_IF_AGC
+
+*/
+int
+rtl2836_GetIfAgc(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pIfAgc
+	)
+{
+	unsigned long IfAgcVal;
+
+
+
+	// Get IF AGC binary value from IF_AGC_VAL.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_IF_AGC_VAL, &IfAgcVal) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Convert IF AGC binary value to signed integer.
+	*pIfAgc = (long)BinToSignedInt(IfAgcVal, RTL2836_IF_AGC_REG_BIT_NUM);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_DI_AGC
+
+*/
+int
+rtl2836_GetDiAgc(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pDiAgc
+	)
+{
+	unsigned long GainOutR;
+
+
+
+	// Get GAIN_OUT_R to DiAgc.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_GAIN_OUT_R, &GainOutR) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	*pDiAgc = GainOutR;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_TR_OFFSET_PPM
+
+*/
+int
+rtl2836_GetTrOffsetPpm(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pTrOffsetPpm
+	)
+{
+	unsigned long TrOutRBinary;
+	long TrOutRInt;
+	unsigned long SfoaqOutRBinary;
+	long SfoaqOutRInt;
+
+	MPI MpiVar, MpiNone, MpiConst;
+
+
+	// Get TR_OUT_R and SFOAQ_OUT_R binary value.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_TR_OUT_R, &TrOutRBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_SFOAQ_OUT_R, &SfoaqOutRBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Convert TR_OUT_R and SFOAQ_OUT_R binary value to signed integer.
+	TrOutRInt = BinToSignedInt(TrOutRBinary, RTL2836_TR_OUT_R_BIT_NUM);
+	SfoaqOutRInt = BinToSignedInt(SfoaqOutRBinary, RTL2836_SFOAQ_OUT_R_BIT_NUM);
+
+	
+	// Get TR offset in ppm.
+	// Note: Original formula:   TrOffsetPpm = ((TrOutRInt + SfoaqOutRInt * 8) * 15.12 * pow(10, 6)) / (48 * pow(2, 23))
+	//       Adjusted formula:   TrOffsetPpm = ((TrOutRInt + SfoaqOutRInt * 8) * 15120000) / 402653184
+	MpiSetValue(&MpiVar, (TrOutRInt + SfoaqOutRInt * 8));
+
+	MpiSetValue(&MpiConst, 15120000);
+	MpiMul(&MpiVar, MpiVar, MpiConst);
+
+	MpiSetValue(&MpiConst, 402653184);
+	MpiDiv(&MpiVar, &MpiNone, MpiVar, MpiConst);
+
+	MpiGetValue(MpiVar, pTrOffsetPpm);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_CR_OFFSET_HZ
+
+*/
+int
+rtl2836_GetCrOffsetHz(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pCrOffsetHz
+	)
+{
+	unsigned long CfoEstRBinary;
+	long CfoEstRInt;
+
+	MPI MpiVar, MpiConst;
+
+
+	// Get CFO_EST_R binary value.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_CFO_EST_R, &CfoEstRBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+	// Convert CFO_EST_R binary value to signed integer.
+	CfoEstRInt = BinToSignedInt(CfoEstRBinary, RTL2836_CFO_EST_R_BIT_NUM);
+
+	
+	// Get CR offset in Hz.
+	// Note: Original formula:   CrOffsetHz = (CfoEstRInt * 15.12 * pow(10, 6)) / pow(2, 26)
+	//       Adjusted formula:   CrOffsetHz = (CfoEstRInt * 15120000) >> 26
+	MpiSetValue(&MpiVar, CfoEstRInt);
+
+	MpiSetValue(&MpiConst, 15120000);
+	MpiMul(&MpiVar, MpiVar, MpiConst);
+
+	MpiRightShift(&MpiVar, MpiVar, 26);
+
+	MpiGetValue(MpiVar, pCrOffsetHz);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_CARRIER_MODE
+
+*/
+int
+rtl2836_GetCarrierMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pCarrierMode
+	)
+{
+	unsigned long EstCarrier;
+
+
+	// Get carrier mode from EST_CARRIER.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_EST_CARRIER, &EstCarrier) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(EstCarrier)
+	{
+		case 0:		*pCarrierMode = DTMB_CARRIER_SINGLE;		break;
+		case 1:		*pCarrierMode = DTMB_CARRIER_MULTI;			break;
+
+		default:	goto error_status_get_undefined_value;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+error_status_get_undefined_value:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_PN_MODE
+
+*/
+int
+rtl2836_GetPnMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pPnMode
+	)
+{
+	unsigned long RxModeR;
+
+
+	// Get PN mode from RX_MODE_R.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_RX_MODE_R, &RxModeR) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(RxModeR)
+	{
+		case 0:		*pPnMode = DTMB_PN_420;		break;
+		case 1:		*pPnMode = DTMB_PN_595;		break;
+		case 2:		*pPnMode = DTMB_PN_945;		break;
+
+		default:	goto error_status_get_undefined_value;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+error_status_get_undefined_value:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_QAM_MODE
+
+*/
+int
+rtl2836_GetQamMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pQamMode
+	)
+{
+	unsigned long UseTps;
+
+
+	// Get QAM mode from USE_TPS.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_USE_TPS, &UseTps) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(UseTps)
+	{
+		case 0:		*pQamMode = DTMB_QAM_UNKNOWN;		break;
+
+		case 2:
+		case 3:		*pQamMode = DTMB_QAM_4QAM_NR;		break;
+
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		case 8:
+		case 9:		*pQamMode = DTMB_QAM_4QAM;			break;
+
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+		case 15:	*pQamMode = DTMB_QAM_16QAM;			break;
+
+		case 16:
+		case 17:	*pQamMode = DTMB_QAM_32QAM;			break;
+
+		case 18:
+		case 19:
+		case 20:
+		case 21:
+		case 22:
+		case 23:	*pQamMode = DTMB_QAM_64QAM;			break;
+
+		default:	goto error_status_get_undefined_value;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+error_status_get_undefined_value:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_CODE_RATE_MODE
+
+*/
+int
+rtl2836_GetCodeRateMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pCodeRateMode
+	)
+{
+	unsigned long UseTps;
+
+
+	// Get QAM mode from USE_TPS.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_USE_TPS, &UseTps) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(UseTps)
+	{
+		case 0:		*pCodeRateMode = DTMB_CODE_RATE_UNKNOWN;		break;
+
+		case 4:
+		case 5:
+		case 10:
+		case 11:
+		case 18:
+		case 19:	*pCodeRateMode = DTMB_CODE_RATE_0P4;			break;
+
+		case 6:
+		case 7:
+		case 12:
+		case 13:
+		case 20:
+		case 21:	*pCodeRateMode = DTMB_CODE_RATE_0P6;			break;
+
+		case 2:
+		case 3:
+		case 8:
+		case 9:
+		case 14:
+		case 15:
+		case 16:
+		case 17:
+		case 22:
+		case 23:	*pCodeRateMode = DTMB_CODE_RATE_0P8;			break;
+
+		default:	goto error_status_get_undefined_value;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+error_status_get_undefined_value:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_TIME_INTERLEAVER_MODE
+
+*/
+int
+rtl2836_GetTimeInterleaverMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pTimeInterleaverMode
+	)
+{
+	unsigned long UseTps;
+
+
+	// Get QAM mode from USE_TPS.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_USE_TPS, &UseTps) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	switch(UseTps)
+	{
+		case 0:		*pTimeInterleaverMode = DTMB_TIME_INTERLEAVER_UNKNOWN;		break;
+
+		case 2:
+		case 4:
+		case 6:
+		case 8:
+		case 10:
+		case 12:
+		case 14:
+		case 16:
+		case 18:
+		case 20:
+		case 22:	*pTimeInterleaverMode = DTMB_TIME_INTERLEAVER_240;			break;
+
+		case 3:
+		case 5:
+		case 7:
+		case 9:
+		case 11:
+		case 13:
+		case 15:
+		case 17:
+		case 19:
+		case 21:
+		case 23:	*pTimeInterleaverMode = DTMB_TIME_INTERLEAVER_720;			break;
+
+		default:	goto error_status_get_undefined_value;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+error_status_get_undefined_value:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_UPDATE_FUNCTION
+
+*/
+int
+rtl2836_UpdateFunction(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	RTL2836_EXTRA_MODULE *pExtra;
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2836);
+
+
+	// Execute Function 1 according to Function 1 enabling status
+	if(pExtra->IsFunc1Enabled == YES)
+	{
+		if(rtl2836_func1_Update(pDemod) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+	}
+
+	// Execute Function 2 according to Function 2 enabling status
+	if(pExtra->IsFunc2Enabled == YES)
+	{
+		if(rtl2836_func2_Update(pDemod) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_RESET_FUNCTION
+
+*/
+int
+rtl2836_ResetFunction(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	RTL2836_EXTRA_MODULE *pExtra;
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2836);
+
+
+	// Reset Function 1 settings according to Function 1 enabling status.
+	if(pExtra->IsFunc1Enabled == YES)
+	{
+		if(rtl2836_func1_Reset(pDemod) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+	}
+
+	// Reset Function 2 settings according to Function 2 enabling status.
+	if(pExtra->IsFunc2Enabled == YES)
+	{
+		if(rtl2836_func2_Reset(pDemod) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   I2C_BRIDGE_FP_FORWARD_I2C_READING_CMD
+
+*/
+int
+rtl2836_ForwardI2cReadingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+
+
+	// Get demod module.
+	pDemod = (DTMB_DEMOD_MODULE *)pI2cBridge->pPrivateData;
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Send I2C reading command.
+	if(pBaseInterface->I2cRead(pBaseInterface, DeviceAddr, pReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_send_i2c_reading_command;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_send_i2c_reading_command:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   I2C_BRIDGE_FP_FORWARD_I2C_WRITING_CMD
+
+*/
+int
+rtl2836_ForwardI2cWritingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+
+
+	// Get demod module.
+	pDemod = (DTMB_DEMOD_MODULE *)pI2cBridge->pPrivateData;
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Send I2C writing command.
+	if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, pWritingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_send_i2c_writing_command;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_send_i2c_writing_command:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Initialize RTL2836 register table.
+
+Use rtl2836_InitRegTable() to initialize RTL2836 register table.
+
+
+@param [in]   pDemod   RTL2836 demod module pointer
+
+
+@note
+	-# The rtl2836_InitRegTable() function will be called by BuildRtl2836Module().
+
+*/
+void
+rtl2836_InitRegTable(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	static const DTMB_PRIMARY_REG_ENTRY_ADDR_8BIT PrimaryRegTable[RTL2836_REG_TABLE_LEN] =
+	{
+		// Software reset
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_SOFT_RST_N,					0x0,		0x4,			0,		0	},
+
+		// Tuner I2C forwording
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_I2CT_EN_CTRL,					0x0,		0x6,			0,		0	},
+
+		// Chip ID
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_CHIP_ID,						0x5,		0x10,			15,		0	},
+
+		// IF setting
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_EN_SP_INV,					0x1,		0x31,			1,		1	},
+		{DTMB_EN_DCR,						0x1,		0x31,			0,		0	},
+		{DTMB_BBIN_EN,						0x1,		0x6a,			0,		0	},
+		{DTMB_IFFREQ,						0x1,		0x32,			9,		0	},
+
+		// AGC setting
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_TARGET_VAL,					0x1,		0x3,			7,		0	},
+
+		// IF setting
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_SERIAL,						0x4,		0x50,			7,		7	},
+		{DTMB_CDIV_PH0,						0x4,		0x51,			4,		0	},
+		{DTMB_CDIV_PH1,						0x4,		0x52,			4,		0	},
+
+		// Signal lock status
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_TPS_LOCK,						0x8,		0x2a,			6,		6	},
+		{DTMB_PN_PEAK_EXIST,				0x6,		0x53,			0,		0	},
+
+		// FSM
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_FSM_STATE_R,					0x6,		0xc0,			4,		0	},
+
+		// Performance measurement
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_RO_PKT_ERR_RATE,				0x9,		0x2d,			15,		0	},
+		{DTMB_EST_SNR,						0x8,		0x3e,			8,		0	},
+
+		// AGC
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_GAIN_OUT_R,					0x6,		0xb4,			12,		1	},
+		{DTMB_RF_AGC_VAL,					0x6,		0x16,			13,		0	},
+		{DTMB_IF_AGC_VAL,					0x6,		0x14,			13,		0	},
+
+		// TR and CR
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_TR_OUT_R,						0x7,		0x7c,			16,		0	},
+		{DTMB_SFOAQ_OUT_R,					0x7,		0x21,			13,		0	},
+		{DTMB_CFO_EST_R,					0x6,		0x94,			22,		0	},
+
+		// Signal information
+		// RegBitName,						PageNo,		RegStartAddr,	MSB,	LSB
+		{DTMB_EST_CARRIER,					0x8,		0x2a,			0,		0	},
+		{DTMB_RX_MODE_R,					0x7,		0x17,			1,		0	},
+		{DTMB_USE_TPS,						0x8,		0x2a,			5,		1	},
+	};
+
+
+	int i;
+	int RegBitName;
+
+
+
+	// Initialize register table according to primary register table.
+	// Note: 1. Register table rows are sorted by register bit name key.
+	//       2. The default value of the IsAvailable variable is "NO".
+	for(i = 0; i < DTMB_REG_TABLE_LEN_MAX; i++)
+		pDemod->RegTable.Addr8Bit[i].IsAvailable  = NO;
+
+	for(i = 0; i < RTL2836_REG_TABLE_LEN; i++)
+	{
+		RegBitName = PrimaryRegTable[i].RegBitName;
+
+		pDemod->RegTable.Addr8Bit[RegBitName].IsAvailable  = YES;
+		pDemod->RegTable.Addr8Bit[RegBitName].PageNo       = PrimaryRegTable[i].PageNo;
+		pDemod->RegTable.Addr8Bit[RegBitName].RegStartAddr = PrimaryRegTable[i].RegStartAddr;
+		pDemod->RegTable.Addr8Bit[RegBitName].Msb          = PrimaryRegTable[i].Msb;
+		pDemod->RegTable.Addr8Bit[RegBitName].Lsb          = PrimaryRegTable[i].Lsb;
+	}
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Set I2C bridge module demod arguments.
+
+RTL2836 builder will use rtl2836_BuildI2cBridgeModule() to set I2C bridge module demod arguments.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@see   BuildRtl2836Module()
+
+*/
+void
+rtl2836_BuildI2cBridgeModule(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	I2C_BRIDGE_MODULE *pI2cBridge;
+
+
+
+	// Get I2C bridge module.
+	pI2cBridge = pDemod->pI2cBridge;
+
+	// Set I2C bridge module demod arguments.
+	pI2cBridge->pPrivateData = (void *)pDemod;
+	pI2cBridge->ForwardI2cReadingCmd = rtl2836_ForwardI2cReadingCmd;
+	pI2cBridge->ForwardI2cWritingCmd = rtl2836_ForwardI2cWritingCmd;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Reset Function 1 variables and registers.
+
+One can use rtl2836_func1_Reset() to reset Function 1 variables and registers.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset Function 1 variables and registers successfully.
+@retval   FUNCTION_ERROR     Reset Function 1 variables and registers unsuccessfully.
+
+
+@note
+	-# Need to execute Function 1 reset function when change tuner RF frequency or demod parameters.
+	-# Function 1 update flow also employs Function 1 reset function.
+
+*/
+int
+rtl2836_func1_Reset(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	RTL2836_EXTRA_MODULE *pExtra;
+
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2836);
+
+	// Reset demod Function 1 variables.
+	pExtra->Func1Cnt = 0;
+
+
+	return FUNCTION_SUCCESS;
+}
+
+
+
+
+
+/**
+
+@brief   Update demod registers with Function 1.
+
+One can use rtl2836_func1_Update() to update demod registers with Function 1.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update demod registers with Function 1 successfully.
+@retval   FUNCTION_ERROR     Update demod registers with Function 1 unsuccessfully.
+
+
+@note
+	-# Recommended update period is 50 ~ 200 ms for Function 1.
+	-# Need to execute Function 1 reset function when change tuner RF frequency or demod parameters.
+	-# Function 1 update flow also employs Function 1 reset function.
+
+*/
+int
+rtl2836_func1_Update(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	RTL2836_EXTRA_MODULE *pExtra;
+
+	unsigned long Reg0;
+	unsigned long Reg1;
+	unsigned long PnPeakExist;
+	unsigned long FsmStateR;
+	unsigned long TpsLock;
+
+	long SnrDbNum;
+	long SnrDbDen;
+	long SnrDbInt;
+
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2836);
+
+
+	// Update Function 1 counter.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 0x9) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.GetRegMaskBits(pDemod, 0x1e, 9, 0, &Reg0) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if((Reg0 & 0x3fb) == 0)
+	{
+		pExtra->Func1Cnt += 1;
+	}
+	else
+	{
+		pExtra->Func1Cnt = 0;
+	}
+
+
+	// Get PN_PEAK_EXIST and FSM_STATE_R value.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 0x6) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.GetRegBits(pDemod, DTMB_PN_PEAK_EXIST, &PnPeakExist) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.GetRegBits(pDemod, DTMB_FSM_STATE_R, &FsmStateR) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Get Reg1 and TPS_LOCK value.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 0x8) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.GetRegMaskBits(pDemod, 0x28, 3, 0, &Reg1) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.GetRegBits(pDemod, DTMB_TPS_LOCK, &TpsLock) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Get SNR integer part.
+	if(pDemod->GetSnrDb(pDemod, &SnrDbNum, &SnrDbDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	SnrDbInt = SnrDbNum / SnrDbDen;
+
+
+	// Determine if reset demod by software reset.
+	// Note: Need to reset Function 2 when reset demod.
+	if((pExtra->Func1Cnt > pExtra->Func1CntThd) || ((PnPeakExist == 0) && (FsmStateR > 9)) ||
+		((Reg1 >= 6) && (TpsLock == 0)) || (SnrDbInt == -64))
+	{
+		pExtra->Func1Cnt = 0;
+
+		if(pExtra->IsFunc2Enabled == ON)
+		{
+			if(rtl2836_func2_Reset(pDemod) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+		}
+
+		if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_get_registers:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Reset Function 2 variables and registers.
+
+One can use rtl2836_func2_Reset() to reset Function 1 variables and registers.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset Function 2 variables and registers successfully.
+@retval   FUNCTION_ERROR     Reset Function 2 variables and registers unsuccessfully.
+
+
+@note
+	-# Need to execute Function 2 reset function when change tuner RF frequency or demod parameters.
+	-# Function 2 update flow also employs Function 2 reset function.
+
+*/
+int
+rtl2836_func2_Reset(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	RTL2836_EXTRA_MODULE *pExtra;
+
+
+
+	// Get demod extra module.
+	pExtra = &(pDemod->Extra.Rtl2836);
+
+	// Reset demod Function 2 variables and registers to signal normal mode.
+	pExtra->Func2SignalModePrevious = RTL2836_FUNC2_SIGNAL_NORMAL;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 0x2) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x15, 7, 0, 0xf) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x1e, 6, 0, 0x3a) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x1f, 5, 0, 0x19) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x23, 4, 0, 0x1e) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Update demod registers with Function 2.
+
+One can use rtl2836_func2_Update() to update demod registers with Function 2.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update demod registers with Function 2 successfully.
+@retval   FUNCTION_ERROR     Update demod registers with Function 2 unsuccessfully.
+
+
+@note
+	-# Recommended update period is 50 ~ 200 ms for Function 2.
+	-# Need to execute Function 2 reset function when change tuner RF frequency or demod parameters.
+	-# Function 2 update flow also employs Function 2 reset function.
+
+*/
+int
+rtl2836_func2_Update(
+	DTMB_DEMOD_MODULE *pDemod
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	RTL2836_EXTRA_MODULE *pExtra;
+
+	int i;
+
+	unsigned long TpsLock;
+	unsigned long PnPeakExist;
+
+	int PnMode;
+	int QamMode;
+	int CodeRateMode;
+
+	int SignalLockStatus;
+
+	int SignalMode;
+
+
+
+	// Get base interface and demod extra module.
+	pBaseInterface = pDemod->pBaseInterface;
+	pExtra = &(pDemod->Extra.Rtl2836);
+
+
+	// Get TPS_LOCK value.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_TPS_LOCK, &TpsLock) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Get PN_PEAK_EXIST value.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, DTMB_PN_PEAK_EXIST, &PnPeakExist) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Get PN mode.
+	if(pDemod->GetPnMode(pDemod, &PnMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get QAM mode.
+	if(pDemod->GetQamMode(pDemod, &QamMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get code rate mode.
+	if(pDemod->GetCodeRateMode(pDemod, &CodeRateMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// If TPS is not locked or PN peak doesn't exist, do nothing.
+	if((TpsLock != 0x1) || (PnPeakExist != 0x1))
+		goto success_status_tps_is_not_locked;
+
+	// Determine signal mode.
+	if((PnMode == DTMB_PN_945) && (QamMode == DTMB_QAM_64QAM) && (CodeRateMode == DTMB_CODE_RATE_0P6))
+	{
+		SignalMode = RTL2836_FUNC2_SIGNAL_PARTICULAR;
+	}
+	else
+	{
+		SignalMode = RTL2836_FUNC2_SIGNAL_NORMAL;
+	}
+
+	// If signal mode is the same as previous one, do nothing.
+	if(SignalMode == pExtra->Func2SignalModePrevious)
+		goto success_status_signal_mode_is_the_same;
+
+
+	// Set demod registers according to signal mode
+	switch(SignalMode)
+	{
+		default:
+		case RTL2836_FUNC2_SIGNAL_NORMAL:
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 0x2) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x15, 7, 0, 0xf) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x1e, 6, 0, 0x3a) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x1f, 5, 0, 0x19) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x23, 4, 0, 0x1e) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			break;
+
+
+		case RTL2836_FUNC2_SIGNAL_PARTICULAR:
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 0x2) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x15, 7, 0, 0x4) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x1e, 6, 0, 0xa) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x1f, 5, 0, 0x3f) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, 0x23, 4, 0, 0x1f) != FUNCTION_SUCCESS)
+				goto error_status_set_registers;
+
+			break;
+	}
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Wait 1000 ms for signal lock check.
+	for(i = 0; i < 10; i++)
+	{
+		// Wait 100 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 100);
+
+		// Check signal lock status on demod.
+		// Note: If signal is locked, stop signal lock check.
+		if(pDemod->IsSignalLocked(pDemod, &SignalLockStatus) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		if(SignalLockStatus == YES)
+			break;
+	}
+
+
+	// Update previous signal mode.
+	pExtra->Func2SignalModePrevious = SignalMode;
+
+
+success_status_signal_mode_is_the_same:
+success_status_tps_is_not_locked:
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+error_status_execute_function:
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/demod_rtl2836.h b/drivers/media/usb/dvb-usb/demod_rtl2836.h
new file mode 100644
index 0000000..af3c79e
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/demod_rtl2836.h
@@ -0,0 +1,376 @@
+#ifndef __DEMOD_RTL2836_H
+#define __DEMOD_RTL2836_H
+
+/**
+
+@file
+
+@brief   RTL2836 demod module declaration
+
+One can manipulate RTL2836 demod through RTL2836 module.
+RTL2836 module is derived from DTMB demod module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the DTMB demod example in dtmb_demod_base.h except the listed lines.
+
+
+
+#include "demod_rtl2836.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+	DTMB_DEMOD_MODULE     DtmbDemodModuleMemory;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+	I2C_BRIDGE_MODULE     I2cBridgeModuleMemory;
+
+
+	...
+
+
+
+	// Build RTL2836 demod module.
+	BuildRtl2836Module(
+		&pDemod,
+		&DtmbDemodModuleMemory,
+		&BaseInterfaceModuleMemory,
+		&I2cBridgeModuleMemory,
+		0x3e,								// I2C device address is 0x3e in 8-bit format.
+		CRYSTAL_FREQ_27000000HZ,			// Crystal frequency is 27.0 MHz.
+		TS_INTERFACE_SERIAL,				// TS interface mode is serial.
+		50,									// Update function reference period is 50 millisecond
+		YES,								// Function 1 enabling status is on.
+		YES									// Function 2 enabling status is on.
+		);
+
+
+
+	// See the example for other DTMB demod functions in dtmb_demod_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "dtmb_demod_base.h"
+
+
+
+
+
+// Definitions
+
+// Initializing
+#define RTL2836_INIT_REG_TABLE_LEN					86
+#define RTL2836_TS_INTERFACE_INIT_TABLE_LEN			3
+
+
+// Chip ID
+#define RTL2836_CHIP_ID_VALUE			0x4
+
+
+// IF frequency setting
+#define RTL2836_ADC_FREQ_HZ			48000000
+#define RTL2836_IFFREQ_BIT_NUM		10
+
+
+// BER
+#define RTL2836_BER_DEN_VALUE				1000000
+
+
+// PER
+#define RTL2836_PER_DEN_VALUE				32768
+
+
+// SNR
+#define RTL2836_EST_SNR_BIT_NUM				9
+#define RTL2836_SNR_DB_DEN_VALUE			4
+
+
+// AGC
+#define RTL2836_RF_AGC_REG_BIT_NUM		14
+#define RTL2836_IF_AGC_REG_BIT_NUM		14
+
+
+// TR offset and CR offset
+#define RTL2836_TR_OUT_R_BIT_NUM			17
+#define RTL2836_SFOAQ_OUT_R_BIT_NUM			14
+#define RTL2836_CFO_EST_R_BIT_NUM			23
+
+
+// Register table length
+#define RTL2836_REG_TABLE_LEN			25
+
+
+// Function 1
+#define RTL2836_FUNC1_CHECK_TIME_MS			500
+
+
+// Function 2
+enum RTL2836_FUNC2_SIGNAL_MODE
+{
+	RTL2836_FUNC2_SIGNAL_NORMAL,
+	RTL2836_FUNC2_SIGNAL_PARTICULAR,
+};
+
+
+
+
+
+// Demod module builder
+void
+BuildRtl2836Module(
+	DTMB_DEMOD_MODULE **ppDemod,
+	DTMB_DEMOD_MODULE *pDtmbDemodModuleMemory,
+	BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory,
+	I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory,
+	unsigned char DeviceAddr,
+	unsigned long CrystalFreqHz,
+	int TsInterfaceMode,
+	unsigned long UpdateFuncRefPeriodMs,
+	int IsFunc1Enabled,
+	int IsFunc2Enabled
+	);
+
+
+
+
+
+// Manipulating functions
+void
+rtl2836_IsConnectedToI2c(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pAnswer
+);
+
+int
+rtl2836_SoftwareReset(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2836_Initialize(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2836_SetIfFreqHz(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long IfFreqHz
+	);
+
+int
+rtl2836_SetSpectrumMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int SpectrumMode
+	);
+
+int
+rtl2836_IsSignalLocked(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+int
+rtl2836_GetSignalStrength(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalStrength
+	);
+
+int
+rtl2836_GetSignalQuality(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalQuality
+	);
+
+int
+rtl2836_GetBer(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	);
+
+int
+rtl2836_GetPer(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	);
+
+int
+rtl2836_GetSnrDb(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+int
+rtl2836_GetRfAgc(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pRfAgc
+	);
+
+int
+rtl2836_GetIfAgc(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pIfAgc
+	);
+
+int
+rtl2836_GetDiAgc(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pDiAgc
+	);
+
+int
+rtl2836_GetTrOffsetPpm(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pTrOffsetPpm
+	);
+
+int
+rtl2836_GetCrOffsetHz(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pCrOffsetHz
+	);
+
+int
+rtl2836_GetCarrierMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pCarrierMode
+	);
+
+int
+rtl2836_GetPnMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pPnMode
+	);
+
+int
+rtl2836_GetQamMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pQamMode
+	);
+
+int
+rtl2836_GetCodeRateMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pCodeRateMode
+	);
+
+int
+rtl2836_GetTimeInterleaverMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pTimeInterleaverMode
+	);
+
+int
+rtl2836_UpdateFunction(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2836_ResetFunction(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+// I2C command forwarding functions
+int
+rtl2836_ForwardI2cReadingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+int
+rtl2836_ForwardI2cWritingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+// Register table initializing
+void
+rtl2836_InitRegTable(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+// I2C birdge module builder
+void
+rtl2836_BuildI2cBridgeModule(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+// RTL2836 dependence
+int
+rtl2836_func1_Reset(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2836_func1_Update(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2836_func2_Reset(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2836_func2_Update(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/demod_rtl2840.c b/drivers/media/usb/dvb-usb/demod_rtl2840.c
new file mode 100644
index 0000000..226caf9
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/demod_rtl2840.c
@@ -0,0 +1,2437 @@
+/**
+
+@file
+
+@brief   RTL2840 QAM demod module definition
+
+One can manipulate RTL2840 QAM demod through RTL2840 module.
+RTL2840 module is derived from QAM demod module.
+
+*/
+
+
+#include "demod_rtl2840.h"
+
+
+
+
+
+/**
+
+@brief   RTL2840 demod module builder
+
+Use BuildRtl2840Module() to build RTL2840 module, set all module function pointers with the corresponding functions, and
+initialize module private variables.
+
+
+@param [in]   ppDemod                      Pointer to RTL2840 demod module pointer
+@param [in]   pQamDemodModuleMemory        Pointer to an allocated QAM demod module memory
+@param [in]   pBaseInterfaceModuleMemory   Pointer to an allocated base interface module memory
+@param [in]   pI2cBridgeModuleMemory       Pointer to an allocated I2C bridge module memory
+@param [in]   DeviceAddr                   RTL2840 I2C device address
+@param [in]   CrystalFreqHz                RTL2840 crystal frequency in Hz
+@param [in]   TsInterfaceMode              RTL2840 TS interface mode for setting
+@param [in]   EnhancementMode              RTL2840 enhancement mode for setting
+
+
+@note
+	-# One should call BuildRtl2840Module() to build RTL2840 module before using it.
+
+*/
+void
+BuildRtl2840Module(
+	QAM_DEMOD_MODULE **ppDemod,
+	QAM_DEMOD_MODULE *pQamDemodModuleMemory,
+	BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory,
+	I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory,
+	unsigned char DeviceAddr,
+	unsigned long CrystalFreqHz,
+	int TsInterfaceMode,
+	int EnhancementMode
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+
+
+
+	// Set demod module pointer.
+	*ppDemod = pQamDemodModuleMemory;
+
+	// Get demod module.
+	pDemod = *ppDemod;
+
+	// Set base interface module pointer and I2C bridge module pointer.
+	pDemod->pBaseInterface = pBaseInterfaceModuleMemory;
+	pDemod->pI2cBridge     = pI2cBridgeModuleMemory;
+
+
+	// Set demod type.
+	pDemod->DemodType = QAM_DEMOD_TYPE_RTL2840;
+
+	// Set demod I2C device address.
+	pDemod->DeviceAddr = DeviceAddr;
+
+	// Set demod crystal frequency in Hz.
+	pDemod->CrystalFreqHz = CrystalFreqHz;
+
+	// Set demod TS interface mode.
+	pDemod->TsInterfaceMode = TsInterfaceMode;
+
+
+	// Initialize demod parameter setting status
+	pDemod->IsQamModeSet       = NO;
+	pDemod->IsSymbolRateHzSet  = NO;
+	pDemod->IsAlphaModeSet     = NO;
+	pDemod->IsIfFreqHzSet      = NO;
+	pDemod->IsSpectrumModeSet  = NO;
+
+
+	// Initialize register tables in demod extra module.
+	rtl2840_InitBaseRegTable(pDemod);
+	rtl2840_InitMonitorRegTable(pDemod);
+
+
+	// Build I2C birdge module.
+	rtl2840_BuildI2cBridgeModule(pDemod);
+
+
+	// Set demod module I2C function pointers with default functions.
+	pDemod->RegAccess.Addr8Bit.SetRegPage         = qam_demod_addr_8bit_default_SetRegPage;
+	pDemod->RegAccess.Addr8Bit.SetRegBytes        = qam_demod_addr_8bit_default_SetRegBytes;
+	pDemod->RegAccess.Addr8Bit.GetRegBytes        = qam_demod_addr_8bit_default_GetRegBytes;
+	pDemod->RegAccess.Addr8Bit.SetRegMaskBits     = qam_demod_addr_8bit_default_SetRegMaskBits;
+	pDemod->RegAccess.Addr8Bit.GetRegMaskBits     = qam_demod_addr_8bit_default_GetRegMaskBits;
+	pDemod->RegAccess.Addr8Bit.SetRegBits         = qam_demod_addr_8bit_default_SetRegBits;
+	pDemod->RegAccess.Addr8Bit.GetRegBits         = qam_demod_addr_8bit_default_GetRegBits;
+	pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage = qam_demod_addr_8bit_default_SetRegBitsWithPage;
+	pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage = qam_demod_addr_8bit_default_GetRegBitsWithPage;
+
+
+	// Set demod module manipulating function pointers with default functions.
+	pDemod->GetDemodType     = qam_demod_default_GetDemodType;
+	pDemod->GetDeviceAddr    = qam_demod_default_GetDeviceAddr;
+	pDemod->GetCrystalFreqHz = qam_demod_default_GetCrystalFreqHz;
+
+	pDemod->GetQamMode       = qam_demod_default_GetQamMode;
+	pDemod->GetSymbolRateHz  = qam_demod_default_GetSymbolRateHz;
+	pDemod->GetAlphaMode     = qam_demod_default_GetAlphaMode;
+	pDemod->GetIfFreqHz      = qam_demod_default_GetIfFreqHz;
+	pDemod->GetSpectrumMode  = qam_demod_default_GetSpectrumMode;
+
+
+	// Set demod module manipulating function pointers with particular functions.
+	// Note: Need to assign manipulating function pointers according to enhancement mode.
+	pDemod->IsConnectedToI2c  = rtl2840_IsConnectedToI2c;
+	pDemod->SoftwareReset     = rtl2840_SoftwareReset;
+
+	pDemod->Initialize        = rtl2840_Initialize;
+	pDemod->SetSymbolRateHz   = rtl2840_SetSymbolRateHz;
+	pDemod->SetAlphaMode      = rtl2840_SetAlphaMode;
+	pDemod->SetIfFreqHz       = rtl2840_SetIfFreqHz;
+	pDemod->SetSpectrumMode   = rtl2840_SetSpectrumMode;
+
+	pDemod->GetRfAgc          = rtl2840_GetRfAgc;
+	pDemod->GetIfAgc          = rtl2840_GetIfAgc;
+	pDemod->GetDiAgc          = rtl2840_GetDiAgc;
+	pDemod->GetTrOffsetPpm    = rtl2840_GetTrOffsetPpm;
+	pDemod->GetCrOffsetHz     = rtl2840_GetCrOffsetHz;
+
+	pDemod->IsAagcLocked      = rtl2840_IsAagcLocked;
+	pDemod->IsEqLocked        = rtl2840_IsEqLocked;
+	pDemod->IsFrameLocked     = rtl2840_IsFrameLocked;
+
+	pDemod->GetErrorRate      = rtl2840_GetErrorRate;
+	pDemod->GetSnrDb          = rtl2840_GetSnrDb;
+
+	pDemod->GetSignalStrength = rtl2840_GetSignalStrength;
+	pDemod->GetSignalQuality  = rtl2840_GetSignalQuality;
+
+	pDemod->UpdateFunction    = rtl2840_UpdateFunction;
+	pDemod->ResetFunction     = rtl2840_ResetFunction;
+
+	switch(EnhancementMode)
+	{
+		case QAM_DEMOD_EN_NONE:
+			pDemod->SetQamMode = rtl2840_SetQamMode;
+			break;
+
+		case QAM_DEMOD_EN_AM_HUM:
+			pDemod->SetQamMode = rtl2840_am_hum_en_SetQamMode;
+			break;
+	}
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_IS_CONNECTED_TO_I2C
+
+*/
+void
+rtl2840_IsConnectedToI2c(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	unsigned long ReadingValue;
+
+
+
+	// Set reading value to zero, and get SYS_VERSION value.
+	// Note: Use GetRegBitsWithPage() to get register bits with page setting.
+	ReadingValue = 0;
+
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, QAM_SYS_VERSION, &ReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Compare SYS_VERSION value with RTL2840_SYS_VERSION_VALUE.
+	if(ReadingValue == RTL2840_SYS_VERSION_VALUE)
+		*pAnswer = YES;
+	else
+		*pAnswer = NO;
+
+
+	return;
+
+
+error_status_get_demod_registers:
+
+	*pAnswer = NO;
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SOFTWARE_RESET
+
+*/
+int
+rtl2840_SoftwareReset(
+	QAM_DEMOD_MODULE *pDemod
+	)
+{
+	// Set register page number with system page number for software resetting.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 0) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set and clear SOFT_RESET register bit.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SOFT_RESET, ON) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SOFT_RESET, OFF) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_INITIALIZE
+
+*/
+int
+rtl2840_Initialize(
+	QAM_DEMOD_MODULE *pDemod
+	)
+{
+	typedef struct
+	{
+		unsigned char PageNo;
+		unsigned char RegStartAddr;
+		unsigned char Msb;
+		unsigned char Lsb;
+		unsigned long WritingValue;
+	}
+	INIT_REG_ENTRY;
+
+
+	typedef struct
+	{
+		unsigned char SpecReg0Sel;
+		unsigned char SpecReg0ValueTable[RTL2840_SPEC_REG_0_VALUE_TABLE_LEN];
+	}
+	INIT_SPEC_REG_0_ENTRY;
+
+
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long WritingValue[TS_INTERFACE_MODE_NUM];
+	}
+	TS_INTERFACE_INIT_TABLE_ENTRY;
+
+
+
+	static const INIT_REG_ENTRY InitRegTable[RTL2840_INIT_REG_TABLE_LEN] =
+	{
+		// PageNo,	RegStartAddr,	Msb,	Lsb,	WritingValue
+		{0,			0x04,			2,		0,		0x5			},
+		{0,			0x04,			4,		3,		0x0			},
+		{0,			0x04,			5,		5,		0x1			},
+		{0,			0x06,			0,		0,		0x0			},
+		{0,			0x07,			2,		2,		0x0			},
+		{1,			0x04,			0,		0,		0x0			},
+		{1,			0x04,			1,		1,		0x0			},
+		{1,			0x04,			2,		2,		0x0			},
+		{1,			0x04,			3,		3,		0x0			},
+		{1,			0x0c,			2,		0,		0x7			},
+		{1,			0x19,			5,		5,		0x0			},
+		{1,			0x19,			6,		6,		0x1			},
+		{1,			0x19,			7,		7,		0x1			},
+		{1,			0x1a,			0,		0,		0x0			},
+		{1,			0x1a,			1,		1,		0x1			},
+		{1,			0x1a,			2,		2,		0x0			},
+		{1,			0x1a,			3,		3,		0x1			},
+		{1,			0x1a,			4,		4,		0x0			},
+		{1,			0x1a,			5,		5,		0x1			},
+		{1,			0x1a,			6,		6,		0x1			},
+		{1,			0x1b,			3,		0,		0x7			},
+		{1,			0x1b,			7,		4,		0xc			},
+		{1,			0x1c,			2,		0,		0x4			},
+		{1,			0x1c,			5,		3,		0x3			},
+		{1,			0x1d,			5,		0,		0x7			},
+		{1,			0x27,			9,		0,		0x6d		},
+		{1,			0x2b,			7,		0,		0x26		},
+		{1,			0x2c,			7,		0,		0x1e		},
+		{1,			0x2e,			7,		6,		0x3			},
+		{1,			0x32,			2,		0,		0x7			},
+		{1,			0x32,			5,		3,		0x0			},
+		{1,			0x32,			6,		6,		0x1			},
+		{1,			0x32,			7,		7,		0x0			},
+		{1,			0x33,			6,		0,		0xf			},
+		{1,			0x33,			7,		7,		0x1			},
+		{1,			0x39,			7,		0,		0x88		},
+		{1,			0x3a,			7,		0,		0x36		},
+		{1,			0x3e,			7,		0,		0x26		},
+		{1,			0x3f,			7,		0,		0x15		},
+		{1,			0x4b,			8,		0,		0x166		},
+		{1,			0x4d,			8,		0,		0x166		},
+		{2,			0x11,			0,		0,		0x0			},
+		{2,			0x02,			7,		0,		0x7e		},
+		{2,			0x12,			3,		0,		0x7			},
+		{2,			0x12,			7,		4,		0x7			},
+	};
+
+
+	static const INIT_SPEC_REG_0_ENTRY InitSpecReg0Table[RTL2840_INIT_SPEC_REG_0_TABLE_LEN] =
+	{
+		// SpecReg0Sel,		{SpecReg0ValueTable																	}
+		{0,					{0x00,	0xd0,	0x49,	0x8e,	0xf2,	0x01,	0x00,	0xc0,	0x62,	0x62,	0x00}	},
+		{1,					{0x11,	0x21,	0x89,	0x8e,	0xf2,	0x01,	0x80,	0x8b,	0x62,	0xe2,	0x00}	},
+		{2,					{0x22,	0x32,	0x89,	0x8e,	0x72,	0x00,	0xc0,	0x86,	0xe2,	0xe3,	0x00}	},
+		{3,					{0x43,	0x44,	0x8b,	0x0e,	0xf2,	0xdd,	0xb5,	0x84,	0xe2,	0xcb,	0x00}	},
+		{4,					{0x54,	0x55,	0xcb,	0x1e,	0xf3,	0x4d,	0xb5,	0x84,	0xe2,	0xcb,	0x00}	},
+		{5,					{0x65,	0x66,	0xcb,	0x1e,	0xf5,	0x4b,	0xb4,	0x84,	0xe2,	0xcb,	0x00}	},
+		{6,					{0x76,	0x77,	0xcb,	0x9e,	0xf7,	0xc7,	0x73,	0x80,	0xe2,	0xcb,	0x00}	},
+		{7,					{0x87,	0x88,	0xcb,	0x2e,	0x48,	0x41,	0x72,	0x80,	0xe2,	0xcb,	0x00}	},
+		{8,					{0x98,	0x99,	0xcc,	0x3e,	0x48,	0x21,	0x71,	0x80,	0xea,	0xcb,	0x00}	},
+		{11,				{0xbb,	0xc8,	0xcb,	0x6e,	0x24,	0x18,	0x73,	0xa0,	0xfa,	0xcf,	0x01}	},
+		{13,				{0x1d,	0x1e,	0x4f,	0x8e,	0xf2,	0x01,	0x00,	0x80,	0x62,	0x62,	0x00}	},
+		{14,				{0x1e,	0x1f,	0x4f,	0x8e,	0xf2,	0x01,	0x00,	0x80,	0x62,	0x62,	0x00}	},
+		{15,				{0x1f,	0x11,	0x4f,	0x8e,	0xf2,	0x01,	0x00,	0x80,	0x62,	0x62,	0x00}	},
+	};
+
+
+	static const TS_INTERFACE_INIT_TABLE_ENTRY TsInterfaceInitTable[RTL2840_TS_INTERFACE_INIT_TABLE_LEN] =
+	{
+		// RegBitName,				WritingValue for {Parallel, Serial}
+		{QAM_SERIAL,				{0x0,	0x1}},
+		{QAM_CDIV_PH0,				{0x7,	0x0}},
+		{QAM_CDIV_PH1,				{0x7,	0x0}},
+	};
+
+
+	int i;
+
+	int TsInterfaceMode;
+
+	unsigned char PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+	unsigned long WritingValue;
+
+	unsigned char SpecReg0Sel;
+	const unsigned char *pSpecReg0ValueTable;
+
+	unsigned long QamSpecInitA2Backup;
+	unsigned long RegValue, RegValueComparison;
+	int AreAllValueEqual;
+
+
+
+	// Get TS interface mode.
+	TsInterfaceMode = pDemod->TsInterfaceMode;
+
+	// Initialize demod with register initializing table.
+	for(i = 0; i < RTL2840_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get all information from each register initializing entry.
+		PageNo       = InitRegTable[i].PageNo;
+		RegStartAddr = InitRegTable[i].RegStartAddr;
+		Msb          = InitRegTable[i].Msb;
+		Lsb          = InitRegTable[i].Lsb;
+		WritingValue = InitRegTable[i].WritingValue;
+
+		// Set register page number.
+		if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set register mask bits.
+		if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, WritingValue) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Set register page number with inner page number for specific register 0 initializing.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 1) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+	// Initialize demod with specific register 0 initializing table.
+	for(i = 0; i < RTL2840_INIT_SPEC_REG_0_TABLE_LEN; i++)
+	{
+		// Get all information from each specific register 0 initializing entry.
+		SpecReg0Sel         = InitSpecReg0Table[i].SpecReg0Sel;
+		pSpecReg0ValueTable = InitSpecReg0Table[i].SpecReg0ValueTable;
+
+		// Set specific register 0 selection.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_REG_0_SEL, SpecReg0Sel) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set specific register 0 values.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBytes(pDemod, RTL2840_SPEC_REG_0_VAL_START_ADDR, pSpecReg0ValueTable, LEN_11_BYTE) !=
+			FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set specific register 0 strobe.
+		// Note: RTL2840 hardware will clear strobe automatically.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_REG_0_STROBE, ON) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Initialize demod registers according to the TS interface initializing table.
+	for(i = 0; i < RTL2840_TS_INTERFACE_INIT_TABLE_LEN; i++)
+	{
+		if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, TsInterfaceInitTable[i].RegBitName,
+			TsInterfaceInitTable[i].WritingValue[TsInterfaceMode]) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Backup SPEC_INIT_A2 value.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, QAM_SPEC_INIT_A2, &QamSpecInitA2Backup)!= FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+	// Set SPEC_INIT_A2 with 0.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_SPEC_INIT_A2, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+	// Get SPEC_MONITER_INIT_0 several times.
+	// If all SPEC_MONITER_INIT_0 getting values are the same, set SPEC_INIT_A1 with 0.
+	// Note: 1. Need to set SPEC_INIT_A2 with 0 when get SPEC_MONITER_INIT_0.
+	//       2. The function rtl2840_GetMonitorRegBits() will set register page automatically.
+	if(rtl2840_GetMonitorRegBits(pDemod, QAM_SPEC_MONITER_INIT_0, &RegValueComparison) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+	for(i = 0, AreAllValueEqual = YES; i < RTL2840_SPEC_MONITOR_INIT_0_COMPARISON_TIMES; i++)
+	{
+		if(rtl2840_GetMonitorRegBits(pDemod, QAM_SPEC_MONITER_INIT_0, &RegValue) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+
+		if(RegValue != RegValueComparison)
+		{
+			AreAllValueEqual = NO;
+
+			break;
+		}
+	}
+
+	if(AreAllValueEqual == YES)
+	{
+		if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_SPEC_INIT_A1, 0x0) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+	// Restore SPEC_INIT_A2 value.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_SPEC_INIT_A2, QamSpecInitA2Backup) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_QAM_MODE
+
+*/
+int
+rtl2840_SetQamMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int QamMode
+	)
+{
+	typedef struct
+	{
+		unsigned char PageNo;
+		unsigned char RegStartAddr;
+		unsigned char Msb;
+		unsigned char Lsb;
+		unsigned long WritingValue[QAM_QAM_MODE_NUM];
+	}
+	QAM_MODE_REG_ENTRY;
+
+
+	typedef struct
+	{
+		unsigned char SpecReg0Sel;
+		unsigned char SpecReg0ValueTable[QAM_QAM_MODE_NUM][RTL2840_SPEC_REG_0_VALUE_TABLE_LEN];
+	}
+	QAM_MODE_SPEC_REG_0_ENTRY;
+
+
+
+	static const QAM_MODE_REG_ENTRY QamModeRegTable[RTL2840_QAM_MODE_REG_TABLE_LEN] =
+	{
+		// Reg,									WritingValue according to QAM mode
+		// PageNo,	StartAddr,	Msb,	Lsb,	{4-Q,   16-Q,  32-Q,  64-Q,  128-Q, 256-Q, 512-Q, 1024-Q}
+		{1,			0x02,		2,		0,		{0x7,   0x0,   0x1,   0x2,   0x3,   0x4,   0x5,   0x6	}},
+		{1,			0x05,		7,		0,		{0x6b,  0x6b,  0x6b,  0x6b,  0x6b,  0x6b,  0x6b,  0x6b  }},
+		{1,			0x2f,		15,		5,		{0x37,  0x82,  0xb9,  0x10e, 0x177, 0x21c, 0x2ee, 0x451	}},
+		{1,			0x31,		5,		0,		{0x1,   0x3,   0x4,   0x5,   0x8,   0xa,   0xf,   0x14	}},
+		{1,			0x2e,		5,		0,		{0x2,   0x4,   0x6,   0x8,   0xc,   0x10,  0x18,  0x20	}},
+		{1,			0x18,		7,		0,		{0x0,   0xdb,  0x79,  0x0,   0x8a,  0x0,   0x8c,  0x0	}},
+		{1,			0x19,		4,		0,		{0x14,  0x14,  0xf,   0x14,  0xf,   0x14,  0xf,   0x14  }},
+		{1,			0x3b,		2,		0,		{0x0,   0x0,   0x0,   0x0,   0x0,   0x0,   0x1,   0x1	}},
+		{1,			0x3b,		5,		3,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3c,		2,		0,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3c,		4,		3,		{0x0,   0x0,   0x0,   0x0,   0x0,   0x0,   0x1,   0x1	}},
+		{1,			0x3c,		6,		5,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3d,		1,		0,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3d,		3,		2,		{0x0,   0x0,   0x0,   0x0,   0x0,   0x0,   0x1,   0x1	}},
+		{1,			0x3d,		5,		4,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3d,		7,		6,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x40,		2,		0,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x40,		5,		3,		{0x2,   0x2,   0x2,   0x2,   0x2,   0x2,   0x3,   0x3	}},
+		{1,			0x41,		2,		0,		{0x3,   0x3,   0x3,   0x3,   0x3,   0x3,   0x4,   0x4	}},
+		{1,			0x41,		4,		3,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x1	}},
+		{1,			0x41,		6,		5,		{0x2,   0x2,   0x2,   0x2,   0x2,   0x2,   0x2,   0x2	}},
+		{1,			0x42,		1,		0,		{0x3,   0x3,   0x3,   0x3,   0x3,   0x3,   0x3,   0x3	}},
+		{1,			0x42,		3,		2,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x1	}},
+		{1,			0x42,		5,		4,		{0x2,   0x2,   0x2,   0x2,   0x2,   0x2,   0x2,   0x2	}},
+		{1,			0x42,		7,		6,		{0x3,   0x3,   0x3,   0x3,   0x3,   0x3,   0x3,   0x3	}},
+	};
+
+
+	static const QAM_MODE_SPEC_REG_0_ENTRY QamModeSpecReg0Table[RTL2840_QAM_MODE_SPEC_REG_0_TABLE_LEN] =
+	{
+		// SpecReg0Sel,		{SpecReg0ValueTable                                              }		   QAM mode
+		{9,				{	{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},		// 4-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},		// 16-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x10, 0x70, 0x80, 0xfa, 0xcb, 0x00},		// 32-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},		// 64-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x10, 0x70, 0x80, 0xfa, 0xcb, 0x00},		// 128-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},		// 256-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x10, 0x70, 0x80, 0xfa, 0xcb, 0x00},		// 512-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},	}	// 1024-QAM
+		},
+
+
+		// SpecReg0Sel,		{SpecReg0ValueTable                                              }		   QAM mode
+		{10,			{	{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x20, 0x71, 0xa0, 0xfa, 0xcb, 0x00},		// 4-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x20, 0x71, 0xa0, 0xfa, 0xcb, 0x00},		// 16-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x10, 0x70, 0xa0, 0xfa, 0xcb, 0x00},		// 32-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x20, 0x71, 0xa0, 0xfa, 0xcb, 0x00},		// 64-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x10, 0x70, 0xa0, 0xfa, 0xcb, 0x00},		// 128-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x20, 0x71, 0xa0, 0xfa, 0xcb, 0x00},		// 256-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x10, 0x70, 0xa0, 0xfa, 0xcb, 0x00},		// 512-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x10, 0x70, 0xa0, 0xfa, 0xcb, 0x00},	}	// 1024-QAM
+		},
+
+		// SpecReg0Sel,		{SpecReg0ValueTable                                              }		   QAM mode
+		{12,			{	{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 4-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 16-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 32-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 64-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 128-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 256-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 512-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},	}	// 1024-QAM
+		},
+	};
+
+
+	int i;
+
+	unsigned char PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+	unsigned long WritingValue;
+
+	unsigned char SpecReg0Sel;
+	const unsigned char *pSpecReg0ValueTable;
+
+
+
+	// Set demod QAM mode with QAM mode register setting table.
+	for(i = 0; i < RTL2840_QAM_MODE_REG_TABLE_LEN; i++)
+	{
+		// Get all information from each register setting entry according to QAM mode.
+		PageNo       = QamModeRegTable[i].PageNo;
+		RegStartAddr = QamModeRegTable[i].RegStartAddr;
+		Msb          = QamModeRegTable[i].Msb;
+		Lsb          = QamModeRegTable[i].Lsb;
+		WritingValue = QamModeRegTable[i].WritingValue[QamMode];
+
+		// Set register page number.
+		if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set register mask bits.
+		if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, WritingValue) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Set register page number with inner page number for QAM mode specific register 0 setting.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 1) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+	// Set demod QAM mode with QAM mode specific register 0 setting table.
+	for(i = 0; i < RTL2840_QAM_MODE_SPEC_REG_0_TABLE_LEN; i++)
+	{
+		// Get all information from each specific register 0 setting entry according to QAM mode.
+		SpecReg0Sel         = QamModeSpecReg0Table[i].SpecReg0Sel;
+		pSpecReg0ValueTable = QamModeSpecReg0Table[i].SpecReg0ValueTable[QamMode];
+
+		// Set specific register 0 selection.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_REG_0_SEL, SpecReg0Sel) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set specific register 0 values.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBytes(pDemod, RTL2840_SPEC_REG_0_VAL_START_ADDR, pSpecReg0ValueTable, LEN_11_BYTE) != 
+			FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set specific register 0 strobe.
+		// Note: RTL2840 hardware will clear strobe automatically.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_REG_0_STROBE, ON) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Set demod QAM mode parameter.
+	pDemod->QamMode      = QamMode;
+	pDemod->IsQamModeSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_SYMBOL_RATE_HZ
+
+*/
+int
+rtl2840_SetSymbolRateHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long SymbolRateHz
+	)
+{
+	typedef struct
+	{
+		unsigned long TrDeciRatioRangeMin;
+		unsigned char SymbolRateReg0;
+		unsigned long SymbolRateValue[RTL2840_SYMBOL_RATE_VALUE_TABLE_LEN];
+	}
+	SYMBOL_RATE_ENTRY;
+
+
+
+	static const SYMBOL_RATE_ENTRY SymbolRateTable[RTL2840_SYMBOL_RATE_TABLE_LEN] =
+	{
+		// TrDeciRatioRangeMin,	SymbolRateReg0,	{SymbolRateValue                              }
+		{0x1a0000,				0x4,			{10,   14,   1,  988,  955, 977, 68,  257, 438}	},
+		{0x160000,				0x5,			{2,    15,   19, 1017, 967, 950, 12,  208, 420}	},
+		{0x0,					0x6,			{1019, 1017, 9,  29,   3,   957, 956, 105, 377}	},
+	};
+
+
+	int i;
+
+	unsigned long CrystalFreqHz;
+	const SYMBOL_RATE_ENTRY *pSymbolRateEntry;
+
+	MPI MpiCrystalFreqHz, MpiSymbolRateHz, MpiConst, MpiVar, MpiNone;
+
+	unsigned long TrDeciRatio;
+	unsigned char SymbolRateReg0;
+	unsigned long SymbolRateValue;
+
+
+
+	// Get demod crystal frequency in Hz.
+	pDemod->GetCrystalFreqHz(pDemod, &CrystalFreqHz);
+
+	
+	// Calculate TR_DECI_RATIO value.
+	// Note: Original formula:   TR_DECI_RATIO = round( (CrystalFreqHz * pow(2, 18)) / SymbolRateHz )
+	//       Adjusted formula:   TR_DECI_RATIO = floor( ((CrystalFreqHz << 19) / SymbolRateHz + 1) >> 1 )
+	MpiSetValue(&MpiCrystalFreqHz, CrystalFreqHz);
+	MpiSetValue(&MpiSymbolRateHz, SymbolRateHz);
+	MpiSetValue(&MpiConst, 1);
+
+	MpiLeftShift(&MpiVar, MpiCrystalFreqHz, 19);
+	MpiDiv(&MpiVar, &MpiNone, MpiVar, MpiSymbolRateHz);
+	MpiAdd(&MpiVar, MpiVar, MpiConst);
+	MpiRightShift(&MpiVar, MpiVar, 1);
+
+	MpiGetValue(MpiVar, (long *)&TrDeciRatio);
+
+
+	// Determine symbol rate entry according to TR_DECI_RATIO value and minimum of TR_DECI_RATIO range.
+	for(i = 0; i < RTL2840_SYMBOL_RATE_TABLE_LEN; i++)
+	{
+		if(TrDeciRatio >= SymbolRateTable[i].TrDeciRatioRangeMin)
+		{
+			pSymbolRateEntry = &SymbolRateTable[i];
+
+			break;
+		}
+	}
+
+
+	// Set register page number with inner page number for symbol rate setting.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 1) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+	// Set TR_DECI_RATIO with calculated value.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_TR_DECI_RATIO, TrDeciRatio) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set SPEC_SYMBOL_RATE_REG_0 value with determined symbol rate entry.
+	SymbolRateReg0 = pSymbolRateEntry->SymbolRateReg0;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_SYMBOL_RATE_REG_0, SymbolRateReg0) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set symbol rate value with determined symbol rate entry.
+	for(i = 0; i < RTL2840_SYMBOL_RATE_VALUE_TABLE_LEN; i++)
+	{
+		// Get symbol rate value.
+		SymbolRateValue = pSymbolRateEntry->SymbolRateValue[i];
+
+		// Set symbol rate register selection.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_SYMBOL_RATE_SEL, i) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set symbol rate register value.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_SYMBOL_RATE_VAL, SymbolRateValue) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set symbol rate register strobe.
+		// Note: RTL2840 hardware will clear strobe automatically.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_SYMBOL_RATE_STROBE, ON) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Set demod symbol rate parameter.
+	pDemod->SymbolRateHz      = SymbolRateHz;
+	pDemod->IsSymbolRateHzSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_ALPHA_MODE
+
+*/
+int
+rtl2840_SetAlphaMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int AlphaMode
+	)
+{
+	static const unsigned long AlphaValueTable[QAM_ALPHA_MODE_NUM][RTL2840_ALPHA_VALUE_TABLE_LEN] =
+	{
+		{258,  94,   156,  517,  6,  1015,  1016,  17,  11,  994,   1011,  51,  15,  926,  1008,  313},	// alpha = 0.12
+		{258,  31,   28,   3,    6,  1016,  1016,  16,  11,  996,   1010,  50,  16,  927,  1007,  312},	// alpha = 0.13
+		{131,  257,  27,   2,    8,  1017,  1013,  16,  14,  996,   1008,  50,  18,  927,  1004,  310},	// alpha = 0.15
+		{0,    195,  30,   30,   6,  1022,  1014,  10,  14,  1002,  1006,  45,  21,  931,  1001,  307},	// alpha = 0.18
+		{415,  68,   31,   29,   4,  1,     1016,  6,   13,  1006,  1006,  41,  23,  934,  998,   304},	// alpha = 0.20
+	};
+
+
+	int i;
+	unsigned long AlphaValue;
+
+
+
+	// Set register page number with inner page number for alpha value setting.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 1) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+	// Set demod alpha mode with alpha value table.
+	for(i = 0; i < RTL2840_ALPHA_VALUE_TABLE_LEN; i++)
+	{
+		// Get alpha value from alpha value entry according to alpha mode.
+		AlphaValue = AlphaValueTable[AlphaMode][i];
+
+		// Set alpha register selection.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_ALPHA_SEL, i) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set alpha register value.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_ALPHA_VAL, AlphaValue) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set alpha register strobe.
+		// Note: RTL2840 hardware will clear strobe automatically.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_ALPHA_STROBE, ON) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Set demod alpha mode parameter.
+	pDemod->AlphaMode      = AlphaMode;
+	pDemod->IsAlphaModeSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_IF_FREQ_HZ
+
+*/
+int
+rtl2840_SetIfFreqHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long IfFreqHz
+	)
+{
+	unsigned long CrystalFreqHz;
+	unsigned long DdcFreq;
+
+	MPI MpiIfFreqHz, MpiCrystalFreqHz, MpiConst, MpiVar, MpiNone;
+
+
+
+	// Get demod crystal frequency in Hz.
+	pDemod->GetCrystalFreqHz(pDemod, &CrystalFreqHz);
+
+
+	// Calculate DDC_FREQ value.
+	// Note: Original formula:   DDC_FREQ = round( (CrystalFreqHz - (IfFreqHz % CrystalFreqHz)) * pow(2, 15) /
+	//                                             CrystalFreqHz )
+	//       Adjusted formula:   DDC_FREQ = floor( ( ((CrystalFreqHz - (IfFreqHz % CrystalFreqHz)) << 16) /
+	//                                               CrystalFreqHz + 1 ) >> 1)
+	MpiSetValue(&MpiIfFreqHz, IfFreqHz);
+	MpiSetValue(&MpiCrystalFreqHz, CrystalFreqHz);
+	MpiSetValue(&MpiConst, 1);
+
+	MpiSetValue(&MpiVar, CrystalFreqHz - (IfFreqHz % CrystalFreqHz));
+	MpiLeftShift(&MpiVar, MpiVar, 16);
+	MpiDiv(&MpiVar, &MpiNone, MpiVar, MpiCrystalFreqHz);
+	MpiAdd(&MpiVar, MpiVar, MpiConst);
+	MpiRightShift(&MpiVar, MpiVar, 1);
+
+	MpiGetValue(MpiVar, (long *)&DdcFreq);
+
+
+	// Set DDC_FREQ with calculated value.
+	// Note: Use SetRegBitsWithPage() to set register bits with page setting.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_DDC_FREQ, DdcFreq) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set demod IF frequnecy parameter.
+	pDemod->IfFreqHz      = IfFreqHz;
+	pDemod->IsIfFreqHzSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_SPECTRUM_MODE
+
+*/
+int
+rtl2840_SetSpectrumMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int SpectrumMode
+	)
+{
+	static const char SpecInvValueTable[SPECTRUM_MODE_NUM] =
+	{
+		// SpecInv
+		0,				// Normal spectrum
+		1,				// Inverse spectrum
+	};
+
+
+	unsigned long SpecInv;
+
+
+
+	// Get SPEC_INV value from spectrum inverse value table according to spectrum mode.
+	SpecInv = SpecInvValueTable[SpectrumMode];
+
+
+	// Set SPEC_INV with gotten value.
+	// Note: Use SetRegBitsWithPage() to set register bits with page setting.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_SPEC_INV, SpecInv) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set demod spectrum mode parameter.
+	pDemod->SpectrumMode      = SpectrumMode;
+	pDemod->IsSpectrumModeSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_RF_AGC
+
+*/
+int
+rtl2840_GetRfAgc(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pRfAgc
+	)
+{
+	unsigned long RfAgcBinary;
+
+
+	// Get RF AGC binary value from RF_AGC_VALUE monitor register bits.
+	// Note: The function rtl2840_GetMonitorRegBits() will set register page automatically.
+	if(rtl2840_GetMonitorRegBits(pDemod, QAM_RF_AGC_VALUE, &RfAgcBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Convert RF AGC binary value to signed integer.
+	*pRfAgc = BinToSignedInt(RfAgcBinary, RTL2840_RF_AGC_VALUE_BIT_NUM);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_IF_AGC
+
+*/
+int
+rtl2840_GetIfAgc(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pIfAgc
+	)
+{
+	unsigned long IfAgcBinary;
+
+
+	// Get IF AGC binary value from IF_AGC_VALUE monitor register bits.
+	// Note: The function rtl2840_GetMonitorRegBits() will set register page automatically.
+	if(rtl2840_GetMonitorRegBits(pDemod, QAM_IF_AGC_VALUE, &IfAgcBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Convert IF AGC binary value to signed integer.
+	*pIfAgc = BinToSignedInt(IfAgcBinary, RTL2840_IF_AGC_VALUE_BIT_NUM);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_DI_AGC
+
+*/
+int
+rtl2840_GetDiAgc(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pDiAgc
+	)
+{
+	// Get digital AGC value from DAGC_VALUE monitor register bits.
+	// Note: The function rtl2840_GetMonitorRegBits() will set register page automatically.
+	if(rtl2840_GetMonitorRegBits(pDemod, QAM_DAGC_VALUE, pDiAgc) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_TR_OFFSET_PPM
+
+*/
+int
+rtl2840_GetTrOffsetPpm(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pTrOffsetPpm
+	)
+{
+	unsigned long SymbolRateHz;
+	unsigned long CrystalFreqHz;
+
+	unsigned long TrOffsetBinary;
+	long          TrOffsetInt;
+
+	MPI MpiTrOffsetInt, MpiSymbolRateHz, MpiCrystalFreqHz, MpiVar0, MpiVar1;
+
+
+
+	// Get demod symbol rate in Hz.
+	if(pDemod->GetSymbolRateHz(pDemod, &SymbolRateHz) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_symbol_rate;
+
+
+	// Get demod crystal frequency in Hz.
+	pDemod->GetCrystalFreqHz(pDemod, &CrystalFreqHz);
+
+
+	// Get TR offset binary value from TR_OFFSET monitor register bits.
+	// Note: The function rtl2840_GetMonitorRegBits() will set register page automatically.
+	if(rtl2840_GetMonitorRegBits(pDemod, QAM_TR_OFFSET, &TrOffsetBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Convert TR offset binary value to signed integer.
+	TrOffsetInt = BinToSignedInt(TrOffsetBinary, RTL2840_TR_OFFSET_BIT_NUM);
+
+
+	// Get TR offset in ppm.
+	// Note: (TR offset in ppm) = ((TR offset integer) * (symbol rate in Hz) * 1000000) /
+	//                            ((pow(2, 35) * (crystal frequency in Hz))
+	//       TR offset integer is 31 bit value.
+	MpiSetValue(&MpiTrOffsetInt,   TrOffsetInt);
+	MpiSetValue(&MpiSymbolRateHz,  (long)SymbolRateHz);
+	MpiSetValue(&MpiCrystalFreqHz, (long)CrystalFreqHz);
+	MpiSetValue(&MpiVar0,          1000000);
+
+	MpiMul(&MpiVar0, MpiVar0, MpiTrOffsetInt);
+	MpiMul(&MpiVar0, MpiVar0, MpiSymbolRateHz);
+	MpiLeftShift(&MpiVar1, MpiCrystalFreqHz, 35);
+	MpiDiv(&MpiVar0, &MpiVar1, MpiVar0, MpiVar1);
+
+	MpiGetValue(MpiVar0, pTrOffsetPpm);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_get_demod_symbol_rate:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_CR_OFFSET_HZ
+
+*/
+int
+rtl2840_GetCrOffsetHz(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pCrOffsetHz
+	)
+{
+	unsigned long SymbolRateHz;
+
+	unsigned long CrOffsetBinary;
+	long          CrOffsetInt;
+
+	MPI MpiCrOffsetInt, MpiSymbolRateHz, MpiMiddleResult;
+
+
+
+	// Get demod symbol rate in Hz.
+	if(pDemod->GetSymbolRateHz(pDemod, &SymbolRateHz) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_symbol_rate;
+
+
+	// Get CR offset binary value from CR_OFFSET monitor register bits.
+	// Note: The function rtl2840_GetMonitorRegBits() will set register page automatically.
+	if(rtl2840_GetMonitorRegBits(pDemod, QAM_CR_OFFSET, &CrOffsetBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Convert CR offset binary value to signed integer.
+	CrOffsetInt = BinToSignedInt(CrOffsetBinary, RTL2840_CR_OFFSET_BIT_NUM);
+
+
+	// Get CR offset in Hz.
+	// Note: (CR offset in Hz) = (CR offset integer) * (symbol rate in Hz) / pow(2, 34)
+	//       CR offset integer is 32 bit value.
+	MpiSetValue(&MpiCrOffsetInt,  CrOffsetInt);
+	MpiSetValue(&MpiSymbolRateHz, (long)SymbolRateHz);
+
+	MpiMul(&MpiMiddleResult, MpiCrOffsetInt, MpiSymbolRateHz);
+	MpiRightShift(&MpiMiddleResult, MpiMiddleResult, 34);
+
+	MpiGetValue(MpiMiddleResult, pCrOffsetHz);
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_get_demod_symbol_rate:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_IS_AAGC_LOCKED
+
+*/
+int
+rtl2840_IsAagcLocked(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	unsigned long LockStatus;
+
+
+
+	// Get AAGC lock status from AAGC_LD inner strobe register bits.
+	// Note: The function rtl2840_GetInnerStrobeRegBits() will set register page automatically.
+	if(rtl2840_GetInnerStrobeRegBits(pDemod, QAM_AAGC_LD, &LockStatus) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Determine answer according to AAGC lock status.
+	if(LockStatus == LOCKED)
+		*pAnswer = YES;
+	else
+		*pAnswer = NO;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_IS_EQ_LOCKED
+
+*/
+int
+rtl2840_IsEqLocked(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	unsigned long LockStatus;
+
+
+
+	// Get EQ lock status from EQ_LD inner strobe register bits.
+	// Note: The function rtl2840_GetInnerStrobeRegBits() will set register page automatically.
+	if(rtl2840_GetInnerStrobeRegBits(pDemod, QAM_EQ_LD, &LockStatus) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Determine answer according to EQ lock status.
+	if(LockStatus == LOCKED)
+		*pAnswer = YES;
+	else
+		*pAnswer = NO;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_IS_FRAME_LOCKED
+
+*/
+int
+rtl2840_IsFrameLocked(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	)
+{
+	unsigned long LossStatus;
+
+
+
+	// Get frame loss status from SYNCLOST register bits.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, QAM_SYNCLOST, &LossStatus) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Determine answer according to frame loss status.
+	if(LossStatus == NOT_LOST)
+		*pAnswer = YES;
+	else
+		*pAnswer = NO;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_ERROR_RATE
+
+*/
+int
+rtl2840_GetErrorRate(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long TestVolume,
+	unsigned int WaitTimeMsMax,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned int i;
+	unsigned long TestPacketNum;
+	unsigned int  WaitCnt;
+	int FrameLock;
+	unsigned long BerReg2, BerReg2Msb, BerReg2Lsb;
+	unsigned long BerReg0, BerReg1;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Calculate test packet number and wait counter value.
+	TestPacketNum = 0x1 << (TestVolume * 2 + 4);
+	WaitCnt = WaitTimeMsMax / RTL2840_BER_WAIT_TIME_MS;
+
+
+	// Set TEST_VOLUME with test volume.
+	// Note: The function SetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_TEST_VOLUME, TestVolume) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Clear and enable error counter.
+	// Note: The function SetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_BERT_EN, OFF) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_BERT_EN, ON) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Check if error test is finished.
+	for(i = 0; i < WaitCnt; i++)
+	{
+		// Check if demod is frame-locked.
+		if(pDemod->IsFrameLocked(pDemod, &FrameLock) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+
+		if(FrameLock == NO)
+			goto error_status_frame_lock;
+
+
+		// Wait a minute.
+		// Note: The input unit of WaitMs() is ms.
+		pBaseInterface->WaitMs(pBaseInterface, RTL2840_BER_WAIT_TIME_MS);
+
+
+		// Set error counter strobe.
+		// Note: RTL2840 hardware will clear strobe automatically.
+		//       The function SetRegBitsWithPage() will set register page automatically.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_BER_RD_STROBE, ON) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+
+		// Check if error test is finished.
+		// Note: The function GetRegBitsWithPage() will set register page automatically.
+		if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, QAM_BER_REG2_15_0, &BerReg2Lsb) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+
+		if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, QAM_BER_REG2_18_16, &BerReg2Msb) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+
+		BerReg2 = (BerReg2Msb << RTL2840_BER_REG2_MSB_SHIFT) | BerReg2Lsb;
+
+		if(BerReg2 == TestPacketNum)
+			break;
+	}
+
+
+	// Check time-out status.
+	if(i == WaitCnt)
+		goto error_status_time_out;
+
+
+	// Get BER register 0 from BER_REG0.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, QAM_BER_REG0, &BerReg0) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Get BER register 1 from BER_REG1.
+	// Note: The function GetRegBitsWithPage() will set register page automatically.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBitsWithPage(pDemod, QAM_BER_REG1, &BerReg1) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Set BER numerator and denominator.
+	*pBerNum = 27 * BerReg0 + BerReg1;
+	*pBerDen = 1632 * TestPacketNum;
+
+
+	// Set PER numerator and denominator.
+	*pPerNum = BerReg0;
+	*pPerDen = TestPacketNum;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+error_status_get_demod_registers:
+error_status_frame_lock:
+error_status_time_out:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_SNR_DB
+
+*/
+int
+rtl2840_GetSnrDb(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	)
+{
+	static const unsigned long SnrConstTable[QAM_QAM_MODE_NUM] =
+	{
+		26880,		// for    4-QAM mode
+		29852,		// for   16-QAM mode
+		31132,		// for   32-QAM mode
+		32502,		// for   64-QAM mode
+		33738,		// for  128-QAM mode
+		35084,		// for  256-QAM mode
+		36298,		// for  512-QAM mode
+		37649,		// for 1024-QAM mode
+	};
+
+	int QamMode;
+
+	unsigned long Mse;
+	long MiddleResult;
+	MPI MpiMse, MpiResult;
+
+
+
+	// Get demod QAM mode.
+	if(pDemod->GetQamMode(pDemod, &QamMode) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_qam_mode;
+
+
+	// Get mean-square error from MSE.
+	// Note: The function rtl2840_GetInnerStrobeRegBits() will set register page automatically.
+	if(rtl2840_GetInnerStrobeRegBits(pDemod, QAM_MSE, &Mse) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Calculate SNR dB numerator.
+	MpiSetValue(&MpiMse, Mse);
+	MpiLog2(&MpiResult, MpiMse, RTL2840_SNR_FRAC_BIT_NUM);
+	MpiGetValue(MpiResult, &MiddleResult);
+
+	*pSnrDbNum = SnrConstTable[QamMode] - 10 * MiddleResult;
+
+	
+	// Set SNR dB denominator.
+	*pSnrDbDen = RTL2840_SNR_DB_DEN;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_get_demod_qam_mode:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_SIGNAL_STRENGTH
+
+*/
+int
+rtl2840_GetSignalStrength(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalStrength
+	)
+{
+	int FrameLock;
+	long IfAgcValue;
+
+
+
+	// Get demod frame lock status.
+	if(pDemod->IsFrameLocked(pDemod, &FrameLock) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+	// If demod is not frame-locked, set signal strength with zero.
+	if(FrameLock == NO)
+	{
+		*pSignalStrength = 0;
+		goto success_status_non_frame_lock;
+	}
+
+
+	// Get IF AGC value.
+	if(pDemod->GetIfAgc(pDemod, &IfAgcValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Determine signal strength according to IF AGC value.
+	// Note: Map IF AGC value (1023 ~ -1024) to signal strength (0 ~ 100).
+	*pSignalStrength = (102300 - IfAgcValue * 100) / 2047;
+
+
+success_status_non_frame_lock:
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_SIGNAL_QUALITY
+
+*/
+int
+rtl2840_GetSignalQuality(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalQuality
+	)
+{
+	int FrameLock;
+
+	unsigned long Mse;
+	long MiddleResult;
+	MPI MpiMse, MpiResult;
+
+
+
+	// Get demod frame lock status.
+	if(pDemod->IsFrameLocked(pDemod, &FrameLock) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+	// If demod is not frame-locked, set signal quality with zero.
+	if(FrameLock == NO)
+	{
+		*pSignalQuality = 0;
+		goto success_status_non_frame_lock;
+	}
+
+
+	// Get mean-square error from MSE.
+	// Note: The function rtl2840_GetInnerStrobeRegBits() will set register page automatically.
+	if(rtl2840_GetInnerStrobeRegBits(pDemod, QAM_MSE, &Mse) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Determine signal quality according to MSE value.
+	// Note: Map MSE value (pow(2, 19) ~ pow(2, 17)) to signal quality (0 ~ 100).
+	//       If MSE value < pow(2, 17), signal quality is 100.
+	//       If MSE value > pow(2, 19), signal quality is 0.
+	if(Mse > 524288)
+	{
+		*pSignalQuality = 0;
+	}
+	else if(Mse < 131072)
+	{
+		*pSignalQuality = 100;
+	}
+	else
+	{
+		MpiSetValue(&MpiMse, Mse);
+		MpiLog2(&MpiResult, MpiMse, RTL2840_SIGNAL_QUALITY_FRAC_BIT_NUM);
+		MpiGetValue(MpiResult, &MiddleResult);
+
+		*pSignalQuality = (243200 - MiddleResult * 100) / 256;
+	}
+
+
+success_status_non_frame_lock:
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_UPDATE_FUNCTION
+
+*/
+int
+rtl2840_UpdateFunction(
+	QAM_DEMOD_MODULE *pDemod
+	)
+{
+	// RTL2840 does not use UpdateFunction(), so we just return FUNCTION_SUCCESS.
+	return FUNCTION_SUCCESS;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_RESET_FUNCTION
+
+*/
+int
+rtl2840_ResetFunction(
+	QAM_DEMOD_MODULE *pDemod
+	)
+{
+	// RTL2840 does not use UpdateFunction(), so we just return FUNCTION_SUCCESS.
+	return FUNCTION_SUCCESS;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_QAM_MODE
+
+*/
+int
+rtl2840_am_hum_en_SetQamMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int QamMode
+	)
+{
+	typedef struct
+	{
+		unsigned char PageNo;
+		unsigned char RegStartAddr;
+		unsigned char Msb;
+		unsigned char Lsb;
+		unsigned long WritingValue[QAM_QAM_MODE_NUM];
+	}
+	QAM_MODE_REG_ENTRY;
+
+
+	typedef struct
+	{
+		unsigned char SpecReg0Sel;
+		unsigned char SpecReg0ValueTable[QAM_QAM_MODE_NUM][RTL2840_SPEC_REG_0_VALUE_TABLE_LEN];
+	}
+	QAM_MODE_SPEC_REG_0_ENTRY;
+
+
+
+	static const QAM_MODE_REG_ENTRY QamModeRegTable[RTL2840_QAM_MODE_REG_TABLE_LEN] =
+	{
+		// Reg,									WritingValue according to QAM mode
+		// PageNo,	StartAddr,	Msb,	Lsb,	{4-Q,   16-Q,  32-Q,  64-Q,  128-Q, 256-Q, 512-Q, 1024-Q}
+		{1,			0x02,		2,		0,		{0x7,   0x0,   0x1,   0x2,   0x3,   0x4,   0x5,   0x6	}},
+		{1,			0x2f,		15,		5,		{0x37,  0x82,  0xb9,  0x10e, 0x177, 0x21c, 0x2ee, 0x451	}},
+		{1,			0x31,		5,		0,		{0x1,   0x3,   0x4,   0x5,   0x8,   0xa,   0xf,   0x14	}},
+		{1,			0x2e,		5,		0,		{0x2,   0x4,   0x6,   0x8,   0xc,   0x10,  0x18,  0x20	}},
+		{1,			0x18,		7,		0,		{0x0,   0xdb,  0x79,  0x0,   0x8a,  0x0,   0x8c,  0x0	}},
+		{1,			0x19,		4,		0,		{0x14,  0x14,  0xf,   0x14,  0xf,   0x14,  0xf,   0x14  }},
+		{1,			0x3b,		2,		0,		{0x0,   0x0,   0x0,   0x0,   0x0,   0x0,   0x1,   0x1	}},
+		{1,			0x3b,		5,		3,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3c,		2,		0,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3c,		4,		3,		{0x0,   0x0,   0x0,   0x0,   0x0,   0x0,   0x1,   0x1	}},
+		{1,			0x3c,		6,		5,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3d,		1,		0,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3d,		3,		2,		{0x0,   0x0,   0x0,   0x0,   0x0,   0x0,   0x1,   0x1	}},
+		{1,			0x3d,		5,		4,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x3d,		7,		6,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x41,		4,		3,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x1	}},
+		{1,			0x41,		6,		5,		{0x2,   0x2,   0x2,   0x2,   0x2,   0x2,   0x2,   0x2	}},
+		{1,			0x42,		1,		0,		{0x3,   0x3,   0x3,   0x3,   0x3,   0x3,   0x3,   0x3	}},
+		{1,			0x42,		3,		2,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x1	}},
+		{1,			0x42,		5,		4,		{0x2,   0x2,   0x2,   0x2,   0x2,   0x2,   0x2,   0x2	}},
+		{1,			0x42,		7,		6,		{0x3,   0x3,   0x3,   0x3,   0x3,   0x3,   0x3,   0x3	}},
+
+
+		// For AM-hum enhancement
+		// Reg,									WritingValue according to QAM mode
+		// PageNo,	StartAddr,	Msb,	Lsb,	{4-Q,   16-Q,  32-Q,  64-Q,  128-Q, 256-Q, 512-Q, 1024-Q}
+		{1,			0x05,		7,		0,		{0x64,  0x64,  0x64,  0x64,  0x6b,  0x6b,  0x6b,  0x6b  }},
+		{1,			0x40,		2,		0,		{0x1,   0x1,   0x1,   0x1,   0x1,   0x1,   0x2,   0x2	}},
+		{1,			0x40,		5,		3,		{0x1,   0x1,   0x1,   0x1,   0x2,   0x2,   0x3,   0x3	}},
+		{1,			0x41,		2,		0,		{0x0,   0x0,   0x0,   0x0,   0x3,   0x3,   0x4,   0x4	}},
+	};
+
+
+	static const QAM_MODE_SPEC_REG_0_ENTRY QamModeSpecReg0Table[RTL2840_QAM_MODE_SPEC_REG_0_TABLE_LEN] =
+	{
+		// SpecReg0Sel,		{SpecReg0ValueTable                                              }		   QAM mode
+		{9,				{	{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},		// 4-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},		// 16-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x10, 0x70, 0x80, 0xfa, 0xcb, 0x00},		// 32-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},		// 64-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x10, 0x70, 0x80, 0xfa, 0xcb, 0x00},		// 128-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},		// 256-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x10, 0x70, 0x80, 0xfa, 0xcb, 0x00},		// 512-QAM
+							{0x99, 0xa9, 0xc9, 0x4e, 0x48, 0x20, 0x71, 0x80, 0xfa, 0xcb, 0x00},	}	// 1024-QAM
+		},
+
+
+		// SpecReg0Sel,		{SpecReg0ValueTable                                              }		   QAM mode
+		{10,			{	{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x20, 0x71, 0xa0, 0xfa, 0xcb, 0x00},		// 4-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x20, 0x71, 0xa0, 0xfa, 0xcb, 0x00},		// 16-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x10, 0x70, 0xa0, 0xfa, 0xcb, 0x00},		// 32-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x20, 0x71, 0xa0, 0xfa, 0xcb, 0x00},		// 64-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x10, 0x70, 0xa0, 0xfa, 0xcb, 0x00},		// 128-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x20, 0x71, 0xa0, 0xfa, 0xcb, 0x00},		// 256-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x10, 0x70, 0xa0, 0xfa, 0xcb, 0x00},		// 512-QAM
+							{0xaa, 0xbb, 0xee, 0x5e, 0x48, 0x10, 0x70, 0xa0, 0xfa, 0xcb, 0x00},	}	// 1024-QAM
+		},
+
+
+
+		// For AM-hum enhancement
+		// SpecReg0Sel,		{SpecReg0ValueTable                                              }		   QAM mode
+		{12,			{	{0xc8, 0xcc, 0x40, 0x7e, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 4-QAM
+							{0xc8, 0xcc, 0x40, 0x7e, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 16-QAM
+							{0xc8, 0xcc, 0x40, 0x7e, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 32-QAM
+							{0xc8, 0xcc, 0x40, 0x7e, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 64-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 128-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 256-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},		// 512-QAM
+							{0xc8, 0xcc, 0x00, 0x7f, 0x28, 0xda, 0x4b, 0xa0, 0xfe, 0xcd, 0x01},	}	// 1024-QAM
+		},
+	};
+
+
+	int i;
+
+	unsigned char PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+	unsigned long WritingValue;
+
+	unsigned char SpecReg0Sel;
+	const unsigned char *pSpecReg0ValueTable;
+
+
+
+	// Set demod QAM mode with QAM mode register setting table.
+	for(i = 0; i < RTL2840_QAM_MODE_REG_TABLE_LEN; i++)
+	{
+		// Get all information from each register setting entry according to QAM mode.
+		PageNo       = QamModeRegTable[i].PageNo;
+		RegStartAddr = QamModeRegTable[i].RegStartAddr;
+		Msb          = QamModeRegTable[i].Msb;
+		Lsb          = QamModeRegTable[i].Lsb;
+		WritingValue = QamModeRegTable[i].WritingValue[QamMode];
+
+		// Set register page number.
+		if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set register mask bits.
+		if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, WritingValue) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Set register page number with inner page number for QAM mode specific register 0 setting.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 1) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+	// Set demod QAM mode with QAM mode specific register 0 setting table.
+	for(i = 0; i < RTL2840_QAM_MODE_SPEC_REG_0_TABLE_LEN; i++)
+	{
+		// Get all information from each specific register 0 setting entry according to QAM mode.
+		SpecReg0Sel         = QamModeSpecReg0Table[i].SpecReg0Sel;
+		pSpecReg0ValueTable = QamModeSpecReg0Table[i].SpecReg0ValueTable[QamMode];
+
+		// Set specific register 0 selection.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_REG_0_SEL, SpecReg0Sel) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set specific register 0 values.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBytes(pDemod, RTL2840_SPEC_REG_0_VAL_START_ADDR, pSpecReg0ValueTable, LEN_11_BYTE) != 
+			FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+
+		// Set specific register 0 strobe.
+		// Note: RTL2840 hardware will clear strobe automatically.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_SPEC_REG_0_STROBE, ON) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Set demod QAM mode parameter.
+	pDemod->QamMode      = QamMode;
+	pDemod->IsQamModeSet = YES;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   I2C_BRIDGE_FP_FORWARD_I2C_READING_CMD
+
+*/
+int
+rtl2840_ForwardI2cReadingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+
+
+	// Get demod module and tuner device address.
+	pDemod = (QAM_DEMOD_MODULE *)pI2cBridge->pPrivateData;
+
+	
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Enable demod I2C relay.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_OPT_I2C_RELAY, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Send I2C reading command.
+	if(pBaseInterface->I2cRead(pBaseInterface, DeviceAddr, pReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_send_i2c_reading_command;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_send_i2c_reading_command:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   I2C_BRIDGE_FP_FORWARD_I2C_WRITING_CMD
+
+*/
+int
+rtl2840_ForwardI2cWritingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+
+
+	// Get demod module and tuner device address.
+	pDemod = (QAM_DEMOD_MODULE *)pI2cBridge->pPrivateData;
+
+	
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Enable demod I2C relay.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_OPT_I2C_RELAY, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Send I2C writing command.
+	if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, pWritingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_send_i2c_writing_command;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_send_i2c_writing_command:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Initialize base register table
+
+RTL2840 builder will use rtl2840_InitBaseRegTable() to initialize base register table.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@see   BuildRtl2840Module()
+
+*/
+void
+rtl2840_InitBaseRegTable(
+	QAM_DEMOD_MODULE *pDemod
+	)
+{
+	static const QAM_PRIMARY_BASE_REG_ENTRY_ADDR_8BIT PrimaryBaseRegTable[RTL2840_BASE_REG_TABLE_LEN] =
+	{
+		// Generality
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_SYS_VERSION,					0,			0x01,			7,		0	},
+		{QAM_OPT_I2C_RELAY,					0,			0x03,			5,		5	},
+		{QAM_SOFT_RESET,					0,			0x09,			0,		0	},
+
+		// Miscellany
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_OPT_I2C_DRIVE_CURRENT,			0,			0x07,			7,		7	},
+		{QAM_GPIO2_OEN,						0,			0x05,			6,		6	},
+		{QAM_GPIO3_OEN,						0,			0x05,			7,		7	},
+		{QAM_GPIO2_O,						0,			0x0a,			2,		2	},
+		{QAM_GPIO3_O,						0,			0x0a,			3,		3	},
+		{QAM_GPIO2_I,						0,			0x0a,			6,		6	},
+		{QAM_GPIO3_I,						0,			0x0a,			7,		7	},
+		{QAM_INNER_DATA_STROBE,				1,			0x69,			0,		0	},
+		{QAM_INNER_DATA_SEL1,				1,			0x48,			7,		0	},
+		{QAM_INNER_DATA_SEL2,				1,			0x49,			7,		0	},
+		{QAM_INNER_DATA1,					1,			0x6a,			15,		0	},
+		{QAM_INNER_DATA2,					1,			0x6c,			15,		0	},
+
+		// QAM mode
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_QAM_MODE,						1,			0x02,			2,		0	},
+
+		// AD
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_AD_AV,							0,			0x0b,			2,		0	},
+
+		// AAGC
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_OPT_RF_AAGC_DRIVE_CURRENT,		0,			0x07,			0,		0	},
+		{QAM_OPT_IF_AAGC_DRIVE_CURRENT,		0,			0x07,			1,		1	},
+		{QAM_OPT_RF_AAGC_DRIVE,				0,			0x04,			3,		3	},
+		{QAM_OPT_IF_AAGC_DRIVE,				0,			0x04,			4,		4	},
+		{QAM_OPT_RF_AAGC_OEN,				0,			0x04,			6,		6	},
+		{QAM_OPT_IF_AAGC_OEN,				0,			0x04,			7,		7	},
+		{QAM_PAR_RF_SD_IB,					0,			0x03,			0,		0	},
+		{QAM_PAR_IF_SD_IB,					0,			0x03,			1,		1	},
+		{QAM_AAGC_FZ_OPTION,				1,			0x04,			5,		4	},
+		{QAM_AAGC_TARGET,					1,			0x05,			7,		0	},
+		{QAM_RF_AAGC_MAX,					1,			0x06,			7,		0	},
+		{QAM_RF_AAGC_MIN,					1,			0x07,			7,		0	},
+		{QAM_IF_AAGC_MAX,					1,			0x08,			7,		0	},
+		{QAM_IF_AAGC_MIN,					1,			0x09,			7,		0	},
+		{QAM_VTOP,							1,			0x0b,			7,		0	},
+		{QAM_KRF_MSB,						1,			0x0c,			6,		3	},
+		{QAM_KRF_LSB,						1,			0x04,			7,		6	},
+		{QAM_AAGC_MODE_SEL,					1,			0x0c,			7,		7	},
+		{QAM_AAGC_LD,						1,			0x72,			0,		0	},
+		{QAM_AAGC_INIT_LEVEL,				1,			0x0a,			7,		0	},
+
+		// DDC
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_DDC_FREQ,						1,			0x0d,			14,		0	},
+		{QAM_SPEC_INV,						1,			0x0e,			7,		7	},
+
+		// Timing recovery
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_TR_DECI_RATIO,					1,			0x1f,			23,		0	},
+
+		// Carrier recovery
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_CR_LD,							1,			0x74,			5,		0	},
+
+		// Equalizer
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_EQ_LD,							1,			0x72,			1,		1	},
+		{QAM_MSE,							1,			0x76,			21,		0	},
+
+		// Frame sync. indicator
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_SYNCLOST,						2,			0x02,			7,		7	},
+
+		// BER
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_BER_RD_STROBE,					2,			0x05,			7,		7	},
+		{QAM_BERT_EN,						2,			0x06,			0,		0	},
+		{QAM_BERT_HOLD,						2,			0x06,			1,		1	},
+		{QAM_DIS_AUTO_MODE,					2,			0x06,			2,		2	},
+		{QAM_TEST_VOLUME,					2,			0x06,			5,		3	},
+		{QAM_BER_REG0,						2,			0x0e,			15,		0	},
+		{QAM_BER_REG1,						2,			0x07,			20,		0	},
+		{QAM_BER_REG2_15_0,					2,			0x0a,			15,		0	},
+		{QAM_BER_REG2_18_16,				2,			0x09,			7,		5	},
+
+		// MPEG TS output interface
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_CKOUTPAR,						2,			0x11,			0,		0	},
+		{QAM_CKOUT_PWR,						2,			0x11,			1,		1	},
+		{QAM_CDIV_PH0,						2,			0x12,			3,		0	},
+		{QAM_CDIV_PH1,						2,			0x12,			7,		4	},
+		{QAM_MPEG_OUT_EN,					0,			0x04,			5,		5	},
+		{QAM_OPT_MPEG_DRIVE_CURRENT,		0,			0x07,			2,		2	},
+		{QAM_NO_REINVERT,					2,			0x10,			2,		2	},
+		{QAM_FIX_TEI,						2,			0x10,			3,		3	},
+		{QAM_SERIAL,						2,			0x11,			2,		2	},
+
+		// Monitor
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_ADC_CLIP_CNT_REC,				1,			0x6a,			15,		4	},
+		{QAM_DAGC_LEVEL_26_11,				1,			0x6a,			15,		0	},
+		{QAM_DAGC_LEVEL_10_0,				1,			0x6c,			15,		5	},
+		{QAM_RF_AAGC_SD_IN,					1,			0x6a,			15,		5	},
+		{QAM_IF_AAGC_SD_IN,					1,			0x6c,			15,		5	},
+		{QAM_KI_TR_OUT_30_15,				1,			0x6a,			15,		0	},
+		{QAM_KI_TR_OUT_14_0,				1,			0x6c,			15,		1	},
+		{QAM_KI_CR_OUT_15_0,				1,			0x6a,			15,		0	},
+		{QAM_KI_CR_OUT_31_16,				1,			0x6c,			15,		0	},
+
+		// Specific register
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_SPEC_SIGNAL_INDICATOR,			1,			0x73,			5,		3	},
+		{QAM_SPEC_ALPHA_STROBE,				1,			0x57,			0,		0	},
+		{QAM_SPEC_ALPHA_SEL,				1,			0x57,			4,		1	},
+		{QAM_SPEC_ALPHA_VAL,				1,			0x57,			14,		5	},
+		{QAM_SPEC_SYMBOL_RATE_REG_0,		1,			0x0f,			2,		0	},
+		{QAM_SPEC_SYMBOL_RATE_STROBE,		1,			0x5b,			0,		0	},
+		{QAM_SPEC_SYMBOL_RATE_SEL,			1,			0x5b,			4,		1	},
+		{QAM_SPEC_SYMBOL_RATE_VAL,			1,			0x5b,			14,		5	},
+		{QAM_SPEC_REG_0_STROBE,				1,			0x5d,			0,		0	},
+		{QAM_SPEC_REG_0_SEL,				1,			0x5d,			4,		1	},
+
+		// Specific register for initialization
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_SPEC_INIT_A0,					1,			0x6a,			15,		6	},
+		{QAM_SPEC_INIT_A1,					0,			0x0f,			0,		0	},
+		{QAM_SPEC_INIT_A2,					1,			0x2b,			1,		1	},
+
+		// Pseudo register for test only
+		// RegBitName,						PageNo,		RegStartAddr,	Msb,	Lsb
+		{QAM_TEST_REG_0,					1,			0x17,			6,		2	},
+		{QAM_TEST_REG_1,					1,			0x17,			14,		1	},
+		{QAM_TEST_REG_2,					1,			0x17,			21,		3	},
+		{QAM_TEST_REG_3,					1,			0x17,			30,		2	},
+	};
+
+
+	int i;
+	int RegBitName;
+
+
+
+	// Initialize base register table according to primary base register table.
+	// Note: 1. Base register table rows are sorted by register bit name key.
+	//       2. The default value of the IsAvailable variable is "NO".
+	for(i = 0; i < QAM_BASE_REG_TABLE_LEN_MAX; i++)
+		pDemod->BaseRegTable.Addr8Bit[i].IsAvailable  = NO;
+
+	for(i = 0; i < RTL2840_BASE_REG_TABLE_LEN; i++)
+	{
+		RegBitName = PrimaryBaseRegTable[i].RegBitName;
+
+		pDemod->BaseRegTable.Addr8Bit[RegBitName].IsAvailable  = YES;
+		pDemod->BaseRegTable.Addr8Bit[RegBitName].PageNo       = PrimaryBaseRegTable[i].PageNo;
+		pDemod->BaseRegTable.Addr8Bit[RegBitName].RegStartAddr = PrimaryBaseRegTable[i].RegStartAddr;
+		pDemod->BaseRegTable.Addr8Bit[RegBitName].Msb          = PrimaryBaseRegTable[i].Msb;
+		pDemod->BaseRegTable.Addr8Bit[RegBitName].Lsb          = PrimaryBaseRegTable[i].Lsb;
+	}
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Initialize monitor register table
+
+RTL2840 builder will use rtl2840_InitMonitorRegTable() to initialize monitor register table.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@see   BuildRtl2840Module()
+
+*/
+void
+rtl2840_InitMonitorRegTable(
+	QAM_DEMOD_MODULE *pDemod
+	)
+{
+	static const QAM_PRIMARY_MONITOR_REG_ENTRY_ADDR_8BIT PrimaryMonitorRegTable[RTL2840_MONITOR_REG_TABLE_LEN] =
+	{
+		// Generality
+		// MonitorRegBitName,		InfoNum,		{SelRegAddr,	SelValue,	RegBitName,				Shift	}
+		{QAM_ADC_CLIP_CNT,			1,			{	{0x48,			0x01,		QAM_ADC_CLIP_CNT_REC,	0		},
+													{NO_USE,		NO_USE,		NO_USE,					NO_USE	},	}},
+
+		{QAM_DAGC_VALUE,			2,			{	{0x48,			0x20,		QAM_DAGC_LEVEL_26_11,	11		},
+													{0x49,			0x20,		QAM_DAGC_LEVEL_10_0,	0		},	}},
+
+		{QAM_RF_AGC_VALUE,			1,			{	{0x48,			0x80,		QAM_RF_AAGC_SD_IN,		0		},
+													{NO_USE,		NO_USE,		NO_USE,					NO_USE	},	}},
+
+		{QAM_IF_AGC_VALUE,			1,			{	{0x49,			0x80,		QAM_IF_AAGC_SD_IN,		0		},
+													{NO_USE,		NO_USE,		NO_USE,					NO_USE	},	}},
+
+		{QAM_TR_OFFSET,				2,			{	{0x48,			0xc2,		QAM_KI_TR_OUT_30_15,	15		},
+													{0x49,			0xc2,		QAM_KI_TR_OUT_14_0,		0		},	}},
+
+		{QAM_CR_OFFSET,				2,			{	{0x48,			0xc3,		QAM_KI_CR_OUT_15_0,		0		},
+													{0x49,			0xc3,		QAM_KI_CR_OUT_31_16,	16		},	}},
+
+		// Specific monitor register for initialization
+		// MonitorRegBitName,		InfoNum,		{SelRegAddr,	SelValue,	RegBitName,				Shift	}
+		{QAM_SPEC_MONITER_INIT_0,	1,			{	{0x48,			0x00,		QAM_SPEC_INIT_A0,		0		},
+													{NO_USE,		NO_USE,		NO_USE,					NO_USE	},	}},
+	};
+
+
+	int i, j;
+	int MonitorRegBitName;
+
+
+
+	// Initialize monitor register table according to primary monitor register table.
+	// Note: 1. Monitor register table rows are sorted by monitor register name key.
+	//       2. The default value of the IsAvailable variable is "NO".
+	for(i = 0; i < QAM_MONITOR_REG_TABLE_LEN_MAX; i++)
+		pDemod->MonitorRegTable.Addr8Bit[i].IsAvailable  = NO;
+
+	for(i = 0; i < RTL2840_MONITOR_REG_TABLE_LEN; i++)
+	{
+		MonitorRegBitName = PrimaryMonitorRegTable[i].MonitorRegBitName;
+
+		pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].IsAvailable = YES;
+		pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoNum = PrimaryMonitorRegTable[i].InfoNum;
+
+		for(j = 0; j < QAM_MONITOR_REG_INFO_TABLE_LEN; j++)
+		{
+			pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoTable[j].SelRegAddr =
+				PrimaryMonitorRegTable[i].InfoTable[j].SelRegAddr;
+			pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoTable[j].SelValue =
+				PrimaryMonitorRegTable[i].InfoTable[j].SelValue;
+			pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoTable[j].RegBitName =
+				PrimaryMonitorRegTable[i].InfoTable[j].RegBitName;
+			pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoTable[j].Shift =
+				PrimaryMonitorRegTable[i].InfoTable[j].Shift;
+		}
+	}
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Get inner strobe register bits.
+
+RTL2840 upper level functions will use rtl2840_GetInnerStrobeRegBits() to get register bits with inner strobe.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegBitName      Pre-defined demod register bit name
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bits successfully with bit name and inner strobe.
+@retval   FUNCTION_ERROR     Get demod register bits unsuccessfully.
+
+
+@note
+	-# Don't need to set register page before using rtl2840_GetInnerStrobeRegBits().
+
+*/
+int
+rtl2840_GetInnerStrobeRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	// Set register page number with inner page number.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 1) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set inner data strobe.
+	// Note: RTL2840 hardware will clear strobe automatically.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_INNER_DATA_STROBE, ON) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Get the inner strobe register bits.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBits(pDemod, RegBitName, pReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Get monitor register bits.
+
+RTL2840 upper level functions will use rtl2840_GetMonitorRegBits() to get monitor register bits.
+
+
+@param [in]    pDemod              The demod module pointer
+@param [in]    MonitorRegBitName   Pre-defined demod monitor register bit name
+@param [out]   pReadingValue       Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod monitor register bits successfully with monitor bit name.
+@retval   FUNCTION_ERROR     Get demod monitor register bits unsuccessfully.
+
+
+@note
+	-# Don't need to set register page before using rtl2840_GetMonitorRegBits().
+
+*/
+int
+rtl2840_GetMonitorRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int MonitorRegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	int i;
+
+	unsigned char InfoNum;
+	unsigned char SelRegAddr;
+	unsigned char SelValue;
+	int RegBitName;
+	unsigned char Shift;
+	
+	unsigned long Buffer[QAM_MONITOR_REG_INFO_TABLE_LEN];
+
+
+
+	// Check if register bit name is available.
+	if(pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].IsAvailable == NO)
+		goto error_status_monitor_register_bit_name;
+
+
+	// Get information entry number from monitor register table by monitor register name key.
+	InfoNum = pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoNum;
+
+
+	// Set register page number with inner page number.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, 1) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set selection register with selection value for each information entry.
+	for(i = 0; i < InfoNum; i++)
+	{
+		// Get selection register address and value from information entry by monitor register name key.
+		SelRegAddr = pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoTable[i].SelRegAddr;
+		SelValue   = pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoTable[i].SelValue;
+
+		// Set selection register with selection value.
+		if(pDemod->RegAccess.Addr8Bit.SetRegBytes(pDemod, SelRegAddr, &SelValue, LEN_1_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	// Set inner data strobe.
+	// Note: RTL2840 hardware will clear strobe automatically.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, QAM_INNER_DATA_STROBE, ON) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Get register bits to buffer according to register bit names for each information entry.
+	for(i = 0; i < InfoNum; i++)
+	{
+		// Get register bit name from information entry by monitor register name key.
+		RegBitName = pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoTable[i].RegBitName;
+
+		// Get register bits and store it to buffer.
+		if(pDemod->RegAccess.Addr8Bit.GetRegBits(pDemod, RegBitName, &Buffer[i]) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+	}
+
+
+	// Combine the buffer values into reading value.
+	*pReadingValue = 0;
+
+	for(i = 0; i < InfoNum; i++)
+	{
+		// Get shift from information entry by monitor register name key.
+		Shift = pDemod->MonitorRegTable.Addr8Bit[MonitorRegBitName].InfoTable[i].Shift;
+
+		// Combine the buffer values into reading value with shift.
+		*pReadingValue |= Buffer[i] << Shift;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+error_status_get_demod_registers:
+error_status_monitor_register_bit_name:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Set I2C bridge module demod arguments.
+
+RTL2840 builder will use rtl2840_BuildI2cBridgeModule() to set I2C bridge module demod arguments.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@see   BuildRtl2840Module()
+
+*/
+void
+rtl2840_BuildI2cBridgeModule(
+	QAM_DEMOD_MODULE *pDemod
+	)
+{
+	I2C_BRIDGE_MODULE *pI2cBridge;
+
+
+
+	// Get I2C bridge module.
+	pI2cBridge = pDemod->pI2cBridge;
+
+	// Set I2C bridge module demod arguments.
+	pI2cBridge->pPrivateData = (void *)pDemod;
+	pI2cBridge->ForwardI2cReadingCmd = rtl2840_ForwardI2cReadingCmd;
+	pI2cBridge->ForwardI2cWritingCmd = rtl2840_ForwardI2cWritingCmd;
+
+
+	return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/demod_rtl2840.h b/drivers/media/usb/dvb-usb/demod_rtl2840.h
new file mode 100644
index 0000000..16f4723
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/demod_rtl2840.h
@@ -0,0 +1,386 @@
+#ifndef __DEMOD_RTL2840_H
+#define __DEMOD_RTL2840_H
+
+/**
+
+@file
+
+@brief   RTL2840 QAM demod module declaration
+
+One can manipulate RTL2840 QAM demod through RTL2840 module.
+RTL2840 module is derived from QAM demod module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the QAM demod example in qam_demod_base.h except the listed lines.
+
+
+
+#include "demod_rtl2840.h"
+
+
+...
+
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+
+	QAM_DEMOD_MODULE      QamDemodModuleMemory;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+	I2C_BRIDGE_MODULE     I2cBridgeModuleMemory;
+
+
+	...
+
+
+
+	// Build RTL2840 demod module.
+	BuildRtl2840Module(
+		&pDemod,
+		&QamDemodModuleMemory,
+		&BaseInterfaceModuleMemory,
+		&I2cBridgeModuleMemory,
+		0x44,								// I2C device address is 0x44 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,			// Crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,				// TS interface mode is serial.
+		QAM_DEMOD_EN_AM_HUM					// Enhancement mode is AM-hum.
+		);
+
+
+
+	// See the example for other QAM demod functions in qam_demod_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "qam_demod_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2840_BASE_REG_TABLE_LEN				88
+#define RTL2840_MONITOR_REG_TABLE_LEN			7
+
+#define RTL2840_PAGE_REG_ADDR					0x0
+#define RTL2840_SYS_VERSION_VALUE				0xa3
+
+
+
+// Specific register
+#define RTL2840_SPEC_REG_0_VAL_START_ADDR		0x5e
+
+
+
+// Initialization
+#define RTL2840_SPEC_MONITOR_INIT_0_COMPARISON_TIMES		30
+
+// RF_AGC_VALUE register
+#define RTL2840_RF_AGC_VALUE_BIT_NUM		11
+
+// IF_AGC_VALUE register
+#define RTL2840_IF_AGC_VALUE_BIT_NUM		11
+
+// CR_OFFSET register
+#define RTL2840_CR_OFFSET_BIT_NUM			32
+
+// TR_OFFSET register
+#define RTL2840_TR_OFFSET_BIT_NUM			31
+
+
+
+// BER and UPER
+#define RTL2840_BER_WAIT_TIME_MS			10
+#define RTL2840_BER_REG2_MSB_SHIFT			16
+
+// SNR
+// Note: RTL2840_SNR_DB_DEN = round(log2(10) * pow(2, RTL2840_SNR_FRAC_BIT_NUM))
+#define RTL2840_SNR_FRAC_BIT_NUM			7
+#define RTL2840_SNR_DB_DEN					425
+
+
+
+// Singal strength and signal quality
+#define RTL2840_SIGNAL_QUALITY_FRAC_BIT_NUM			7
+
+
+
+
+
+// Table length
+#define RTL2840_SPEC_REG_0_VALUE_TABLE_LEN						11
+#define RTL2840_SYMBOL_RATE_VALUE_TABLE_LEN						9
+
+#define RTL2840_INIT_REG_TABLE_LEN								45
+#define RTL2840_INIT_SPEC_REG_0_TABLE_LEN						13
+#define RTL2840_TS_INTERFACE_INIT_TABLE_LEN						3
+
+#define RTL2840_QAM_MODE_REG_TABLE_LEN							25
+#define RTL2840_QAM_MODE_SPEC_REG_0_TABLE_LEN					3
+
+#define RTL2840_ALPHA_VALUE_TABLE_LEN							16
+
+#define RTL2840_SYMBOL_RATE_TABLE_LEN							3
+
+
+
+
+
+// Builder
+void
+BuildRtl2840Module(
+	QAM_DEMOD_MODULE **ppDemod,
+	QAM_DEMOD_MODULE *pQamDemodModuleMemory,
+	BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory,
+	I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory,
+	unsigned char DeviceAddr,
+	unsigned long CrystalFreqHz,
+	int TsInterfaceMode,
+	int EnhancementMode
+	);
+
+
+
+
+
+// Manipulaing functions
+void
+rtl2840_IsConnectedToI2c(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+int
+rtl2840_SoftwareReset(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2840_Initialize(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2840_SetQamMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int QamMode
+	);
+
+int
+rtl2840_SetSymbolRateHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long SymbolRateHz
+	);
+
+int
+rtl2840_SetAlphaMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int AlphaMode
+	);
+
+int
+rtl2840_SetIfFreqHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long IfFreqHz
+	);
+
+int
+rtl2840_SetSpectrumMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int SpectrumMode
+	);
+
+int
+rtl2840_GetRfAgc(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pRfAgc
+	);
+
+int
+rtl2840_GetIfAgc(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pIfAgc
+	);
+
+int
+rtl2840_GetDiAgc(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pDiAgc
+	);
+
+int
+rtl2840_GetTrOffsetPpm(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pTrOffsetPpm
+	);
+
+int
+rtl2840_GetCrOffsetHz(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pCrOffsetHz
+	);
+
+int
+rtl2840_IsAagcLocked(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+int
+rtl2840_IsEqLocked(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+int
+rtl2840_IsFrameLocked(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+int
+rtl2840_GetErrorRate(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long TestVolume,
+	unsigned int WaitTimeMsMax,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	);
+
+int
+rtl2840_GetSnrDb(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+int
+rtl2840_GetSignalStrength(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalStrength
+	);
+
+int
+rtl2840_GetSignalQuality(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalQuality
+	);
+
+int
+rtl2840_UpdateFunction(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+int
+rtl2840_ResetFunction(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+// Demod AM-hum enhancement functions
+int
+rtl2840_am_hum_en_SetQamMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int QamMode
+	);
+
+
+
+
+
+// I2C command forwarding functions
+int
+rtl2840_ForwardI2cReadingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+int
+rtl2840_ForwardI2cWritingCmd(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+// Register table initialization
+void
+rtl2840_InitBaseRegTable(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+void
+rtl2840_InitMonitorRegTable(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+// Register getting methods	
+int
+rtl2840_GetInnerStrobeRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+int
+rtl2840_GetMonitorRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int MonitorRegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+// I2C birdge module builder
+void
+rtl2840_BuildI2cBridgeModule(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/dtmb_demod_base.c b/drivers/media/usb/dvb-usb/dtmb_demod_base.c
new file mode 100644
index 0000000..b0de54a
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/dtmb_demod_base.c
@@ -0,0 +1,1566 @@
+/**
+
+@file
+
+@brief   DTMB demod default function definition
+
+DTMB demod default functions.
+
+*/
+#include "rtl2832u_io.h"
+#include "dtmb_demod_base.h"
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_REG_PAGE
+
+*/
+int
+dtmb_demod_addr_8bit_default_SetRegPage(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long PageNo
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBytes[LEN_2_BYTE];
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Set demod register page with page number.
+	// Note: The I2C format of demod register page setting is as follows:
+	//       start_bit + (DeviceAddr | writing_bit) + DTMB_DEMOD_PAGE_REG_ADDR + PageNo + stop_bit
+	WritingBytes[0] = DTMB_DEMOD_PAGE_REG_ADDR;
+	WritingBytes[1] = (unsigned char)PageNo;
+
+	if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBytes, LEN_2_BYTE) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+	// temp, because page register is write-only.
+	pDemod->CurrentPageNo = PageNo;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+// Internal function:
+// Set register bytes separately.
+int
+internal_dtmb_demod_addr_8bit_SetRegBytesSeparately(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+#if 0
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBuffer[LEN_2_BYTE];
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Set demod register bytes with writing bytes.
+	// Note: Set demod register bytes one by one.
+	for(i = 0; i < ByteNum; i++)
+	{
+		// Set writing buffer.
+		// Note: The I2C format of demod register byte setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegWritingAddr + writing_bytes (WritingByteNum bytes) + stop_bit
+		WritingBuffer[0] = (unsigned char)(RegStartAddr + i);
+		WritingBuffer[1] = pWritingBytes[i];
+
+		// Set demod register bytes with writing buffer.
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, LEN_2_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+#endif
+	BASE_INTERFACE_MODULE *pBaseInterface;
+        struct dvb_usb_device	*d;
+	unsigned int i;
+	unsigned char DeviceAddr;
+	//unsigned char WritingBuffer[LEN_2_BYTE];
+	
+	unsigned long PageNo = pDemod->CurrentPageNo;
+		
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+	// Get user defined data pointer of base interface structure for context.
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);
+	
+	
+	// Set demod register bytes with writing bytes.
+	// Note: Set demod register bytes one by one.
+	for(i = 0; i < ByteNum; i++)
+	{
+
+		// Set demod register bytes with writing buffer.
+			if(write_demod_register(d, DeviceAddr, PageNo,  RegStartAddr+i,  (unsigned char*)pWritingBytes+i, LEN_1_BYTE))
+			goto error_status_set_demod_registers;	
+	
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+// Internal function:
+// Set register bytes continuously.
+int
+internal_dtmb_demod_addr_8bit_SetRegBytesContinuously(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i, j;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBuffer[I2C_BUFFER_LEN];
+	unsigned long WritingByteNum, WritingByteNumMax, WritingByteNumRem;
+	unsigned char RegWritingAddr;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum writing byte number.
+	WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax - LEN_1_BYTE;
+
+
+	// Set demod register bytes with writing bytes.
+	// Note: Set demod register bytes considering maximum writing byte number.
+	for(i = 0; i < ByteNum; i += WritingByteNumMax)
+	{
+		// Set register writing address.
+		RegWritingAddr = (unsigned char)(RegStartAddr + i);
+
+		// Calculate remainder writing byte number.
+		WritingByteNumRem = ByteNum - i;
+
+		// Determine writing byte number.
+		WritingByteNum = (WritingByteNumRem > WritingByteNumMax) ? WritingByteNumMax : WritingByteNumRem;
+
+
+		// Set writing buffer.
+		// Note: The I2C format of demod register byte setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegWritingAddr + writing_bytes (WritingByteNum bytes) + stop_bit
+		WritingBuffer[0] = RegWritingAddr;
+
+		for(j = 0; j < WritingByteNum; j++)
+			WritingBuffer[LEN_1_BYTE + j] = pWritingBytes[i + j];
+
+
+		// Set demod register bytes with writing buffer.
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, WritingByteNum + LEN_1_BYTE) !=
+			FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_REG_BYTES
+
+*/
+int
+dtmb_demod_addr_8bit_default_SetRegBytes(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	unsigned long CurrentPageNo;		// temp, because page register is write-only.
+
+
+
+	// Get page register number.
+	CurrentPageNo = pDemod->CurrentPageNo;		// temp, because page register is write-only.
+
+
+	// Set register bytes according to page register number.
+	switch(CurrentPageNo)
+	{
+		case 0:
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+
+			if(internal_dtmb_demod_addr_8bit_SetRegBytesSeparately(pDemod, RegStartAddr, pWritingBytes, ByteNum) != FUNCTION_SUCCESS)
+				goto error_status_set_demod_registers;
+
+			break;
+
+
+		default:
+			
+			goto error_status_set_demod_registers;
+			
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+// Internal function:
+// Get register bytes separately.
+int
+internal_dtmb_demod_addr_8bit_GetRegBytesSeparately(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+#if 0
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i;
+
+	unsigned char DeviceAddr;
+	unsigned char RegAddr;
+	unsigned char RegByte;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Get demod register bytes.
+	// Note: Get demod register bytes one by one.
+	for(i = 0; i < ByteNum; i++)
+	{
+		// Set demod register reading address.
+		// Note: The I2C format of demod register reading address setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegReadingAddr + stop_bit
+		RegAddr = (unsigned char)(RegStartAddr + i);
+
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, &RegAddr, LEN_1_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_register_reading_address;
+
+		// Get demod register bytes.
+		// Note: The I2C format of demod register byte getting is as follows:
+		//       start_bit + (DeviceAddr | reading_bit) + reading_bytes (ReadingByteNum bytes) + stop_bit
+		if(pBaseInterface->I2cRead(pBaseInterface, DeviceAddr, &RegByte, LEN_1_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+
+		// Copy register byte to reading bytes.
+		pReadingBytes[i] = RegByte;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_register_reading_address:
+	return FUNCTION_ERROR;
+#endif
+	BASE_INTERFACE_MODULE *pBaseInterface;
+        struct dvb_usb_device	*d;
+	unsigned int i;
+
+	unsigned char DeviceAddr;
+
+	unsigned long PageNo = pDemod->CurrentPageNo;
+		
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+	// Get user defined data pointer of base interface structure for context.
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);
+
+
+	// Get demod register bytes.
+	// Note: Get demod register bytes one by one.
+	for(i = 0; i < ByteNum; i++)
+	{
+
+		// Get demod register bytes.
+		if(read_demod_register(d, DeviceAddr, PageNo,  RegStartAddr+i,  pReadingBytes+i, LEN_1_BYTE))
+			goto error_status_get_demod_registers;	
+
+
+
+		
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+//error_status_set_demod_register_reading_address:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+// Internal function:
+// Get register bytes continuously.
+int
+internal_dtmb_demod_addr_8bit_GetRegBytesContinuously(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+#if 0
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i;
+	unsigned char DeviceAddr;
+	unsigned long ReadingByteNum, ReadingByteNumMax, ReadingByteNumRem;
+	unsigned char RegReadingAddr;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum reading byte number.
+	ReadingByteNumMax = pBaseInterface->I2cReadingByteNumMax;
+
+
+	// Get demod register bytes.
+	// Note: Get demod register bytes considering maximum reading byte number.
+	for(i = 0; i < ByteNum; i += ReadingByteNumMax)
+	{
+		// Set register reading address.
+		RegReadingAddr = (unsigned char)(RegStartAddr + i);
+
+		// Calculate remainder reading byte number.
+		ReadingByteNumRem = ByteNum - i;
+
+		// Determine reading byte number.
+		ReadingByteNum = (ReadingByteNumRem > ReadingByteNumMax) ? ReadingByteNumMax : ReadingByteNumRem;
+
+
+		// Set demod register reading address.
+		// Note: The I2C format of demod register reading address setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegReadingAddr + stop_bit
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, &RegReadingAddr, LEN_1_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_register_reading_address;
+
+		// Get demod register bytes.
+		// Note: The I2C format of demod register byte getting is as follows:
+		//       start_bit + (DeviceAddr | reading_bit) + reading_bytes (ReadingByteNum bytes) + stop_bit
+		if(pBaseInterface->I2cRead(pBaseInterface, DeviceAddr, &pReadingBytes[i], ReadingByteNum) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_register_reading_address:
+	return FUNCTION_ERROR;
+#endif
+	BASE_INTERFACE_MODULE *pBaseInterface;
+        struct dvb_usb_device	*d;
+	
+	unsigned char DeviceAddr;
+	
+	unsigned long PageNo = pDemod->CurrentPageNo;
+		
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+	// Get user defined data pointer of base interface structure for context.
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);
+
+
+	// Get demod register bytes.
+	if(read_demod_register(d, DeviceAddr, PageNo,  RegStartAddr,  pReadingBytes, ByteNum))
+		goto error_status_get_demod_registers;	
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_REG_BYTES
+
+*/
+int
+dtmb_demod_addr_8bit_default_GetRegBytes(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	unsigned long CurrentPageNo;		// temp, because page register is write-only.
+
+
+
+	// Get page register number.
+	CurrentPageNo = pDemod->CurrentPageNo;		// temp, because page register is write-only.
+
+
+	// Get register bytes according to page register number.
+	switch(CurrentPageNo)
+	{
+		case 0:
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+
+			if(internal_dtmb_demod_addr_8bit_GetRegBytesSeparately(pDemod, RegStartAddr, pReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+				goto error_status_get_demod_registers;
+
+			break;
+
+
+		case 5:
+		case 6:
+		case 7:
+		case 8:
+		case 9:
+
+			if(internal_dtmb_demod_addr_8bit_GetRegBytesContinuously(pDemod, RegStartAddr, pReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+				goto error_status_get_demod_registers;
+
+			break;
+
+
+		default:
+			
+			goto error_status_get_demod_registers;
+			
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_REG_MASK_BITS
+
+*/
+int
+dtmb_demod_addr_8bit_default_SetRegMaskBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+	unsigned char WritingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value LSB.
+	//       Put upper address byte on value MSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * i);
+
+
+	// Reserve unsigned integer value unmask bit with mask and inlay writing value into it.
+	Value &= ~Mask;
+	Value |= (WritingValue << Shift) & Mask;
+
+
+	// Separate unsigned integer value into writing bytes.
+	// Note: Pick up lower address byte from value LSB.
+	//       Pick up upper address byte from value MSB.
+	for(i = 0; i < ByteNum; i++)
+		WritingBytes[i] = (unsigned char)((Value >> (BYTE_SHIFT * i)) & BYTE_MASK);
+
+
+	// Write demod register bytes with writing bytes.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBytes(pDemod, RegStartAddr, WritingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_REG_MASK_BITS
+
+*/
+int
+dtmb_demod_addr_8bit_default_GetRegMaskBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value LSB.
+	//       Put upper address byte on value MSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * i);
+
+
+	// Get register bits from unsigned integaer value with mask and shift
+	*pReadingValue = (Value & Mask) >> Shift;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_REG_BITS
+
+*/
+int
+dtmb_demod_addr_8bit_default_SetRegBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	)
+{
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->RegTable.Addr8Bit[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from register table with register bit name key.
+	RegStartAddr = pDemod->RegTable.Addr8Bit[RegBitName].RegStartAddr;
+	Msb          = pDemod->RegTable.Addr8Bit[RegBitName].Msb;
+	Lsb          = pDemod->RegTable.Addr8Bit[RegBitName].Lsb;
+
+
+	// Set register mask bits.
+	if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, WritingValue) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_REG_BITS
+
+*/
+int
+dtmb_demod_addr_8bit_default_GetRegBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->RegTable.Addr8Bit[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from register table with register bit name key.
+	RegStartAddr = pDemod->RegTable.Addr8Bit[RegBitName].RegStartAddr;
+	Msb          = pDemod->RegTable.Addr8Bit[RegBitName].Msb;
+	Lsb          = pDemod->RegTable.Addr8Bit[RegBitName].Lsb;
+
+
+	// Get register mask bits.
+	if(pDemod->RegAccess.Addr8Bit.GetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, pReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_REG_BITS_WITH_PAGE
+
+*/
+int
+dtmb_demod_addr_8bit_default_SetRegBitsWithPage(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	)
+{
+	unsigned long PageNo;
+
+
+	// Get register page number from register table with register bit name key.
+	PageNo = pDemod->RegTable.Addr8Bit[RegBitName].PageNo;
+
+
+	// Set register page number.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set register mask bits with register bit name key.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, RegBitName, WritingValue) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_REG_BITS_WITH_PAGE
+
+*/
+int
+dtmb_demod_addr_8bit_default_GetRegBitsWithPage(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	unsigned long PageNo;
+
+
+	// Get register page number from register table with register bit name key.
+	PageNo = pDemod->RegTable.Addr8Bit[RegBitName].PageNo;
+
+
+	// Set register page number.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Get register mask bits with register bit name key.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBits(pDemod, RegBitName, pReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_REG_BYTES
+
+*/
+int
+dtmb_demod_addr_16bit_default_SetRegBytes(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i, j;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBuffer[I2C_BUFFER_LEN];
+	unsigned long WritingByteNum, WritingByteNumMax, WritingByteNumRem;
+	unsigned short RegWritingAddr;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum writing byte number.
+	WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax - LEN_2_BYTE;
+
+
+	// Set demod register bytes with writing bytes.
+	// Note: Set demod register bytes considering maximum writing byte number.
+	for(i = 0; i < ByteNum; i += WritingByteNumMax)
+	{
+		// Set register writing address.
+		RegWritingAddr = (unsigned short)(RegStartAddr + i);
+
+		// Calculate remainder writing byte number.
+		WritingByteNumRem = ByteNum - i;
+
+		// Determine writing byte number.
+		WritingByteNum = (WritingByteNumRem > WritingByteNumMax) ? WritingByteNumMax : WritingByteNumRem;
+
+
+		// Set writing buffer.
+		// Note: The I2C format of demod register byte setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegWritingAddrMsb + RegWritingAddrLsb +
+		//       writing_bytes (WritingByteNum bytes) + stop_bit
+		WritingBuffer[0] = (RegWritingAddr >> BYTE_SHIFT) & BYTE_MASK;
+		WritingBuffer[1] = RegWritingAddr & BYTE_MASK;
+
+		for(j = 0; j < WritingByteNum; j++)
+			WritingBuffer[LEN_2_BYTE + j] = pWritingBytes[i + j];
+
+
+		// Set demod register bytes with writing buffer.
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, WritingByteNum + LEN_2_BYTE) !=
+			FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+// Internal function:
+// Get register bytes normally.
+int
+internal_dtmb_demod_addr_16bit_GetRegBytesNormally(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i;
+	unsigned char DeviceAddr;
+	unsigned long ReadingByteNum, ReadingByteNumMax, ReadingByteNumRem;
+	unsigned short RegReadingAddr;
+	unsigned char WritingBuffer[LEN_2_BYTE];
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum reading byte number.
+	ReadingByteNumMax = pBaseInterface->I2cReadingByteNumMax;
+
+
+	// Get demod register bytes.
+	// Note: Get demod register bytes considering maximum reading byte number.
+	for(i = 0; i < ByteNum; i += ReadingByteNumMax)
+	{
+		// Set register reading address.
+		RegReadingAddr = (unsigned short)(RegStartAddr + i);
+
+		// Calculate remainder reading byte number.
+		ReadingByteNumRem = ByteNum - i;
+
+		// Determine reading byte number.
+		ReadingByteNum = (ReadingByteNumRem > ReadingByteNumMax) ? ReadingByteNumMax : ReadingByteNumRem;
+
+
+		// Set demod register reading address.
+		// Note: The I2C format of demod register reading address setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegReadingAddrMsb + RegReadingAddrLsb + stop_bit
+		WritingBuffer[0] = (RegReadingAddr >> BYTE_SHIFT) & BYTE_MASK;
+		WritingBuffer[1] = RegReadingAddr & BYTE_MASK;
+
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, LEN_2_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_register_reading_address;
+
+		// Get demod register bytes.
+		// Note: The I2C format of demod register byte getting is as follows:
+		//       start_bit + (DeviceAddr | reading_bit) + reading_bytes (ReadingByteNum bytes) + stop_bit
+		if(pBaseInterface->I2cRead(pBaseInterface, DeviceAddr, &pReadingBytes[i], ReadingByteNum) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_register_reading_address:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+// Internal function:
+// Get register bytes with freeze.
+
+#define DTMB_I2C_REG_DEBUG_PAGE_ADDR		0xc708
+#define DTMB_I2C_REG_DEBUG_ADDR_ADDR		0xc709
+#define DTMB_I2C_REG_DEBUG_FREEZE_ADDR		0xc70a
+#define DTMB_I2C_REG_DEBUG_BYTE_ADDR		0xc70b
+
+int
+internal_dtmb_demod_addr_16bit_GetRegBytesWithFreeze(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i;
+	unsigned char DeviceAddr;
+
+	unsigned char WritingBuffer[LEN_4_BYTE];
+	unsigned char ReadingBuffer[LEN_4_BYTE];
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+
+	// Note: The I2C format of demod register byte setting is as follows:
+	//       start_bit + (DeviceAddr | writing_bit) + RegWritingAddrMsb + RegWritingAddrLsb + writing_bytes (WritingByteNum bytes) + stop_bit
+
+	// Note: The I2C format of demod register byte getting is as follows:
+	//       start_bit + (DeviceAddr | reading_bit) + reading_bytes (ReadingByteNum bytes) + stop_bit
+
+	// Set I2C_REG_DEBUG_PAGE and I2C_REG_DEBUG_ADDR with register start address.
+	// Note: 1. Set I2C_REG_DEBUG_PAGE with register start address [11:8].
+	//       2. Set I2C_REG_DEBUG_ADDR with register start address [7:0].
+	WritingBuffer[0] = (DTMB_I2C_REG_DEBUG_PAGE_ADDR >> BYTE_SHIFT) & BYTE_MASK;
+	WritingBuffer[1] = DTMB_I2C_REG_DEBUG_PAGE_ADDR & BYTE_MASK;
+	WritingBuffer[2] = (RegStartAddr >> BYTE_SHIFT) & HEX_DIGIT_MASK;
+	WritingBuffer[3] = RegStartAddr & BYTE_MASK;
+
+	if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, LEN_4_BYTE) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set I2C_REG_DEBUG_FREEZE with 0x1.
+	WritingBuffer[0] = (DTMB_I2C_REG_DEBUG_FREEZE_ADDR >> BYTE_SHIFT) & BYTE_MASK;
+	WritingBuffer[1] = DTMB_I2C_REG_DEBUG_FREEZE_ADDR & BYTE_MASK;
+	WritingBuffer[2] = 0x1;
+
+	if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, LEN_3_BYTE) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Get I2C_REG_DEBUG_BYTE 4 bytes.
+	if(internal_dtmb_demod_addr_16bit_GetRegBytesNormally(pDemod, DTMB_I2C_REG_DEBUG_BYTE_ADDR, ReadingBuffer, LEN_4_BYTE) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Arrange reading bytes from big-endian to little-endian.
+	// Note: 1. The bytes format reading from I2C_REG_DEBUG_BYTE is big-endian.
+	//       2. The bytes format we needs is little-endian.
+	for(i = 0; i < ByteNum; i++)
+	{
+		// Set reading bytes.
+		pReadingBytes[i] = ReadingBuffer[LEN_3_BYTE - i];
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_REG_BYTES
+
+*/
+int
+dtmb_demod_addr_16bit_default_GetRegBytes(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	unsigned char RegStartAddrMsb;
+
+
+
+	// Get regiser start address MSB.
+	RegStartAddrMsb = (RegStartAddr >> BYTE_SHIFT) & BYTE_MASK;
+
+
+	// Get register bytes according to page register number.
+	switch(RegStartAddrMsb)
+	{
+		case 0xc0:
+		case 0xc1:
+		case 0xc2:
+		case 0xc3:
+		case 0xc4:
+		case 0xc5:
+		case 0xc6:
+		case 0xc7:
+		case 0xe0:
+		case 0xe1:
+		case 0xe2:
+		case 0xe3:
+		case 0xe4:
+		case 0xf0:
+
+			if(internal_dtmb_demod_addr_16bit_GetRegBytesNormally(pDemod, RegStartAddr, pReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+				goto error_status_get_demod_registers;
+
+			break;
+
+
+		case 0xc8:
+		case 0xc9:
+		case 0xca:
+		case 0xcb:
+		case 0xcc:
+		case 0xcd:
+
+			if(internal_dtmb_demod_addr_16bit_GetRegBytesWithFreeze(pDemod, RegStartAddr, pReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+				goto error_status_get_demod_registers;
+
+			break;
+
+
+		default:
+			
+			goto error_status_get_demod_registers;
+			
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_REG_MASK_BITS
+
+*/
+int
+dtmb_demod_addr_16bit_default_SetRegMaskBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+	unsigned char WritingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->RegAccess.Addr16Bit.GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value LSB.
+	//       Put upper address byte on value MSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * i);
+
+
+	// Reserve unsigned integer value unmask bit with mask and inlay writing value into it.
+	Value &= ~Mask;
+	Value |= (WritingValue << Shift) & Mask;
+
+
+	// Separate unsigned integer value into writing bytes.
+	// Note: Pick up lower address byte from value LSB.
+	//       Pick up upper address byte from value MSB.
+	for(i = 0; i < ByteNum; i++)
+		WritingBytes[i] = (unsigned char)((Value >> (BYTE_SHIFT * i)) & BYTE_MASK);
+
+
+	// Write demod register bytes with writing bytes.
+	if(pDemod->RegAccess.Addr16Bit.SetRegBytes(pDemod, RegStartAddr, WritingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_REG_MASK_BITS
+
+*/
+int
+dtmb_demod_addr_16bit_default_GetRegMaskBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->RegAccess.Addr16Bit.GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value LSB.
+	//       Put upper address byte on value MSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * i);
+
+
+	// Get register bits from unsigned integaer value with mask and shift
+	*pReadingValue = (Value & Mask) >> Shift;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_SET_REG_BITS
+
+*/
+int
+dtmb_demod_addr_16bit_default_SetRegBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	)
+{
+	unsigned short RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->RegTable.Addr16Bit[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from register table with register bit name key.
+	RegStartAddr = pDemod->RegTable.Addr16Bit[RegBitName].RegStartAddr;
+	Msb          = pDemod->RegTable.Addr16Bit[RegBitName].Msb;
+	Lsb          = pDemod->RegTable.Addr16Bit[RegBitName].Lsb;
+
+
+	// Set register mask bits.
+	if(pDemod->RegAccess.Addr16Bit.SetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, WritingValue) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_REG_BITS
+
+*/
+int
+dtmb_demod_addr_16bit_default_GetRegBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	unsigned short RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->RegTable.Addr16Bit[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from register table with register bit name key.
+	RegStartAddr = pDemod->RegTable.Addr16Bit[RegBitName].RegStartAddr;
+	Msb          = pDemod->RegTable.Addr16Bit[RegBitName].Msb;
+	Lsb          = pDemod->RegTable.Addr16Bit[RegBitName].Lsb;
+
+
+	// Get register mask bits.
+	if(pDemod->RegAccess.Addr16Bit.GetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, pReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_DEMOD_TYPE
+
+*/
+void
+dtmb_demod_default_GetDemodType(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pDemodType
+	)
+{
+	// Get demod type from demod module.
+	*pDemodType = pDemod->DemodType;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_DEVICE_ADDR
+
+*/
+void
+dtmb_demod_default_GetDeviceAddr(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char *pDeviceAddr
+	)
+{
+	// Get demod I2C device address from demod module.
+	*pDeviceAddr = pDemod->DeviceAddr;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_CRYSTAL_FREQ_HZ
+
+*/
+void
+dtmb_demod_default_GetCrystalFreqHz(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pCrystalFreqHz
+	)
+{
+	// Get demod crystal frequency in Hz from demod module.
+	*pCrystalFreqHz = pDemod->CrystalFreqHz;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_IF_FREQ_HZ
+
+*/
+int
+dtmb_demod_default_GetIfFreqHz(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pIfFreqHz
+	)
+{
+	// Get demod IF frequency in Hz from demod module.
+	if(pDemod->IsIfFreqHzSet != YES)
+		goto error_status_get_demod_if_frequency;
+
+	*pIfFreqHz = pDemod->IfFreqHz;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_if_frequency:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_DEMOD_FP_GET_SPECTRUM_MODE
+
+*/
+int
+dtmb_demod_default_GetSpectrumMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pSpectrumMode
+	)
+{
+	// Get demod spectrum mode from demod module.
+	if(pDemod->IsSpectrumModeSet != YES)
+		goto error_status_get_demod_spectrum_mode;
+
+	*pSpectrumMode = pDemod->SpectrumMode;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_spectrum_mode:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/dtmb_demod_base.h b/drivers/media/usb/dvb-usb/dtmb_demod_base.h
new file mode 100644
index 0000000..3c04cff
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/dtmb_demod_base.h
@@ -0,0 +1,2505 @@
+#ifndef __DTMB_DEMOD_BASE_H
+#define __DTMB_DEMOD_BASE_H
+
+/**
+
+@file
+
+@brief   DTMB demod base module definition
+
+DTMB demod base module definitions contains demod module structure, demod funciton pointers, and demod definitions.
+
+
+
+@par Example:
+@code
+
+
+#include "demod_xxx.h"
+
+
+
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C reading format:
+	// start_bit + (DeviceAddr | reading_bit) + reading_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+int
+CustomI2cWrite(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C writing format:
+	// start_bit + (DeviceAddr | writing_bit) + writing_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+void
+CustomWaitMs(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned long WaitTimeMs
+	)
+{
+	// Wait WaitTimeMs milliseconds.
+
+	...
+
+	return;
+}
+
+
+
+int main(void)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+
+	I2C_BRIDGE_MODULE I2cBridgeModuleMemory;
+
+	unsigned long IfFreqHz;
+	int SpectrumMode;
+
+	int DemodType;
+	unsigned char DeviceAddr;
+	unsigned long CrystalFreqHz;
+
+	long RfAgc, IfAgc;
+	unsigned long DiAgc;
+
+	int Answer;
+	long TrOffsetPpm, CrOffsetHz;
+	unsigned long BerNum, BerDen;
+	double Ber;
+	unsigned long PerNum, PerDen;
+	double Per;
+	long SnrDbNum, SnrDbDen;
+	double SnrDb;
+	unsigned long SignalStrength, SignalQuality;
+
+	int CarrierMode;
+	int PnMode;
+	int QamMode;
+	int CodeRateMode;
+	int TimeInterleaverMode;
+
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pBaseInterface,
+		&BaseInterfaceModuleMemory,
+		9,								// Set maximum I2C reading byte number with 9.
+		8,								// Set maximum I2C writing byte number with 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs					// Employ CustomWaitMs() as basic waiting function.
+		);
+
+
+	// Build DTMB demod XXX module.
+	BuildXxxModule(
+		&pDemod,
+		&DtmbDemodModuleMemory,
+		&BaseInterfaceModuleMemory,
+		&I2cBridgeModuleMemory,
+		0x3e,							// Demod I2C device address is 0x3e in 8-bit format.
+		CRYSTAL_FREQ_27000000HZ,		// Demod crystal frequency is 27.0 MHz.
+		TS_INTERFACE_SERIAL,			// Demod TS interface mode is serial.
+		DIVERSITY_PIP_OFF				// Demod diversity and PIP both are disabled.
+		...								// Other arguments by each demod module
+		);
+
+
+
+
+
+	// ==== Initialize DTMB demod and set its parameters =====
+
+	// Initialize demod.
+	pDemod->Initialize(pDemod);
+
+
+	// Set demod parameters. (IF frequency and spectrum mode)
+	// Note: In the example:
+	//       1. IF frequency is 36.125 MHz.
+	//       2. Spectrum mode is SPECTRUM_INVERSE.
+	IfFreqHz      = IF_FREQ_36125000HZ;
+	SpectrumMode  = SPECTRUM_INVERSE;
+
+	pDemod->SetIfFreqHz(pDemod,      IfFreqHz);
+	pDemod->SetSpectrumMode(pDemod,  SpectrumMode);
+
+
+	// Need to set tuner before demod software reset.
+	// The order to set demod and tuner is not important.
+	// Note: 1. For 8-bit register address demod, one can use
+	//          "pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_I2CT_EN_CTRL, 0x1);"
+	//          for tuner I2C command forwarding.
+	//       2. For 16-bit register address demod, one can use
+	//          "pDemod->RegAccess.Addr16Bit.SetRegBits(pDemod, DTMB_I2CT_EN_CTRL, 0x1);"
+	//       for tuner I2C command forwarding.
+
+
+	// Reset demod by software reset.
+	pDemod->SoftwareReset(pDemod);
+
+
+	// Wait maximum 1000 ms for demod converge.
+	for(i = 0; i < 25; i++)
+	{
+		// Wait 40 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 40);
+
+		// Check signal lock status.
+		// Note: If Answer is YES, signal is locked.
+		//       If Answer is NO, signal is not locked.
+		pDemod->IsSignalLocked(pDemod, &Answer);
+
+		if(Answer == YES)
+		{
+			// Signal is locked.
+			break;
+		}
+	}
+
+
+
+
+
+	// ==== Get DTMB demod information =====
+
+	// Get demod type.
+	// Note: One can find demod type in MODULE_TYPE enumeration.
+	pDemod->GetDemodType(pDemod, &DemodType);
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+	// Get demod crystal frequency in Hz.
+	pDemod->GetCrystalFreqHz(pDemod, &CrystalFreqHz);
+
+
+	// Ask demod if it is connected to I2C bus.
+	// Note: If Answer is YES, demod is connected to I2C bus.
+	//       If Answer is NO, demod is not connected to I2C bus.
+	pDemod->IsConnectedToI2c(pDemod, &Answer);
+
+
+	// Get demod parameters. (IF frequency and spectrum mode)
+	pDemod->GetIfFreqHz(pDemod,      &IfFreqHz);
+	pDemod->GetSpectrumMode(pDemod,  &SpectrumMode);
+
+
+	// Get demod AGC value.
+	// Note: The range of RF AGC and IF AGC value is -8192 ~ 8191.
+	//       The range of digital AGC value is 0 ~ 255.
+	pDemod->GetRfAgc(pDemod, &RfAgc);
+	pDemod->GetIfAgc(pDemod, &IfAgc);
+	pDemod->GetDiAgc(pDemod, &DiAgc);
+
+
+	// Get demod lock status.
+	// Note: If Answer is YES, it is locked.
+	//       If Answer is NO, it is not locked.
+	pDemod->IsSignalLocked(pDemod, &Answer);
+
+
+	// Get TR offset (symbol timing offset) in ppm.
+	pDemod->GetTrOffsetPpm(pDemod, &TrOffsetPpm);
+
+	// Get CR offset (RF frequency offset) in Hz.
+	pDemod->GetCrOffsetHz(pDemod, &CrOffsetHz);
+
+
+	// Get BER.
+	pDemod->GetBer(pDemod, &BerNum, &BerDen);
+	Ber = (double)BerNum / (double)BerDen;
+
+	// Get PER.
+	pDemod->GetPer(pDemod, &PerNum, &PerDen);
+	Per = (double)PerNum / (double)PerDen;
+
+	// Get SNR in dB.
+	pDemod->GetSnrDb(pDemod, &SnrDbNum, &SnrDbDen);
+	SnrDb = (double)SnrDbNum / (double)SnrDbDen;
+
+
+	// Get signal strength.
+	// Note: 1. The range of SignalStrength is 0~100.
+	//       2. Need to map SignalStrength value to UI signal strength bar manually.
+	pDemod->GetSignalStrength(pDemod, &SignalStrength);
+
+	// Get signal quality.
+	// Note: 1. The range of SignalQuality is 0~100.
+	//       2. Need to map SignalQuality value to UI signal quality bar manually.
+	pDemod->GetSignalQuality(pDemod, &SignalQuality);
+
+
+	// Get signal information.
+	// Note: One can find signal information definitions in the enumerations as follows:
+	//       1. DTMB_CARRIER_MODE
+	//       2. DTMB_PN_MODE
+	//       3. DTMB_QAM_MODE
+	//       4. DTMB_CODE_RATE_MODE
+	//       5. DTMB_TIME_INTERLEAVER_MODE
+	pDemod->GetCarrierMode(pDemod, &CarrierMode);
+	pDemod->GetPnMode(pDemod, &PnMode);
+	pDemod->GetQamMode(pDemod, &QamMode);
+	pDemod->GetCodeRateMode(pDemod, &CodeRateMode);
+	pDemod->GetTimeInterleaverMode(pDemod, &TimeInterleaverMode);
+
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "foundation.h"
+
+
+
+
+
+// Definitions
+
+// Page register address
+#define DTMB_DEMOD_PAGE_REG_ADDR		0x0
+
+
+// Carrier mode
+enum DTMB_CARRIER_MODE
+{
+	DTMB_CARRIER_SINGLE,
+	DTMB_CARRIER_MULTI,
+};
+
+
+// PN mode
+enum DTMB_PN_MODE
+{
+	DTMB_PN_420,
+	DTMB_PN_595,
+	DTMB_PN_945,
+};
+
+
+// QAM mode
+enum DTMB_QAM_MODE
+{
+	DTMB_QAM_4QAM_NR,
+	DTMB_QAM_4QAM,
+	DTMB_QAM_16QAM,
+	DTMB_QAM_32QAM,
+	DTMB_QAM_64QAM,
+};
+#define DTMB_QAM_UNKNOWN		-1
+
+
+// Code rate mode
+enum DTMB_CODE_RATE_MODE
+{
+	DTMB_CODE_RATE_0P4,
+	DTMB_CODE_RATE_0P6,
+	DTMB_CODE_RATE_0P8,
+};
+#define DTMB_CODE_RATE_UNKNOWN		-1
+
+
+// Time interleaver mode
+enum DTMB_TIME_INTERLEAVER_MODE
+{
+	DTMB_TIME_INTERLEAVER_240,
+	DTMB_TIME_INTERLEAVER_720,
+};
+#define DTMB_TIME_INTERLEAVER_UNKNOWN		-1
+
+
+
+
+
+// Register entry definitions
+
+// Register entry for 8-bit address
+typedef struct
+{
+	int IsAvailable;
+	unsigned long PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+DTMB_REG_ENTRY_ADDR_8BIT;
+
+
+
+// Primary register entry for 8-bit address
+typedef struct
+{
+	int RegBitName;
+	unsigned long PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+DTMB_PRIMARY_REG_ENTRY_ADDR_8BIT;
+
+
+
+// Register entry for 16-bit address
+typedef struct
+{
+	int IsAvailable;
+	unsigned short RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+DTMB_REG_ENTRY_ADDR_16BIT;
+
+
+
+// Primary register entry for 16-bit address
+typedef struct
+{
+	int RegBitName;
+	unsigned short RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+DTMB_PRIMARY_REG_ENTRY_ADDR_16BIT;
+
+
+
+
+
+// Register table dependence
+
+// Demod register bit names
+enum DTMB_REG_BIT_NAME
+{
+	// Software reset
+	DTMB_SOFT_RST_N,
+
+	// Tuner I2C forwording
+	DTMB_I2CT_EN_CTRL,
+
+	// Chip ID
+	DTMB_CHIP_ID,
+
+
+	// IF setting
+	DTMB_EN_SP_INV,
+	DTMB_EN_DCR,
+	DTMB_BBIN_EN,
+	DTMB_IFFREQ,
+
+	// AGC setting
+	DTMB_AGC_DRIVE_LV,						// for RTL2836B DTMB only
+	DTMB_Z_AGC,								// for RTL2836B DTMB only
+	DTMB_EN_PGA_MODE,						// for RTL2836B DTMB only
+	DTMB_TARGET_VAL,
+	DTMB_AAGC_LOOPGAIN1,					// for RTL2836B DTMB only
+	DTMB_POLAR_IFAGC,						// for RTL2836B DTMB only
+	DTMB_POLAR_RFAGC,						// for RTL2836B DTMB only
+	DTMB_INTEGRAL_CNT_LEN,					// for RTL2836B DTMB only
+	DTMB_AAGC_LOCK_PGA_HIT_LEN,				// for RTL2836B DTMB only
+	DTMB_THD_LOCK_UP,						// for RTL2836B DTMB only
+	DTMB_THD_LOCK_DW,						// for RTL2836B DTMB only
+	DTMB_THD_UP1,							// for RTL2836B DTMB only
+	DTMB_THD_DW1,							// for RTL2836B DTMB only
+	DTMB_THD_UP2,							// for RTL2836B DTMB only
+	DTMB_THD_DW2,							// for RTL2836B DTMB only
+	DTMB_GAIN_PULSE_SPACE_LEN,				// for RTL2836B DTMB only
+	DTMB_GAIN_PULSE_HOLD_LEN,				// for RTL2836B DTMB only
+	DTMB_GAIN_STEP_SUM_UP_THD,				// for RTL2836B DTMB only
+	DTMB_GAIN_STEP_SUM_DW_THD,				// for RTL2836B DTMB only
+
+
+	// TS interface
+	DTMB_SERIAL,
+	DTMB_CDIV_PH0,
+	DTMB_CDIV_PH1,
+	DTMB_SER_LSB,
+	DTMB_SYNC_DUR,
+	DTMB_ERR_DUR,
+	DTMB_FIX_TEI,
+
+	// Signal lock status
+	DTMB_TPS_LOCK,
+	DTMB_PN_PEAK_EXIST,
+
+	// FSM
+	DTMB_FSM_STATE_R,
+
+	// Performance measurement
+	DTMB_RO_PKT_ERR_RATE,
+	DTMB_EST_SNR,
+	DTMB_RO_LDPC_BER,
+
+	// AGC
+	DTMB_GAIN_OUT_R,
+	DTMB_RF_AGC_VAL,
+	DTMB_IF_AGC_VAL,
+
+	// TR and CR
+	DTMB_TR_OUT_R,
+	DTMB_SFOAQ_OUT_R,
+	DTMB_CFO_EST_R,
+
+	// Signal information
+	DTMB_EST_CARRIER,
+	DTMB_RX_MODE_R,
+	DTMB_USE_TPS,
+
+	// GPIO
+	DTMB_DMBT_GPIOA_OE,			// For RTL2836B only
+	DTMB_DMBT_GPIOB_OE,			// For RTL2836B only
+	DTMB_DMBT_OPT_GPIOA_SEL,	// For RTL2836B only
+	DTMB_DMBT_OPT_GPIOB_SEL,	// For RTL2836B only
+	DTMB_GPIOA_SEL,				// For RTL2836B only
+	DTMB_GPIOB_SEL,				// For RTL2836B only
+
+	// AD7
+	DTMB_RSSI_R,				// For RTL2836B only
+	DTMB_AV_SET7,				// For RTL2836B only
+	DTMB_IBX,					// For RTL2836B only
+	DTMB_POW_AD7,				// For RTL2836B only
+	DTMB_VICM_SET,				// For RTL2836B only
+	DTMB_VRC,					// For RTL2836B only
+	DTMB_ATT_AD7,				// For RTL2836B only
+
+	// Diversity
+	DTMB_DIV_EN,				// For RTL2836B DTMB only
+	DTMB_DIV_MODE,				// For RTL2836B DTMB only
+	DTMB_DIV_RX_CLK_XOR,		// For RTL2836B DTMB only
+	DTMB_DIV_THD_ERR_CMP0,		// For RTL2836B DTMB only
+	DTMB_FSM_10L_MSB_3Byte,		// For RTL2836B DTMB only
+
+	// Item terminator
+	DTMB_REG_BIT_NAME_ITEM_TERMINATOR,
+};
+
+
+
+// Register table length definitions
+#define DTMB_REG_TABLE_LEN_MAX			DTMB_REG_BIT_NAME_ITEM_TERMINATOR
+
+
+
+
+
+// DTMB demod module pre-definition
+typedef struct DTMB_DEMOD_MODULE_TAG DTMB_DEMOD_MODULE;
+
+
+
+
+
+/**
+
+@brief   DTMB demod register page setting function pointer
+
+Demod upper level functions will use DTMB_DEMOD_FP_SET_REG_PAGE() to set demod register page.
+
+
+@param [in]   pDemod   The demod module pointer
+@param [in]   PageNo   Page number
+
+
+@retval   FUNCTION_SUCCESS   Set register page successfully with page number.
+@retval   FUNCTION_ERROR     Set register page unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_SET_REG_PAGE() with the corresponding function.
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register page with page number 2.
+	pDemod->SetRegPage(pDemod, 2);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_PAGE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long PageNo
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod register byte setting function pointer
+
+Demod upper level functions will use DTMB_DEMOD_FP_SET_REG_BYTES() to set demod register bytes.
+
+
+@param [in]   pDemod          The demod module pointer
+@param [in]   RegStartAddr    Demod register start address
+@param [in]   pWritingBytes   Pointer to writing bytes
+@param [in]   ByteNum         Writing byte number
+
+
+@retval   FUNCTION_SUCCESS   Set demod register bytes successfully with writing bytes.
+@retval   FUNCTION_ERROR     Set demod register bytes unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_SET_REG_BYTES() with the corresponding function.
+	-# Need to set register page by DTMB_DEMOD_FP_SET_REG_PAGE() before using DTMB_DEMOD_FP_SET_REG_BYTES().
+
+
+@see   DTMB_DEMOD_FP_SET_REG_PAGE, DTMB_DEMOD_FP_GET_REG_BYTES
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned char WritingBytes[10];
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bytes (page 1, address 0x17 ~ 0x1b) with 5 writing bytes.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->SetRegBytes(pDemod, 0x17, WritingBytes, 5);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_BYTES)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+typedef int
+(*DTMB_DEMOD_FP_ADDR_16BIT_SET_REG_BYTES)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod register byte getting function pointer
+
+Demod upper level functions will use DTMB_DEMOD_FP_GET_REG_BYTES() to get demod register bytes.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegStartAddr    Demod register start address
+@param [out]   pReadingBytes   Pointer to an allocated memory for storing reading bytes
+@param [in]    ByteNum         Reading byte number
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bytes successfully with reading byte number.
+@retval   FUNCTION_ERROR     Get demod register bytes unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_REG_BYTES() with the corresponding function.
+	-# Need to set register page by DTMB_DEMOD_FP_SET_REG_PAGE() before using DTMB_DEMOD_FP_GET_REG_BYTES().
+
+
+@see   DTMB_DEMOD_FP_SET_REG_PAGE, DTMB_DEMOD_FP_SET_REG_BYTES
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned char ReadingBytes[10];
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bytes (page 1, address 0x17 ~ 0x1b) with reading byte number 5.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->GetRegBytes(pDemod, 0x17, ReadingBytes, 5);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_ADDR_8BIT_GET_REG_BYTES)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+typedef int
+(*DTMB_DEMOD_FP_ADDR_16BIT_GET_REG_BYTES)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod register mask bits setting function pointer
+
+Demod upper level functions will use DTMB_DEMOD_FP_SET_REG_MASK_BITS() to set demod register mask bits.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   RegStartAddr   Demod register start address
+@param [in]   Msb            Mask MSB with 0-based index
+@param [in]   Lsb            Mask LSB with 0-based index
+@param [in]   WritingValue   The mask bits writing value
+
+
+@retval   FUNCTION_SUCCESS   Set demod register mask bits successfully with writing value.
+@retval   FUNCTION_ERROR     Set demod register mask bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_SET_REG_MASK_BITS() with the corresponding function.
+	-# Need to set register page by DTMB_DEMOD_FP_SET_REG_PAGE() before using DTMB_DEMOD_FP_SET_REG_MASK_BITS().
+	-# The constraints of DTMB_DEMOD_FP_SET_REG_MASK_BITS() function usage are described as follows:
+		-# The mask MSB and LSB must be 0~31.
+		-# The mask MSB must be greater than or equal to LSB.
+
+
+@see   DTMB_DEMOD_FP_SET_REG_PAGE, DTMB_DEMOD_FP_GET_REG_MASK_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bits (page 1, address {0x18, 0x17} [12:5]) with writing value 0x1d.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->SetRegMaskBits(pDemod, 0x17, 12, 5, 0x1d);
+
+
+	// Result:
+	//
+	// Writing value = 0x1d = 0001 1101 b
+	// 
+	// Page 1
+	// Register address   0x17          0x18
+	// Register value     xxx0 0011 b   101x xxxx b
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_MASK_BITS)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+typedef int
+(*DTMB_DEMOD_FP_ADDR_16BIT_SET_REG_MASK_BITS)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod register mask bits getting function pointer
+
+Demod upper level functions will use DTMB_DEMOD_FP_GET_REG_MASK_BITS() to get demod register mask bits.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegStartAddr    Demod register start address
+@param [in]    Msb             Mask MSB with 0-based index
+@param [in]    Lsb             Mask LSB with 0-based index
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register mask bits successfully.
+@retval   FUNCTION_ERROR     Get demod register mask bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_REG_MASK_BITS() with the corresponding function.
+	-# Need to set register page by DTMB_DEMOD_FP_SET_REG_PAGE() before using DTMB_DEMOD_FP_GET_REG_MASK_BITS().
+	-# The constraints of DTMB_DEMOD_FP_GET_REG_MASK_BITS() function usage are described as follows:
+		-# The mask MSB and LSB must be 0~31.
+		-# The mask MSB must be greater than or equal to LSB.
+
+
+@see   DTMB_DEMOD_FP_SET_REG_PAGE, DTMB_DEMOD_FP_SET_REG_MASK_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned long ReadingValue;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bits (page 1, address {0x18, 0x17} [12:5]).
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->GetRegMaskBits(pDemod, 0x17, 12, 5, &ReadingValue);
+
+
+	// Result:
+	//
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+	//
+	// Reading value = 0001 1101 b = 0x1d
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_ADDR_8BIT_GET_REG_MASK_BITS)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+typedef int
+(*DTMB_DEMOD_FP_ADDR_16BIT_GET_REG_MASK_BITS)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod register bits setting function pointer
+
+Demod upper level functions will use DTMB_DEMOD_FP_SET_REG_BITS() to set demod register bits with bit name.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   RegBitName     Pre-defined demod register bit name
+@param [in]   WritingValue   The mask bits writing value
+
+
+@retval   FUNCTION_SUCCESS   Set demod register bits successfully with bit name and writing value.
+@retval   FUNCTION_ERROR     Set demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_SET_REG_BITS() with the corresponding function.
+	-# Need to set register page before using DTMB_DEMOD_FP_SET_REG_BITS().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   DTMB_DEMOD_FP_SET_REG_PAGE, DTMB_DEMOD_FP_GET_REG_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bits with bit name PSEUDO_REG_BIT_NAME and writing value 0x1d.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->SetRegBits(pDemod, PSEUDO_REG_BIT_NAME, 0x1d);
+
+
+	// Result:
+	//
+	// Writing value = 0x1d = 0001 1101 b
+	// 
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_BITS)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+typedef int
+(*DTMB_DEMOD_FP_ADDR_16BIT_SET_REG_BITS)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod register bits getting function pointer
+
+Demod upper level functions will use DTMB_DEMOD_FP_GET_REG_BITS() to get demod register bits with bit name.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegBitName      Pre-defined demod register bit name
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bits successfully with bit name.
+@retval   FUNCTION_ERROR     Get demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_REG_BITS() with the corresponding function.
+	-# Need to set register page before using DTMB_DEMOD_FP_GET_REG_BITS().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   DTMB_DEMOD_FP_SET_REG_PAGE, DTMB_DEMOD_FP_SET_REG_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned long ReadingValue;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bits with bit name PSEUDO_REG_BIT_NAME.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->GetRegBits(pDemod, PSEUDO_REG_BIT_NAME, &ReadingValue);
+
+
+	// Result:
+	//
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+	//
+	// Reading value = 0001 1101 b = 0x1d
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_ADDR_8BIT_GET_REG_BITS)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+typedef int
+(*DTMB_DEMOD_FP_ADDR_16BIT_GET_REG_BITS)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod register bits setting function pointer (with page setting)
+
+Demod upper level functions will use DTMB_DEMOD_FP_SET_REG_BITS_WITH_PAGE() to set demod register bits with bit name and
+page setting.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   RegBitName     Pre-defined demod register bit name
+@param [in]   WritingValue   The mask bits writing value
+
+
+@retval   FUNCTION_SUCCESS   Set demod register bits successfully with bit name, page setting, and writing value.
+@retval   FUNCTION_ERROR     Set demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_SET_REG_BITS_WITH_PAGE() with the corresponding function.
+	-# Don't need to set register page before using DTMB_DEMOD_FP_SET_REG_BITS_WITH_PAGE().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   DTMB_DEMOD_FP_GET_REG_BITS_WITH_PAGE
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bits with bit name PSEUDO_REG_BIT_NAME and writing value 0x1d.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->SetRegBitsWithPage(pDemod, PSEUDO_REG_BIT_NAME, 0x1d);
+
+
+	// Result:
+	//
+	// Writing value = 0x1d = 0001 1101 b
+	// 
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_BITS_WITH_PAGE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod register bits getting function pointer (with page setting)
+
+Demod upper level functions will use DTMB_DEMOD_FPT_GET_REG_BITS_WITH_PAGE() to get demod register bits with bit name and
+page setting.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegBitName      Pre-defined demod register bit name
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bits successfully with bit name and page setting.
+@retval   FUNCTION_ERROR     Get demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_REG_BITS_WITH_PAGE() with the corresponding function.
+	-# Don't need to set register page before using DTMB_DEMOD_FP_GET_REG_BITS_WITH_PAGE().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   DTMB_DEMOD_FP_SET_REG_BITS_WITH_PAGE
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned long ReadingValue;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bits with bit name PSEUDO_REG_BIT_NAME.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->GetRegBitsWithPage(pDemod, PSEUDO_REG_BIT_NAME, &ReadingValue);
+
+
+	// Result:
+	//
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+	//
+	// Reading value = 0001 1101 b = 0x1d
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_ADDR_8BIT_GET_REG_BITS_WITH_PAGE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+// Demod register access for 8-bit address
+typedef struct
+{
+	DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_PAGE             SetRegPage;
+	DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_BYTES            SetRegBytes;
+	DTMB_DEMOD_FP_ADDR_8BIT_GET_REG_BYTES            GetRegBytes;
+	DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_MASK_BITS        SetRegMaskBits;
+	DTMB_DEMOD_FP_ADDR_8BIT_GET_REG_MASK_BITS        GetRegMaskBits;
+	DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_BITS             SetRegBits;
+	DTMB_DEMOD_FP_ADDR_8BIT_GET_REG_BITS             GetRegBits;
+	DTMB_DEMOD_FP_ADDR_8BIT_SET_REG_BITS_WITH_PAGE   SetRegBitsWithPage;
+	DTMB_DEMOD_FP_ADDR_8BIT_GET_REG_BITS_WITH_PAGE   GetRegBitsWithPage;
+}
+DTMB_DEMOD_REG_ACCESS_ADDR_8BIT;
+
+
+
+
+
+// Demod register access for 16-bit address
+typedef struct
+{
+	DTMB_DEMOD_FP_ADDR_16BIT_SET_REG_BYTES       SetRegBytes;
+	DTMB_DEMOD_FP_ADDR_16BIT_GET_REG_BYTES       GetRegBytes;
+	DTMB_DEMOD_FP_ADDR_16BIT_SET_REG_MASK_BITS   SetRegMaskBits;
+	DTMB_DEMOD_FP_ADDR_16BIT_GET_REG_MASK_BITS   GetRegMaskBits;
+	DTMB_DEMOD_FP_ADDR_16BIT_SET_REG_BITS        SetRegBits;
+	DTMB_DEMOD_FP_ADDR_16BIT_GET_REG_BITS        GetRegBits;
+}
+DTMB_DEMOD_REG_ACCESS_ADDR_16BIT;
+
+
+
+
+
+/**
+
+@brief   DTMB demod type getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_DEMOD_TYPE() to get DTMB demod type.
+
+
+@param [in]    pDemod       The demod module pointer
+@param [out]   pDemodType   Pointer to an allocated memory for storing demod type
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_DEMOD_TYPE() with the corresponding function.
+
+
+@see   MODULE_TYPE
+
+*/
+typedef void
+(*DTMB_DEMOD_FP_GET_DEMOD_TYPE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pDemodType
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod I2C device address getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_DEVICE_ADDR() to get DTMB demod I2C device address.
+
+
+@param [in]    pDemod        The demod module pointer
+@param [out]   pDeviceAddr   Pointer to an allocated memory for storing demod I2C device address
+
+
+@retval   FUNCTION_SUCCESS   Get demod device address successfully.
+@retval   FUNCTION_ERROR     Get demod device address unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_DEVICE_ADDR() with the corresponding function.
+
+*/
+typedef void
+(*DTMB_DEMOD_FP_GET_DEVICE_ADDR)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char *pDeviceAddr
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod crystal frequency getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_CRYSTAL_FREQ_HZ() to get DTMB demod crystal frequency in Hz.
+
+
+@param [in]    pDemod           The demod module pointer
+@param [out]   pCrystalFreqHz   Pointer to an allocated memory for storing demod crystal frequency in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod crystal frequency successfully.
+@retval   FUNCTION_ERROR     Get demod crystal frequency unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_CRYSTAL_FREQ_HZ() with the corresponding function.
+
+*/
+typedef void
+(*DTMB_DEMOD_FP_GET_CRYSTAL_FREQ_HZ)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pCrystalFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod I2C bus connection asking function pointer
+
+One can use DTMB_DEMOD_FP_IS_CONNECTED_TO_I2C() to ask DTMB demod if it is connected to I2C bus.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_IS_CONNECTED_TO_I2C() with the corresponding function.
+
+*/
+typedef void
+(*DTMB_DEMOD_FP_IS_CONNECTED_TO_I2C)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod software resetting function pointer
+
+One can use DTMB_DEMOD_FP_SOFTWARE_RESET() to reset DTMB demod by software reset.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset demod by software reset successfully.
+@retval   FUNCTION_ERROR     Reset demod by software reset unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_SOFTWARE_RESET() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_SOFTWARE_RESET)(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod initializing function pointer
+
+One can use DTMB_DEMOD_FP_INITIALIZE() to initialie DTMB demod.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Initialize demod successfully.
+@retval   FUNCTION_ERROR     Initialize demod unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_INITIALIZE() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_INITIALIZE)(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod IF frequency setting function pointer
+
+One can use DTMB_DEMOD_FP_SET_IF_FREQ_HZ() to set DTMB demod IF frequency in Hz.
+
+
+@param [in]   pDemod     The demod module pointer
+@param [in]   IfFreqHz   IF frequency in Hz for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod IF frequency successfully.
+@retval   FUNCTION_ERROR     Set demod IF frequency unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_SET_IF_FREQ_HZ() with the corresponding function.
+
+
+@see   IF_FREQ_HZ
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_SET_IF_FREQ_HZ)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long IfFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod spectrum mode setting function pointer
+
+One can use DTMB_DEMOD_FP_SET_SPECTRUM_MODE() to set DTMB demod spectrum mode.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   SpectrumMode   Spectrum mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod spectrum mode successfully.
+@retval   FUNCTION_ERROR     Set demod spectrum mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_SET_SPECTRUM_MODE() with the corresponding function.
+
+
+@see   SPECTRUM_MODE
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_SET_SPECTRUM_MODE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int SpectrumMode
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod IF frequency getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_IF_FREQ_HZ() to get DTMB demod IF frequency in Hz.
+
+
+@param [in]    pDemod      The demod module pointer
+@param [out]   pIfFreqHz   Pointer to an allocated memory for storing demod IF frequency in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod IF frequency successfully.
+@retval   FUNCTION_ERROR     Get demod IF frequency unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_IF_FREQ_HZ() with the corresponding function.
+
+
+@see   IF_FREQ_HZ
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_IF_FREQ_HZ)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pIfFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod spectrum mode getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_SPECTRUM_MODE() to get DTMB demod spectrum mode.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [out]   pSpectrumMode   Pointer to an allocated memory for storing demod spectrum mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod spectrum mode successfully.
+@retval   FUNCTION_ERROR     Get demod spectrum mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_SPECTRUM_MODE() with the corresponding function.
+
+
+@see   SPECTRUM_MODE
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_SPECTRUM_MODE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pSpectrumMode
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod signal lock asking function pointer
+
+One can use DTMB_DEMOD_FP_IS_SIGNAL_LOCKED() to ask DTMB demod if it is signal-locked.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform signal lock asking to demod successfully.
+@retval   FUNCTION_ERROR     Perform signal lock asking to demod unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_IS_SIGNAL_LOCKED() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_IS_SIGNAL_LOCKED)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod signal strength getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_SIGNAL_STRENGTH() to get signal strength.
+
+
+@param [in]    pDemod            The demod module pointer
+@param [out]   pSignalStrength   Pointer to an allocated memory for storing signal strength (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get demod signal strength successfully.
+@retval   FUNCTION_ERROR     Get demod signal strength unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_SIGNAL_STRENGTH() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_SIGNAL_STRENGTH)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalStrength
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod signal quality getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_SIGNAL_QUALITY() to get signal quality.
+
+
+@param [in]    pDemod           The demod module pointer
+@param [out]   pSignalQuality   Pointer to an allocated memory for storing signal quality (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get demod signal quality successfully.
+@retval   FUNCTION_ERROR     Get demod signal quality unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_SIGNAL_QUALITY() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_SIGNAL_QUALITY)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalQuality
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod BER getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_BER() to get BER.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [out]   pBerNum         Pointer to an allocated memory for storing BER numerator
+@param [out]   pBerDen         Pointer to an allocated memory for storing BER denominator
+
+
+@retval   FUNCTION_SUCCESS   Get demod error rate value successfully.
+@retval   FUNCTION_ERROR     Get demod error rate value unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_BER() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_BER)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod PER getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_PER() to get PER.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [out]   pPerNum         Pointer to an allocated memory for storing PER numerator
+@param [out]   pPerDen         Pointer to an allocated memory for storing PER denominator
+
+
+@retval   FUNCTION_SUCCESS   Get demod error rate value successfully.
+@retval   FUNCTION_ERROR     Get demod error rate value unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_PER() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_PER)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod SNR getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_SNR_DB() to get SNR in dB.
+
+
+@param [in]    pDemod      The demod module pointer
+@param [out]   pSnrDbNum   Pointer to an allocated memory for storing SNR dB numerator
+@param [out]   pSnrDbDen   Pointer to an allocated memory for storing SNR dB denominator
+
+
+@retval   FUNCTION_SUCCESS   Get demod SNR successfully.
+@retval   FUNCTION_ERROR     Get demod SNR unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_SNR_DB() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_SNR_DB)(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod RF AGC getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_RF_AGC() to get DTMB demod RF AGC value.
+
+
+@param [in]    pDemod   The demod module pointer
+@param [out]   pRfAgc   Pointer to an allocated memory for storing RF AGC value
+
+
+@retval   FUNCTION_SUCCESS   Get demod RF AGC value successfully.
+@retval   FUNCTION_ERROR     Get demod RF AGC value unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_RF_AGC() with the corresponding function.
+	-# The range of RF AGC value is 0 ~ (pow(2, 14) - 1).
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_RF_AGC)(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pRfAgc
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod IF AGC getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_IF_AGC() to get DTMB demod IF AGC value.
+
+
+@param [in]    pDemod   The demod module pointer
+@param [out]   pIfAgc   Pointer to an allocated memory for storing IF AGC value
+
+
+@retval   FUNCTION_SUCCESS   Get demod IF AGC value successfully.
+@retval   FUNCTION_ERROR     Get demod IF AGC value unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_IF_AGC() with the corresponding function.
+	-# The range of IF AGC value is 0 ~ (pow(2, 14) - 1).
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_IF_AGC)(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pIfAgc
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod digital AGC getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_DI_AGC() to get DTMB demod digital AGC value.
+
+
+@param [in]    pDemod   The demod module pointer
+@param [out]   pDiAgc   Pointer to an allocated memory for storing digital AGC value
+
+
+@retval   FUNCTION_SUCCESS   Get demod digital AGC value successfully.
+@retval   FUNCTION_ERROR     Get demod digital AGC value unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_DI_AGC() with the corresponding function.
+	-# The range of digital AGC value is 0 ~ (pow(2, 12) - 1).
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_DI_AGC)(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pDiAgc
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod TR offset getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_TR_OFFSET_PPM() to get TR offset in ppm.
+
+
+@param [in]    pDemod         The demod module pointer
+@param [out]   pTrOffsetPpm   Pointer to an allocated memory for storing TR offset in ppm
+
+
+@retval   FUNCTION_SUCCESS   Get demod TR offset successfully.
+@retval   FUNCTION_ERROR     Get demod TR offset unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_TR_OFFSET_PPM() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_TR_OFFSET_PPM)(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pTrOffsetPpm
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod CR offset getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_CR_OFFSET_HZ() to get CR offset in Hz.
+
+
+@param [in]    pDemod        The demod module pointer
+@param [out]   pCrOffsetHz   Pointer to an allocated memory for storing CR offset in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod CR offset successfully.
+@retval   FUNCTION_ERROR     Get demod CR offset unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_CR_OFFSET_HZ() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_CR_OFFSET_HZ)(
+	DTMB_DEMOD_MODULE *pDemod,
+	long *pCrOffsetHz
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod carrier mode getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_CARRIER_MODE() to get DTMB demod carrier mode.
+
+
+@param [in]    pDemod         The demod module pointer
+@param [out]   pCarrierMode   Pointer to an allocated memory for storing demod carrier mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod carrier mode successfully.
+@retval   FUNCTION_ERROR     Get demod carrier mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_CARRIER_MODE() with the corresponding function.
+
+
+@see   DTMB_CARRIER_MODE
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_CARRIER_MODE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pCarrierMode
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod PN mode getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_PN_MODE() to get DTMB demod PN mode.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pPnMode   Pointer to an allocated memory for storing demod PN mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod PN mode successfully.
+@retval   FUNCTION_ERROR     Get demod PN mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_PN_MODE() with the corresponding function.
+
+
+@see   DTMB_PN_MODE
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_PN_MODE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pPnMode
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod QAM mode getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_QAM_MODE() to get DTMB demod QAM mode.
+
+
+@param [in]    pDemod     The demod module pointer
+@param [out]   pQamMode   Pointer to an allocated memory for storing demod QAM mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod QAM mode successfully.
+@retval   FUNCTION_ERROR     Get demod QAM mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_QAM_MODE() with the corresponding function.
+
+
+@see   DTMB_QAM_MODE
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_QAM_MODE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pQamMode
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod code rate mode getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_CODE_RATE_MODE() to get DTMB demod code rate mode.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [out]   pCodeRateMode   Pointer to an allocated memory for storing demod code rate mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod code rate mode successfully.
+@retval   FUNCTION_ERROR     Get demod code rate mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_CODE_RATE_MODE() with the corresponding function.
+
+
+@see   DTMB_CODE_RATE_MODE
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_CODE_RATE_MODE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pCodeRateMode
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod time interleaver mode getting function pointer
+
+One can use DTMB_DEMOD_FP_GET_TIME_INTERLEAVER_MODE() to get DTMB demod time interleaver mode.
+
+
+@param [in]    pDemod                 The demod module pointer
+@param [out]   pTimeInterleaverMode   Pointer to an allocated memory for storing demod time interleaver mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod time interleaver mode successfully.
+@retval   FUNCTION_ERROR     Get demod time interleaver mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_GET_TIME_INTERLEAVER_MODE() with the corresponding function.
+
+
+@see   DTMB_TIME_INTERLEAVER_MODE
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_GET_TIME_INTERLEAVER_MODE)(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pTimeInterleaverMode
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod updating function pointer
+
+One can use DTMB_DEMOD_FP_UPDATE_FUNCTION() to update demod register setting.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update demod setting successfully.
+@retval   FUNCTION_ERROR     Update demod setting unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_UPDATE_FUNCTION() with the corresponding function.
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Execute ResetFunction() before demod software reset.
+	pDemod->ResetFunction(pDemod);
+
+	// Reset demod by software.
+	pDemod->SoftwareReset(pDemod);
+
+	...
+
+	return 0;
+}
+
+
+void PeriodicallyExecutingFunction
+{
+	// Executing UpdateFunction() periodically.
+	pDemod->UpdateFunction(pDemod);
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_UPDATE_FUNCTION)(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB demod reseting function pointer
+
+One can use DTMB_DEMOD_FP_RESET_FUNCTION() to reset demod register setting.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset demod setting successfully.
+@retval   FUNCTION_ERROR     Reset demod setting unsuccessfully.
+
+
+@note
+	-# Demod building function will set DTMB_DEMOD_FP_RESET_FUNCTION() with the corresponding function.
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DtmbDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Execute ResetFunction() before demod software reset.
+	pDemod->ResetFunction(pDemod);
+
+	// Reset demod by software.
+	pDemod->SoftwareReset(pDemod);
+
+	...
+
+	return 0;
+}
+
+
+void PeriodicallyExecutingFunction
+{
+	// Executing UpdateFunction() periodically.
+	pDemod->UpdateFunction(pDemod);
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_DEMOD_FP_RESET_FUNCTION)(
+	DTMB_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/// RTL2836 extra module
+typedef struct RTL2836_EXTRA_MODULE_TAG RTL2836_EXTRA_MODULE;
+struct RTL2836_EXTRA_MODULE_TAG
+{
+	// RTL2836 update procedure enabling status
+	int IsFunc1Enabled;
+	int IsFunc2Enabled;
+
+	// RTL2836 update Function 1 variables
+	int Func1CntThd;
+	int Func1Cnt;
+
+	// RTL2836 update Function 2 variables
+	int Func2SignalModePrevious;
+};
+
+
+
+
+
+/// DTMB demod module structure
+struct DTMB_DEMOD_MODULE_TAG
+{
+	// Private variables
+	int           DemodType;
+	unsigned char DeviceAddr;
+	unsigned long CrystalFreqHz;
+	int           TsInterfaceMode;
+	int           DiversityPipMode;
+
+	unsigned long IfFreqHz;
+	int           SpectrumMode;
+
+	int IsIfFreqHzSet;
+	int IsSpectrumModeSet;
+
+	unsigned long CurrentPageNo;		// temp, because page register is write-only.
+
+	union											///<   Demod extra module used by driving module
+	{
+		RTL2836_EXTRA_MODULE Rtl2836;
+	}
+	Extra;
+
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	I2C_BRIDGE_MODULE *pI2cBridge;
+
+
+	// Demod register table
+	union
+	{
+		DTMB_REG_ENTRY_ADDR_8BIT  Addr8Bit[DTMB_REG_TABLE_LEN_MAX];
+		DTMB_REG_ENTRY_ADDR_16BIT Addr16Bit[DTMB_REG_TABLE_LEN_MAX];
+	}
+	RegTable;
+
+
+	// Demod I2C function pointers
+	union
+	{
+		DTMB_DEMOD_REG_ACCESS_ADDR_8BIT  Addr8Bit;
+		DTMB_DEMOD_REG_ACCESS_ADDR_16BIT Addr16Bit;
+	}
+	RegAccess;
+
+
+	// Demod manipulating function pointers
+	DTMB_DEMOD_FP_GET_DEMOD_TYPE              GetDemodType;
+	DTMB_DEMOD_FP_GET_DEVICE_ADDR             GetDeviceAddr;
+	DTMB_DEMOD_FP_GET_CRYSTAL_FREQ_HZ         GetCrystalFreqHz;
+
+	DTMB_DEMOD_FP_IS_CONNECTED_TO_I2C         IsConnectedToI2c;
+
+	DTMB_DEMOD_FP_SOFTWARE_RESET              SoftwareReset;
+
+	DTMB_DEMOD_FP_INITIALIZE                  Initialize;
+	DTMB_DEMOD_FP_SET_IF_FREQ_HZ              SetIfFreqHz;
+	DTMB_DEMOD_FP_SET_SPECTRUM_MODE           SetSpectrumMode;
+	DTMB_DEMOD_FP_GET_IF_FREQ_HZ              GetIfFreqHz;
+	DTMB_DEMOD_FP_GET_SPECTRUM_MODE           GetSpectrumMode;
+
+	DTMB_DEMOD_FP_IS_SIGNAL_LOCKED            IsSignalLocked;
+
+	DTMB_DEMOD_FP_GET_SIGNAL_STRENGTH         GetSignalStrength;
+	DTMB_DEMOD_FP_GET_SIGNAL_QUALITY          GetSignalQuality;
+
+	DTMB_DEMOD_FP_GET_BER                     GetBer;
+	DTMB_DEMOD_FP_GET_PER                     GetPer;
+	DTMB_DEMOD_FP_GET_SNR_DB                  GetSnrDb;
+
+	DTMB_DEMOD_FP_GET_RF_AGC                  GetRfAgc;
+	DTMB_DEMOD_FP_GET_IF_AGC                  GetIfAgc;
+	DTMB_DEMOD_FP_GET_DI_AGC                  GetDiAgc;
+
+	DTMB_DEMOD_FP_GET_TR_OFFSET_PPM           GetTrOffsetPpm;
+	DTMB_DEMOD_FP_GET_CR_OFFSET_HZ            GetCrOffsetHz;
+
+	DTMB_DEMOD_FP_GET_CARRIER_MODE            GetCarrierMode;
+	DTMB_DEMOD_FP_GET_PN_MODE                 GetPnMode;
+	DTMB_DEMOD_FP_GET_QAM_MODE                GetQamMode;
+	DTMB_DEMOD_FP_GET_CODE_RATE_MODE          GetCodeRateMode;
+	DTMB_DEMOD_FP_GET_TIME_INTERLEAVER_MODE   GetTimeInterleaverMode;
+
+	DTMB_DEMOD_FP_UPDATE_FUNCTION             UpdateFunction;
+	DTMB_DEMOD_FP_RESET_FUNCTION              ResetFunction;
+};
+
+
+
+
+
+
+
+// DTMB demod default I2C functions for 8-bit address
+int
+dtmb_demod_addr_8bit_default_SetRegPage(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long PageNo
+	);
+
+int
+dtmb_demod_addr_8bit_default_SetRegBytes(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+int
+dtmb_demod_addr_8bit_default_GetRegBytes(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+int
+dtmb_demod_addr_8bit_default_SetRegMaskBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+int
+dtmb_demod_addr_8bit_default_GetRegMaskBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+int
+dtmb_demod_addr_8bit_default_SetRegBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+int
+dtmb_demod_addr_8bit_default_GetRegBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+int
+dtmb_demod_addr_8bit_default_SetRegBitsWithPage(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+int
+dtmb_demod_addr_8bit_default_GetRegBitsWithPage(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+// DTMB demod default I2C functions for 16-bit address
+int
+dtmb_demod_addr_16bit_default_SetRegBytes(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+int
+dtmb_demod_addr_16bit_default_GetRegBytes(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+int
+dtmb_demod_addr_16bit_default_SetRegMaskBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+int
+dtmb_demod_addr_16bit_default_GetRegMaskBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+int
+dtmb_demod_addr_16bit_default_SetRegBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+int
+dtmb_demod_addr_16bit_default_GetRegBits(
+	DTMB_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+// DTMB demod default manipulating functions
+void
+dtmb_demod_default_GetDemodType(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pDemodType
+	);
+
+void
+dtmb_demod_default_GetDeviceAddr(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned char *pDeviceAddr
+	);
+
+void
+dtmb_demod_default_GetCrystalFreqHz(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pCrystalFreqHz
+	);
+
+int
+dtmb_demod_default_GetBandwidthMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pBandwidthMode
+	);
+
+int
+dtmb_demod_default_GetIfFreqHz(
+	DTMB_DEMOD_MODULE *pDemod,
+	unsigned long *pIfFreqHz
+	);
+
+int
+dtmb_demod_default_GetSpectrumMode(
+	DTMB_DEMOD_MODULE *pDemod,
+	int *pSpectrumMode
+	);
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/dtmb_nim_base.c b/drivers/media/usb/dvb-usb/dtmb_nim_base.c
new file mode 100644
index 0000000..541bd48
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/dtmb_nim_base.c
@@ -0,0 +1,545 @@
+/**
+
+@file
+
+@brief   DTMB NIM base module definition
+
+DTMB NIM base module definitions contains NIM module structure, NIM funciton pointers, NIM definitions, and NIM default
+functions.
+
+*/
+
+
+#include "dtmb_nim_base.h"
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_NIM_TYPE
+
+*/
+void
+dtmb_nim_default_GetNimType(
+	DTMB_NIM_MODULE *pNim,
+	int *pNimType
+	)
+{
+	// Get NIM type from NIM module.
+	*pNimType = pNim->NimType;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_SET_PARAMETERS
+
+*/
+int
+dtmb_nim_default_SetParameters(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long RfFreqHz
+	)
+{
+	TUNER_MODULE *pTuner;
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_PARAMETERS
+
+*/
+int
+dtmb_nim_default_GetParameters(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pRfFreqHz
+	)
+{
+	TUNER_MODULE *pTuner;
+
+
+	// Get tuner module.
+	pTuner = pNim->pTuner;
+
+
+	// Get tuner RF frequency in Hz.
+	if(pTuner->GetRfFreqHz(pTuner, pRfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_IS_SIGNAL_PRESENT
+
+*/
+int
+dtmb_nim_default_IsSignalPresent(
+	DTMB_NIM_MODULE *pNim,
+	int *pAnswer
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	DTMB_DEMOD_MODULE *pDemod;
+	int i;
+
+
+	// Get base interface and demod module.
+	pBaseInterface = pNim->pBaseInterface;
+	pDemod         = pNim->pDemod;
+
+
+	// Wait for signal present check.
+	for(i = 0; i < DTMB_NIM_SINGAL_PRESENT_CHECK_TIMES_MAX_DEFAULT; i++)
+	{
+		// Wait 20 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 20);
+
+		// Check signal lock status on demod.
+		// Note: If signal is locked, stop signal lock check.
+		if(pDemod->IsSignalLocked(pDemod, pAnswer) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		if(*pAnswer == YES)
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_IS_SIGNAL_LOCKED
+
+*/
+int
+dtmb_nim_default_IsSignalLocked(
+	DTMB_NIM_MODULE *pNim,
+	int *pAnswer
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	DTMB_DEMOD_MODULE *pDemod;
+	int i;
+
+
+	// Get base interface and demod module.
+	pBaseInterface = pNim->pBaseInterface;
+	pDemod         = pNim->pDemod;
+
+
+	// Wait for signal lock check.
+	for(i = 0; i < DTMB_NIM_SINGAL_LOCK_CHECK_TIMES_MAX_DEFAULT; i++)
+	{
+		// Wait 20 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 20);
+
+		// Check signal lock status on demod.
+		// Note: If signal is locked, stop signal lock check.
+		if(pDemod->IsSignalLocked(pDemod, pAnswer) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		if(*pAnswer == YES)
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_SIGNAL_STRENGTH
+
+*/
+int
+dtmb_nim_default_GetSignalStrength(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pSignalStrength
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get signal strength from demod.
+	if(pDemod->GetSignalStrength(pDemod, pSignalStrength) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_SIGNAL_QUALITY
+
+*/
+int
+dtmb_nim_default_GetSignalQuality(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pSignalQuality
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get signal quality from demod.
+	if(pDemod->GetSignalQuality(pDemod, pSignalQuality) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_BER
+
+*/
+int
+dtmb_nim_default_GetBer(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get BER from demod.
+	if(pDemod->GetBer(pDemod, pBerNum, pBerDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_PER
+
+*/
+int
+dtmb_nim_default_GetPer(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get PER from demod.
+	if(pDemod->GetPer(pDemod, pPerNum, pPerDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_SNR_DB
+
+*/
+int
+dtmb_nim_default_GetSnrDb(
+	DTMB_NIM_MODULE *pNim,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get SNR in dB from demod.
+	if(pDemod->GetSnrDb(pDemod, pSnrDbNum, pSnrDbDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_TR_OFFSET_PPM
+
+*/
+int
+dtmb_nim_default_GetTrOffsetPpm(
+	DTMB_NIM_MODULE *pNim,
+	long *pTrOffsetPpm
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get TR offset in ppm from demod.
+	if(pDemod->GetTrOffsetPpm(pDemod, pTrOffsetPpm) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_CR_OFFSET_HZ
+
+*/
+int
+dtmb_nim_default_GetCrOffsetHz(
+	DTMB_NIM_MODULE *pNim,
+	long *pCrOffsetHz
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get CR offset in Hz from demod.
+	if(pDemod->GetCrOffsetHz(pDemod, pCrOffsetHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_GET_SIGNAL_INFO
+
+*/
+int
+dtmb_nim_default_GetSignalInfo(
+	DTMB_NIM_MODULE *pNim,
+	int *pCarrierMode,
+	int *pPnMode,
+	int *pQamMode,
+	int *pCodeRateMode,
+	int *pTimeInterleaverMode
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get signal information from demod.
+	if(pDemod->GetCarrierMode(pDemod, pCarrierMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	if(pDemod->GetPnMode(pDemod, pPnMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	if(pDemod->GetQamMode(pDemod, pQamMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	if(pDemod->GetCodeRateMode(pDemod, pCodeRateMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	if(pDemod->GetTimeInterleaverMode(pDemod, pTimeInterleaverMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_UPDATE_FUNCTION
+
+*/
+int
+dtmb_nim_default_UpdateFunction(
+	DTMB_NIM_MODULE *pNim
+	)
+{
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Update demod particular registers.
+	if(pDemod->UpdateFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/dtmb_nim_base.h b/drivers/media/usb/dvb-usb/dtmb_nim_base.h
new file mode 100644
index 0000000..4c24bd3
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/dtmb_nim_base.h
@@ -0,0 +1,967 @@
+#ifndef __DTMB_NIM_BASE_H
+#define __DTMB_NIM_BASE_H
+
+/**
+
+@file
+
+@brief   DTMB NIM base module definition
+
+DTMB NIM base module definitions contains NIM module structure, NIM funciton pointers, NIM definitions, and NIM default
+functions.
+
+
+
+@par Example:
+@code
+
+
+#include "nim_demodx_tunery.h"
+
+
+
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C reading format:
+	// start_bit + (DeviceAddr | reading_bit) + reading_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+int
+CustomI2cWrite(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C writing format:
+	// start_bit + (DeviceAddr | writing_bit) + writing_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+void
+CustomWaitMs(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned long WaitTimeMs
+	)
+{
+	// Wait WaitTimeMs milliseconds.
+
+	...
+
+	return;
+}
+
+
+
+int main(void)
+{
+	DTMB_NIM_MODULE *pNim;
+	DTMB_NIM_MODULE DtmbNimModuleMemory;
+	DEMODX_EXTRA_MODULE DemodxExtraModuleMemory;
+	TUNERY_EXTRA_MODULE TuneryExtraModuleMemory;
+
+	unsigned long RfFreqHz;
+
+	int Answer;
+	unsigned long SignalStrength, SignalQuality;
+	unsigned long BerNum, BerDen;
+	double Ber;
+	unsigned long PerNum, PerDen;
+	double Per;
+	unsigned long SnrDbNum, SnrDbDen;
+	double SnrDb;
+	long TrOffsetPpm, CrOffsetHz;
+
+	int CarrierMode;
+	int PnMode;
+	int QamMode;
+	int CodeRateMode;
+	int TimeInterleaverMode;
+
+
+
+	// Build Demod-X Tuner-Y NIM module.
+	BuildDemodxTuneryModule(
+		&pNim,
+		&DtmbNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs					// Employ CustomWaitMs() as basic waiting function.
+
+		&DemodxExtraModuleMemory,		// Employ Demod-X extra module.
+		0x3e,							// The Demod-X I2C device address is 0x3e in 8-bit format.
+		CRYSTAL_FREQ_27000000HZ,		// The Demod-X crystal frequency is 27.0 MHz.
+		...								// Other arguments for Demod-X
+
+		&TunerxExtraModuleMemory,		// Employ Tuner-Y extra module.
+		0xc0,							// The Tuner-Y I2C device address is 0xc0 in 8-bit format.
+		...								// Other arguments for Tuner-Y
+		);
+
+
+
+	// Get NIM type.
+	// Note: NIM types are defined in the MODULE_TYPE enumeration.
+	pNim->GetNimType(pNim, &NimType);
+
+
+
+
+
+
+
+	// ==== Initialize NIM and set its parameters =====
+
+	// Initialize NIM.
+	pNim->Initialize(pNim);
+
+	// Set NIM parameters. (RF frequency)
+	// Note: In the example: RF frequency is 666 MHz.
+	RfFreqHz = 666000000;
+	pNim->SetParameters(pNim, RfFreqHz);
+
+
+
+	// Wait 1 second for demod convergence.
+
+
+
+
+
+	// ==== Get NIM information =====
+
+	// Get NIM parameters. (RF frequency)
+	pNim->GetParameters(pNim, &RfFreqHz);
+
+
+	// Get signal present status.
+	// Note: 1. The argument Answer is YES when the NIM module has found DTMB signal in the RF channel.
+	//       2. The argument Answer is NO when the NIM module does not find DTMB signal in the RF channel.
+	// Recommendation: Use the IsSignalPresent() function for channel scan.
+	pNim->IsSignalPresent(pNim, &Answer);
+
+	// Get signal lock status.
+	// Note: 1. The argument Answer is YES when the NIM module has locked DTMB signal in the RF channel.
+	//          At the same time, the NIM module sends TS packets through TS interface hardware pins.
+	//       2. The argument Answer is NO when the NIM module does not lock DTMB signal in the RF channel.
+	// Recommendation: Use the IsSignalLocked() function for signal lock check.
+	pNim->IsSignalLocked(pNim, &Answer);
+
+
+	// Get signal strength.
+	// Note: 1. The range of SignalStrength is 0~100.
+	//       2. Need to map SignalStrength value to UI signal strength bar manually.
+	pNim->GetSignalStrength(pNim, &SignalStrength);
+
+	// Get signal quality.
+	// Note: 1. The range of SignalQuality is 0~100.
+	//       2. Need to map SignalQuality value to UI signal quality bar manually.
+	pNim->GetSignalQuality(pNim, &SignalQuality);
+
+
+	// Get BER.
+	pNim->GetBer(pNim, &BerNum, &BerDen);
+	Ber = (double)BerNum / (double)BerDen;
+
+	// Get PER.
+	pNim->GetPer(pNim, &PerNum, &PerDen);
+	Per = (double)PerNum / (double)PerDen;
+
+	// Get SNR in dB.
+	pNim->GetSnrDb(pNim, &SnrDbNum, &SnrDbDen);
+	SnrDb = (double)SnrDbNum / (double)SnrDbDen;
+
+
+	// Get TR offset (symbol timing offset) in ppm.
+	pNim->GetTrOffsetPpm(pNim, &TrOffsetPpm);
+
+	// Get CR offset (RF frequency offset) in Hz.
+	pNim->GetCrOffsetHz(pNim, &CrOffsetHz);
+
+
+	// Get signal information.
+	// Note: One can find signal information definitions in the enumerations as follows:
+	//       1. DTMB_CARRIER_MODE
+	//       2. DTMB_PN_MODE
+	//       3. DTMB_QAM_MODE
+	//       4. DTMB_CODE_RATE_MODE
+	//       5. DTMB_TIME_INTERLEAVER_MODE
+	pNim->GetSignalInfo(pNim, &CarrierMode, &PnMode, &QamMode, &CodeRateMode, &TimeInterleaverMode);
+
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "foundation.h"
+#include "tuner_base.h"
+#include "dtmb_demod_base.h"
+
+
+
+
+
+// Definitions
+#define DTMB_NIM_SINGAL_PRESENT_CHECK_TIMES_MAX_DEFAULT			1
+#define DTMB_NIM_SINGAL_LOCK_CHECK_TIMES_MAX_DEFAULT			1
+
+
+
+
+
+/// DTMB NIM module pre-definition
+typedef struct DTMB_NIM_MODULE_TAG DTMB_NIM_MODULE;
+
+
+
+
+
+/**
+
+@brief   DTMB demod type getting function pointer
+
+One can use DTMB_NIM_FP_GET_NIM_TYPE() to get DTMB NIM type.
+
+
+@param [in]    pNim       The NIM module pointer
+@param [out]   pNimType   Pointer to an allocated memory for storing NIM type
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_NIM_TYPE() with the corresponding function.
+
+
+@see   MODULE_TYPE
+
+*/
+typedef void
+(*DTMB_NIM_FP_GET_NIM_TYPE)(
+	DTMB_NIM_MODULE *pNim,
+	int *pNimType
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM initializing function pointer
+
+One can use DTMB_NIM_FP_INITIALIZE() to initialie DTMB NIM.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Initialize NIM successfully.
+@retval   FUNCTION_ERROR     Initialize NIM unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_INITIALIZE() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_INITIALIZE)(
+	DTMB_NIM_MODULE *pNim
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM parameter setting function pointer
+
+One can use DTMB_NIM_FP_SET_PARAMETERS() to set DTMB NIM parameters.
+
+
+@param [in]   pNim            The NIM module pointer
+@param [in]   RfFreqHz        RF frequency in Hz for setting
+
+
+@retval   FUNCTION_SUCCESS   Set NIM parameters successfully.
+@retval   FUNCTION_ERROR     Set NIM parameters unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_SET_PARAMETERS() with the corresponding function.
+
+
+@see   DTMB_BANDWIDTH_MODE
+
+*/
+typedef int
+(*DTMB_NIM_FP_SET_PARAMETERS)(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long RfFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM parameter getting function pointer
+
+One can use DTMB_NIM_FP_GET_PARAMETERS() to get DTMB NIM parameters.
+
+
+@param [in]    pNim             The NIM module pointer
+@param [out]   pRfFreqHz        Pointer to an allocated memory for storing NIM RF frequency in Hz
+@param [out]   pBandwidthMode   Pointer to an allocated memory for storing NIM bandwidth mode
+
+
+@retval   FUNCTION_SUCCESS   Get NIM parameters successfully.
+@retval   FUNCTION_ERROR     Get NIM parameters unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_PARAMETERS() with the corresponding function.
+
+
+@see   DTMB_BANDWIDTH_MODE
+
+*/
+typedef int
+(*DTMB_NIM_FP_GET_PARAMETERS)(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pRfFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM signal present asking function pointer
+
+One can use DTMB_NIM_FP_IS_SIGNAL_PRESENT() to ask DTMB NIM if signal is present.
+
+
+@param [in]    pNim      The NIM module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform signal present asking to NIM successfully.
+@retval   FUNCTION_ERROR     Perform signal present asking to NIM unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_IS_SIGNAL_PRESENT() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_IS_SIGNAL_PRESENT)(
+	DTMB_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM signal lock asking function pointer
+
+One can use DTMB_NIM_FP_IS_SIGNAL_LOCKED() to ask DTMB NIM if signal is locked.
+
+
+@param [in]    pNim      The NIM module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform signal lock asking to NIM successfully.
+@retval   FUNCTION_ERROR     Perform signal lock asking to NIM unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_IS_SIGNAL_LOCKED() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_IS_SIGNAL_LOCKED)(
+	DTMB_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM signal strength getting function pointer
+
+One can use DTMB_NIM_FP_GET_SIGNAL_STRENGTH() to get signal strength.
+
+
+@param [in]    pNim              The NIM module pointer
+@param [out]   pSignalStrength   Pointer to an allocated memory for storing signal strength (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get NIM signal strength successfully.
+@retval   FUNCTION_ERROR     Get NIM signal strength unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_SIGNAL_STRENGTH() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_GET_SIGNAL_STRENGTH)(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pSignalStrength
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM signal quality getting function pointer
+
+One can use DTMB_NIM_FP_GET_SIGNAL_QUALITY() to get signal quality.
+
+
+@param [in]    pNim             The NIM module pointer
+@param [out]   pSignalQuality   Pointer to an allocated memory for storing signal quality (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get NIM signal quality successfully.
+@retval   FUNCTION_ERROR     Get NIM signal quality unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_SIGNAL_QUALITY() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_GET_SIGNAL_QUALITY)(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pSignalQuality
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM BER value getting function pointer
+
+One can use DTMB_NIM_FP_GET_BER() to get BER.
+
+
+@param [in]    pNim      The NIM module pointer
+@param [out]   pBerNum   Pointer to an allocated memory for storing BER numerator
+@param [out]   pBerDen   Pointer to an allocated memory for storing BER denominator
+
+
+@retval   FUNCTION_SUCCESS   Get NIM BER value successfully.
+@retval   FUNCTION_ERROR     Get NIM BER value unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_BER() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_GET_BER)(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM PER value getting function pointer
+
+One can use DTMB_NIM_FP_GET_PER() to get PER.
+
+
+@param [in]    pNim      The NIM module pointer
+@param [out]   pPerNum   Pointer to an allocated memory for storing PER numerator
+@param [out]   pPerDen   Pointer to an allocated memory for storing PER denominator
+
+
+@retval   FUNCTION_SUCCESS   Get NIM PER value successfully.
+@retval   FUNCTION_ERROR     Get NIM PER value unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_PER() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_GET_PER)(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM SNR getting function pointer
+
+One can use DTMB_NIM_FP_GET_SNR_DB() to get SNR in dB.
+
+
+@param [in]    pNim        The NIM module pointer
+@param [out]   pSnrDbNum   Pointer to an allocated memory for storing SNR dB numerator
+@param [out]   pSnrDbDen   Pointer to an allocated memory for storing SNR dB denominator
+
+
+@retval   FUNCTION_SUCCESS   Get NIM SNR successfully.
+@retval   FUNCTION_ERROR     Get NIM SNR unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_SNR_DB() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_GET_SNR_DB)(
+	DTMB_NIM_MODULE *pNim,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM TR offset getting function pointer
+
+One can use DTMB_NIM_FP_GET_TR_OFFSET_PPM() to get TR offset in ppm.
+
+
+@param [in]    pNim           The NIM module pointer
+@param [out]   pTrOffsetPpm   Pointer to an allocated memory for storing TR offset in ppm
+
+
+@retval   FUNCTION_SUCCESS   Get NIM TR offset successfully.
+@retval   FUNCTION_ERROR     Get NIM TR offset unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_TR_OFFSET_PPM() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_GET_TR_OFFSET_PPM)(
+	DTMB_NIM_MODULE *pNim,
+	long *pTrOffsetPpm
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM CR offset getting function pointer
+
+One can use DTMB_NIM_FP_GET_CR_OFFSET_HZ() to get CR offset in Hz.
+
+
+@param [in]    pNim          The NIM module pointer
+@param [out]   pCrOffsetHz   Pointer to an allocated memory for storing CR offset in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get NIM CR offset successfully.
+@retval   FUNCTION_ERROR     Get NIM CR offset unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_CR_OFFSET_HZ() with the corresponding function.
+
+*/
+typedef int
+(*DTMB_NIM_FP_GET_CR_OFFSET_HZ)(
+	DTMB_NIM_MODULE *pNim,
+	long *pCrOffsetHz
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM signal information getting function pointer
+
+One can use DTMB_NIM_FP_GET_SIGNAL_INFO() to get signal information.
+
+
+@param [in]    pNim                   The NIM module pointer
+@param [out]   pCarrierMode           Pointer to an allocated memory for storing demod carrier mode
+@param [out]   pPnMode                Pointer to an allocated memory for storing demod PN mode
+@param [out]   pQamMode               Pointer to an allocated memory for storing demod QAM mode
+@param [out]   pCodeRateMode          Pointer to an allocated memory for storing demod code rate mode
+@param [out]   pTimeInterleaverMode   Pointer to an allocated memory for storing demod time interleaver mode
+
+
+@retval   FUNCTION_SUCCESS   Get NIM signal information successfully.
+@retval   FUNCTION_ERROR     Get NIM signal information unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_GET_SIGNAL_INFO() with the corresponding function.
+
+
+@see   DTMB_CARRIER_MODE, DTMB_PN_MODE, DTMB_QAM_MODE, DTMB_CODE_RATE_MODE, DTMB_TIME_INTERLEAVER_MODE
+
+*/
+typedef int
+(*DTMB_NIM_FP_GET_SIGNAL_INFO)(
+	DTMB_NIM_MODULE *pNim,
+	int *pCarrierMode,
+	int *pPnMode,
+	int *pQamMode,
+	int *pCodeRateMode,
+	int *pTimeInterleaverMode
+	);
+
+
+
+
+
+/**
+
+@brief   DTMB NIM updating function pointer
+
+One can use DTMB_NIM_FP_UPDATE_FUNCTION() to update NIM register setting.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update NIM setting successfully.
+@retval   FUNCTION_ERROR     Update NIM setting unsuccessfully.
+
+
+@note
+	-# NIM building function will set DTMB_NIM_FP_UPDATE_FUNCTION() with the corresponding function.
+
+
+
+@par Example:
+@code
+
+
+#include "nim_demodx_tunery.h"
+
+
+int main(void)
+{
+	DTMB_NIM_MODULE *pNim;
+	DTMB_NIM_MODULE DtmbNimModuleMemory;
+	DEMODX_EXTRA_MODULE DemodxExtraModuleMemory;
+	TUNERY_EXTRA_MODULE TuneryExtraModuleMemory;
+
+
+	// Build Demod-X Tuner-Y NIM module.
+	BuildDemodxTuneryModule(
+		...
+		);
+
+	...
+
+
+	return 0;
+}
+
+
+void PeriodicallyExecutingFunction
+{
+	// Executing UpdateFunction() periodically.
+	pNim->UpdateFunction(pNim);
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DTMB_NIM_FP_UPDATE_FUNCTION)(
+	DTMB_NIM_MODULE *pNim
+	);
+
+
+
+
+
+// RTL2836 E4000 extra module
+typedef struct RTL2836_E4000_EXTRA_MODULE_TAG RTL2836_E4000_EXTRA_MODULE;
+struct RTL2836_E4000_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long TunerModeUpdateWaitTimeMax;
+	unsigned long TunerModeUpdateWaitTime;
+	unsigned char TunerGainMode;
+};
+
+
+
+
+
+// RTL2836B DTMB E4000 extra module
+typedef struct RTL2836B_DTMB_E4000_EXTRA_MODULE_TAG RTL2836B_DTMB_E4000_EXTRA_MODULE;
+struct RTL2836B_DTMB_E4000_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long TunerModeUpdateWaitTimeMax;
+	unsigned long TunerModeUpdateWaitTime;
+	unsigned char TunerGainMode;
+};
+
+
+
+
+
+// RTL2836B DTMB E4005 extra module
+typedef struct RTL2836B_DTMB_E4005_EXTRA_MODULE_TAG RTL2836B_DTMB_E4005_EXTRA_MODULE;
+struct RTL2836B_DTMB_E4005_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long TunerModeUpdateWaitTimeMax;
+	unsigned long TunerModeUpdateWaitTime;
+	unsigned char TunerGainMode;
+};
+
+
+
+
+
+// RTL2836B DTMB FC0012 extra module
+typedef struct RTL2836B_DTMB_FC0012_EXTRA_MODULE_TAG RTL2836B_DTMB_FC0012_EXTRA_MODULE;
+struct RTL2836B_DTMB_FC0012_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long LnaUpdateWaitTimeMax;
+	unsigned long LnaUpdateWaitTime;
+	unsigned long RssiRCalOn;
+};
+
+
+
+
+
+// RTL2836B DTMB FC0013B extra module
+typedef struct RTL2836B_DTMB_FC0013B_EXTRA_MODULE_TAG RTL2836B_DTMB_FC0013B_EXTRA_MODULE;
+struct RTL2836B_DTMB_FC0013B_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long LnaUpdateWaitTimeMax;
+	unsigned long LnaUpdateWaitTime;
+	unsigned long RssiRCalOn;
+	unsigned char LowGainTestMode;
+};
+
+
+
+
+
+/// DTMB NIM module structure
+struct DTMB_NIM_MODULE_TAG
+{
+	// Private variables
+	int NimType;
+
+	union														///<   NIM extra module used by driving module
+	{
+		RTL2836_E4000_EXTRA_MODULE        Rtl2836E4000;
+		RTL2836B_DTMB_E4000_EXTRA_MODULE  Rtl2836bDtmbE4000;
+		RTL2836B_DTMB_E4005_EXTRA_MODULE  Rtl2836bDtmbE4005;
+		RTL2836B_DTMB_FC0012_EXTRA_MODULE Rtl2836bDtmbFc0012;
+		RTL2836B_DTMB_FC0013B_EXTRA_MODULE Rtl2836bDtmbFc0013b;
+	}
+	Extra;
+
+
+	// Modules
+	BASE_INTERFACE_MODULE *pBaseInterface;						///<   Base interface module pointer
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;			///<   Base interface module memory
+
+	I2C_BRIDGE_MODULE *pI2cBridge;								///<   I2C bridge module pointer
+	I2C_BRIDGE_MODULE I2cBridgeModuleMemory;					///<   I2C bridge module memory
+
+	TUNER_MODULE *pTuner;										///<   Tuner module pointer
+	TUNER_MODULE TunerModuleMemory;								///<   Tuner module memory
+
+	DTMB_DEMOD_MODULE *pDemod;									///<   DTMB demod module pointer
+	DTMB_DEMOD_MODULE DtmbDemodModuleMemory;					///<   DTMB demod module memory
+
+
+	// NIM manipulating functions
+	DTMB_NIM_FP_GET_NIM_TYPE          GetNimType;
+	DTMB_NIM_FP_INITIALIZE            Initialize;
+	DTMB_NIM_FP_SET_PARAMETERS        SetParameters;
+	DTMB_NIM_FP_GET_PARAMETERS        GetParameters;
+	DTMB_NIM_FP_IS_SIGNAL_PRESENT     IsSignalPresent;
+	DTMB_NIM_FP_IS_SIGNAL_LOCKED      IsSignalLocked;
+	DTMB_NIM_FP_GET_SIGNAL_STRENGTH   GetSignalStrength;
+	DTMB_NIM_FP_GET_SIGNAL_QUALITY    GetSignalQuality;
+	DTMB_NIM_FP_GET_BER               GetBer;
+	DTMB_NIM_FP_GET_PER               GetPer;
+	DTMB_NIM_FP_GET_SNR_DB            GetSnrDb;
+	DTMB_NIM_FP_GET_TR_OFFSET_PPM     GetTrOffsetPpm;
+	DTMB_NIM_FP_GET_CR_OFFSET_HZ      GetCrOffsetHz;
+	DTMB_NIM_FP_GET_SIGNAL_INFO       GetSignalInfo;
+	DTMB_NIM_FP_UPDATE_FUNCTION       UpdateFunction;
+};
+
+
+
+
+
+
+
+// DTMB NIM default manipulaing functions
+void
+dtmb_nim_default_GetNimType(
+	DTMB_NIM_MODULE *pNim,
+	int *pNimType
+	);
+
+int
+dtmb_nim_default_SetParameters(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long RfFreqHz
+	);
+
+int
+dtmb_nim_default_GetParameters(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pRfFreqHz
+	);
+
+int
+dtmb_nim_default_IsSignalPresent(
+	DTMB_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+int
+dtmb_nim_default_IsSignalLocked(
+	DTMB_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+int
+dtmb_nim_default_GetSignalStrength(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pSignalStrength
+	);
+
+int
+dtmb_nim_default_GetSignalQuality(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pSignalQuality
+	);
+
+int
+dtmb_nim_default_GetBer(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	);
+
+int
+dtmb_nim_default_GetPer(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	);
+
+int
+dtmb_nim_default_GetSnrDb(
+	DTMB_NIM_MODULE *pNim,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+int
+dtmb_nim_default_GetTrOffsetPpm(
+	DTMB_NIM_MODULE *pNim,
+	long *pTrOffsetPpm
+	);
+
+int
+dtmb_nim_default_GetCrOffsetHz(
+	DTMB_NIM_MODULE *pNim,
+	long *pCrOffsetHz
+	);
+
+int
+dtmb_nim_default_GetSignalInfo(
+	DTMB_NIM_MODULE *pNim,
+	int *pCarrierMode,
+	int *pPnMode,
+	int *pQamMode,
+	int *pCodeRateMode,
+	int *pTimeInterleaverMode
+	);
+
+int
+dtmb_nim_default_UpdateFunction(
+	DTMB_NIM_MODULE *pNim
+	);
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/dvbt_demod_base.c b/drivers/media/usb/dvb-usb/dvbt_demod_base.c
new file mode 100644
index 0000000..d1bd1f6
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/dvbt_demod_base.c
@@ -0,0 +1,816 @@
+/**
+
+@file
+
+@brief   DVB-T demod default function definition
+
+DVB-T demod default functions.
+
+*/
+
+#include "dvbt_demod_base.h"
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_SET_REG_PAGE
+
+*/
+int
+dvbt_demod_default_SetRegPage(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long PageNo
+	)
+{
+#if 0
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBytes[LEN_2_BYTE];
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Set demod register page with page number.
+	// Note: The I2C format of demod register page setting is as follows:
+	//       start_bit + (DeviceAddr | writing_bit) + DVBT_DEMOD_PAGE_REG_ADDR + PageNo + stop_bit
+	WritingBytes[0] = DVBT_DEMOD_PAGE_REG_ADDR;
+	WritingBytes[1] = (unsigned char)PageNo;
+
+	if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBytes, LEN_2_BYTE) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+#endif
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	struct dvb_usb_device	*d;
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+	
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);  //add by chialing
+
+	if( mutex_lock_interruptible(&d->usb_mutex) )	goto error;
+
+	 pDemod->CurrentPageNo = PageNo;
+
+	mutex_unlock(&d->usb_mutex);
+	
+	return FUNCTION_SUCCESS;
+
+error:
+	return FUNCTION_ERROR;
+
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_SET_REG_BYTES
+
+*/
+int
+dvbt_demod_default_SetRegBytes(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned char ByteNum
+	)
+{
+#if 0
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned int i, j;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBuffer[I2C_BUFFER_LEN];
+	unsigned long WritingByteNum, WritingByteNumMax, WritingByteNumRem;
+	unsigned char RegWritingAddr;
+	
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+	
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum writing byte number.
+	WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax - LEN_1_BYTE;
+
+
+	// Set demod register bytes with writing bytes.
+	// Note: Set demod register bytes considering maximum writing byte number.
+	for(i = 0; i < ByteNum; i += WritingByteNumMax)
+	{
+		// Set register writing address.
+		RegWritingAddr = RegStartAddr + i;
+
+		// Calculate remainder writing byte number.
+		WritingByteNumRem = ByteNum - i;
+
+		// Determine writing byte number.
+		WritingByteNum = (WritingByteNumRem > WritingByteNumMax) ? WritingByteNumMax : WritingByteNumRem;
+
+
+		// Set writing buffer.
+		// Note: The I2C format of demod register byte setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegWritingAddr + writing_bytes (WritingByteNum bytes) + stop_bit
+		WritingBuffer[0] = RegWritingAddr;
+
+		for(j = 0; j < WritingByteNum; j++)
+			WritingBuffer[LEN_1_BYTE + j] = pWritingBytes[i + j];
+
+
+		// Set demod register bytes with writing buffer.
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, WritingByteNum + LEN_1_BYTE) !=
+			FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+#endif
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned int i, j;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBuffer[I2C_BUFFER_LEN];
+	unsigned char WritingByteNum, WritingByteNumMax, WritingByteNumRem;
+	unsigned char RegWritingAddr;
+	
+	struct dvb_usb_device	*d;
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+	
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);  //add by chialing
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum writing byte number.
+	WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax - LEN_1_BYTE;
+
+
+	// Set demod register bytes with writing bytes.
+	// Note: Set demod register bytes considering maximum writing byte number.
+	for(i = 0; i < ByteNum; i += WritingByteNumMax)
+	{
+		// Set register writing address.
+		RegWritingAddr = RegStartAddr + i;
+
+		// Calculate remainder writing byte number.
+		WritingByteNumRem = ByteNum - i;
+
+		// Determine writing byte number.
+		WritingByteNum = (WritingByteNumRem > WritingByteNumMax) ? WritingByteNumMax : WritingByteNumRem;
+
+
+		for(j = 0; j < WritingByteNum; j++)
+			WritingBuffer[j] = pWritingBytes[i + j];
+
+		// Set demod register bytes with writing buffer.
+		if(write_demod_register( d, DeviceAddr, pDemod->CurrentPageNo, RegWritingAddr, WritingBuffer, WritingByteNum )) goto error;
+
+		
+	}
+
+
+	return FUNCTION_SUCCESS;
+error:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_REG_BYTES
+
+*/
+int
+dvbt_demod_default_GetRegBytes(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned char ByteNum
+	)
+{
+#if 0
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned int i;
+	unsigned char DeviceAddr;
+	unsigned long ReadingByteNum, ReadingByteNumMax, ReadingByteNumRem;
+	unsigned char RegReadingAddr;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum reading byte number.
+	ReadingByteNumMax = pBaseInterface->I2cReadingByteNumMax;
+
+
+	// Get demod register bytes.
+	// Note: Get demod register bytes considering maximum reading byte number.
+	for(i = 0; i < ByteNum; i += ReadingByteNumMax)
+	{
+		// Set register reading address.
+		RegReadingAddr = RegStartAddr + i;
+
+		// Calculate remainder reading byte number.
+		ReadingByteNumRem = ByteNum - i;
+
+		// Determine reading byte number.
+		ReadingByteNum = (ReadingByteNumRem > ReadingByteNumMax) ? ReadingByteNumMax : ReadingByteNumRem;
+
+
+		// Set demod register reading address.
+		// Note: The I2C format of demod register reading address setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegReadingAddr + stop_bit
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, &RegReadingAddr, LEN_1_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_register_reading_address;
+
+		// Get demod register bytes.
+		// Note: The I2C format of demod register byte getting is as follows:
+		//       start_bit + (DeviceAddr | reading_bit) + reading_bytes (ReadingByteNum bytes) + stop_bit
+		if(pBaseInterface->I2cRead(pBaseInterface, DeviceAddr, &pReadingBytes[i], ReadingByteNum) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_register_reading_address:
+	return FUNCTION_ERROR;
+#endif
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned int i;
+	unsigned char DeviceAddr;
+	unsigned char ReadingByteNum, ReadingByteNumMax, ReadingByteNumRem;
+	unsigned char RegReadingAddr;
+
+	struct dvb_usb_device	*d;
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);  //add by chialing
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum reading byte number.
+	ReadingByteNumMax = pBaseInterface->I2cReadingByteNumMax;
+
+
+	// Get demod register bytes.
+	// Note: Get demod register bytes considering maximum reading byte number.
+	for(i = 0; i < ByteNum; i += ReadingByteNumMax)
+	{
+		// Set register reading address.
+		RegReadingAddr = RegStartAddr + i;
+
+		// Calculate remainder reading byte number.
+		ReadingByteNumRem = ByteNum - i;
+
+		// Determine reading byte number.
+		ReadingByteNum = (ReadingByteNumRem > ReadingByteNumMax) ? ReadingByteNumMax : ReadingByteNumRem;
+
+
+		// Get demod register bytes.
+		if(read_demod_register(d, DeviceAddr, pDemod->CurrentPageNo, RegReadingAddr, &pReadingBytes[i], ReadingByteNum)) goto error;
+
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+error:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_SET_REG_MASK_BITS
+
+*/
+int
+dvbt_demod_default_SetRegMaskBits(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+	unsigned char WritingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value MSB.
+	//       Put upper address byte on value LSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * (ByteNum - i -1));
+
+
+	// Reserve unsigned integer value unmask bit with mask and inlay writing value into it.
+	Value &= ~Mask;
+	Value |= (WritingValue << Shift) & Mask;
+
+
+	// Separate unsigned integer value into writing bytes.
+	// Note: Pick up lower address byte from value MSB.
+	//       Pick up upper address byte from value LSB.
+	for(i = 0; i < ByteNum; i++)
+		WritingBytes[i] = (unsigned char)((Value >> (BYTE_SHIFT * (ByteNum - i -1))) & BYTE_MASK);
+
+
+	// Write demod register bytes with writing bytes.
+	if(pDemod->SetRegBytes(pDemod, RegStartAddr, WritingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_REG_MASK_BITS
+
+*/
+int
+dvbt_demod_default_GetRegMaskBits(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value MSB.
+	//       Put upper address byte on value LSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * (ByteNum - i -1));
+
+
+	// Get register bits from unsigned integaer value with mask and shift
+	*pReadingValue = (Value & Mask) >> Shift;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_SET_REG_BITS
+
+*/
+int
+dvbt_demod_default_SetRegBits(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	)
+{
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->RegTable[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from register table with register bit name key.
+	RegStartAddr = pDemod->RegTable[RegBitName].RegStartAddr;
+	Msb          = pDemod->RegTable[RegBitName].Msb;
+	Lsb          = pDemod->RegTable[RegBitName].Lsb;
+
+
+	// Set register mask bits.
+	if(pDemod->SetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, WritingValue) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_REG_BITS
+
+*/
+int
+dvbt_demod_default_GetRegBits(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->RegTable[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from register table with register bit name key.
+	RegStartAddr = pDemod->RegTable[RegBitName].RegStartAddr;
+	Msb          = pDemod->RegTable[RegBitName].Msb;
+	Lsb          = pDemod->RegTable[RegBitName].Lsb;
+
+
+	// Get register mask bits.
+	if(pDemod->GetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, pReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_SET_REG_BITS_WITH_PAGE
+
+*/
+int
+dvbt_demod_default_SetRegBitsWithPage(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	)
+{
+	unsigned long PageNo;
+
+
+	// Get register page number from register table with register bit name key.
+	PageNo = pDemod->RegTable[RegBitName].PageNo;
+
+
+	// Set register page number.
+	if(pDemod->SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set register mask bits with register bit name key.
+	if(pDemod->SetRegBits(pDemod, RegBitName, WritingValue) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_REG_BITS_WITH_PAGE
+
+*/
+int
+dvbt_demod_default_GetRegBitsWithPage(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	unsigned long PageNo;
+
+
+	// Get register page number from register table with register bit name key.
+	PageNo = pDemod->RegTable[RegBitName].PageNo;
+
+
+	// Set register page number.
+	if(pDemod->SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Get register mask bits with register bit name key.
+	if(pDemod->GetRegBits(pDemod, RegBitName, pReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_DEMOD_TYPE
+
+*/
+void
+dvbt_demod_default_GetDemodType(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pDemodType
+	)
+{
+	// Get demod type from demod module.
+	*pDemodType = pDemod->DemodType;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_DEVICE_ADDR
+
+*/
+void
+dvbt_demod_default_GetDeviceAddr(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char *pDeviceAddr
+	)
+{
+	// Get demod I2C device address from demod module.
+	*pDeviceAddr = pDemod->DeviceAddr;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_CRYSTAL_FREQ_HZ
+
+*/
+void
+dvbt_demod_default_GetCrystalFreqHz(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pCrystalFreqHz
+	)
+{
+	// Get demod crystal frequency in Hz from demod module.
+	*pCrystalFreqHz = pDemod->CrystalFreqHz;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_BANDWIDTH_MODE
+
+*/
+int
+dvbt_demod_default_GetBandwidthMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pBandwidthMode
+	)
+{
+	// Get demod bandwidth mode from demod module.
+	if(pDemod->IsBandwidthModeSet != YES)
+		goto error_status_get_demod_bandwidth_mode;
+
+	*pBandwidthMode = pDemod->BandwidthMode;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_bandwidth_mode:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_IF_FREQ_HZ
+
+*/
+int
+dvbt_demod_default_GetIfFreqHz(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pIfFreqHz
+	)
+{
+	// Get demod IF frequency in Hz from demod module.
+	if(pDemod->IsIfFreqHzSet != YES)
+		goto error_status_get_demod_if_frequency;
+
+	*pIfFreqHz = pDemod->IfFreqHz;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_if_frequency:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_DEMOD_FP_GET_SPECTRUM_MODE
+
+*/
+int
+dvbt_demod_default_GetSpectrumMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pSpectrumMode
+	)
+{
+	// Get demod spectrum mode from demod module.
+	if(pDemod->IsSpectrumModeSet != YES)
+		goto error_status_get_demod_spectrum_mode;
+
+	*pSpectrumMode = pDemod->SpectrumMode;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_spectrum_mode:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/dvbt_demod_base.h b/drivers/media/usb/dvb-usb/dvbt_demod_base.h
new file mode 100644
index 0000000..edf7f19
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/dvbt_demod_base.h
@@ -0,0 +1,2722 @@
+#ifndef __DVBT_DEMOD_BASE_H
+#define __DVBT_DEMOD_BASE_H
+
+/**
+
+@file
+
+@brief   DVB-T demod base module definition
+
+DVB-T demod base module definitions contains demod module structure, demod funciton pointers, and demod definitions.
+
+
+
+@par Example:
+@code
+
+
+#include "demod_xxx.h"
+
+
+
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C reading format:
+	// start_bit + (DeviceAddr | reading_bit) + reading_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+int
+CustomI2cWrite(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C writing format:
+	// start_bit + (DeviceAddr | writing_bit) + writing_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+void
+CustomWaitMs(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned long WaitTimeMs
+	)
+{
+	// Wait WaitTimeMs milliseconds.
+
+	...
+
+	return;
+}
+
+
+
+int main(void)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+
+	I2C_BRIDGE_MODULE I2cBridgeModuleMemory;
+
+	int BandwidthMode;
+	unsigned long IfFreqHz;
+	int SpectrumMode;
+
+	int DemodType;
+	unsigned char DeviceAddr;
+	unsigned long CrystalFreqHz;
+
+	long RfAgc, IfAgc;
+	unsigned char DiAgc;
+
+	int Answer;
+	long TrOffsetPpm, CrOffsetHz;
+	unsigned long BerNum, BerDen;
+	double Ber;
+	long SnrDbNum, SnrDbDen;
+	double SnrDb;
+	unsigned long SignalStrength, SignalQuality;
+
+	int Constellation;
+	int Hierarchy;
+	int CodeRateLp;
+	int CodeRateHp;
+	int GuardInterval;
+	int FftMode;
+
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pBaseInterface,
+		&BaseInterfaceModuleMemory,
+		9,								// Set maximum I2C reading byte number with 9.
+		8,								// Set maximum I2C writing byte number with 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs					// Employ CustomWaitMs() as basic waiting function.
+		);
+
+
+	// Build DVB-T demod XXX module.
+	BuildXxxModule(
+		&pDemod,
+		&DvbtDemodModuleMemory,
+		&BaseInterfaceModuleMemory,
+		&I2cBridgeModuleMemory,
+		0x20,							// Demod I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// Demod crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// Demod TS interface mode is serial.
+		...								// Other arguments by each demod module
+		);
+
+
+
+
+
+	// ==== Initialize DVB-T demod and set its parameters =====
+
+	// Initialize demod.
+	pDemod->Initialize(pDemod);
+
+
+	// Set demod parameters. (bandwidth mode, IF frequency, spectrum mode)
+	// Note: In the example:
+	//       1. Bandwidth mode is 8 MHz.
+	//       2. IF frequency is 36.125 MHz.
+	//       3. Spectrum mode is SPECTRUM_INVERSE.
+	BandwidthMode = DVBT_BANDWIDTH_8MHZ;
+	IfFreqHz      = IF_FREQ_36125000HZ;
+	SpectrumMode  = SPECTRUM_INVERSE;
+
+	pDemod->SetBandwidthMode(pDemod, BandwidthMode);
+	pDemod->SetIfFreqHz(pDemod,      IfFreqHz);
+	pDemod->SetSpectrumMode(pDemod,  SpectrumMode);
+
+
+	// Need to set tuner before demod software reset.
+	// The order to set demod and tuner is not important.
+	// Note: One can use "pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1);"
+	//       for tuner I2C command forwarding.
+
+
+	// Reset demod by software reset.
+	pDemod->SoftwareReset(pDemod);
+
+
+	// Wait maximum 1000 ms for demod converge.
+	for(i = 0; i < 25; i++)
+	{
+		// Wait 40 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 40);
+
+		// Check signal lock status.
+		// Note: If Answer is YES, signal is locked.
+		//       If Answer is NO, signal is not locked.
+		pDemod->IsSignalLocked(pDemod, &Answer);
+
+		if(Answer == YES)
+		{
+			// Signal is locked.
+			break;
+		}
+	}
+
+
+
+
+
+	// ==== Get DVB-T demod information =====
+
+	// Get demod type.
+	// Note: One can find demod type in MODULE_TYPE enumeration.
+	pDemod->GetDemodType(pDemod, &DemodType);
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+	// Get demod crystal frequency in Hz.
+	pDemod->GetCrystalFreqHz(pDemod, &CrystalFreqHz);
+
+
+	// Ask demod if it is connected to I2C bus.
+	// Note: If Answer is YES, demod is connected to I2C bus.
+	//       If Answer is NO, demod is not connected to I2C bus.
+	pDemod->IsConnectedToI2c(pDemod, &Answer);
+
+
+	// Get demod parameters. (bandwidth mode, IF frequency, spectrum mode)
+	pDemod->GetBandwidthMode(pDemod, &BandwidthMode);
+	pDemod->GetIfFreqHz(pDemod,      &IfFreqHz);
+	pDemod->GetSpectrumMode(pDemod,  &SpectrumMode);
+
+
+	// Get demod AGC value.
+	// Note: The range of RF AGC and IF AGC value is -8192 ~ 8191.
+	//       The range of digital AGC value is 0 ~ 255.
+	pDemod->GetRfAgc(pDemod, &RfAgc);
+	pDemod->GetIfAgc(pDemod, &IfAgc);
+	pDemod->GetDiAgc(pDemod, &DiAgc);
+
+
+	// Get demod lock status.
+	// Note: If Answer is YES, it is locked.
+	//       If Answer is NO, it is not locked.
+	pDemod->IsTpsLocked(pDemod,    &Answer);
+	pDemod->IsSignalLocked(pDemod, &Answer);
+
+
+	// Get TR offset (symbol timing offset) in ppm.
+	pDemod->GetTrOffsetPpm(pDemod, &TrOffsetPpm);
+
+	// Get CR offset (RF frequency offset) in Hz.
+	pDemod->GetCrOffsetHz(pDemod, &CrOffsetHz);
+
+
+	// Get BER.
+	pDemod->GetBer(pDemod, &BerNum, &BerDen);
+	Ber = (double)BerNum / (double)BerDen;
+
+	// Get SNR in dB.
+	pDemod->GetSnrDb(pDemod, &SnrDbNum, &SnrDbDen);
+	SnrDb = (double)SnrDbNum / (double)SnrDbDen;
+
+
+	// Get signal strength.
+	// Note: 1. The range of SignalStrength is 0~100.
+	//       2. Need to map SignalStrength value to UI signal strength bar manually.
+	pDemod->GetSignalStrength(pDemod, &SignalStrength);
+
+	// Get signal quality.
+	// Note: 1. The range of SignalQuality is 0~100.
+	//       2. Need to map SignalQuality value to UI signal quality bar manually.
+	pDemod->GetSignalQuality(pDemod, &SignalQuality);
+
+
+	// Get TPS information.
+	// Note: One can find TPS information definitions in the enumerations as follows:
+	//       1. DVBT_CONSTELLATION_MODE
+	//       2. DVBT_HIERARCHY_MODE
+	//       3. DVBT_CODE_RATE_MODE (for low-priority and high-priority code rate)
+	//       4. DVBT_GUARD_INTERVAL_MODE
+	//       5. DVBT_FFT_MODE_MODE
+	pDemod->GetConstellation(pDemod, &Constellation);
+	pDemod->GetHierarchy(pDemod,     &Hierarchy);
+	pDemod->GetCodeRateLp(pDemod,    &CodeRateLp);
+	pDemod->GetCodeRateHp(pDemod,    &CodeRateHp);
+	pDemod->GetGuardInterval(pDemod, &GuardInterval);
+	pDemod->GetFftMode(pDemod,       &FftMode);
+
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "foundation.h"
+
+
+
+
+
+// Definitions
+
+// Page register address
+#define DVBT_DEMOD_PAGE_REG_ADDR		0x00
+
+
+// Bandwidth modes
+#define DVBT_BANDWIDTH_NONE			-1
+enum DVBT_BANDWIDTH_MODE
+{
+	DVBT_BANDWIDTH_6MHZ,
+	DVBT_BANDWIDTH_7MHZ,
+	DVBT_BANDWIDTH_8MHZ,
+};
+#define DVBT_BANDWIDTH_MODE_NUM		3
+
+
+// Constellation
+enum DVBT_CONSTELLATION_MODE
+{
+	DVBT_CONSTELLATION_QPSK,
+	DVBT_CONSTELLATION_16QAM,
+	DVBT_CONSTELLATION_64QAM,
+};
+#define DVBT_CONSTELLATION_NUM		3
+
+
+// Hierarchy
+enum DVBT_HIERARCHY_MODE
+{
+	DVBT_HIERARCHY_NONE,
+	DVBT_HIERARCHY_ALPHA_1,
+	DVBT_HIERARCHY_ALPHA_2,
+	DVBT_HIERARCHY_ALPHA_4,
+};
+#define DVBT_HIERARCHY_NUM			4
+
+
+// Code rate
+enum DVBT_CODE_RATE_MODE
+{
+	DVBT_CODE_RATE_1_OVER_2,
+	DVBT_CODE_RATE_2_OVER_3,
+	DVBT_CODE_RATE_3_OVER_4,
+	DVBT_CODE_RATE_5_OVER_6,
+	DVBT_CODE_RATE_7_OVER_8,
+};
+#define DVBT_CODE_RATE_NUM			5
+
+
+// Guard interval
+enum DVBT_GUARD_INTERVAL_MODE
+{
+	DVBT_GUARD_INTERVAL_1_OVER_32,
+	DVBT_GUARD_INTERVAL_1_OVER_16,
+	DVBT_GUARD_INTERVAL_1_OVER_8,
+	DVBT_GUARD_INTERVAL_1_OVER_4,
+};
+#define DVBT_GUARD_INTERVAL_NUM		4
+
+
+// FFT mode
+enum DVBT_FFT_MODE_MODE
+{
+	DVBT_FFT_MODE_2K,
+	DVBT_FFT_MODE_8K,
+};
+#define DVBT_FFT_MODE_NUM			2
+
+
+
+
+
+// Register entry definitions
+
+// Register entry
+typedef struct
+{
+	int IsAvailable;
+	unsigned long PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+DVBT_REG_ENTRY;
+
+
+
+// Primary register entry
+typedef struct
+{
+	int RegBitName;
+	unsigned long PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+DVBT_PRIMARY_REG_ENTRY;
+
+
+
+
+
+// Register table dependence
+
+// Demod register bit names
+enum DVBT_REG_BIT_NAME
+{
+	// Software reset register
+	DVBT_SOFT_RST,
+
+	// Tuner I2C forwording register
+	DVBT_IIC_REPEAT,
+
+
+	// Registers for initializing
+	DVBT_TR_WAIT_MIN_8K,
+	DVBT_RSD_BER_FAIL_VAL,
+	DVBT_EN_BK_TRK,
+	DVBT_REG_PI,
+
+	DVBT_REG_PFREQ_1_0,				// For RTL2830 only
+	DVBT_PD_DA8,					// For RTL2830 only
+	DVBT_LOCK_TH,					// For RTL2830 only
+	DVBT_BER_PASS_SCAL,				// For RTL2830 only
+	DVBT_CE_FFSM_BYPASS,			// For RTL2830 only
+	DVBT_ALPHAIIR_N,				// For RTL2830 only
+	DVBT_ALPHAIIR_DIF,				// For RTL2830 only
+	DVBT_EN_TRK_SPAN,				// For RTL2830 only
+	DVBT_LOCK_TH_LEN,				// For RTL2830 only
+	DVBT_CCI_THRE,					// For RTL2830 only
+	DVBT_CCI_MON_SCAL,				// For RTL2830 only
+	DVBT_CCI_M0,					// For RTL2830 only
+	DVBT_CCI_M1,					// For RTL2830 only
+	DVBT_CCI_M2,					// For RTL2830 only
+	DVBT_CCI_M3,					// For RTL2830 only
+	DVBT_SPEC_INIT_0,				// For RTL2830 only
+	DVBT_SPEC_INIT_1,				// For RTL2830 only
+	DVBT_SPEC_INIT_2,				// For RTL2830 only
+
+	DVBT_AD_EN_REG,					// For RTL2832 only
+	DVBT_AD_EN_REG1,				// For RTL2832 only
+	DVBT_EN_BBIN,					// For RTL2832 only
+	DVBT_MGD_THD0,					// For RTL2832 only
+	DVBT_MGD_THD1,					// For RTL2832 only
+	DVBT_MGD_THD2,					// For RTL2832 only
+	DVBT_MGD_THD3,					// For RTL2832 only
+	DVBT_MGD_THD4,					// For RTL2832 only
+	DVBT_MGD_THD5,					// For RTL2832 only
+	DVBT_MGD_THD6,					// For RTL2832 only
+	DVBT_MGD_THD7,					// For RTL2832 only
+	DVBT_EN_CACQ_NOTCH,				// For RTL2832 only
+	DVBT_AD_AV_REF,					// For RTL2832 only
+	DVBT_PIP_ON,					// For RTL2832 only
+	DVBT_SCALE1_B92,				// For RTL2832 only
+	DVBT_SCALE1_B93,				// For RTL2832 only
+	DVBT_SCALE1_BA7,				// For RTL2832 only
+	DVBT_SCALE1_BA9,				// For RTL2832 only
+	DVBT_SCALE1_BAA,				// For RTL2832 only
+	DVBT_SCALE1_BAB,				// For RTL2832 only
+	DVBT_SCALE1_BAC,				// For RTL2832 only
+	DVBT_SCALE1_BB0,				// For RTL2832 only
+	DVBT_SCALE1_BB1,				// For RTL2832 only
+	DVBT_KB_P1,						// For RTL2832 only
+	DVBT_KB_P2,						// For RTL2832 only
+	DVBT_KB_P3,						// For RTL2832 only
+	DVBT_OPT_ADC_IQ,				// For RTL2832 only
+	DVBT_AD_AVI,					// For RTL2832 only
+	DVBT_AD_AVQ,					// For RTL2832 only
+	DVBT_K1_CR_STEP12,				// For RTL2832 only
+
+	// Registers for initializing according to mode
+	DVBT_TRK_KS_P2,
+	DVBT_TRK_KS_I2,
+	DVBT_TR_THD_SET2,
+	DVBT_TRK_KC_P2,
+	DVBT_TRK_KC_I2,
+	DVBT_CR_THD_SET2,
+
+	// Registers for IF setting
+	DVBT_PSET_IFFREQ,
+	DVBT_SPEC_INV,
+
+
+	// Registers for bandwidth programming
+	DVBT_BW_INDEX,					// For RTL2830 only
+
+	DVBT_RSAMP_RATIO,				// For RTL2832 only
+	DVBT_CFREQ_OFF_RATIO,			// For RTL2832 only
+
+
+	// FSM stage register
+	DVBT_FSM_STAGE,
+
+	// TPS content registers
+	DVBT_RX_CONSTEL,
+	DVBT_RX_HIER,
+	DVBT_RX_C_RATE_LP,
+	DVBT_RX_C_RATE_HP,
+	DVBT_GI_IDX,
+	DVBT_FFT_MODE_IDX,
+	
+	// Performance measurement registers
+	DVBT_RSD_BER_EST,
+	DVBT_CE_EST_EVM,
+
+	// AGC registers
+	DVBT_RF_AGC_VAL,
+	DVBT_IF_AGC_VAL,
+	DVBT_DAGC_VAL,
+
+	// TR offset and CR offset registers
+	DVBT_SFREQ_OFF,
+	DVBT_CFREQ_OFF,
+
+
+	// AGC relative registers
+	DVBT_POLAR_RF_AGC,
+	DVBT_POLAR_IF_AGC,
+	DVBT_AAGC_HOLD,
+	DVBT_EN_RF_AGC,
+	DVBT_EN_IF_AGC,
+	DVBT_IF_AGC_MIN,
+	DVBT_IF_AGC_MAX,
+	DVBT_RF_AGC_MIN,
+	DVBT_RF_AGC_MAX,
+	DVBT_IF_AGC_MAN,
+	DVBT_IF_AGC_MAN_VAL,
+	DVBT_RF_AGC_MAN,
+	DVBT_RF_AGC_MAN_VAL,
+	DVBT_DAGC_TRG_VAL,
+
+	DVBT_AGC_TARG_VAL,				// For RTL2830 only
+	DVBT_LOOP_GAIN_3_0,				// For RTL2830 only
+	DVBT_LOOP_GAIN_4,				// For RTL2830 only
+	DVBT_VTOP,						// For RTL2830 only
+	DVBT_KRF,						// For RTL2830 only
+
+	DVBT_AGC_TARG_VAL_0,			// For RTL2832 only
+	DVBT_AGC_TARG_VAL_8_1,			// For RTL2832 only
+	DVBT_AAGC_LOOP_GAIN,			// For RTL2832 only
+	DVBT_LOOP_GAIN2_3_0,			// For RTL2832 only
+	DVBT_LOOP_GAIN2_4,				// For RTL2832 only
+	DVBT_LOOP_GAIN3,				// For RTL2832 only
+	DVBT_VTOP1,						// For RTL2832 only
+	DVBT_VTOP2,						// For RTL2832 only
+	DVBT_VTOP3,						// For RTL2832 only
+	DVBT_KRF1,						// For RTL2832 only
+	DVBT_KRF2,						// For RTL2832 only
+	DVBT_KRF3,						// For RTL2832 only
+	DVBT_KRF4,						// For RTL2832 only
+	DVBT_EN_GI_PGA,					// For RTL2832 only
+	DVBT_THD_LOCK_UP,				// For RTL2832 only
+	DVBT_THD_LOCK_DW,				// For RTL2832 only
+	DVBT_THD_UP1,					// For RTL2832 only
+	DVBT_THD_DW1,					// For RTL2832 only
+	DVBT_INTER_CNT_LEN,				// For RTL2832 only
+	DVBT_GI_PGA_STATE,				// For RTL2832 only
+	DVBT_EN_AGC_PGA,				// For RTL2832 only
+
+
+	// TS interface registers
+	DVBT_CKOUTPAR,
+	DVBT_CKOUT_PWR,
+	DVBT_SYNC_DUR,
+	DVBT_ERR_DUR,
+	DVBT_SYNC_LVL,
+	DVBT_ERR_LVL,
+	DVBT_VAL_LVL,
+	DVBT_SERIAL,
+	DVBT_SER_LSB,
+	DVBT_CDIV_PH0,
+	DVBT_CDIV_PH1,
+
+	DVBT_MPEG_IO_OPT_2_2,			// For RTL2832 only
+	DVBT_MPEG_IO_OPT_1_0,			// For RTL2832 only
+	DVBT_CKOUTPAR_PIP,				// For RTL2832 only
+	DVBT_CKOUT_PWR_PIP,				// For RTL2832 only
+	DVBT_SYNC_LVL_PIP,				// For RTL2832 only
+	DVBT_ERR_LVL_PIP,				// For RTL2832 only
+	DVBT_VAL_LVL_PIP,				// For RTL2832 only
+	DVBT_CKOUTPAR_PID,				// For RTL2832 only
+	DVBT_CKOUT_PWR_PID,				// For RTL2832 only
+	DVBT_SYNC_LVL_PID,				// For RTL2832 only
+	DVBT_ERR_LVL_PID,				// For RTL2832 only
+	DVBT_VAL_LVL_PID,				// For RTL2832 only
+
+
+	// FSM state-holding register
+	DVBT_SM_PASS,
+
+	// Registers for function 2 (for RTL2830 only)
+	DVBT_UPDATE_REG_2,
+
+	// Registers for function 3 (for RTL2830 only)
+	DVBT_BTHD_P3,
+	DVBT_BTHD_D3,
+
+	// Registers for function 4 (for RTL2830 only)
+	DVBT_FUNC4_REG0,
+	DVBT_FUNC4_REG1,
+	DVBT_FUNC4_REG2,
+	DVBT_FUNC4_REG3,
+	DVBT_FUNC4_REG4,
+	DVBT_FUNC4_REG5,
+	DVBT_FUNC4_REG6,
+	DVBT_FUNC4_REG7,
+	DVBT_FUNC4_REG8,
+	DVBT_FUNC4_REG9,
+	DVBT_FUNC4_REG10,
+
+	// Registers for functin 5 (for RTL2830 only)
+	DVBT_FUNC5_REG0,
+	DVBT_FUNC5_REG1,
+	DVBT_FUNC5_REG2,
+	DVBT_FUNC5_REG3,
+	DVBT_FUNC5_REG4,
+	DVBT_FUNC5_REG5,
+	DVBT_FUNC5_REG6,
+	DVBT_FUNC5_REG7,
+	DVBT_FUNC5_REG8,
+	DVBT_FUNC5_REG9,
+	DVBT_FUNC5_REG10,
+	DVBT_FUNC5_REG11,
+	DVBT_FUNC5_REG12,
+	DVBT_FUNC5_REG13,
+	DVBT_FUNC5_REG14,
+	DVBT_FUNC5_REG15,
+	DVBT_FUNC5_REG16,
+	DVBT_FUNC5_REG17,
+	DVBT_FUNC5_REG18,
+
+
+	// AD7 registers (for RTL2832 only)
+	DVBT_AD7_SETTING,
+	DVBT_RSSI_R,
+
+	// ACI detection registers (for RTL2832 only)
+	DVBT_ACI_DET_IND,
+
+	// Clock output registers (for RTL2832 only)
+	DVBT_REG_MON,
+	DVBT_REG_MONSEL,
+	DVBT_REG_GPE,
+	DVBT_REG_GPO,
+	DVBT_REG_4MSEL,
+
+
+	// Test registers for test only
+	DVBT_TEST_REG_1,
+	DVBT_TEST_REG_2,
+	DVBT_TEST_REG_3,
+	DVBT_TEST_REG_4,
+
+	// Item terminator
+	DVBT_REG_BIT_NAME_ITEM_TERMINATOR,
+};
+
+
+
+// Register table length definitions
+#define DVBT_REG_TABLE_LEN_MAX			DVBT_REG_BIT_NAME_ITEM_TERMINATOR
+
+
+
+
+
+// DVB-T demod module pre-definition
+typedef struct DVBT_DEMOD_MODULE_TAG DVBT_DEMOD_MODULE;
+
+
+
+
+
+/**
+
+@brief   DVB-T demod register page setting function pointer
+
+Demod upper level functions will use DVBT_DEMOD_FP_SET_REG_PAGE() to set demod register page.
+
+
+@param [in]   pDemod   The demod module pointer
+@param [in]   PageNo   Page number
+
+
+@retval   FUNCTION_SUCCESS   Set register page successfully with page number.
+@retval   FUNCTION_ERROR     Set register page unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_SET_REG_PAGE() with the corresponding function.
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register page with page number 2.
+	pDemod->SetRegPage(pDemod, 2);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_SET_REG_PAGE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long PageNo
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod register byte setting function pointer
+
+Demod upper level functions will use DVBT_DEMOD_FP_SET_REG_BYTES() to set demod register bytes.
+
+
+@param [in]   pDemod          The demod module pointer
+@param [in]   RegStartAddr    Demod register start address
+@param [in]   pWritingBytes   Pointer to writing bytes
+@param [in]   ByteNum         Writing byte number
+
+
+@retval   FUNCTION_SUCCESS   Set demod register bytes successfully with writing bytes.
+@retval   FUNCTION_ERROR     Set demod register bytes unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_SET_REG_BYTES() with the corresponding function.
+	-# Need to set register page by DVBT_DEMOD_FP_SET_REG_PAGE() before using DVBT_DEMOD_FP_SET_REG_BYTES().
+
+
+@see   DVBT_DEMOD_FP_SET_REG_PAGE, DVBT_DEMOD_FP_GET_REG_BYTES
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned char WritingBytes[10];
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bytes (page 1, address 0x17 ~ 0x1b) with 5 writing bytes.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->SetRegBytes(pDemod, 0x17, WritingBytes, 5);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_SET_REG_BYTES)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned char ByteNum
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod register byte getting function pointer
+
+Demod upper level functions will use DVBT_DEMOD_FP_GET_REG_BYTES() to get demod register bytes.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegStartAddr    Demod register start address
+@param [out]   pReadingBytes   Pointer to an allocated memory for storing reading bytes
+@param [in]    ByteNum         Reading byte number
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bytes successfully with reading byte number.
+@retval   FUNCTION_ERROR     Get demod register bytes unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_REG_BYTES() with the corresponding function.
+	-# Need to set register page by DVBT_DEMOD_FP_SET_REG_PAGE() before using DVBT_DEMOD_FP_GET_REG_BYTES().
+
+
+@see   DVBT_DEMOD_FP_SET_REG_PAGE, DVBT_DEMOD_FP_SET_REG_BYTES
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned char ReadingBytes[10];
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bytes (page 1, address 0x17 ~ 0x1b) with reading byte number 5.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->GetRegBytes(pDemod, 0x17, ReadingBytes, 5);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_REG_BYTES)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned char ByteNum
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod register mask bits setting function pointer
+
+Demod upper level functions will use DVBT_DEMOD_FP_SET_REG_MASK_BITS() to set demod register mask bits.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   RegStartAddr   Demod register start address
+@param [in]   Msb            Mask MSB with 0-based index
+@param [in]   Lsb            Mask LSB with 0-based index
+@param [in]   WritingValue   The mask bits writing value
+
+
+@retval   FUNCTION_SUCCESS   Set demod register mask bits successfully with writing value.
+@retval   FUNCTION_ERROR     Set demod register mask bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_SET_REG_MASK_BITS() with the corresponding function.
+	-# Need to set register page by DVBT_DEMOD_FP_SET_REG_PAGE() before using DVBT_DEMOD_FP_SET_REG_MASK_BITS().
+	-# The constraints of DVBT_DEMOD_FP_SET_REG_MASK_BITS() function usage are described as follows:
+		-# The mask MSB and LSB must be 0~31.
+		-# The mask MSB must be greater than or equal to LSB.
+
+
+@see   DVBT_DEMOD_FP_SET_REG_PAGE, DVBT_DEMOD_FP_GET_REG_MASK_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bits (page 1, address {0x18, 0x17} [12:5]) with writing value 0x1d.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->SetRegMaskBits(pDemod, 0x17, 12, 5, 0x1d);
+
+
+	// Result:
+	//
+	// Writing value = 0x1d = 0001 1101 b
+	// 
+	// Page 1
+	// Register address   0x17          0x18
+	// Register value     xxx0 0011 b   101x xxxx b
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_SET_REG_MASK_BITS)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod register mask bits getting function pointer
+
+Demod upper level functions will use DVBT_DEMOD_FP_GET_REG_MASK_BITS() to get demod register mask bits.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegStartAddr    Demod register start address
+@param [in]    Msb             Mask MSB with 0-based index
+@param [in]    Lsb             Mask LSB with 0-based index
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register mask bits successfully.
+@retval   FUNCTION_ERROR     Get demod register mask bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_REG_MASK_BITS() with the corresponding function.
+	-# Need to set register page by DVBT_DEMOD_FP_SET_REG_PAGE() before using DVBT_DEMOD_FP_GET_REG_MASK_BITS().
+	-# The constraints of DVBT_DEMOD_FP_GET_REG_MASK_BITS() function usage are described as follows:
+		-# The mask MSB and LSB must be 0~31.
+		-# The mask MSB must be greater than or equal to LSB.
+
+
+@see   DVBT_DEMOD_FP_SET_REG_PAGE, DVBT_DEMOD_FP_SET_REG_MASK_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned long ReadingValue;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bits (page 1, address {0x18, 0x17} [12:5]).
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->GetRegMaskBits(pDemod, 0x17, 12, 5, &ReadingValue);
+
+
+	// Result:
+	//
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+	//
+	// Reading value = 0001 1101 b = 0x1d
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_REG_MASK_BITS)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod register bits setting function pointer
+
+Demod upper level functions will use DVBT_DEMOD_FP_SET_REG_BITS() to set demod register bits with bit name.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   RegBitName     Pre-defined demod register bit name
+@param [in]   WritingValue   The mask bits writing value
+
+
+@retval   FUNCTION_SUCCESS   Set demod register bits successfully with bit name and writing value.
+@retval   FUNCTION_ERROR     Set demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_SET_REG_BITS() with the corresponding function.
+	-# Need to set register page before using DVBT_DEMOD_FP_SET_REG_BITS().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   DVBT_DEMOD_FP_SET_REG_PAGE, DVBT_DEMOD_FP_GET_REG_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bits with bit name PSEUDO_REG_BIT_NAME and writing value 0x1d.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->SetRegBits(pDemod, PSEUDO_REG_BIT_NAME, 0x1d);
+
+
+	// Result:
+	//
+	// Writing value = 0x1d = 0001 1101 b
+	// 
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_SET_REG_BITS)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod register bits getting function pointer
+
+Demod upper level functions will use DVBT_DEMOD_FP_GET_REG_BITS() to get demod register bits with bit name.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegBitName      Pre-defined demod register bit name
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bits successfully with bit name.
+@retval   FUNCTION_ERROR     Get demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_REG_BITS() with the corresponding function.
+	-# Need to set register page before using DVBT_DEMOD_FP_GET_REG_BITS().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   DVBT_DEMOD_FP_SET_REG_PAGE, DVBT_DEMOD_FP_SET_REG_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned long ReadingValue;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bits with bit name PSEUDO_REG_BIT_NAME.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->GetRegBits(pDemod, PSEUDO_REG_BIT_NAME, &ReadingValue);
+
+
+	// Result:
+	//
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+	//
+	// Reading value = 0001 1101 b = 0x1d
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_REG_BITS)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod register bits setting function pointer (with page setting)
+
+Demod upper level functions will use DVBT_DEMOD_FP_SET_REG_BITS_WITH_PAGE() to set demod register bits with bit name and
+page setting.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   RegBitName     Pre-defined demod register bit name
+@param [in]   WritingValue   The mask bits writing value
+
+
+@retval   FUNCTION_SUCCESS   Set demod register bits successfully with bit name, page setting, and writing value.
+@retval   FUNCTION_ERROR     Set demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_SET_REG_BITS_WITH_PAGE() with the corresponding function.
+	-# Don't need to set register page before using DVBT_DEMOD_FP_SET_REG_BITS_WITH_PAGE().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   DVBT_DEMOD_FP_GET_REG_BITS_WITH_PAGE
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bits with bit name PSEUDO_REG_BIT_NAME and writing value 0x1d.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->SetRegBitsWithPage(pDemod, PSEUDO_REG_BIT_NAME, 0x1d);
+
+
+	// Result:
+	//
+	// Writing value = 0x1d = 0001 1101 b
+	// 
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_SET_REG_BITS_WITH_PAGE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod register bits getting function pointer (with page setting)
+
+Demod upper level functions will use DVBT_DEMOD_FP_GET_REG_BITS_WITH_PAGE() to get demod register bits with bit name and
+page setting.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegBitName      Pre-defined demod register bit name
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bits successfully with bit name and page setting.
+@retval   FUNCTION_ERROR     Get demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_REG_BITS_WITH_PAGE() with the corresponding function.
+	-# Don't need to set register page before using DVBT_DEMOD_FP_GET_REG_BITS_WITH_PAGE().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   DVBT_DEMOD_FP_SET_REG_BITS_WITH_PAGE
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned long ReadingValue;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bits with bit name PSEUDO_REG_BIT_NAME.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->GetRegBitsWithPage(pDemod, PSEUDO_REG_BIT_NAME, &ReadingValue);
+
+
+	// Result:
+	//
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+	//
+	// Reading value = 0001 1101 b = 0x1d
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_REG_BITS_WITH_PAGE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod type getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_DEMOD_TYPE() to get DVB-T demod type.
+
+
+@param [in]    pDemod       The demod module pointer
+@param [out]   pDemodType   Pointer to an allocated memory for storing demod type
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_DEMOD_TYPE() with the corresponding function.
+
+
+@see   MODULE_TYPE
+
+*/
+typedef void
+(*DVBT_DEMOD_FP_GET_DEMOD_TYPE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pDemodType
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod I2C device address getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_DEVICE_ADDR() to get DVB-T demod I2C device address.
+
+
+@param [in]    pDemod        The demod module pointer
+@param [out]   pDeviceAddr   Pointer to an allocated memory for storing demod I2C device address
+
+
+@retval   FUNCTION_SUCCESS   Get demod device address successfully.
+@retval   FUNCTION_ERROR     Get demod device address unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_DEVICE_ADDR() with the corresponding function.
+
+*/
+typedef void
+(*DVBT_DEMOD_FP_GET_DEVICE_ADDR)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char *pDeviceAddr
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod crystal frequency getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_CRYSTAL_FREQ_HZ() to get DVB-T demod crystal frequency in Hz.
+
+
+@param [in]    pDemod           The demod module pointer
+@param [out]   pCrystalFreqHz   Pointer to an allocated memory for storing demod crystal frequency in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod crystal frequency successfully.
+@retval   FUNCTION_ERROR     Get demod crystal frequency unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_CRYSTAL_FREQ_HZ() with the corresponding function.
+
+*/
+typedef void
+(*DVBT_DEMOD_FP_GET_CRYSTAL_FREQ_HZ)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pCrystalFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod I2C bus connection asking function pointer
+
+One can use DVBT_DEMOD_FP_IS_CONNECTED_TO_I2C() to ask DVB-T demod if it is connected to I2C bus.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_IS_CONNECTED_TO_I2C() with the corresponding function.
+
+*/
+typedef void
+(*DVBT_DEMOD_FP_IS_CONNECTED_TO_I2C)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod software resetting function pointer
+
+One can use DVBT_DEMOD_FP_SOFTWARE_RESET() to reset DVB-T demod by software reset.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset demod by software reset successfully.
+@retval   FUNCTION_ERROR     Reset demod by software reset unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_SOFTWARE_RESET() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_SOFTWARE_RESET)(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod initializing function pointer
+
+One can use DVBT_DEMOD_FP_INITIALIZE() to initialie DVB-T demod.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Initialize demod successfully.
+@retval   FUNCTION_ERROR     Initialize demod unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_INITIALIZE() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_INITIALIZE)(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod bandwidth mode setting function pointer
+
+One can use DVBT_DEMOD_FP_SET_DVBT_MODE() to set DVB-T demod bandwidth mode.
+
+
+@param [in]   pDemod	      The demod module pointer
+@param [in]   BandwidthMode   Bandwidth mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod bandwidth mode successfully.
+@retval   FUNCTION_ERROR     Set demod bandwidth mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_SET_DVBT_MODE() with the corresponding function.
+
+
+@see   DVBT_BANDWIDTH_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_SET_BANDWIDTH_MODE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int BandwidthMode
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod IF frequency setting function pointer
+
+One can use DVBT_DEMOD_FP_SET_IF_FREQ_HZ() to set DVB-T demod IF frequency in Hz.
+
+
+@param [in]   pDemod     The demod module pointer
+@param [in]   IfFreqHz   IF frequency in Hz for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod IF frequency successfully.
+@retval   FUNCTION_ERROR     Set demod IF frequency unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_SET_IF_FREQ_HZ() with the corresponding function.
+
+
+@see   IF_FREQ_HZ
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_SET_IF_FREQ_HZ)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long IfFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod spectrum mode setting function pointer
+
+One can use DVBT_DEMOD_FP_SET_SPECTRUM_MODE() to set DVB-T demod spectrum mode.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   SpectrumMode   Spectrum mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod spectrum mode successfully.
+@retval   FUNCTION_ERROR     Set demod spectrum mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_SET_SPECTRUM_MODE() with the corresponding function.
+
+
+@see   SPECTRUM_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_SET_SPECTRUM_MODE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int SpectrumMode
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod bandwidth mode getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_DVBT_MODE() to get DVB-T demod bandwidth mode.
+
+
+@param [in]    pDemod           The demod module pointer
+@param [out]   pBandwidthMode   Pointer to an allocated memory for storing demod bandwidth mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod bandwidth mode successfully.
+@retval   FUNCTION_ERROR     Get demod bandwidth mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_DVBT_MODE() with the corresponding function.
+
+
+@see   DVBT_DVBT_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_BANDWIDTH_MODE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pBandwidthMode
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod IF frequency getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_IF_FREQ_HZ() to get DVB-T demod IF frequency in Hz.
+
+
+@param [in]    pDemod      The demod module pointer
+@param [out]   pIfFreqHz   Pointer to an allocated memory for storing demod IF frequency in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod IF frequency successfully.
+@retval   FUNCTION_ERROR     Get demod IF frequency unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_IF_FREQ_HZ() with the corresponding function.
+
+
+@see   IF_FREQ_HZ
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_IF_FREQ_HZ)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pIfFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod spectrum mode getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_SPECTRUM_MODE() to get DVB-T demod spectrum mode.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [out]   pSpectrumMode   Pointer to an allocated memory for storing demod spectrum mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod spectrum mode successfully.
+@retval   FUNCTION_ERROR     Get demod spectrum mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_SPECTRUM_MODE() with the corresponding function.
+
+
+@see   SPECTRUM_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_SPECTRUM_MODE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pSpectrumMode
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod TPS lock asking function pointer
+
+One can use DVBT_DEMOD_FP_IS_TPS_LOCKED() to ask DVB-T demod if it is TPS-locked.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform TPS lock asking to demod successfully.
+@retval   FUNCTION_ERROR     Perform TPS lock asking to demod unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_IS_TPS_LOCKED() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_IS_TPS_LOCKED)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod signal lock asking function pointer
+
+One can use DVBT_DEMOD_FP_IS_SIGNAL_LOCKED() to ask DVB-T demod if it is signal-locked.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform signal lock asking to demod successfully.
+@retval   FUNCTION_ERROR     Perform signal lock asking to demod unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_IS_SIGNAL_LOCKED() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_IS_SIGNAL_LOCKED)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod signal strength getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_SIGNAL_STRENGTH() to get signal strength.
+
+
+@param [in]    pDemod            The demod module pointer
+@param [out]   pSignalStrength   Pointer to an allocated memory for storing signal strength (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get demod signal strength successfully.
+@retval   FUNCTION_ERROR     Get demod signal strength unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_SIGNAL_STRENGTH() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_SIGNAL_STRENGTH)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalStrength
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod signal quality getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_SIGNAL_QUALITY() to get signal quality.
+
+
+@param [in]    pDemod           The demod module pointer
+@param [out]   pSignalQuality   Pointer to an allocated memory for storing signal quality (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get demod signal quality successfully.
+@retval   FUNCTION_ERROR     Get demod signal quality unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_SIGNAL_QUALITY() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_SIGNAL_QUALITY)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalQuality
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod BER getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_BER() to get BER.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [out]   pBerNum         Pointer to an allocated memory for storing BER numerator
+@param [out]   pBerDen         Pointer to an allocated memory for storing BER denominator
+
+
+@retval   FUNCTION_SUCCESS   Get demod error rate value successfully.
+@retval   FUNCTION_ERROR     Get demod error rate value unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_BER() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_BER)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod SNR getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_SNR_DB() to get SNR in dB.
+
+
+@param [in]    pDemod      The demod module pointer
+@param [out]   pSnrDbNum   Pointer to an allocated memory for storing SNR dB numerator
+@param [out]   pSnrDbDen   Pointer to an allocated memory for storing SNR dB denominator
+
+
+@retval   FUNCTION_SUCCESS   Get demod SNR successfully.
+@retval   FUNCTION_ERROR     Get demod SNR unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_SNR_DB() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_SNR_DB)(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod RF AGC getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_RF_AGC() to get DVB-T demod RF AGC value.
+
+
+@param [in]    pDemod   The demod module pointer
+@param [out]   pRfAgc   Pointer to an allocated memory for storing RF AGC value
+
+
+@retval   FUNCTION_SUCCESS   Get demod RF AGC value successfully.
+@retval   FUNCTION_ERROR     Get demod RF AGC value unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_RF_AGC() with the corresponding function.
+	-# The range of RF AGC value is (-pow(2, 13)) ~ (pow(2, 13) - 1).
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_RF_AGC)(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pRfAgc
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod IF AGC getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_IF_AGC() to get DVB-T demod IF AGC value.
+
+
+@param [in]    pDemod   The demod module pointer
+@param [out]   pIfAgc   Pointer to an allocated memory for storing IF AGC value
+
+
+@retval   FUNCTION_SUCCESS   Get demod IF AGC value successfully.
+@retval   FUNCTION_ERROR     Get demod IF AGC value unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_IF_AGC() with the corresponding function.
+	-# The range of IF AGC value is (-pow(2, 13)) ~ (pow(2, 13) - 1).
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_IF_AGC)(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pIfAgc
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod digital AGC getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_DI_AGC() to get DVB-T demod digital AGC value.
+
+
+@param [in]    pDemod   The demod module pointer
+@param [out]   pDiAgc   Pointer to an allocated memory for storing digital AGC value
+
+
+@retval   FUNCTION_SUCCESS   Get demod digital AGC value successfully.
+@retval   FUNCTION_ERROR     Get demod digital AGC value unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_DI_AGC() with the corresponding function.
+	-# The range of digital AGC value is 0 ~ (pow(2, 8) - 1).
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_DI_AGC)(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char *pDiAgc
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod TR offset getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_TR_OFFSET_PPM() to get TR offset in ppm.
+
+
+@param [in]    pDemod         The demod module pointer
+@param [out]   pTrOffsetPpm   Pointer to an allocated memory for storing TR offset in ppm
+
+
+@retval   FUNCTION_SUCCESS   Get demod TR offset successfully.
+@retval   FUNCTION_ERROR     Get demod TR offset unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_TR_OFFSET_PPM() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_TR_OFFSET_PPM)(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pTrOffsetPpm
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod CR offset getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_CR_OFFSET_HZ() to get CR offset in Hz.
+
+
+@param [in]    pDemod        The demod module pointer
+@param [out]   pCrOffsetHz   Pointer to an allocated memory for storing CR offset in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod CR offset successfully.
+@retval   FUNCTION_ERROR     Get demod CR offset unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_CR_OFFSET_HZ() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_CR_OFFSET_HZ)(
+	DVBT_DEMOD_MODULE *pDemod,
+	long *pCrOffsetHz
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod constellation mode getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_CONSTELLATION() to get DVB-T demod constellation mode.
+
+
+@param [in]    pDemod           The demod module pointer
+@param [out]   pConstellation   Pointer to an allocated memory for storing demod constellation mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod constellation mode successfully.
+@retval   FUNCTION_ERROR     Get demod constellation mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_CONSTELLATION() with the corresponding function.
+
+
+@see   DVBT_CONSTELLATION_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_CONSTELLATION)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pConstellation
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod hierarchy mode getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_HIERARCHY() to get DVB-T demod hierarchy mode.
+
+
+@param [in]    pDemod       The demod module pointer
+@param [out]   pHierarchy   Pointer to an allocated memory for storing demod hierarchy mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod hierarchy mode successfully.
+@retval   FUNCTION_ERROR     Get demod hierarchy mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_HIERARCHY() with the corresponding function.
+
+
+@see   DVBT_HIERARCHY_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_HIERARCHY)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pHierarchy
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod low-priority code rate mode getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_CODE_RATE_LP() to get DVB-T demod low-priority code rate mode.
+
+
+@param [in]    pDemod        The demod module pointer
+@param [out]   pCodeRateLp   Pointer to an allocated memory for storing demod low-priority code rate mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod low-priority code rate mode successfully.
+@retval   FUNCTION_ERROR     Get demod low-priority code rate mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_CODE_RATE_LP() with the corresponding function.
+
+
+@see   DVBT_CODE_RATE_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_CODE_RATE_LP)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pCodeRateLp
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod high-priority code rate mode getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_CODE_RATE_HP() to get DVB-T demod high-priority code rate mode.
+
+
+@param [in]    pDemod        The demod module pointer
+@param [out]   pCodeRateHp   Pointer to an allocated memory for storing demod high-priority code rate mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod high-priority code rate mode successfully.
+@retval   FUNCTION_ERROR     Get demod high-priority code rate mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_CODE_RATE_HP() with the corresponding function.
+
+
+@see   DVBT_CODE_RATE_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_CODE_RATE_HP)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pCodeRateHp
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod guard interval mode getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_GUARD_INTERVAL() to get DVB-T demod guard interval mode.
+
+
+@param [in]    pDemod           The demod module pointer
+@param [out]   pGuardInterval   Pointer to an allocated memory for storing demod guard interval mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod guard interval mode successfully.
+@retval   FUNCTION_ERROR     Get demod guard interval mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_GUARD_INTERVAL() with the corresponding function.
+
+
+@see   DVBT_GUARD_INTERVAL_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_GUARD_INTERVAL)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pGuardInterval
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod FFT mode getting function pointer
+
+One can use DVBT_DEMOD_FP_GET_FFT_MODE() to get DVB-T demod FFT mode.
+
+
+@param [in]    pDemod     The demod module pointer
+@param [out]   pFftMode   Pointer to an allocated memory for storing demod FFT mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod FFT mode successfully.
+@retval   FUNCTION_ERROR     Get demod FFT mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_GET_FFT_MODE() with the corresponding function.
+
+
+@see   DVBT_FFT_MODE_MODE
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_GET_FFT_MODE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pFftMode
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod updating function pointer
+
+One can use DVBT_DEMOD_FP_UPDATE_FUNCTION() to update demod register setting.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update demod setting successfully.
+@retval   FUNCTION_ERROR     Update demod setting unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_UPDATE_FUNCTION() with the corresponding function.
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Execute ResetFunction() before demod software reset.
+	pDemod->ResetFunction(pDemod);
+
+	// Reset demod by software.
+	pDemod->SoftwareReset(pDemod);
+
+	...
+
+	return 0;
+}
+
+
+void PeriodicallyExecutingFunction
+{
+	// Executing UpdateFunction() periodically.
+	pDemod->UpdateFunction(pDemod);
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_UPDATE_FUNCTION)(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T demod reseting function pointer
+
+One can use DVBT_DEMOD_FP_RESET_FUNCTION() to reset demod register setting.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset demod setting successfully.
+@retval   FUNCTION_ERROR     Reset demod setting unsuccessfully.
+
+
+@note
+	-# Demod building function will set DVBT_DEMOD_FP_RESET_FUNCTION() with the corresponding function.
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbtDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Execute ResetFunction() before demod software reset.
+	pDemod->ResetFunction(pDemod);
+
+	// Reset demod by software.
+	pDemod->SoftwareReset(pDemod);
+
+	...
+
+	return 0;
+}
+
+
+void PeriodicallyExecutingFunction
+{
+	// Executing UpdateFunction() periodically.
+	pDemod->UpdateFunction(pDemod);
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_DEMOD_FP_RESET_FUNCTION)(
+	DVBT_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/// RTL2830 extra module
+
+// Definitions for Function 4
+#define DVBT_FUNC4_REG_VALUE_NUM		5
+
+typedef struct RTL2830_EXTRA_MODULE_TAG RTL2830_EXTRA_MODULE;
+
+/*
+
+@brief   RTL2830 application mode getting function pointer
+
+One can use RTL2830_FP_GET_APP_MODE() to get RTL2830 application mode.
+
+
+@param [in]    pDemod     The demod module pointer
+@param [out]   pAppMode   Pointer to an allocated memory for storing demod application mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod application mode successfully.
+@retval   FUNCTION_ERROR     Get demod application mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set RTL2830_FP_GET_APP_MODE() with the corresponding function.
+
+
+@see   RTL2830_APPLICATION_MODE
+
+*/
+typedef void
+(*RTL2830_FP_GET_APP_MODE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAppMode
+	);
+
+struct RTL2830_EXTRA_MODULE_TAG
+{
+	// RTL2830 variables
+	int AppMode;
+
+	// RTL2830 update procedure enabling status
+	int IsFunction2Enabled;
+	int IsFunction3Enabled;
+	int IsFunction4Enabled;
+	int IsFunction5Enabled;
+
+	// RTL2830 update procedure variables
+	unsigned char Func2Executing;
+	unsigned char Func3State;
+	unsigned char Func3Executing;
+	unsigned char Func4State;
+	unsigned long Func4DelayCnt;
+	unsigned long Func4DelayCntMax;
+	unsigned char Func4ParamSetting;
+	unsigned long Func4RegValue[DVBT_FUNC4_REG_VALUE_NUM];
+	unsigned char Func5State;
+	unsigned char Func5QamBak;
+	unsigned char Func5HierBak;
+	unsigned char Func5LpCrBak;
+	unsigned char Func5HpCrBak;
+	unsigned char Func5GiBak;
+	unsigned char Func5FftBak;
+
+	// RTL2830 extra function pointers
+	RTL2830_FP_GET_APP_MODE GetAppMode;
+};
+
+
+
+
+
+/// RTL2832 extra module
+typedef struct RTL2832_EXTRA_MODULE_TAG RTL2832_EXTRA_MODULE;
+
+/*
+
+@brief   RTL2832 application mode getting function pointer
+
+One can use RTL2832_FP_GET_APP_MODE() to get RTL2832 application mode.
+
+
+@param [in]    pDemod     The demod module pointer
+@param [out]   pAppMode   Pointer to an allocated memory for storing demod application mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod application mode successfully.
+@retval   FUNCTION_ERROR     Get demod application mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set RTL2832_FP_GET_APP_MODE() with the corresponding function.
+
+
+@see   RTL2832_APPLICATION_MODE
+
+*/
+typedef void
+(*RTL2832_FP_GET_APP_MODE)(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pAppMode
+	);
+
+struct RTL2832_EXTRA_MODULE_TAG
+{
+	// RTL2832 extra variables
+	int AppMode;
+
+	// RTL2832 update procedure enabling status
+	int IsFunc1Enabled;
+
+	// RTL2832 update Function 1 variables
+	int Func1State;
+
+	int Func1WaitTimeMax;
+	int Func1GettingTimeMax;
+	int Func1GettingNumEachTime;
+
+	int Func1WaitTime;
+	int Func1GettingTime;
+
+	unsigned long Func1RsdBerEstSumNormal;
+	unsigned long Func1RsdBerEstSumConfig1;
+	unsigned long Func1RsdBerEstSumConfig2;
+	unsigned long Func1RsdBerEstSumConfig3;
+
+	int Func1QamBak;
+	int Func1HierBak;
+	int Func1LpCrBak;
+	int Func1HpCrBak;
+	int Func1GiBak;
+	int Func1FftBak;
+
+	// RTL2832 extra function pointers
+	RTL2832_FP_GET_APP_MODE GetAppMode;
+};
+
+
+
+
+
+/// DVB-T demod module structure
+struct DVBT_DEMOD_MODULE_TAG
+{
+	unsigned long CurrentPageNo;
+	// Private variables
+	int           DemodType;
+	unsigned char DeviceAddr;
+	unsigned long CrystalFreqHz;
+	int           TsInterfaceMode;
+
+	int           BandwidthMode;
+	unsigned long IfFreqHz;
+	int           SpectrumMode;
+
+	int IsBandwidthModeSet;
+	int IsIfFreqHzSet;
+	int IsSpectrumModeSet;
+
+	union											///<   Demod extra module used by driving module
+	{
+		RTL2830_EXTRA_MODULE Rtl2830;
+		RTL2832_EXTRA_MODULE Rtl2832;
+	}
+	Extra;
+
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	I2C_BRIDGE_MODULE *pI2cBridge;
+
+
+	// Demod register table
+	DVBT_REG_ENTRY RegTable[DVBT_REG_TABLE_LEN_MAX];
+
+
+	// Demod I2C function pointers
+	DVBT_DEMOD_FP_SET_REG_PAGE             SetRegPage;
+	DVBT_DEMOD_FP_SET_REG_BYTES            SetRegBytes;
+	DVBT_DEMOD_FP_GET_REG_BYTES            GetRegBytes;
+	DVBT_DEMOD_FP_SET_REG_MASK_BITS        SetRegMaskBits;
+	DVBT_DEMOD_FP_GET_REG_MASK_BITS        GetRegMaskBits;
+	DVBT_DEMOD_FP_SET_REG_BITS             SetRegBits;
+	DVBT_DEMOD_FP_GET_REG_BITS             GetRegBits;
+	DVBT_DEMOD_FP_SET_REG_BITS_WITH_PAGE   SetRegBitsWithPage;
+	DVBT_DEMOD_FP_GET_REG_BITS_WITH_PAGE   GetRegBitsWithPage;
+
+
+	// Demod manipulating function pointers
+	DVBT_DEMOD_FP_GET_DEMOD_TYPE        GetDemodType;
+	DVBT_DEMOD_FP_GET_DEVICE_ADDR       GetDeviceAddr;
+	DVBT_DEMOD_FP_GET_CRYSTAL_FREQ_HZ   GetCrystalFreqHz;
+
+	DVBT_DEMOD_FP_IS_CONNECTED_TO_I2C   IsConnectedToI2c;
+
+	DVBT_DEMOD_FP_SOFTWARE_RESET        SoftwareReset;
+
+	DVBT_DEMOD_FP_INITIALIZE            Initialize;
+	DVBT_DEMOD_FP_SET_BANDWIDTH_MODE    SetBandwidthMode;
+	DVBT_DEMOD_FP_SET_IF_FREQ_HZ        SetIfFreqHz;
+	DVBT_DEMOD_FP_SET_SPECTRUM_MODE     SetSpectrumMode;
+	DVBT_DEMOD_FP_GET_BANDWIDTH_MODE    GetBandwidthMode;
+	DVBT_DEMOD_FP_GET_IF_FREQ_HZ        GetIfFreqHz;
+	DVBT_DEMOD_FP_GET_SPECTRUM_MODE     GetSpectrumMode;
+
+	DVBT_DEMOD_FP_IS_TPS_LOCKED         IsTpsLocked;
+	DVBT_DEMOD_FP_IS_SIGNAL_LOCKED      IsSignalLocked;
+
+	DVBT_DEMOD_FP_GET_SIGNAL_STRENGTH   GetSignalStrength;
+	DVBT_DEMOD_FP_GET_SIGNAL_QUALITY    GetSignalQuality;
+
+	DVBT_DEMOD_FP_GET_BER               GetBer;
+	DVBT_DEMOD_FP_GET_SNR_DB            GetSnrDb;
+
+	DVBT_DEMOD_FP_GET_RF_AGC            GetRfAgc;
+	DVBT_DEMOD_FP_GET_IF_AGC            GetIfAgc;
+	DVBT_DEMOD_FP_GET_DI_AGC            GetDiAgc;
+
+	DVBT_DEMOD_FP_GET_TR_OFFSET_PPM     GetTrOffsetPpm;
+	DVBT_DEMOD_FP_GET_CR_OFFSET_HZ      GetCrOffsetHz;
+
+	DVBT_DEMOD_FP_GET_CONSTELLATION     GetConstellation;
+	DVBT_DEMOD_FP_GET_HIERARCHY         GetHierarchy;
+	DVBT_DEMOD_FP_GET_CODE_RATE_LP      GetCodeRateLp;
+	DVBT_DEMOD_FP_GET_CODE_RATE_HP      GetCodeRateHp;
+	DVBT_DEMOD_FP_GET_GUARD_INTERVAL    GetGuardInterval;
+	DVBT_DEMOD_FP_GET_FFT_MODE          GetFftMode;
+
+	DVBT_DEMOD_FP_UPDATE_FUNCTION       UpdateFunction;
+	DVBT_DEMOD_FP_RESET_FUNCTION        ResetFunction;
+};
+
+
+
+
+
+
+
+// DVB-T demod default I2C functions
+int
+dvbt_demod_default_SetRegPage(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long PageNo
+	);
+
+int
+dvbt_demod_default_SetRegBytes(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned char ByteNum
+	);
+
+int
+dvbt_demod_default_GetRegBytes(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned char ByteNum
+	);
+
+int
+dvbt_demod_default_SetRegMaskBits(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+int
+dvbt_demod_default_GetRegMaskBits(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+int
+dvbt_demod_default_SetRegBits(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+int
+dvbt_demod_default_GetRegBits(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+int
+dvbt_demod_default_SetRegBitsWithPage(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+int
+dvbt_demod_default_GetRegBitsWithPage(
+	DVBT_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+// DVB-T demod default manipulating functions
+void
+dvbt_demod_default_GetDemodType(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pDemodType
+	);
+
+void
+dvbt_demod_default_GetDeviceAddr(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned char *pDeviceAddr
+	);
+
+void
+dvbt_demod_default_GetCrystalFreqHz(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pCrystalFreqHz
+	);
+
+int
+dvbt_demod_default_GetBandwidthMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pBandwidthMode
+	);
+
+int
+dvbt_demod_default_GetIfFreqHz(
+	DVBT_DEMOD_MODULE *pDemod,
+	unsigned long *pIfFreqHz
+	);
+
+int
+dvbt_demod_default_GetSpectrumMode(
+	DVBT_DEMOD_MODULE *pDemod,
+	int *pSpectrumMode
+	);
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/dvbt_nim_base.c b/drivers/media/usb/dvb-usb/dvbt_nim_base.c
new file mode 100644
index 0000000..76a5e94
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/dvbt_nim_base.c
@@ -0,0 +1,531 @@
+/**
+
+@file
+
+@brief   DVB-T NIM base module definition
+
+DVB-T NIM base module definitions contains NIM module structure, NIM funciton pointers, NIM definitions, and NIM default
+functions.
+
+*/
+
+
+#include "dvbt_nim_base.h"
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_NIM_TYPE
+
+*/
+void
+dvbt_nim_default_GetNimType(
+	DVBT_NIM_MODULE *pNim,
+	int *pNimType
+	)
+{
+	// Get NIM type from NIM module.
+	*pNimType = pNim->NimType;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+dvbt_nim_default_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_PARAMETERS
+
+*/
+int
+dvbt_nim_default_GetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pRfFreqHz,
+	int *pBandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Get tuner RF frequency in Hz.
+	if(pTuner->GetRfFreqHz(pTuner, pRfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get demod bandwidth mode.
+	if(pDemod->GetBandwidthMode(pDemod, pBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_IS_SIGNAL_PRESENT
+
+*/
+int
+dvbt_nim_default_IsSignalPresent(
+	DVBT_NIM_MODULE *pNim,
+	int *pAnswer
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	DVBT_DEMOD_MODULE *pDemod;
+	int i;
+
+
+	// Get base interface and demod module.
+	pBaseInterface = pNim->pBaseInterface;
+	pDemod         = pNim->pDemod;
+
+
+	// Wait for signal present check.
+	for(i = 0; i < DVBT_NIM_SINGAL_PRESENT_CHECK_TIMES_MAX_DEFAULT; i++)
+	{
+		// Wait 20 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 20);
+
+		// Check TPS present status on demod.
+		// Note: If TPS is locked, stop signal present check.
+		if(pDemod->IsTpsLocked(pDemod, pAnswer) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		if(*pAnswer == YES)
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_IS_SIGNAL_LOCKED
+
+*/
+int
+dvbt_nim_default_IsSignalLocked(
+	DVBT_NIM_MODULE *pNim,
+	int *pAnswer
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	DVBT_DEMOD_MODULE *pDemod;
+	int i;
+
+
+	// Get base interface and demod module.
+	pBaseInterface = pNim->pBaseInterface;
+	pDemod         = pNim->pDemod;
+
+
+	// Wait for signal lock check.
+	for(i = 0; i < DVBT_NIM_SINGAL_LOCK_CHECK_TIMES_MAX_DEFAULT; i++)
+	{
+		// Wait 20 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 20);
+
+		// Check signal lock status on demod.
+		// Note: If signal is locked, stop signal lock check.
+		if(pDemod->IsSignalLocked(pDemod, pAnswer) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		if(*pAnswer == YES)
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_SIGNAL_STRENGTH
+
+*/
+int
+dvbt_nim_default_GetSignalStrength(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pSignalStrength
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get signal strength from demod.
+	if(pDemod->GetSignalStrength(pDemod, pSignalStrength) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_SIGNAL_QUALITY
+
+*/
+int
+dvbt_nim_default_GetSignalQuality(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pSignalQuality
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get signal quality from demod.
+	if(pDemod->GetSignalQuality(pDemod, pSignalQuality) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_BER
+
+*/
+int
+dvbt_nim_default_GetBer(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get BER from demod.
+	if(pDemod->GetBer(pDemod, pBerNum, pBerDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_SNR_DB
+
+*/
+int
+dvbt_nim_default_GetSnrDb(
+	DVBT_NIM_MODULE *pNim,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get SNR in dB from demod.
+	if(pDemod->GetSnrDb(pDemod, pSnrDbNum, pSnrDbDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_TR_OFFSET_PPM
+
+*/
+int
+dvbt_nim_default_GetTrOffsetPpm(
+	DVBT_NIM_MODULE *pNim,
+	long *pTrOffsetPpm
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get TR offset in ppm from demod.
+	if(pDemod->GetTrOffsetPpm(pDemod, pTrOffsetPpm) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_CR_OFFSET_HZ
+
+*/
+int
+dvbt_nim_default_GetCrOffsetHz(
+	DVBT_NIM_MODULE *pNim,
+	long *pCrOffsetHz
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get CR offset in Hz from demod.
+	if(pDemod->GetCrOffsetHz(pDemod, pCrOffsetHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_TPS_INFO
+
+*/
+int
+dvbt_nim_default_GetTpsInfo(
+	DVBT_NIM_MODULE *pNim,
+	int *pConstellation,
+	int *pHierarchy,
+	int *pCodeRateLp,
+	int *pCodeRateHp,
+	int *pGuardInterval,
+	int *pFftMode
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get TPS constellation information from demod.
+	if(pDemod->GetConstellation(pDemod, pConstellation) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get TPS hierarchy information from demod.
+	if(pDemod->GetHierarchy(pDemod, pHierarchy) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get TPS low-priority code rate information from demod.
+	if(pDemod->GetCodeRateLp(pDemod, pCodeRateLp) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get TPS high-priority code rate information from demod.
+	if(pDemod->GetCodeRateHp(pDemod, pCodeRateHp) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get TPS guard interval information from demod.
+	if(pDemod->GetGuardInterval(pDemod, pGuardInterval) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get TPS FFT mode information from demod.
+	if(pDemod->GetFftMode(pDemod, pFftMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_UPDATE_FUNCTION
+
+*/
+int
+dvbt_nim_default_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Update demod particular registers.
+	if(pDemod->UpdateFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/dvbt_nim_base.h b/drivers/media/usb/dvb-usb/dvbt_nim_base.h
new file mode 100644
index 0000000..c584735
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/dvbt_nim_base.h
@@ -0,0 +1,964 @@
+#ifndef __DVBT_NIM_BASE_H
+#define __DVBT_NIM_BASE_H
+
+/**
+
+@file
+
+@brief   DVB-T NIM base module definition
+
+DVB-T NIM base module definitions contains NIM module structure, NIM funciton pointers, NIM definitions, and NIM default
+functions.
+
+
+
+@par Example:
+@code
+
+
+#include "nim_demodx_tunery.h"
+
+
+
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C reading format:
+	// start_bit + (DeviceAddr | reading_bit) + reading_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+int
+CustomI2cWrite(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C writing format:
+	// start_bit + (DeviceAddr | writing_bit) + writing_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+void
+CustomWaitMs(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned long WaitTimeMs
+	)
+{
+	// Wait WaitTimeMs milliseconds.
+
+	...
+
+	return;
+}
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+	DEMODX_EXTRA_MODULE DemodxExtraModuleMemory;
+	TUNERY_EXTRA_MODULE TuneryExtraModuleMemory;
+
+	unsigned long RfFreqHz;
+	int BandwidthMode;
+
+	int Answer;
+	unsigned long SignalStrength, SignalQuality;
+	unsigned long BerNum, BerDen, PerNum, PerDen;
+	double Ber, Per;
+	unsigned long SnrDbNum, SnrDbDen;
+	double SnrDb;
+	long TrOffsetPpm, CrOffsetHz;
+
+	int Constellation;
+	int Hierarchy;
+	int CodeRateLp;
+	int CodeRateHp;
+	int GuardInterval;
+	int FftMode;
+
+
+
+	// Build Demod-X Tuner-Y NIM module.
+	BuildDemodxTuneryModule(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		&DemodxExtraModuleMemory,		// Employ Demod-X extra module.
+		0x20,							// The Demod-X I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The Demod-X crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The Demod-X TS interface mode is serial.
+		...								// Other arguments for Demod-X
+
+		&TunerxExtraModuleMemory,		// Employ Tuner-Y extra module.
+		0xc0,							// The Tuner-Y I2C device address is 0xc0 in 8-bit format.
+		...								// Other arguments for Tuner-Y
+		);
+
+
+
+	// Get NIM type.
+	// Note: NIM types are defined in the MODULE_TYPE enumeration.
+	pNim->GetNimType(pNim, &NimType);
+
+
+
+
+
+
+
+	// ==== Initialize NIM and set its parameters =====
+
+	// Initialize NIM.
+	pNim->Initialize(pNim);
+
+	// Set NIM parameters. (RF frequency, bandwdith mode)
+	// Note: In the example:
+	//       1. RF frequency is 666 MHz.
+	//       2. Bandwidth mode is 8 MHz.
+	RfFreqHz      = 666000000;
+	BandwidthMode = DVBT_BANDWIDTH_8MHZ;
+	pNim->SetParameters(pNim, RfFreqHz, BandwidthMode);
+
+
+
+	// Wait 1 second for demod convergence.
+
+
+
+
+
+	// ==== Get NIM information =====
+
+	// Get NIM parameters. (RF frequency, bandwdith mode)
+	pNim->GetParameters(pNim, &RfFreqHz, &BandwidthMode);
+
+
+	// Get signal present status.
+	// Note: 1. The argument Answer is YES when the NIM module has found DVB-T signal in the RF channel.
+	//       2. The argument Answer is NO when the NIM module does not find DVB-T signal in the RF channel.
+	// Recommendation: Use the IsSignalPresent() function for channel scan.
+	pNim->IsSignalPresent(pNim, &Answer);
+
+	// Get signal lock status.
+	// Note: 1. The argument Answer is YES when the NIM module has locked DVB-T signal in the RF channel.
+	//          At the same time, the NIM module sends TS packets through TS interface hardware pins.
+	//       2. The argument Answer is NO when the NIM module does not lock DVB-T signal in the RF channel.
+	// Recommendation: Use the IsSignalLocked() function for signal lock check.
+	pNim->IsSignalLocked(pNim, &Answer);
+
+
+	// Get signal strength.
+	// Note: 1. The range of SignalStrength is 0~100.
+	//       2. Need to map SignalStrength value to UI signal strength bar manually.
+	pNim->GetSignalStrength(pNim, &SignalStrength);
+
+	// Get signal quality.
+	// Note: 1. The range of SignalQuality is 0~100.
+	//       2. Need to map SignalQuality value to UI signal quality bar manually.
+	pNim->GetSignalQuality(pNim, &SignalQuality);
+
+
+	// Get BER.
+	pNim->GetBer(pNim, &BerNum, &BerDen);
+	Ber = (double)BerNum / (double)BerDen;
+
+	// Get SNR in dB.
+	pNim->GetSnrDb(pNim, &SnrDbNum, &SnrDbDen);
+	SnrDb = (double)SnrDbNum / (double)SnrDbDen;
+
+
+	// Get TR offset (symbol timing offset) in ppm.
+	pNim->GetTrOffsetPpm(pNim, &TrOffsetPpm);
+
+	// Get CR offset (RF frequency offset) in Hz.
+	pNim->GetCrOffsetHz(pNim, &CrOffsetHz);
+
+
+	// Get TPS information.
+	// Note: One can find TPS information definitions in the enumerations as follows:
+	//       1. DVBT_CONSTELLATION_MODE.
+	//       2. DVBT_HIERARCHY_MODE.
+	//       3. DVBT_CODE_RATE_MODE. (for low-priority and high-priority code rate)
+	//       4. DVBT_GUARD_INTERVAL_MODE.
+	//       5. DVBT_FFT_MODE_MODE
+	pNim->GetTpsInfo(pNim, &Constellation, &Hierarchy, &CodeRateLp, &CodeRateHp, &GuardInterval, &FftMode);
+
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "foundation.h"
+#include "tuner_base.h"
+#include "dvbt_demod_base.h"
+
+
+
+
+
+// Definitions
+#define DVBT_NIM_SINGAL_PRESENT_CHECK_TIMES_MAX_DEFAULT			1
+#define DVBT_NIM_SINGAL_LOCK_CHECK_TIMES_MAX_DEFAULT			1
+
+
+
+
+
+/// DVB-T NIM module pre-definition
+typedef struct DVBT_NIM_MODULE_TAG DVBT_NIM_MODULE;
+
+
+
+
+
+/**
+
+@brief   DVB-T demod type getting function pointer
+
+One can use DVBT_NIM_FP_GET_NIM_TYPE() to get DVB-T NIM type.
+
+
+@param [in]    pNim       The NIM module pointer
+@param [out]   pNimType   Pointer to an allocated memory for storing NIM type
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_GET_NIM_TYPE() with the corresponding function.
+
+
+@see   MODULE_TYPE
+
+*/
+typedef void
+(*DVBT_NIM_FP_GET_NIM_TYPE)(
+	DVBT_NIM_MODULE *pNim,
+	int *pNimType
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM initializing function pointer
+
+One can use DVBT_NIM_FP_INITIALIZE() to initialie DVB-T NIM.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Initialize NIM successfully.
+@retval   FUNCTION_ERROR     Initialize NIM unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_INITIALIZE() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_NIM_FP_INITIALIZE)(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM parameter setting function pointer
+
+One can use DVBT_NIM_FP_SET_PARAMETERS() to set DVB-T NIM parameters.
+
+
+@param [in]   pNim            The NIM module pointer
+@param [in]   RfFreqHz        RF frequency in Hz for setting
+@param [in]   BandwidthMode   Bandwidth mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set NIM parameters successfully.
+@retval   FUNCTION_ERROR     Set NIM parameters unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_SET_PARAMETERS() with the corresponding function.
+
+
+@see   DVBT_BANDWIDTH_MODE
+
+*/
+typedef int
+(*DVBT_NIM_FP_SET_PARAMETERS)(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM parameter getting function pointer
+
+One can use DVBT_NIM_FP_GET_PARAMETERS() to get DVB-T NIM parameters.
+
+
+@param [in]    pNim             The NIM module pointer
+@param [out]   pRfFreqHz        Pointer to an allocated memory for storing NIM RF frequency in Hz
+@param [out]   pBandwidthMode   Pointer to an allocated memory for storing NIM bandwidth mode
+
+
+@retval   FUNCTION_SUCCESS   Get NIM parameters successfully.
+@retval   FUNCTION_ERROR     Get NIM parameters unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_GET_PARAMETERS() with the corresponding function.
+
+
+@see   DVBT_BANDWIDTH_MODE
+
+*/
+typedef int
+(*DVBT_NIM_FP_GET_PARAMETERS)(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pRfFreqHz,
+	int *pBandwidthMode
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM signal present asking function pointer
+
+One can use DVBT_NIM_FP_IS_SIGNAL_PRESENT() to ask DVB-T NIM if signal is present.
+
+
+@param [in]    pNim      The NIM module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform signal present asking to NIM successfully.
+@retval   FUNCTION_ERROR     Perform signal present asking to NIM unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_IS_SIGNAL_PRESENT() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_NIM_FP_IS_SIGNAL_PRESENT)(
+	DVBT_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM signal lock asking function pointer
+
+One can use DVBT_NIM_FP_IS_SIGNAL_LOCKED() to ask DVB-T NIM if signal is locked.
+
+
+@param [in]    pNim      The NIM module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform signal lock asking to NIM successfully.
+@retval   FUNCTION_ERROR     Perform signal lock asking to NIM unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_IS_SIGNAL_LOCKED() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_NIM_FP_IS_SIGNAL_LOCKED)(
+	DVBT_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM signal strength getting function pointer
+
+One can use DVBT_NIM_FP_GET_SIGNAL_STRENGTH() to get signal strength.
+
+
+@param [in]    pNim              The NIM module pointer
+@param [out]   pSignalStrength   Pointer to an allocated memory for storing signal strength (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get NIM signal strength successfully.
+@retval   FUNCTION_ERROR     Get NIM signal strength unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_GET_SIGNAL_STRENGTH() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_NIM_FP_GET_SIGNAL_STRENGTH)(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pSignalStrength
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM signal quality getting function pointer
+
+One can use DVBT_NIM_FP_GET_SIGNAL_QUALITY() to get signal quality.
+
+
+@param [in]    pNim             The NIM module pointer
+@param [out]   pSignalQuality   Pointer to an allocated memory for storing signal quality (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get NIM signal quality successfully.
+@retval   FUNCTION_ERROR     Get NIM signal quality unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_GET_SIGNAL_QUALITY() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_NIM_FP_GET_SIGNAL_QUALITY)(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pSignalQuality
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM BER value getting function pointer
+
+One can use DVBT_NIM_FP_GET_BER() to get BER.
+
+
+@param [in]    pNim            The NIM module pointer
+@param [out]   pBerNum         Pointer to an allocated memory for storing BER numerator
+@param [out]   pBerDen         Pointer to an allocated memory for storing BER denominator
+
+
+@retval   FUNCTION_SUCCESS   Get NIM BER value successfully.
+@retval   FUNCTION_ERROR     Get NIM BER value unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_GET_BER() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_NIM_FP_GET_BER)(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM SNR getting function pointer
+
+One can use DVBT_NIM_FP_GET_SNR_DB() to get SNR in dB.
+
+
+@param [in]    pNim        The NIM module pointer
+@param [out]   pSnrDbNum   Pointer to an allocated memory for storing SNR dB numerator
+@param [out]   pSnrDbDen   Pointer to an allocated memory for storing SNR dB denominator
+
+
+@retval   FUNCTION_SUCCESS   Get NIM SNR successfully.
+@retval   FUNCTION_ERROR     Get NIM SNR unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_GET_SNR_DB() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_NIM_FP_GET_SNR_DB)(
+	DVBT_NIM_MODULE *pNim,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM TR offset getting function pointer
+
+One can use DVBT_NIM_FP_GET_TR_OFFSET_PPM() to get TR offset in ppm.
+
+
+@param [in]    pNim           The NIM module pointer
+@param [out]   pTrOffsetPpm   Pointer to an allocated memory for storing TR offset in ppm
+
+
+@retval   FUNCTION_SUCCESS   Get NIM TR offset successfully.
+@retval   FUNCTION_ERROR     Get NIM TR offset unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_GET_TR_OFFSET_PPM() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_NIM_FP_GET_TR_OFFSET_PPM)(
+	DVBT_NIM_MODULE *pNim,
+	long *pTrOffsetPpm
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM CR offset getting function pointer
+
+One can use DVBT_NIM_FP_GET_CR_OFFSET_HZ() to get CR offset in Hz.
+
+
+@param [in]    pNim          The NIM module pointer
+@param [out]   pCrOffsetHz   Pointer to an allocated memory for storing CR offset in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get NIM CR offset successfully.
+@retval   FUNCTION_ERROR     Get NIM CR offset unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_GET_CR_OFFSET_HZ() with the corresponding function.
+
+*/
+typedef int
+(*DVBT_NIM_FP_GET_CR_OFFSET_HZ)(
+	DVBT_NIM_MODULE *pNim,
+	long *pCrOffsetHz
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM TPS information getting function pointer
+
+One can use DVBT_NIM_FP_GET_TPS_INFO() to get TPS information.
+
+
+@param [in]    pNim             The NIM module pointer
+@param [out]   pConstellation   Pointer to an allocated memory for storing demod constellation mode
+@param [out]   pHierarchy       Pointer to an allocated memory for storing demod hierarchy mode
+@param [out]   pCodeRateLp      Pointer to an allocated memory for storing demod low-priority code rate mode
+@param [out]   pCodeRateHp      Pointer to an allocated memory for storing demod high-priority code rate mode
+@param [out]   pGuardInterval   Pointer to an allocated memory for storing demod guard interval mode
+@param [out]   pFftMode         Pointer to an allocated memory for storing demod FFT mode
+
+
+@retval   FUNCTION_SUCCESS   Get NIM TPS information successfully.
+@retval   FUNCTION_ERROR     Get NIM TPS information unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_GET_TPS_INFO() with the corresponding function.
+
+
+@see   DVBT_CONSTELLATION_MODE, DVBT_HIERARCHY_MODE, DVBT_CODE_RATE_MODE, DVBT_GUARD_INTERVAL_MODE, DVBT_FFT_MODE_MODE
+
+*/
+typedef int
+(*DVBT_NIM_FP_GET_TPS_INFO)(
+	DVBT_NIM_MODULE *pNim,
+	int *pConstellation,
+	int *pHierarchy,
+	int *pCodeRateLp,
+	int *pCodeRateHp,
+	int *pGuardInterval,
+	int *pFftMode
+	);
+
+
+
+
+
+/**
+
+@brief   DVB-T NIM updating function pointer
+
+One can use DVBT_NIM_FP_UPDATE_FUNCTION() to update NIM register setting.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update NIM setting successfully.
+@retval   FUNCTION_ERROR     Update NIM setting unsuccessfully.
+
+
+@note
+	-# NIM building function will set DVBT_NIM_FP_UPDATE_FUNCTION() with the corresponding function.
+
+
+
+@par Example:
+@code
+
+
+#include "nim_demodx_tunery.h"
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+	DEMODX_EXTRA_MODULE DemodxExtraModuleMemory;
+	TUNERY_EXTRA_MODULE TuneryExtraModuleMemory;
+
+
+	// Build Demod-X Tuner-Y NIM module.
+	BuildDemodxTuneryModule(
+		...
+		);
+
+	...
+
+
+	return 0;
+}
+
+
+void PeriodicallyExecutingFunction
+{
+	// Executing UpdateFunction() periodically.
+	pNim->UpdateFunction(pNim);
+}
+
+
+@endcode
+
+*/
+typedef int
+(*DVBT_NIM_FP_UPDATE_FUNCTION)(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+
+
+
+// RTL2832 MT2266 extra module
+typedef struct RTL2832_MT2266_EXTRA_MODULE_TAG RTL2832_MT2266_EXTRA_MODULE;
+struct RTL2832_MT2266_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned char LnaConfig;
+	unsigned char UhfSens;
+	unsigned char AgcCurrentState;
+	unsigned long LnaGainOld;
+};
+
+
+
+
+
+// RTL2832 E4000 extra module
+typedef struct RTL2832_E4000_EXTRA_MODULE_TAG RTL2832_E4000_EXTRA_MODULE;
+struct RTL2832_E4000_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long TunerModeUpdateWaitTimeMax;
+	unsigned long TunerModeUpdateWaitTime;
+	unsigned char TunerGainMode;
+};
+
+
+
+
+
+// RTL2832 E4005 extra module
+typedef struct RTL2832_E4005_EXTRA_MODULE_TAG RTL2832_E4005_EXTRA_MODULE;
+struct RTL2832_E4005_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long TunerModeUpdateWaitTimeMax;
+	unsigned long TunerModeUpdateWaitTime;
+	unsigned char TunerGainMode;
+};
+
+
+
+
+
+// RTL2832 MT2063 extra module
+typedef struct RTL2832_MT2063_EXTRA_MODULE_TAG RTL2832_MT2063_EXTRA_MODULE;
+struct RTL2832_MT2063_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long IfFreqHz;
+};
+
+
+
+
+
+// RTL2832 FC0012 extra module
+typedef struct RTL2832_FC0012_EXTRA_MODULE_TAG RTL2832_FC0012_EXTRA_MODULE;
+struct RTL2832_FC0012_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long LnaUpdateWaitTimeMax;
+	unsigned long LnaUpdateWaitTime;
+	unsigned long RssiRCalOn;
+};
+
+
+
+
+
+// RTL2832 FC0013 extra module
+typedef struct RTL2832_FC0013_EXTRA_MODULE_TAG RTL2832_FC0013_EXTRA_MODULE;
+struct RTL2832_FC0013_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long LnaUpdateWaitTimeMax;
+	unsigned long LnaUpdateWaitTime;
+	unsigned long RssiRCalOn;
+};
+
+
+
+
+
+// RTL2832 FC0013B extra module
+typedef struct RTL2832_FC0013B_EXTRA_MODULE_TAG RTL2832_FC0013B_EXTRA_MODULE;
+struct RTL2832_FC0013B_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long LnaUpdateWaitTimeMax;
+	unsigned long LnaUpdateWaitTime;
+	unsigned long RssiRCalOn;
+};
+
+
+
+
+
+/// DVB-T NIM module structure
+struct DVBT_NIM_MODULE_TAG
+{
+	// Private variables
+	int NimType;
+
+	union														///<   NIM extra module used by driving module
+	{
+		RTL2832_MT2266_EXTRA_MODULE Rtl2832Mt2266;
+		RTL2832_E4000_EXTRA_MODULE  Rtl2832E4000;
+		RTL2832_E4005_EXTRA_MODULE     Rtl2832E4005;
+		RTL2832_MT2063_EXTRA_MODULE Rtl2832Mt2063;
+		RTL2832_FC0012_EXTRA_MODULE Rtl2832Fc0012;
+		RTL2832_FC0013_EXTRA_MODULE Rtl2832Fc0013;
+		RTL2832_FC0013B_EXTRA_MODULE   Rtl2832Fc0013b;
+	}
+	Extra;
+
+
+	// Modules
+	BASE_INTERFACE_MODULE *pBaseInterface;						///<   Base interface module pointer
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;			///<   Base interface module memory
+
+	I2C_BRIDGE_MODULE *pI2cBridge;								///<   I2C bridge module pointer
+	I2C_BRIDGE_MODULE I2cBridgeModuleMemory;					///<   I2C bridge module memory
+
+	TUNER_MODULE *pTuner;										///<   Tuner module pointer
+	TUNER_MODULE TunerModuleMemory;								///<   Tuner module memory
+
+	DVBT_DEMOD_MODULE *pDemod;									///<   DVB-T demod module pointer
+	DVBT_DEMOD_MODULE DvbtDemodModuleMemory;					///<   DVB-T demod module memory
+
+
+	// NIM manipulating functions
+	DVBT_NIM_FP_GET_NIM_TYPE          GetNimType;
+	DVBT_NIM_FP_INITIALIZE            Initialize;
+	DVBT_NIM_FP_SET_PARAMETERS        SetParameters;
+	DVBT_NIM_FP_GET_PARAMETERS        GetParameters;
+	DVBT_NIM_FP_IS_SIGNAL_PRESENT     IsSignalPresent;
+	DVBT_NIM_FP_IS_SIGNAL_LOCKED      IsSignalLocked;
+	DVBT_NIM_FP_GET_SIGNAL_STRENGTH   GetSignalStrength;
+	DVBT_NIM_FP_GET_SIGNAL_QUALITY    GetSignalQuality;
+	DVBT_NIM_FP_GET_BER               GetBer;
+	DVBT_NIM_FP_GET_SNR_DB            GetSnrDb;
+	DVBT_NIM_FP_GET_TR_OFFSET_PPM     GetTrOffsetPpm;
+	DVBT_NIM_FP_GET_CR_OFFSET_HZ      GetCrOffsetHz;
+	DVBT_NIM_FP_GET_TPS_INFO          GetTpsInfo;
+	DVBT_NIM_FP_UPDATE_FUNCTION       UpdateFunction;
+};
+
+
+
+
+
+
+
+// DVB-T NIM default manipulaing functions
+void
+dvbt_nim_default_GetNimType(
+	DVBT_NIM_MODULE *pNim,
+	int *pNimType
+	);
+
+int
+dvbt_nim_default_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+dvbt_nim_default_GetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pRfFreqHz,
+	int *pBandwidthMode
+	);
+
+int
+dvbt_nim_default_IsSignalPresent(
+	DVBT_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+int
+dvbt_nim_default_IsSignalLocked(
+	DVBT_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+int
+dvbt_nim_default_GetSignalStrength(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pSignalStrength
+	);
+
+int
+dvbt_nim_default_GetSignalQuality(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pSignalQuality
+	);
+
+int
+dvbt_nim_default_GetBer(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen
+	);
+
+int
+dvbt_nim_default_GetSnrDb(
+	DVBT_NIM_MODULE *pNim,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+int
+dvbt_nim_default_GetTrOffsetPpm(
+	DVBT_NIM_MODULE *pNim,
+	long *pTrOffsetPpm
+	);
+
+int
+dvbt_nim_default_GetCrOffsetHz(
+	DVBT_NIM_MODULE *pNim,
+	long *pCrOffsetHz
+	);
+
+int
+dvbt_nim_default_GetTpsInfo(
+	DVBT_NIM_MODULE *pNim,
+	int *pConstellation,
+	int *pHierarchy,
+	int *pCodeRateLp,
+	int *pCodeRateHp,
+	int *pGuardInterval,
+	int *pFftMode
+	);
+
+int
+dvbt_nim_default_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/foundation.c b/drivers/media/usb/dvb-usb/foundation.c
new file mode 100644
index 0000000..c5e8e52
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/foundation.c
@@ -0,0 +1,352 @@
+/**
+
+@file
+
+@brief   Fundamental interface definition
+
+Fundamental interface contains base function pointers and some mathematics tools.
+
+*/
+
+
+#include "foundation.h"
+
+
+
+
+
+// Base interface builder
+void
+BuildBaseInterface(
+	BASE_INTERFACE_MODULE **ppBaseInterface,
+	BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory,
+	unsigned long I2cReadingByteNumMax,
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs
+	)
+{
+	// Set base interface module pointer.
+	*ppBaseInterface = pBaseInterfaceModuleMemory;
+
+
+	// Set all base interface function pointers and arguments.
+	(*ppBaseInterface)->I2cReadingByteNumMax      = I2cReadingByteNumMax;
+	(*ppBaseInterface)->I2cWritingByteNumMax      = I2cWritingByteNumMax;
+	(*ppBaseInterface)->I2cRead                   = I2cRead;
+	(*ppBaseInterface)->I2cWrite                  = I2cWrite;
+	(*ppBaseInterface)->WaitMs                    = WaitMs;
+	(*ppBaseInterface)->SetUserDefinedDataPointer = base_interface_SetUserDefinedDataPointer;
+	(*ppBaseInterface)->GetUserDefinedDataPointer = base_interface_GetUserDefinedDataPointer;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Set user defined data pointer of base interface structure for custom basic function implementation.
+
+@note
+	-# Base interface builder will set BASE_FP_SET_USER_DEFINED_DATA_POINTER() function pointer with
+	   base_interface_SetUserDefinedDataPointer().
+
+@see   BASE_FP_SET_USER_DEFINED_DATA_POINTER
+
+*/
+void
+base_interface_SetUserDefinedDataPointer(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	void *pUserDefinedData
+	)
+{
+	// Set user defined data pointer of base interface structure with user defined data pointer argument.
+	pBaseInterface->pUserDefinedData = pUserDefinedData;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Get user defined data pointer of base interface structure for custom basic function implementation.
+
+@note
+	-# Base interface builder will set BASE_FP_GET_USER_DEFINED_DATA_POINTER() function pointer with
+	   base_interface_GetUserDefinedDataPointer().
+
+@see   BASE_FP_GET_USER_DEFINED_DATA_POINTER
+
+*/
+void
+base_interface_GetUserDefinedDataPointer(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	void **ppUserDefinedData
+	)
+{
+	// Get user defined data pointer from base interface structure to the caller user defined data pointer.
+	*ppUserDefinedData = pBaseInterface->pUserDefinedData;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Convert signed integer to binary.
+
+Convert 2's complement signed integer to binary with bit number.
+
+
+@param [in]   Value    the converting value in 2's complement format
+@param [in]   BitNum   the bit number of the converting value
+
+
+@return   Converted binary
+
+
+@note
+	The converting value must be -pow(2, BitNum - 1) ~ (pow(2, BitNum - 1) -1).
+
+
+
+@par Example:
+@code
+
+
+#include "foundation.h"
+
+
+int main(void)
+{
+	long Value = -345;
+	unsigned long Binary;
+
+
+	// Convert 2's complement integer to binary with 10 bit number.
+	Binary = SignedIntToBin(Value, 10);
+
+
+	// Result in base 2:
+	// Value  = 1111 1111 1111 1111 1111 1110 1010 0111 b = -345  (in 32-bit 2's complement format)
+	// Binary = 0000 0000 0000 0000 0000 0010 1010 0111 b =  679  (in 10-bit binary format)
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+unsigned long
+SignedIntToBin(
+	long Value,
+	unsigned char BitNum
+	)
+{
+	unsigned int i;
+	unsigned long Mask, Binary;
+
+
+
+	// Generate Mask according to BitNum.
+	Mask = 0;
+	for(i = 0; i < BitNum; i++)
+		Mask |= 0x1 << i;
+
+
+	// Convert signed integer to binary with Mask.
+	Binary = Value & Mask;
+
+
+	return Binary;
+}
+
+
+
+
+
+/**
+
+@brief   Convert binary to signed integer.
+
+Convert binary to 2's complement signed integer with bit number.
+
+
+@param [in]   Binary   the converting binary
+@param [in]   BitNum   the bit number of the converting binary
+
+
+@return   Converted 2's complement signed integer
+
+
+@note
+	The converting binary must be 0 ~ (pow(2, BitNum) - 1).
+
+
+
+@par Example:
+@code
+
+
+#include "foundation.h"
+
+
+int main(void)
+{
+	unsigned long Binary = 679;
+	long Value;
+
+
+	// Convert binary to 2's complement integer with 10 bit number.
+	Value = BinToSignedInt(Binary, 10);
+
+
+	// Result in base 2:
+	// Binary = 0000 0000 0000 0000 0000 0010 1010 0111 b =  679  (in 10-bit binary format)
+	// Value  = 1111 1111 1111 1111 1111 1110 1010 0111 b = -345  (in 32-bit 2's complement format)
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+long
+BinToSignedInt(
+	unsigned long Binary,
+	unsigned char BitNum
+	)
+{
+	int i;
+
+	unsigned char SignedBit;
+	unsigned long SignedBitExtension;
+
+	long Value;
+
+
+
+	// Get signed bit.
+	SignedBit = (unsigned char)((Binary >> (BitNum - 1)) & BIT_0_MASK);
+
+
+	// Generate signed bit extension.
+	SignedBitExtension = 0;
+
+	for(i = BitNum; i < LONG_BIT_NUM; i++)
+		SignedBitExtension |= SignedBit << i;
+
+
+	// Combine binary value and signed bit extension to signed integer value.
+	Value = (long)(Binary | SignedBitExtension);
+
+
+	return Value;
+}
+
+
+
+
+
+/**
+
+@brief   Get devision reult with ceiling.
+
+Get unsigned devision reult with ceiling.
+
+
+@param [in]   Dividend   the dividend
+@param [in]   Divisor    the divisor
+
+
+@return   Result with ceiling
+
+
+@note
+	The dividend and divisor must be unsigned integer.
+
+
+
+@par Example:
+@code
+
+
+#include "foundation.h"
+
+
+int main(void)
+{
+	long Value;
+
+
+	// Get ceil(100 / 20) reult.
+	Value = DivideWithCeiling(100, 20);
+
+	// Result: Value  = 5
+
+
+	// Get ceil(100 / 30) reult.
+	Value = DivideWithCeiling(100, 30);
+
+	// Result: Value  = 4
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+unsigned long
+DivideWithCeiling(
+	unsigned long Dividend,
+	unsigned long Divisor
+	)
+{
+	unsigned long Result;
+
+
+	// Get primitive division result.
+	Result = Dividend / Divisor;
+
+	// Adjust primitive result with ceiling.
+	if(Dividend % Divisor > 0)
+		Result += 1;
+
+
+	return Result;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/foundation.h b/drivers/media/usb/dvb-usb/foundation.h
new file mode 100644
index 0000000..d5dcf2d
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/foundation.h
@@ -0,0 +1,1026 @@
+#ifndef __FOUNDATION_H
+#define __FOUNDATION_H
+
+/**
+
+@file
+
+@brief   Fundamental interface declaration
+
+Fundamental interface contains base function pointers and some mathematics tools.
+
+*/
+
+
+#include "i2c_bridge.h"
+#include "math_mpi.h"
+
+
+#include "dvb-usb.h"
+#include "rtl2832u_io.h"
+
+
+
+// Definitions
+
+// API version
+#define REALTEK_NIM_API_VERSION		"Realtek NIM API 2012.03.30"
+
+
+
+// Constants
+#define INVALID_POINTER_VALUE		0
+#define NO_USE						0
+
+#define LEN_1_BYTE					1
+#define LEN_2_BYTE					2
+#define LEN_3_BYTE					3
+#define LEN_4_BYTE					4
+#define LEN_5_BYTE					5
+#define LEN_6_BYTE					6
+#define LEN_11_BYTE					11
+
+#define LEN_1_BIT					1
+
+#define BYTE_MASK					0xff
+#define BYTE_SHIFT					8
+#define HEX_DIGIT_MASK				0xf
+#define BYTE_BIT_NUM				8
+#define LONG_BIT_NUM				32
+
+#define BIT_0_MASK					0x1
+#define BIT_1_MASK					0x2
+#define BIT_2_MASK					0x4
+#define BIT_3_MASK					0x8
+
+#define BIT_4_MASK					0x10
+#define BIT_5_MASK					0x20
+#define BIT_6_MASK					0x40
+#define BIT_7_MASK					0x80
+
+
+#define BIT_8_MASK					0x100
+#define BIT_7_SHIFT					7
+#define BIT_8_SHIFT					8
+
+
+
+// I2C buffer length
+// Note: I2C_BUFFER_LEN must be greater than I2cReadingByteNumMax and I2cWritingByteNumMax in BASE_INTERFACE_MODULE.
+#define I2C_BUFFER_LEN				128
+
+
+
+
+
+/// Module types
+enum MODULE_TYPE
+{
+	// DVB-T demod
+	DVBT_DEMOD_TYPE_RTL2830,				///<   RTL2830 DVB-T demod
+	DVBT_DEMOD_TYPE_RTL2832,				///<   RTL2832 DVB-T demod
+
+	// QAM demod
+	QAM_DEMOD_TYPE_RTL2840,					///<   RTL2840 DVB-C demod
+	QAM_DEMOD_TYPE_RTL2810_OC,				///<   RTL2810 OpenCable demod
+	QAM_DEMOD_TYPE_RTL2820_OC,				///<   RTL2820 OpenCable demod
+	QAM_DEMOD_TYPE_RTD2885_QAM,				///<   RTD2885 QAM demod
+	QAM_DEMOD_TYPE_RTD2932_QAM,				///<   RTD2932 QAM demod
+	QAM_DEMOD_TYPE_RTL2836B_DVBC,			///<   RTL2836 DVB-C demod
+	QAM_DEMOD_TYPE_RTL2810B_QAM,			///<   RTL2810B QAM demod
+	QAM_DEMOD_TYPE_RTD2840B_QAM,			///<   RTD2840B QAM demod
+	QAM_DEMOD_TYPE_RTD2648_QAM,				///<   RTD2648 QAM demod
+
+	// OOB demod
+	OOB_DEMOD_TYPE_RTL2820_OOB,				///<   RTL2820 OOB demod
+
+	// ATSC demod
+	ATSC_DEMOD_TYPE_RTL2820_ATSC,			///<   RTL2820 ATSC demod
+	ATSC_DEMOD_TYPE_RTD2885_ATSC,			///<   RTD2885 ATSC demod
+	ATSC_DEMOD_TYPE_RTD2932_ATSC,			///<   RTD2932 ATSC demod
+	ATSC_DEMOD_TYPE_RTL2810B_ATSC,			///<   RTL2810B ATSC demod
+	ATSC_DEMOD_TYPE_RTD2648_ATSC,			///<   RTD2648 ATSC demod
+
+	// DTMB demod
+	DTMB_DEMOD_TYPE_RTL2836,				///<   RTL2836 DTMB demod
+	DTMB_DEMOD_TYPE_RTL2836B_DTMB,			///<   RTL2836B DTMB demod
+	DTMB_DEMOD_TYPE_RTD2974_DTMB,			///<   RTD2974 DTMB demod
+
+	// ISDB-T demod
+	ISDBT_DEMOD_TYPE_RTD2648_ISDBT,			///<   RTD2648 ISDB-T demod
+
+	// Tuner
+	TUNER_TYPE_TDCGG052D,					///<   TDCG-G052D tuner (QAM)
+	TUNER_TYPE_TDCHG001D,					///<   TDCH-G001D tuner (QAM)
+	TUNER_TYPE_TDQE3003A,					///<   TDQE3-003A tuner (QAM)
+	TUNER_TYPE_DCT7045,						///<   DCT-7045 tuner (QAM)
+	TUNER_TYPE_MT2062,						///<   MT2062 tuner (QAM)
+	TUNER_TYPE_MXL5005S,					///<   MxL5005S tuner (DVB-T, ATSC)
+	TUNER_TYPE_TDVMH715P,					///<   TDVM-H751P tuner (QAM, OOB, ATSC)
+	TUNER_TYPE_UBA00AL,						///<   UBA00AL tuner (QAM, ATSC)
+	TUNER_TYPE_MT2266,						///<   MT2266 tuner (DVB-T)
+	TUNER_TYPE_FC2580,						///<   FC2580 tuner (DVB-T, DTMB)
+	TUNER_TYPE_TUA9001,						///<   TUA9001 tuner (DVB-T)
+	TUNER_TYPE_DTT75300,					///<   DTT-75300 tuner (DVB-T)
+	TUNER_TYPE_MXL5007T,					///<   MxL5007T tuner (DVB-T, ATSC)
+	TUNER_TYPE_VA1T1ED6093,					///<   VA1T1ED6093 tuner (DTMB)
+	TUNER_TYPE_TUA8010,						///<   TUA8010 tuner (DVB-T)
+	TUNER_TYPE_E4000,						///<   E4000 tuner (DVB-T)
+	TUNER_TYPE_E4005,						///<   E4005 tuner (DVB-T)
+	TUNER_TYPE_DCT70704,					///<   DCT-70704 tuner (QAM)
+	TUNER_TYPE_MT2063,						///<   MT2063 tuner (DVB-T, QAM)
+	TUNER_TYPE_FC0012,						///<   FC0012 tuner (DVB-T, DTMB)
+	TUNER_TYPE_TDAG,						///<   TDAG tuner (DTMB)
+	TUNER_TYPE_ADMTV804,					///<   ADMTV804 tuner (DVB-T, DTMB)
+	TUNER_TYPE_MAX3543,						///<   MAX3543 tuner (DVB-T)
+	TUNER_TYPE_TDA18272,					///<   TDA18272 tuner (DVB-T, QAM, DTMB)
+	TUNER_TYPE_TDA18250,					///<   TDA18250 tuner (DVB-T, QAM, DTMB)
+	TUNER_TYPE_FC0013,						///<   FC0013 tuner (DVB-T, DTMB)
+	TUNER_TYPE_FC0013B,						///<   FC0013B tuner (DVB-T, DTMB)
+	TUNER_TYPE_VA1E1ED2403,					///<   VA1E1ED2403 tuner (DTMB)
+	TUNER_TYPE_AVALON,						///<   AVALON tuner (DTMB)
+	TUNER_TYPE_SUTRE201,					///<   SUTRE201 tuner (DTMB)
+	TUNER_TYPE_MR1300,						///<   MR1300 tuner (ISDB-T 1-Seg)
+	TUNER_TYPE_TDAC7,						///<   TDAC7 tuner (DTMB, QAM)
+	TUNER_TYPE_VA1T1ER2094,					///<   VA1T1ER2094 tuner (DTMB)
+	TUNER_TYPE_TDAC3,						///<   TDAC3 tuner (DTMB)
+	TUNER_TYPE_RT910,						///<   RT910 tuner (DVB-T)
+	TUNER_TYPE_DTM4C20,						///<   DTM4C20 tuner (DTMB)
+	TUNER_TYPE_GTFD32,						///<   GTFD32 tuner (DTMB)
+	TUNER_TYPE_GTLP10,						///<   GTLP10 tuner (DTMB)
+	TUNER_TYPE_JSS66T,						///<   JSS66T tuner (DTMB)
+	TUNER_TYPE_NONE,						///<   NONE tuner (DTMB)
+	TUNER_TYPE_MR1500,						///<   MR1500 tuner (ISDB-T full-Seg)
+	TUNER_TYPE_R820T,						///<   R820T tuner (DVB-T)
+	TUNER_TYPE_YTMB04,						///<   YTMB-04 tuner (DTMB)
+	TUNER_TYPE_DTI7,						///<   DTI7 tuner (DTMB)
+
+	// DVB-T NIM
+	DVBT_NIM_USER_DEFINITION,				///<   DVB-T NIM:   User definition
+	DVBT_NIM_RTL2832_MT2266,				///<   DVB-T NIM:   RTL2832 + MT2266
+	DVBT_NIM_RTL2832_FC2580,				///<   DVB-T NIM:   RTL2832 + FC2580
+	DVBT_NIM_RTL2832_TUA9001,				///<   DVB-T NIM:   RTL2832 + TUA9001
+	DVBT_NIM_RTL2832_MXL5005S,				///<   DVB-T NIM:   RTL2832 + MxL5005S
+	DVBT_NIM_RTL2832_DTT75300,				///<   DVB-T NIM:   RTL2832 + DTT-75300
+	DVBT_NIM_RTL2832_MXL5007T,				///<   DVB-T NIM:   RTL2832 + MxL5007T
+	DVBT_NIM_RTL2832_TUA8010,				///<   DVB-T NIM:   RTL2832 + TUA8010
+	DVBT_NIM_RTL2832_E4000,					///<   DVB-T NIM:   RTL2832 + E4000
+	DVBT_NIM_RTL2832_E4005,					///<   DVB-T NIM:   RTL2832 + E4005
+	DVBT_NIM_RTL2832_MT2063,				///<   DVB-T NIM:   RTL2832 + MT2063
+	DVBT_NIM_RTL2832_FC0012,				///<   DVB-T NIM:   RTL2832 + FC0012
+	DVBT_NIM_RTL2832_ADMTV804,				///<   DVB-T NIM:   RTL2832 + ADMTV804
+	DVBT_NIM_RTL2832_MAX3543,				///<   DVB-T NIM:   RTL2832 + MAX3543
+	DVBT_NIM_RTL2832_TDA18272,				///<   DVB-T NIM:   RTL2832 + TDA18272
+	DVBT_NIM_RTL2832_FC0013,				///<   DVB-T NIM:   RTL2832 + FC0013
+	DVBT_NIM_RTL2832_RT910,					///<   DVB-T NIM:   RTL2832 + RT910
+	DVBT_NIM_RTL2832_FC0013B,				///<   DVB-T NIM:   RTL2832 + FC0013B
+	DVBT_NIM_RTL2832_R820T,					///<   DVB-T NIM:   RTL2832 + R820T
+
+	// QAM NIM
+	QAM_NIM_USER_DEFINITION,				///<   QAM NIM:   User definition
+	QAM_NIM_RTL2840_TDQE3003A,				///<   QAM NIM:   RTL2840 + TDQE3-003A
+	QAM_NIM_RTL2840_DCT7045,				///<   QAM NIM:   RTL2840 + DCT-7045
+	QAM_NIM_RTL2840_DCT7046,				///<   QAM NIM:   RTL2840 + DCT-7046
+	QAM_NIM_RTL2840_MT2062,					///<   QAM NIM:   RTL2840 + MT2062
+	QAM_NIM_RTL2840_DCT70704,				///<   QAM NIM:   RTL2840 + DCT-70704
+	QAM_NIM_RTL2840_MT2063,					///<   QAM NIM:   RTL2840 + MT2063
+	QAM_NIM_RTL2840_MAX3543,				///<   QAM NIM:   RTL2840 + MAX3543
+	QAM_NIM_RTL2836B_DVBC_VA1T1ED6093,		///<   QAM NIM:   RTL2836B DVB-C + VA1T1ED6093
+	QAM_NIM_RTD2885_QAM_TDA18272,			///<   QAM NIM:   RTD2885 QAM + TDA18272
+	QAM_NIM_RTL2836B_DVBC_VA1E1ED2403,		///<   QAM NIM:   RTL2836B DVB-C + VA1E1ED2403
+	QAM_NIM_RTD2840B_QAM_MT2062,            ///<   QAM NIM:   RTD2840B QAM + MT2062
+	QAM_NIM_RTL2840_TDA18272,				///<   QAM NIM:   RTL2840 + TDA18272
+	QAM_NIM_RTL2840_TDA18250,				///<   QAM NIM:   RTL2840 + TDA18250
+	QAM_NIM_RTL2836B_DVBC_FC0013B,			///<   QAM NIM:   RTL2836B DVB-C + FC0013B
+	QAM_NIM_RTL2836B_DVBC_TDA18272,			///<   QAM NIM:   RTL2836B DVB-C + TDA18272
+
+	// DCR NIM
+	DCR_NIM_RTL2820_TDVMH715P,				///<   DCR NIM:   RTL2820 + TDVM-H751P
+	DCR_NIM_RTD2885_UBA00AL,				///<   DCR NIM:   RTD2885 + UBA00AL
+
+	// ATSC NIM
+	ATSC_NIM_RTD2885_ATSC_TDA18272,			///<   ATSC NIM:   RTD2885 ATSC + TDA18272
+
+	// DTMB NIM
+	DTMB_NIM_RTL2836_FC2580,				///<   DTMB NIM:   RTL2836 + FC2580
+	DTMB_NIM_RTL2836_VA1T1ED6093,			///<   DTMB NIM:   RTL2836 + VA1T1ED6093
+	DTMB_NIM_RTL2836_TDAG,					///<   DTMB NIM:   RTL2836 + TDAG
+	DTMB_NIM_RTL2836_MXL5007T,				///<   DTMB NIM:   RTL2836 + MxL5007T
+	DTMB_NIM_RTL2836_E4000,					///<   DTMB NIM:   RTL2836 + E4000
+	DTMB_NIM_RTL2836_TDA18272,				///<   DTMB NIM:   RTL2836 + TDA18272
+	DTMB_NIM_RTL2836B_DTMB_VA1T1ED6093,		///<   DTMB NIM:   RTL2836B DTMB + VA1T1ED6093
+	DTMB_NIM_RTL2836B_DTMB_ADMTV804,		///<   DTMB NIM:   RTL2836B DTMB + ADMTV804
+	DTMB_NIM_RTL2836B_DTMB_E4000,			///<   DTMB NIM:   RTL2836B DTMB + E4000
+	DTMB_NIM_RTL2836B_DTMB_FC0012,			///<   DTMB NIM:   RTL2836B DTMB + FC0012
+	DTMB_NIM_RTL2836B_DTMB_VA1E1ED2403,		///<   DTMB NIM:   RTL2836B DTMB + VA1E1ED2403
+	DTMB_NIM_RTL2836B_DTMB_TDA18272,		///<   DTMB NIM:   RTL2836B DTMB + TDA18272
+	DTMB_NIM_RTL2836B_DTMB_AVALON,			///<   DTMB NIM:   RTL2836B DTMB + AVALON
+	DTMB_NIM_RTL2836B_DTMB_SUTRE201,		///<   DTMB NIM:   RTL2836B DTMB + SUTRE201
+	DTMB_NIM_RTL2836B_DTMB_TDAC7,	    	///<   DTMB NIM:   RTL2836B DTMB + ALPS TDAC7
+	DTMB_NIM_RTL2836B_DTMB_FC0013B,	    	///<   DTMB NIM:   RTL2836B DTMB + FC0013B
+	DTMB_NIM_RTL2836B_DTMB_VA1T1ER2094,		///<   DTMB NIM:   RTL2836B DTMB + VA1T1ER2094
+	DTMB_NIM_RTL2836B_DTMB_TDAC3,	    	///<   DTMB NIM:   RTL2836B DTMB + ALPS TDAC3
+	DTMB_NIM_RTL2836B_DTMB_DTM4C20,	    	///<   DTMB NIM:   RTL2836B DTMB + DTM4C20
+	DTMB_NIM_RTL2836B_DTMB_GTFD32,			///<   DTMB NIM:   RTL2836B DTMB + GTFD32
+	DTMB_NIM_RTL2836B_DTMB_GTLP10,			///<   DTMB NIM:   RTL2836B DTMB + GTFD32
+	DTMB_NIM_RTL2836B_DTMB_JSS66T,			///<   DTMB NIM:   RTL2836B DTMB + JSS66T
+	DTMB_NIM_RTL2836B_DTMB_NONE,			///<   DTMB NIM:   RTL2836B DTMB + NONE TUNER
+	DTMB_NIM_RTD2974_DTMB_VA1E1ED2403,		///<   DTMB NIM:   RTD2974 DTMB + VA1E1ED2403
+	DTMB_NIM_RTL2836B_DTMB_E4005,			///<   DTMB NIM:   RTL2836B DTMB + E4005
+	DTMB_NIM_RTL2836B_DTMB_MR1500,			///<   DTMB NIM:   RTL2836B DTMB + MR1500
+	DTMB_NIM_RTL2836B_DTMB_MXL5007T,		///<   DTMB NIM:   RTL2836B DTMB + MxL5007T
+	DTMB_NIM_RTL2836B_DTMB_YTMB04,			///<   DTMB NIM:   RTL2836B DTMB + YTMB-04
+	DTMB_NIM_RTL2836B_DTMB_DTI7,			///<   DTMB NIM:   RTL2836B DTMB + DTI7
+};
+
+
+
+
+
+/// On/off status
+enum ON_OFF_STATUS
+{
+	OFF,		///<   Off
+	ON,			///<   On
+};
+
+
+/// Yes/no status
+enum YES_NO_STATUS
+{
+	NO,			///<   No
+	YES,		///<   Yes
+};
+
+
+/// Lock status
+enum LOCK_STATUS
+{
+	NOT_LOCKED,			///<   Not locked
+	LOCKED,				///<   Locked
+};
+
+
+/// Loss status
+enum LOSS_STATUS
+{
+	NOT_LOST,			///<   Not lost
+	LOST,				///<   Lost
+};
+
+
+/// Function return status
+enum FUNCTION_RETURN_STATUS
+{
+	FUNCTION_SUCCESS,			///<   Execute function successfully.
+	FUNCTION_ERROR,				///<   Execute function unsuccessfully.
+};
+
+
+/// Crystal frequency
+enum CRYSTAL_FREQ_HZ
+{
+	CRYSTAL_FREQ_4000000HZ  =  4000000,			///<   Crystal frequency =    4.0 MHz
+	CRYSTAL_FREQ_16000000HZ = 16000000,			///<   Crystal frequency =   16.0 MHz
+	CRYSTAL_FREQ_16384000HZ = 16384000,			///<   Crystal frequency = 16.384 MHz
+	CRYSTAL_FREQ_16457143HZ = 16457143,			///<   Crystal frequency = 16.457 MHz
+	CRYSTAL_FREQ_20000000HZ = 20000000,			///<   Crystal frequency =   20.0 MHz
+	CRYSTAL_FREQ_20250000HZ = 20250000,			///<   Crystal frequency =  20.25 MHz
+	CRYSTAL_FREQ_20480000HZ = 20480000,			///<   Crystal frequency =  20.48 MHz
+	CRYSTAL_FREQ_24000000HZ = 24000000,			///<   Crystal frequency =   24.0 MHz
+	CRYSTAL_FREQ_25000000HZ = 25000000,			///<   Crystal frequency =   25.0 MHz
+	CRYSTAL_FREQ_25200000HZ = 25200000,			///<   Crystal frequency =   25.2 MHz
+	CRYSTAL_FREQ_26000000HZ = 26000000,			///<   Crystal frequency =   26.0 MHz
+	CRYSTAL_FREQ_26690000HZ = 26690000,			///<   Crystal frequency =  26.69 MHz
+	CRYSTAL_FREQ_27000000HZ = 27000000,			///<   Crystal frequency =   27.0 MHz
+	CRYSTAL_FREQ_28800000HZ = 28800000,			///<   Crystal frequency =   28.8 MHz
+	CRYSTAL_FREQ_32000000HZ = 32000000,			///<   Crystal frequency =   32.0 MHz
+	CRYSTAL_FREQ_36000000HZ = 36000000,			///<   Crystal frequency =   36.0 MHz
+};
+
+
+/// IF frequency
+enum IF_FREQ_HZ
+{
+	IF_FREQ_0HZ        =        0,			///<   IF frequency =      0 MHz
+	IF_FREQ_3250000HZ  =  3250000,			///<   IF frequency =   3.25 MHz
+	IF_FREQ_3570000HZ  =  3570000,			///<   IF frequency =   3.57 MHz
+	IF_FREQ_4000000HZ  =  4000000,			///<   IF frequency =    4.0 MHz
+	IF_FREQ_4570000HZ  =  4570000,			///<   IF frequency =   4.57 MHz
+	IF_FREQ_4571429HZ  =  4571429,			///<   IF frequency =  4.571 MHz
+	IF_FREQ_5000000HZ  =  5000000,			///<   IF frequency =    5.0 MHz
+	IF_FREQ_36000000HZ = 36000000,			///<   IF frequency =   36.0 MHz
+	IF_FREQ_36125000HZ = 36125000,			///<   IF frequency = 36.125 MHz
+	IF_FREQ_36150000HZ = 36150000,			///<   IF frequency =  36.15 MHz
+	IF_FREQ_36166667HZ = 36166667,			///<   IF frequency = 36.167 MHz
+	IF_FREQ_36170000HZ = 36170000,			///<   IF frequency =  36.17 MHz
+	IF_FREQ_43750000HZ = 43750000,			///<   IF frequency =  43.75 MHz
+	IF_FREQ_44000000HZ = 44000000,			///<   IF frequency =   44.0 MHz
+};
+
+
+/// Spectrum mode
+enum SPECTRUM_MODE
+{
+	SPECTRUM_NORMAL,			///<   Normal spectrum
+	SPECTRUM_INVERSE,			///<   Inverse spectrum
+};
+#define SPECTRUM_MODE_NUM		2
+
+
+/// TS interface mode
+enum TS_INTERFACE_MODE
+{
+	TS_INTERFACE_PARALLEL,			///<   Parallel TS interface
+	TS_INTERFACE_SERIAL,			///<   Serial TS interface
+};
+#define TS_INTERFACE_MODE_NUM		2
+
+
+/// Diversity mode
+enum DIVERSITY_PIP_MODE
+{
+	DIVERSITY_PIP_OFF,				///<   Diversity disable and PIP disable
+	DIVERSITY_ON_MASTER,			///<   Diversity enable for Master Demod
+	DIVERSITY_ON_SLAVE,				///<   Diversity enable for Slave Demod
+	PIP_ON_MASTER,					///<   PIP enable for Master Demod
+	PIP_ON_SLAVE,					///<   PIP enable for Slave Demod
+};
+#define DIVERSITY_PIP_MODE_NUM		5
+
+
+
+
+
+/// Base interface module alias
+typedef struct BASE_INTERFACE_MODULE_TAG BASE_INTERFACE_MODULE;
+
+
+
+
+
+/**
+
+@brief   Basic I2C reading function pointer
+
+Upper layer functions will use BASE_FP_I2C_READ() to read ByteNum bytes from I2C device to pReadingBytes buffer.
+
+
+@param [in]    pBaseInterface   The base interface module pointer
+@param [in]    DeviceAddr       I2C device address in 8-bit format
+@param [out]   pReadingBytes    Buffer pointer to an allocated memory for storing reading bytes
+@param [in]    ByteNum          Reading byte number
+
+
+@retval   FUNCTION_SUCCESS   Read bytes from I2C device with reading byte number successfully.
+@retval   FUNCTION_ERROR     Read bytes from I2C device unsuccessfully.
+
+
+@note
+	The requirements of BASE_FP_I2C_READ() function are described as follows:
+	-# Follow the I2C format for BASE_FP_I2C_READ(). \n
+	   start_bit + (DeviceAddr | reading_bit) + reading_byte * ByteNum + stop_bit
+	-# Don't allocate memory on pReadingBytes.
+	-# Upper layer functions should allocate memory on pReadingBytes before using BASE_FP_I2C_READ().
+	-# Need to assign I2C reading funtion to BASE_FP_I2C_READ() for upper layer functions.
+
+
+
+@par Example:
+@code
+
+
+#include "foundation.h"
+
+
+// Implement I2C reading funciton for BASE_FP_I2C_READ function pointer.
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned char ByteNum
+	)
+{
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+
+	return FUNCTION_ERROR;
+}
+
+
+int main(void)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+	unsigned char ReadingBytes[100];
+
+
+	// Assign implemented I2C reading funciton to BASE_FP_I2C_READ in base interface module.
+	BuildBaseInterface(&pBaseInterface, &BaseInterfaceModuleMemory, ..., ..., CustomI2cRead, ..., ...);
+
+	...
+
+	// Use I2cRead() to read 33 bytes from I2C device and store reading bytes to ReadingBytes.
+	pBaseInterface->I2cRead(pBaseInterface, 0x20, ReadingBytes, 33);
+	
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*BASE_FP_I2C_READ)(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+/**
+
+@brief   Basic I2C writing function pointer
+
+Upper layer functions will use BASE_FP_I2C_WRITE() to write ByteNum bytes from pWritingBytes buffer to I2C device.
+
+
+@param [in]   pBaseInterface   The base interface module pointer
+@param [in]   DeviceAddr       I2C device address in 8-bit format
+@param [in]   pWritingBytes    Buffer pointer to writing bytes
+@param [in]   ByteNum          Writing byte number
+
+
+@retval   FUNCTION_SUCCESS   Write bytes to I2C device with writing bytes successfully.
+@retval   FUNCTION_ERROR     Write bytes to I2C device unsuccessfully.
+
+
+@note
+	The requirements of BASE_FP_I2C_WRITE() function are described as follows:
+	-# Follow the I2C format for BASE_FP_I2C_WRITE(). \n
+	   start_bit + (DeviceAddr | writing_bit) + writing_byte * ByteNum + stop_bit
+	-# Need to assign I2C writing funtion to BASE_FP_I2C_WRITE() for upper layer functions.
+
+
+
+@par Example:
+@code
+
+
+#include "foundation.h"
+
+
+// Implement I2C writing funciton for BASE_FP_I2C_WRITE function pointer.
+int
+CustomI2cWrite(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned char ByteNum
+	)
+{
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+
+	return FUNCTION_ERROR;
+}
+
+
+int main(void)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+	unsigned char WritingBytes[100];
+
+
+	// Assign implemented I2C writing funciton to BASE_FP_I2C_WRITE in base interface module.
+	BuildBaseInterface(&pBaseInterface, &BaseInterfaceModuleMemory, ..., ..., ..., CustomI2cWrite, ...);
+
+	...
+
+	// Use I2cWrite() to write 33 bytes from WritingBytes to I2C device.
+	pBaseInterface->I2cWrite(pBaseInterface, 0x20, WritingBytes, 33);
+	
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*BASE_FP_I2C_WRITE)(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+/**
+
+@brief   Basic waiting function pointer
+
+Upper layer functions will use BASE_FP_WAIT_MS() to wait WaitTimeMs milliseconds.
+
+
+@param [in]   pBaseInterface   The base interface module pointer
+@param [in]   WaitTimeMs       Waiting time in millisecond
+
+
+@note
+	The requirements of BASE_FP_WAIT_MS() function are described as follows:
+	-# Need to assign a waiting function to BASE_FP_WAIT_MS() for upper layer functions.
+
+
+
+@par Example:
+@code
+
+
+#include "foundation.h"
+
+
+// Implement waiting funciton for BASE_FP_WAIT_MS function pointer.
+void
+CustomWaitMs(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned long WaitTimeMs
+	)
+{
+	...
+
+	return;
+}
+
+
+int main(void)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+
+
+	// Assign implemented waiting funciton to BASE_FP_WAIT_MS in base interface module.
+	BuildBaseInterface(&pBaseInterface, &BaseInterfaceModuleMemory, ..., ..., ..., ..., CustomWaitMs);
+
+	...
+
+	// Use WaitMs() to wait 30 millisecond.
+	pBaseInterface->WaitMs(pBaseInterface, 30);
+	
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef void
+(*BASE_FP_WAIT_MS)(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned long WaitTimeMs
+	);
+
+
+
+
+
+/**
+
+@brief   User defined data pointer setting function pointer
+
+One can use BASE_FP_SET_USER_DEFINED_DATA_POINTER() to set user defined data pointer of base interface structure for
+custom basic function implementation.
+
+
+@param [in]   pBaseInterface     The base interface module pointer
+@param [in]   pUserDefinedData   Pointer to user defined data
+
+
+@note
+	One can use BASE_FP_GET_USER_DEFINED_DATA_POINTER() to get user defined data pointer of base interface structure for
+	custom basic function implementation.
+
+
+
+@par Example:
+@code
+
+
+#include "foundation.h"
+
+
+// Implement I2C reading funciton for BASE_FP_I2C_READ function pointer.
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned char ByteNum
+	)
+{
+	CUSTOM_USER_DEFINED_DATA *pUserDefinedData;
+
+
+	// Get user defined data pointer of base interface structure for custom I2C reading function.
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&pUserDefinedData);
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+
+	return FUNCTION_ERROR;
+}
+
+
+int main(void)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+	unsigned char ReadingBytes[100];
+
+	CUSTOM_USER_DEFINED_DATA UserDefinedData;
+
+
+	// Assign implemented I2C reading funciton to BASE_FP_I2C_READ in base interface module.
+	BuildBaseInterface(&pBaseInterface, &BaseInterfaceModuleMemory, ..., ..., CustomI2cRead, ..., ...);
+
+	...
+
+	// Set user defined data pointer of base interface structure for custom basic functions.
+	pBaseInterface->SetUserDefinedDataPointer(pBaseInterface, &UserDefinedData);
+
+	// Use I2cRead() to read 33 bytes from I2C device and store reading bytes to ReadingBytes.
+	pBaseInterface->I2cRead(pBaseInterface, 0x20, ReadingBytes, 33);
+	
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef void
+(*BASE_FP_SET_USER_DEFINED_DATA_POINTER)(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	void *pUserDefinedData
+	);
+
+
+
+
+
+/**
+
+@brief   User defined data pointer getting function pointer
+
+One can use BASE_FP_GET_USER_DEFINED_DATA_POINTER() to get user defined data pointer of base interface structure for
+custom basic function implementation.
+
+
+@param [in]   pBaseInterface      The base interface module pointer
+@param [in]   ppUserDefinedData   Pointer to user defined data pointer
+
+
+@note
+	One can use BASE_FP_SET_USER_DEFINED_DATA_POINTER() to set user defined data pointer of base interface structure for
+	custom basic function implementation.
+
+
+
+@par Example:
+@code
+
+
+#include "foundation.h"
+
+
+// Implement I2C reading funciton for BASE_FP_I2C_READ function pointer.
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned char ByteNum
+	)
+{
+	CUSTOM_USER_DEFINED_DATA *pUserDefinedData;
+
+
+	// Get user defined data pointer of base interface structure for custom I2C reading function.
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&pUserDefinedData);
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+
+	return FUNCTION_ERROR;
+}
+
+
+int main(void)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+	unsigned char ReadingBytes[100];
+
+	CUSTOM_USER_DEFINED_DATA UserDefinedData;
+
+
+	// Assign implemented I2C reading funciton to BASE_FP_I2C_READ in base interface module.
+	BuildBaseInterface(&pBaseInterface, &BaseInterfaceModuleMemory, ..., ..., CustomI2cRead, ..., ...);
+
+	...
+
+	// Set user defined data pointer of base interface structure for custom basic functions.
+	pBaseInterface->SetUserDefinedDataPointer(pBaseInterface, &UserDefinedData);
+
+	// Use I2cRead() to read 33 bytes from I2C device and store reading bytes to ReadingBytes.
+	pBaseInterface->I2cRead(pBaseInterface, 0x20, ReadingBytes, 33);
+	
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef void
+(*BASE_FP_GET_USER_DEFINED_DATA_POINTER)(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	void **ppUserDefinedData
+	);
+
+
+
+
+
+/// Base interface module structure
+struct BASE_INTERFACE_MODULE_TAG
+{
+	// Variables and function pointers
+	unsigned long I2cReadingByteNumMax;
+	unsigned long I2cWritingByteNumMax;
+
+	BASE_FP_I2C_READ    I2cRead;
+	BASE_FP_I2C_WRITE   I2cWrite;
+	BASE_FP_WAIT_MS     WaitMs;
+
+	BASE_FP_SET_USER_DEFINED_DATA_POINTER   SetUserDefinedDataPointer;
+	BASE_FP_GET_USER_DEFINED_DATA_POINTER   GetUserDefinedDataPointer;
+
+
+	// User defined data
+	void *pUserDefinedData;
+};
+
+
+
+
+
+/**
+
+@brief   Base interface builder
+
+Use BuildBaseInterface() to build base interface for module functions to access basic functions.
+
+
+@param [in]   ppBaseInterface              Pointer to base interface module pointer
+@param [in]   pBaseInterfaceModuleMemory   Pointer to an allocated base interface module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+
+
+@note
+	-# One should build base interface before using module functions.
+	-# The I2C reading format is described as follows:
+	   start_bit + (device_addr | reading_bit) + reading_byte * byte_num + stop_bit
+	-# The I2cReadingByteNumMax is the maximum byte_num of the I2C reading format.
+	-# The I2C writing format is described as follows:
+	   start_bit + (device_addr | writing_bit) + writing_byte * byte_num + stop_bit
+	-# The I2cWritingByteNumMax is the maximum byte_num of the I2C writing format.
+
+
+
+@par Example:
+@code
+
+
+#include "foundation.h"
+
+
+// Implement I2C reading funciton for BASE_FP_I2C_READ function pointer.
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned char ByteNum
+	)
+{
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+
+	return FUNCTION_ERROR;
+}
+
+
+// Implement I2C writing funciton for BASE_FP_I2C_WRITE function pointer.
+int
+CustomI2cWrite(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned char ByteNum
+	)
+{
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+
+	return FUNCTION_ERROR;
+}
+
+
+// Implement waiting funciton for BASE_FP_WAIT_MS function pointer.
+void
+CustomWaitMs(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned long WaitTimeMs
+	)
+{
+	...
+
+	return;
+}
+
+
+int main(void)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+
+
+	// Build base interface with the following settings.
+	//
+	// 1. Assign 9 to maximum I2C reading byte number.
+	// 2. Assign 8 to maximum I2C writing byte number.
+	// 3. Assign CustomI2cRead() to basic I2C reading function pointer.
+	// 4. Assign CustomI2cWrite() to basic I2C writing function pointer.
+	// 5. Assign CustomWaitMs() to basic waiting function pointer.
+	//
+	BuildBaseInterface(
+		&pBaseInterface,
+		&BaseInterfaceModuleMemory,
+		9,
+		8,
+		CustomI2cRead,
+		CustomI2cWrite,
+		CustomWaitMs
+		);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+void
+BuildBaseInterface(
+	BASE_INTERFACE_MODULE **ppBaseInterface,
+	BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory,
+	unsigned long I2cReadingByteNumMax,
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs
+	);
+
+
+
+
+
+// User data pointer of base interface structure setting and getting functions
+void
+base_interface_SetUserDefinedDataPointer(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	void *pUserDefinedData
+	);
+
+void
+base_interface_GetUserDefinedDataPointer(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	void **ppUserDefinedData
+	);
+
+
+
+
+
+// Math functions
+
+// Binary and signed integer converter
+unsigned long
+SignedIntToBin(
+	long Value,
+	unsigned char BitNum
+	);
+
+long
+BinToSignedInt(
+	unsigned long Binary,
+	unsigned char BitNum
+	);
+
+
+
+// Arithmetic
+unsigned long
+DivideWithCeiling(
+	unsigned long Dividend,
+	unsigned long Divisor
+	);
+
+
+
+
+
+
+
+
+
+
+
+/**
+
+@mainpage Realtek demod Source Code Manual
+
+@note
+	-# The Realtek demod API source code is designed for demod IC driver porting.
+	-# The API source code is written in C language without floating-point arithmetic.
+	-# One can use the API to manipulate Realtek demod IC.
+	-# The API will call custom underlayer functions through API base interface module.
+
+
+@par Important:
+	-# Please assign API base interface module with custom underlayer functions instead of modifying API source code.
+	-# Please see the example code to understand the relation bewteen API and custom system.
+
+*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/i2c_bridge.h b/drivers/media/usb/dvb-usb/i2c_bridge.h
new file mode 100644
index 0000000..ce67e8b
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/i2c_bridge.h
@@ -0,0 +1,122 @@
+#ifndef __I2C_BRIDGE_H
+#define __I2C_BRIDGE_H
+
+/**
+
+@file
+
+@brief   I2C bridge module
+
+I2C bridge module contains I2C forwarding function pointers.
+
+*/
+
+
+
+
+
+/// I2C bridge module pre-definition
+typedef struct I2C_BRIDGE_MODULE_TAG I2C_BRIDGE_MODULE;
+
+
+
+
+
+/**
+
+@brief   I2C reading command forwarding function pointer
+
+Tuner upper level functions will use I2C_BRIDGE_FP_FORWARD_I2C_READING_CMD() to send tuner I2C reading command through
+demod.
+
+
+@param [in]    pI2cBridge      The I2C bridge module pointer
+@param [in]    DeviceAddr       I2C device address in 8-bit format
+@param [out]   pReadingBytes   Pointer to an allocated memory for storing reading bytes
+@param [in]    ByteNum         Reading byte number
+
+
+@retval   FUNCTION_SUCCESS   Forwarding I2C reading command successfully.
+@retval   FUNCTION_ERROR     Forwarding I2C reading command unsuccessfully.
+
+
+@note
+	-# Demod building function will set I2C_BRIDGE_FP_FORWARD_I2C_READING_CMD() with the corresponding function.
+
+*/
+typedef int
+(*I2C_BRIDGE_FP_FORWARD_I2C_READING_CMD)(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+/**
+
+@brief   I2C writing command forwarding function pointer
+
+Tuner upper level functions will use I2C_BRIDGE_FP_FORWARD_I2C_WRITING_CMD() to send tuner I2C writing command through
+demod.
+
+
+@param [in]    pI2cBridge      The I2C bridge module pointer
+@param [in]    DeviceAddr       I2C device address in 8-bit format
+@param [out]   pWritingBytes   Pointer to writing bytes
+@param [in]    ByteNum         Writing byte number
+
+
+@retval   FUNCTION_SUCCESS   Forwarding I2C writing command successfully.
+@retval   FUNCTION_ERROR     Forwarding I2C writing command unsuccessfully.
+
+
+@note
+	-# Demod building function will set I2C_BRIDGE_FP_FORWARD_I2C_WRITING_CMD() with the corresponding function.
+
+*/
+typedef int
+(*I2C_BRIDGE_FP_FORWARD_I2C_WRITING_CMD)(
+	I2C_BRIDGE_MODULE *pI2cBridge,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+/// I2C bridge module structure
+struct I2C_BRIDGE_MODULE_TAG
+{
+	// Private variables
+	void *pPrivateData;
+
+
+	// I2C bridge function pointers
+	I2C_BRIDGE_FP_FORWARD_I2C_READING_CMD   ForwardI2cReadingCmd;	///<   I2C reading command forwading function pointer
+	I2C_BRIDGE_FP_FORWARD_I2C_WRITING_CMD   ForwardI2cWritingCmd;   ///<   I2C writing command forwading function pointer
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/math_mpi.c b/drivers/media/usb/dvb-usb/math_mpi.c
new file mode 100644
index 0000000..d3a2c7c
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/math_mpi.c
@@ -0,0 +1,1054 @@
+/**
+
+@file
+
+@brief   Mutliple precision integer (MPI) arithmetic definition
+
+One can use to mutliple precision arithmetic to manipulate large signed integers.
+
+*/
+
+
+#include "math_mpi.h"
+
+
+
+
+
+/**
+
+@brief   Set multiple precision signed integer value.
+
+Use MpiSetValue() to set multiple precision signed integer MPI value.
+
+
+@param [in]   pMpiVar   Pointer to an MPI variable
+@param [in]   Value     Value for setting
+
+
+@note
+	The MPI bit number will be minimized in MpiSetValue().
+
+*/
+void
+MpiSetValue(
+	MPI *pMpiVar,
+	long Value
+	)
+{
+	int i;
+	unsigned char SignedBit;
+	unsigned char ExtensionByte;
+
+
+
+	// Set MPI value according to ansigned value.
+	for(i = 0; i < MPI_LONG_BYTE_NUM; i++)
+		pMpiVar->Value[i] = (unsigned char)((Value >> (MPI_BYTE_SHIFT * i)) & MPI_BYTE_MASK);
+
+	
+	// Get extension byte according to signed bit.
+	SignedBit = (unsigned char)((Value >> (MPI_LONG_BIT_NUM - 1)) & MPI_BIT_0_MASK);
+	ExtensionByte = (SignedBit == 0x0) ? 0x00 : 0xff;
+
+
+	// Extend MPI signed bit with extension byte stuff.
+	for(i = MPI_LONG_BYTE_NUM; i < MPI_VALUE_BYTE_NUM_MAX; i++)
+		pMpiVar->Value[i] = ExtensionByte;
+
+
+	// Minimize MPI bit number.
+	MpiMinimizeBitNum(pMpiVar);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Get multiple precision signed integer value.
+
+Use MpiGetValue() to get multiple precision unsigned integer MPI value.
+
+
+@param [in]    MpiVar   Pointer to an MPI variable
+@param [out]   pValue   Pointer to an allocated memory for getting MPI value
+
+
+@note
+    The necessary bit number of MPI value must be less than or equal to 32 bits.
+
+*/
+void
+MpiGetValue(
+	MPI MpiVar,
+	long *pValue
+	)
+{
+	int i;
+	unsigned long Value;
+
+
+
+	// Set value with zero.
+	Value = 0x0;
+
+
+	// Combine MPI value bytes into value.
+	for(i = 0; i < MPI_LONG_BYTE_NUM; i++)
+		Value |= MpiVar.Value[i] << (MPI_BYTE_SHIFT * i);
+
+
+	// Assigned value to value pointer.
+	*pValue = (long)Value;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Set multiple precision signed integer bit value.
+
+Use MpiSetBit() to set multiple precision signed integer MPI bit value.
+
+
+@param [in]   pMpiVar       Pointer to an MPI variable
+@param [in]   BitPosition   Bit position with zero-based index
+@param [in]   BitValue      Bit value for setting
+
+
+@note
+	Bit position must be 0 ~ (MPI bit number).
+
+*/
+void
+MpiSetBit(
+	MPI *pMpiVar,
+	unsigned long BitPosition,
+	unsigned char BitValue
+	)
+{
+	unsigned long TargetBytePos, TargetBitPos;
+
+
+
+	// Calculate target byte and bit position.
+	TargetBytePos = BitPosition / MPI_BYTE_BIT_NUM;
+	TargetBitPos  = BitPosition % MPI_BYTE_BIT_NUM;
+
+
+	// Set MPI bit value according to calculated target byte and bit position.
+	pMpiVar->Value[TargetBytePos] &= (unsigned char)(~(0x1 << TargetBitPos));
+	pMpiVar->Value[TargetBytePos] |= (BitValue & MPI_BIT_0_MASK) << TargetBitPos;
+
+
+	return;
+}
+
+
+
+
+
+
+/**
+
+@brief   Get multiple precision signed integer bit value.
+
+Use MpiGetBit() to get multiple precision unsigned integer MPI bit value.
+
+
+@param [in]    MpiVar        Pointer to an MPI variable
+@param [in]    BitPosition   Bit position with zero-based index
+@param [out]   pBitValue     Pointer to an allocated memory for getting MPI bit value
+
+
+@note
+	Bit position must be 0 ~ (MPI bit number).
+
+*/
+void
+MpiGetBit(
+	MPI MpiVar,
+	unsigned long BitPosition,
+	unsigned char *pBitValue
+	)
+{
+	unsigned long TargetBytePos, TargetBitPos;
+
+
+
+	// Calculate target byte and bit position.
+	TargetBytePos = BitPosition / MPI_BYTE_BIT_NUM;
+	TargetBitPos  = BitPosition % MPI_BYTE_BIT_NUM;
+
+
+	// Get MPI bit value according to calculated target byte and bit position.
+	*pBitValue = (MpiVar.Value[TargetBytePos] >> TargetBitPos) & MPI_BIT_0_MASK;
+
+
+	return;
+}
+	
+
+
+
+	
+/**
+
+@brief   Get multiple precision signed integer signed bit value.
+
+Use MpiGetBit() to get multiple precision unsigned integer MPI signed bit value.
+
+
+@param [in]    MpiVar            Pointer to an MPI variable
+@param [out]   pSignedBitValue   Pointer to an allocated memory for getting MPI signed bit value
+
+*/
+void
+MpiGetSignedBit(
+	MPI MpiVar,
+	unsigned char *pSignedBitValue
+	)
+{
+	// Get MPI variable signed bit.
+	MpiGetBit(MpiVar, MPI_VALUE_BIT_NUM_MAX - 1, pSignedBitValue);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Assign multiple precision signed integer with another one.
+
+Use MpiAssign() to assign multiple precision signed integer with another one.
+
+
+@param [out]   pResult   Pointer to an allocated memory for storing result
+@param [in]    Operand   Operand
+
+
+@note
+	The result bit number will be minimized in MpiAssign().
+
+*/
+void
+MpiAssign(
+	MPI *pResult,
+	MPI Operand
+	)
+{
+	unsigned int i;
+
+
+
+	// Copy value bytes from operand to result.
+	for(i = 0; i < MPI_VALUE_BYTE_NUM_MAX; i++)
+		pResult->Value[i] = Operand.Value[i];
+
+
+	// Minimize result bit nubmer.
+	MpiMinimizeBitNum(pResult);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Minus unary multiple precision signed integer.
+
+Use MpiUnaryMinus() to minus unary multiple precision signed integer.
+
+
+@param [out]   pResult   Pointer to an allocated memory for storing result
+@param [in]    Operand   Operand
+
+
+@note
+	The result bit number will be minimized in MpiUnaryMinus().
+
+*/
+void
+MpiUnaryMinus(
+	MPI *pResult,
+	MPI Operand
+	)
+{
+	unsigned int i;
+	MPI Const;
+
+
+
+	// Set result value byte with operand bitwise complement value byte.
+	for(i = 0; i < MPI_VALUE_BYTE_NUM_MAX; i++)
+		pResult->Value[i] = ~Operand.Value[i];
+
+
+	// Add result with 0x1.
+	// Note: MpiAdd() will minimize result bit number.
+	MpiSetValue(&Const, 0x1);
+	MpiAdd(pResult, *pResult, Const);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Add multiple precision signed integers.
+
+Use MpiAdd() to add multiple precision signed integers.
+
+
+@param [out]   pSum     Pointer to an allocated memory for storing sum
+@param [in]    Augend   Augend
+@param [in]    Addend   Addend
+
+
+@note
+	The sum bit number will be minimized in MpiAdd().
+
+*/
+void
+MpiAdd(
+	MPI *pSum,
+	MPI Augend,
+	MPI Addend
+	)
+{
+	unsigned int i;
+	unsigned long MiddleResult;
+	unsigned char Carry;
+
+
+	// Add augend and addend to sum form value LSB byte to value MSB byte.
+	Carry = 0;
+
+	for(i = 0; i < MPI_VALUE_BYTE_NUM_MAX; i++)
+	{
+		// Set current sum value byte and determine carry.
+		MiddleResult   = Augend.Value[i] + Addend.Value[i] + Carry;
+		pSum->Value[i] = (unsigned char)(MiddleResult & MPI_BYTE_MASK);
+		Carry          = (unsigned char)((MiddleResult >> MPI_BYTE_SHIFT) & MPI_BYTE_MASK);
+	}
+	
+
+	// Minimize sum bit nubmer.
+	MpiMinimizeBitNum(pSum);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   subtract multiple precision signed integers.
+
+Use MpiSub() to subtract multiple precision signed integers.
+
+
+@param [out]   pDifference   Pointer to an allocated memory for storing difference
+@param [in]    Minuend       Minuend
+@param [in]    Subtrahend    Subtrahend
+
+
+@note
+	The difference bit number will be minimized in MpiSub().
+
+*/
+void
+MpiSub(
+	MPI *pDifference,
+	MPI Minuend,
+	MPI Subtrahend
+	)
+{
+	MPI MiddleResult;
+
+
+
+	// Take subtrahend unary minus value.
+	MpiUnaryMinus(&MiddleResult, Subtrahend);
+
+
+	// Add minuend and subtrahend unary minus value to difference.
+	// Note: MpiAdd() will minimize result bit number.
+	MpiAdd(pDifference, Minuend, MiddleResult);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Multiply arbitrary precision signed integers.
+
+Use MpiMul() to multiply arbitrary precision signed integers.
+
+
+@param [out]   pProduct        Pointer to an allocated memory for storing product
+@param [in]    Multiplicand    Multiplicand
+@param [in]    Multiplicator   Multiplicator
+
+
+@note
+	-# The sum of multiplicand and multiplicator bit number must be less MPI_VALUE_BIT_NUM_MAX.
+	-# The product bit number will be minimized in MpiMul().
+
+*/
+void
+MpiMul(
+	MPI *pProduct,
+	MPI Multiplicand,
+	MPI Multiplicator
+	)
+{
+	int i;
+
+	unsigned char MultiplicandSignedBit, MultiplicatorSignedBit;
+	MPI MultiplicandAbs, MultiplicatorAbs;
+
+	unsigned char CurrentBit;
+
+
+
+	// Get multiplicand signed bit.
+	MpiGetSignedBit(Multiplicand, &MultiplicandSignedBit);
+
+	// Take absolute value of multiplicand.
+	if(MultiplicandSignedBit == 0x0)
+		MpiAssign(&MultiplicandAbs, Multiplicand);
+	else
+		MpiUnaryMinus(&MultiplicandAbs, Multiplicand);
+
+
+	// Get multiplicator signed bit.
+	MpiGetSignedBit(Multiplicator, &MultiplicatorSignedBit);
+
+	// Take absolute value of multiplicator.
+	if(MultiplicatorSignedBit == 0x0)
+		MpiAssign(&MultiplicatorAbs, Multiplicator);
+	else
+		MpiUnaryMinus(&MultiplicatorAbs, Multiplicator);
+
+
+	// Multiply multiplicand and multiplicator from LSB bit to MSB bit.
+	MpiSetValue(pProduct, 0x0);
+
+	for(i = MPI_VALUE_BIT_NUM_MAX - 1; i > -1; i--)
+	{
+		// Shift product toward left with one bit.
+		MpiLeftShift(pProduct, *pProduct, 1);
+
+		// Get current absolute multiplicator bit value.
+		MpiGetBit(MultiplicatorAbs, i, &CurrentBit);
+
+		// If current multiplicator bit is 0x1, add absolute multiplicand value to product.
+		// Note: MpiAdd() will minimize result bit number.
+		if(CurrentBit == 0x1)
+			MpiAdd(pProduct, *pProduct, MultiplicandAbs);
+	}
+
+
+	// Determine the signed bit of product according to signed bits of multiplicand and multiplicator.
+	// Note: MpiUnaryMinus() will minimize result bit number.
+	if(MultiplicandSignedBit != MultiplicatorSignedBit)
+		MpiUnaryMinus(pProduct, *pProduct);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Divide arbitrary precision signed integers.
+
+Use MpiDiv() to divide arbitrary precision signed integers.
+
+
+@param [out]   pQuotient    Pointer to an allocated memory for storing quotient
+@param [out]   pRemainder   Pointer to an allocated memory for storing remainder
+@param [in]    Dividend     Dividend
+@param [in]    Divisor      Divisor
+
+
+@note
+	-# The dividend bit number must be minimized.
+	-# The divisor must be not equal to zero.
+	-# The product bit number will be minimized in MpiDiv().
+
+*/
+void
+MpiDiv(
+	MPI *pQuotient,
+	MPI *pRemainder,
+	MPI Dividend,
+	MPI Divisor
+	)
+{
+	unsigned int i;
+
+	unsigned char DividendSignedBit, DivisorSignedBit;
+	MPI DividendAbs, DivisorAbs;
+
+	unsigned long PrimaryDividendBitNum;
+	unsigned char ShiftBit;
+
+	MPI Const;
+	MPI MiddleResult;
+
+
+
+	// Get dividend signed bit.
+	MpiGetSignedBit(Dividend, &DividendSignedBit);
+
+	// Take absolute value of dividend.
+	if(DividendSignedBit == 0x0)
+		MpiAssign(&DividendAbs, Dividend);
+	else
+		MpiUnaryMinus(&DividendAbs, Dividend);
+
+
+	// Get divisor signed bit.
+	MpiGetSignedBit(Divisor, &DivisorSignedBit);
+
+	// Take absolute value of divisor.
+	if(DivisorSignedBit == 0x0)
+		MpiAssign(&DivisorAbs, Divisor);
+	else
+		MpiUnaryMinus(&DivisorAbs, Divisor);
+
+
+	// Get primary absolute dividend bit number.
+	PrimaryDividendBitNum = DividendAbs.BitNum;
+
+
+	// Get quotient and remainder by division algorithm.
+	MpiSetValue(pQuotient, 0x0);
+	MpiSetValue(pRemainder, 0x0);
+
+	for(i = 0; i < PrimaryDividendBitNum; i++)
+	{
+		// Shift quotient toward left with one bit.
+		// Note: MpiLeftShift() will minimize result bit number.
+		MpiLeftShift(pQuotient, *pQuotient, 1);
+
+		// Shift remainder toward left with one bit.
+		MpiLeftShift(pRemainder, *pRemainder, 1);
+
+		// Shift absolute dividend toward left with one bit.
+		MpiLeftShift(&DividendAbs, DividendAbs, 1);
+
+		// Set remainder LSB according to absolute dividend.
+		MpiGetBit(DividendAbs, PrimaryDividendBitNum, &ShiftBit);
+		MpiSetBit(pRemainder, 0, ShiftBit);
+
+		// If remainder is greater than or equal to absolute divisor,
+		// substract absolute divisor from remainder and set quotient LSB with one.
+		if(MpiGreaterThan(*pRemainder, DivisorAbs) || MpiEqualTo(*pRemainder, DivisorAbs))
+		{
+			MpiSub(pRemainder, *pRemainder, DivisorAbs);
+			MpiSetBit(pQuotient, 0, 0x1);
+		}
+	}
+
+
+	// Modify quotient according to dividend signed bit, divisor signed bit, and remainder.
+
+	// Determine the signed bit of quotient.
+	if(DividendSignedBit != DivisorSignedBit)
+	{
+		// Take unary minus quotient.
+		// Note: MpiUnaryMinus() will minimize result bit number.
+		MpiUnaryMinus(pQuotient, *pQuotient);
+
+		// If remainder is greater than zero, subtract 1 from quotient.
+		// Note: MpiSub() will minimize result bit number.
+		MpiSetValue(&Const, 0x0);
+
+		if(MpiGreaterThan(*pRemainder, Const))
+		{
+			MpiSetValue(&Const, 0x1);
+			MpiSub(pQuotient, *pQuotient, Const);
+		}
+	}
+
+
+	// Modify remainder according to dividend, divisor, and quotient.
+
+	// Remainder = dividend - divisor * quotient;
+	// Note: MpiSub() will minimize result bit number.
+	MpiMul(&MiddleResult, Divisor, *pQuotient);
+	MpiSub(pRemainder, Dividend, MiddleResult);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Shift multiple precision signed integer toward right.
+
+Use MpiRightShift() to shift arbitrary precision signed integer toward right with assigned bit number.
+
+
+@param [out]   pResult       Pointer to an allocated memory for storing result
+@param [in]    Operand       Operand
+@param [in]    ShiftBitNum   Shift bit number
+
+
+@note
+	-# The result MSB bits will be stuffed with signed bit
+	-# The result bit number will be minimized in MpiRightShift().
+
+*/
+void
+MpiRightShift(
+	MPI *pResult,
+	MPI Operand,
+	unsigned long ShiftBitNum
+	)
+{
+	unsigned int i;
+	unsigned long StuffBitNum;
+	unsigned char CurrentBit;
+	unsigned char SignedBit;
+
+
+
+	// Determine stuff bit number according to shift bit nubmer.
+	StuffBitNum = (ShiftBitNum < MPI_VALUE_BIT_NUM_MAX) ? ShiftBitNum : MPI_VALUE_BIT_NUM_MAX;
+
+
+	// Copy operand bits to result with stuff bit number.
+	for(i = 0; i < (MPI_VALUE_BIT_NUM_MAX - StuffBitNum); i++)
+	{
+		MpiGetBit(Operand, i + StuffBitNum, &CurrentBit);
+		MpiSetBit(pResult, i, CurrentBit);
+	}
+
+
+	// Get operand signed bit.
+	MpiGetSignedBit(Operand, &SignedBit);
+
+
+	// Stuff result MSB bits with signed bit.
+	for(i = (MPI_VALUE_BIT_NUM_MAX - StuffBitNum); i < MPI_VALUE_BIT_NUM_MAX; i++)
+		MpiSetBit(pResult, i, SignedBit);
+
+
+	// Minimize result bit number.
+	MpiMinimizeBitNum(pResult);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Shift multiple precision signed integer toward left.
+
+Use MpiLeftShift() to shift arbitrary precision signed integer toward left with assigned bit number.
+
+
+@param [out]   pResult       Pointer to an allocated memory for storing result
+@param [in]    Operand       Operand
+@param [in]    ShiftBitNum   Shift bit number
+
+
+@note
+	The result bit number will be minimized in MpiLeftShift().
+
+*/
+void
+MpiLeftShift(
+	MPI *pResult,
+	MPI Operand,
+	unsigned long ShiftBitNum
+	)
+{
+	unsigned int i;
+	unsigned long StuffBitNum;
+	unsigned char CurrentBit;
+
+
+	// Determine stuff bit number according to shift bit nubmer.
+	StuffBitNum = (ShiftBitNum < MPI_VALUE_BIT_NUM_MAX) ? ShiftBitNum : MPI_VALUE_BIT_NUM_MAX;
+
+
+	// Stuff result LSB bits with zeros
+	for(i = 0; i < StuffBitNum; i++)
+		MpiSetBit(pResult, i, 0x0);
+
+
+	// Copy operand bits to result with stuff bit number.
+	for(i = StuffBitNum; i < MPI_VALUE_BIT_NUM_MAX; i++)
+	{
+		MpiGetBit(Operand, i - StuffBitNum, &CurrentBit);
+		MpiSetBit(pResult, i, CurrentBit);
+	}
+
+
+	// Minimize result bit number.
+	MpiMinimizeBitNum(pResult);
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@brief   Compare multiple precision signed integes with equal-to criterion.
+
+Use MpiEqualTo() to compare multiple precision signed integes with equal-to criterion.
+
+
+@param [in]   MpiLeft    Left MPI
+@param [in]   MpiRight   Right MPI
+
+
+@retval   MPI_NO    "Left MPI == Right MPI" is false.
+@retval   MPI_YES   "Left MPI == Right MPI" is true.
+
+
+@note
+	The constants MPI_YES and MPI_NO are defined in MPI_YES_NO_STATUS enumeration.
+
+*/
+int
+MpiEqualTo(
+	MPI MpiLeft,
+	MPI MpiRight
+	)
+{
+	unsigned int i;
+
+
+
+	// Check not-equal-to condition.
+	for(i = 0; i < MPI_VALUE_BYTE_NUM_MAX; i++)
+	{
+		if(MpiLeft.Value[i] != MpiRight.Value[i])
+			goto condition_others;
+	}
+		
+
+	// Right MPI is greater than left MPI.
+	return MPI_YES;
+
+
+condition_others:
+
+
+	// Other conditions.
+	return MPI_NO;
+}
+
+
+
+
+
+/**
+
+@brief   Compare multiple precision signed integes with greater-than criterion.
+
+Use MpiGreaterThan() to compare multiple precision signed integes with greater-than criterion.
+
+
+@param [in]   MpiLeft    Left MPI
+@param [in]   MpiRight   Right MPI
+
+
+@retval   MPI_NO    "Left MPI > Right MPI" is false.
+@retval   MPI_YES   "Left MPI > Right MPI" is true.
+
+
+@note
+	The constants MPI_YES and MPI_NO are defined in MPI_YES_NO_STATUS enumeration.
+
+*/
+int
+MpiGreaterThan(
+	MPI MpiLeft,
+	MPI MpiRight
+	)
+{
+	MPI MiddleResult;
+	unsigned char SignedBit;
+
+
+
+	// Check equal-to condition.
+	if(MpiEqualTo(MpiLeft, MpiRight) == MPI_YES)
+		goto condition_others;
+
+
+	// Subtract right MPI form left MPI.
+	MpiSub(&MiddleResult, MpiLeft, MpiRight);
+
+
+	// Check less-than condition.
+	MpiGetSignedBit(MiddleResult, &SignedBit);
+
+	if(SignedBit == 0x1)
+		goto condition_others;
+
+
+	// Right MPI is greater than left MPI.
+	return MPI_YES;
+
+
+condition_others:
+
+
+	// Other conditions.
+	return MPI_NO;
+}
+
+
+
+
+
+/**
+
+@brief   Compare multiple precision signed integes with less-than criterion.
+
+Use MpiLessThan() to compare multiple precision signed integes with less-than criterion.
+
+
+@param [in]   MpiLeft    Left MPI
+@param [in]   MpiRight   Right MPI
+
+
+@retval   MPI_NO    "Left MPI < Right MPI" is false.
+@retval   MPI_YES   "Left MPI < Right MPI" is true.
+
+
+@note
+	The constants MPI_YES and MPI_NO are defined in MPI_YES_NO_STATUS enumeration.
+
+*/
+int
+MpiLessThan(
+	MPI MpiLeft,
+	MPI MpiRight
+	)
+{
+	MPI MiddleResult;
+	unsigned char SignedBit;
+
+
+
+	// Check equal-to condition.
+	if(MpiEqualTo(MpiLeft, MpiRight) == MPI_YES)
+		goto condition_others;
+
+
+	// Subtract right MPI form left MPI.
+	MpiSub(&MiddleResult, MpiLeft, MpiRight);
+
+
+	// Check greater-than condition.
+	MpiGetSignedBit(MiddleResult, &SignedBit);
+
+	if(SignedBit == 0x0)
+		goto condition_others;
+
+
+	// Right MPI is less than left MPI.
+	return MPI_YES;
+
+
+condition_others:
+
+
+	// Other conditions.
+	return MPI_NO;
+}
+
+
+
+
+
+/**
+
+@brief   Minimize multiple precision signed integer bit number.
+
+Use MpiMinimizeBitNum() to minimize multiple precision signed integer MPI bit number.
+
+
+@param [in]   pMpiVar   Pointer to an allocated memory for storing result
+
+*/
+void
+MpiMinimizeBitNum(
+	MPI *pMpiVar
+	)
+{
+	int i;
+	unsigned char SignedBit;
+	unsigned char BitValue;
+
+
+
+	// Get signed bit form MPI;
+	MpiGetSignedBit(*pMpiVar, &SignedBit);
+
+
+	// Find MPI MSB position.
+	// Note: The MSB of signed integer is the rightest signed bit.
+	for(i = (MPI_VALUE_BIT_NUM_MAX - 2); i > -1; i--)
+	{
+		// Get current bit value.
+		MpiGetBit(*pMpiVar, i, &BitValue);
+
+		// Compare current bit with signed bit.
+		if(BitValue != SignedBit)
+			break;
+	}
+
+
+	// Set MPI bit number.
+	// Note: MPI bit number must be greater than one.
+	pMpiVar->BitNum = (i == -1) ? 2 : (i + 2);
+
+
+	return;
+}
+
+
+
+
+
+
+/**
+
+@brief   Calculate multiple precision signed integer logarithm with base 2.
+
+Use MpiMinimizeBitNum() to calculate multiple precision signed integer logarithm with base 2.
+
+
+@param [out]   pResult            Pointer to an allocated memory for storing result (unit: pow(2, - ResultFracBitNum))
+@param [in]    MpiVar             MPI variable for calculating
+@param [in]    ResultFracBitNum   Result fraction bit number
+
+
+@note
+	-# MPI variable bit number must be minimized.
+	-# MPI variable bit number must be less than (MPI_VALUE_BIT_NUM_MAX / 2 + 1).
+    -# MPI variable must be greater than zero.
+	-# If MPI variable is zero, the result is zero in MpiLog2().
+	-# The result bit number will be minimized in MpiLog2().
+
+*/
+void
+MpiLog2(
+	MPI *pResult,
+	MPI MpiVar,
+	unsigned long ResultFracBitNum
+	)
+{
+	unsigned int i;
+	MPI MiddleResult;
+	unsigned char BitValue;
+
+
+
+	// Get integer part of MPI logarithm result with base 2.
+	MpiSetValue(pResult, (long)(MpiVar.BitNum - 2));
+
+
+	// Get fraction part of MPI logarithm result with base 2 by logarithm algorithm.
+	// Note: Take middle result format as follows:
+	//                         x x . x x ~ x
+	//       (integer part 2 bits) . (fraction part MPI_LOG_MIDDLE_RESULT_FRAC_BIT_NUM bits)
+	
+	// Set middle result with initial value.
+	MpiLeftShift(&MiddleResult, MpiVar, (MPI_LOG_MIDDLE_RESULT_FRAC_BIT_NUM - MpiVar.BitNum + 2));
+
+	// Calculate result fraction bits.
+	for(i = 0; i < ResultFracBitNum; i++)
+	{
+		// Shift result toward left with one bit.
+		// Note: MpiLeftShift() will minimize result bit number.
+		MpiLeftShift(pResult, *pResult, 1);
+
+		// Square middle result.
+		MpiMul(&MiddleResult, MiddleResult, MiddleResult);
+
+		// Shift middle result toward right with fraction bit num.
+		MpiRightShift(&MiddleResult, MiddleResult, MPI_LOG_MIDDLE_RESULT_FRAC_BIT_NUM);
+
+		// Get middle result integer part bit 1.
+		MpiGetBit(MiddleResult, MPI_LOG_MIDDLE_RESULT_FRAC_BIT_NUM + 1, &BitValue);
+
+		// If middle result integer part bit 1 is equal to 0x1,
+		// shift middle result with one bit toward right and set result LSB with one.
+		if(BitValue == 0x1)
+		{
+			MpiRightShift(&MiddleResult, MiddleResult, 1);
+			MpiSetBit(pResult, 0, 0x1);
+		}
+	}
+
+
+	return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/math_mpi.h b/drivers/media/usb/dvb-usb/math_mpi.h
new file mode 100644
index 0000000..73a7d1d
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/math_mpi.h
@@ -0,0 +1,201 @@
+#ifndef __MATH_MPI_H
+#define __MATH_MPI_H
+
+/**
+
+@file
+
+@brief   Mutliple precision integer (MPI) arithmetic declaration
+
+One can use to mutliple precision arithmetic to manipulate large signed integers.
+
+*/
+
+
+
+
+
+// Constant
+#define MPI_BYTE_BIT_NUM			8
+#define MPI_LONG_BYTE_NUM			4
+#define MPI_LONG_BIT_NUM			32
+
+
+
+// Mask and shift
+#define MPI_BYTE_MASK				0xff
+#define MPI_BYTE_SHIFT				8
+
+#define MPI_BIT_0_MASK				0x1
+#define MPI_BIT_7_SHIFT				7
+
+
+
+// Multiple precision integer definition
+#define MPI_VALUE_BYTE_NUM_MAX		10												///<   Maximum MPI value byte number
+#define MPI_VALUE_BIT_NUM_MAX		(MPI_VALUE_BYTE_NUM_MAX * MPI_BYTE_BIT_NUM)		///<   Maximum MPI value bit number
+
+/// Multiple precision integer structure
+typedef struct
+{
+	unsigned long BitNum;
+	unsigned char Value[MPI_VALUE_BYTE_NUM_MAX];
+}
+MPI;
+
+
+
+///  MPI yes/no status
+enum MPI_YES_NO_STATUS
+{
+	MPI_NO,			///<   No
+	MPI_YES,		///<   Yes
+};
+
+
+
+// Logarithm with base 2
+#define MPI_LOG_MIDDLE_RESULT_FRAC_BIT_NUM			(MPI_VALUE_BIT_NUM_MAX / 2 - 2)
+
+
+
+
+
+// MPI access
+void
+MpiSetValue(
+	MPI *pMpiVar,
+	long Value
+	);
+
+void
+MpiGetValue(
+	MPI MpiVar,
+	long *pValue
+	);
+
+void
+MpiSetBit(
+	MPI *pMpiVar,
+	unsigned long BitPosition,
+	unsigned char BitValue
+	);
+
+void
+MpiGetBit(
+	MPI MpiVar,
+	unsigned long BitPosition,
+	unsigned char *pBitValue
+	);
+
+void
+MpiGetSignedBit(
+	MPI MpiVar,
+	unsigned char *pSignedBit
+	);
+
+
+
+// MPI operator
+void
+MpiAssign(
+	MPI *pResult,
+	MPI Operand
+	);
+
+void
+MpiUnaryMinus(
+	MPI *pResult,
+	MPI Operand
+	);
+
+void
+MpiAdd(
+	MPI *pSum,
+	MPI Augend,
+	MPI Addend
+	);
+
+void
+MpiSub(
+	MPI *pDifference,
+	MPI Minuend,
+	MPI Subtrahend
+	);
+
+void
+MpiMul(
+	MPI *pProduct,
+	MPI Multiplicand,
+	MPI Multiplicator
+	);
+
+void
+MpiDiv(
+	MPI *pQuotient,
+	MPI *pRemainder,
+	MPI Dividend,
+	MPI Divisor
+	);
+
+void
+MpiRightShift(
+	MPI *pResult,
+	MPI Operand,
+	unsigned long ShiftBitNum
+	);
+
+void
+MpiLeftShift(
+	MPI *pResult,
+	MPI Operand,
+	unsigned long ShiftBitNum
+	);
+
+int
+MpiEqualTo(
+	MPI MpiLeft,
+	MPI MpiRight
+	);
+
+int
+MpiGreaterThan(
+	MPI MpiLeft,
+	MPI MpiRight
+	);
+
+int
+MpiLessThan(
+	MPI MpiLeft,
+	MPI MpiRight
+	);
+
+void
+MpiMinimizeBitNum(
+	MPI *pMpiVar
+	);
+
+
+
+// MPI special function
+void
+MpiLog2(
+	MPI *pResult,
+	MPI MpiVar,
+	unsigned long ResultFracBitNum
+	);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_e4000.c b/drivers/media/usb/dvb-usb/nim_rtl2832_e4000.c
new file mode 100644
index 0000000..c2e9df8
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_e4000.c
@@ -0,0 +1,1001 @@
+/**
+
+@file
+
+@brief   RTL2832 E4000 NIM module definition
+
+One can manipulate RTL2832 E4000 NIM through RTL2832 E4000 NIM module.
+RTL2832 E4000 NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_e4000.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 E4000 NIM module builder
+
+Use BuildRtl2832E4000Module() to build RTL2832 E4000 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 E4000 NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              E4000 I2C device address
+@param [in]   TunerCrystalFreqHz           E4000 crystal frequency in Hz
+
+
+@note
+	-# One should call BuildRtl2832E4000Module() to build RTL2832 E4000 NIM module before using it.
+
+*/
+void
+BuildRtl2832E4000Module(
+	DVBT_NIM_MODULE **ppNim,									// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+	RTL2832_E4000_EXTRA_MODULE *pNimExtra;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832E4000);
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_E4000;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build E4000 tuner module.
+	BuildE4000Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_e4000_Initialize;
+	pNim->SetParameters  = rtl2832_e4000_SetParameters;
+	pNim->UpdateFunction = rtl2832_e4000_UpdateFunction;
+
+
+	// Initialize NIM extra module variables.
+	pNimExtra->TunerModeUpdateWaitTimeMax = 
+		DivideWithCeiling(RTL2832_E4000_TUNER_MODE_UPDATE_WAIT_TIME_MS, DemodUpdateFuncRefPeriodMs);
+	pNimExtra->TunerModeUpdateWaitTime    = 0;
+	pNimExtra->TunerGainMode = RTL2832_E4000_TUNER_GAIN_NORMAL;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_e4000_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_E4000_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x5a	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x5a	},
+		{DVBT_AAGC_LOOP_GAIN,		0x18    },
+		{DVBT_LOOP_GAIN2_3_0,		0x8		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x18	},
+
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9d4	},
+		{DVBT_EN_GI_PGA,			0x0		},
+		{DVBT_THD_LOCK_UP,			0x0		},
+		{DVBT_THD_LOCK_DW,			0x0		},
+		{DVBT_THD_UP1,				0x14	},
+		{DVBT_THD_DW1,				0xec	},
+
+		{DVBT_INTER_CNT_LEN,		0xc		},
+		{DVBT_GI_PGA_STATE,			0x0		},
+		{DVBT_EN_AGC_PGA,			0x1		},
+
+		{DVBT_REG_GPE,				0x1		},
+		{DVBT_REG_GPO,				0x1		},
+		{DVBT_REG_MONSEL,			0x1		},
+		{DVBT_REG_MON,				0x1		},
+		{DVBT_REG_4MSEL,			0x0		},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_E4000_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+int
+rtl2832_e4000_Initialize_fm(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_E4000_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x5a	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x5a	},
+		{DVBT_AAGC_LOOP_GAIN,		0x18    },
+		{DVBT_LOOP_GAIN2_3_0,		0x8		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x18	},
+
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9d4	},
+		{DVBT_EN_GI_PGA,			0x0		},
+		{DVBT_THD_LOCK_UP,			0x0		},
+		{DVBT_THD_LOCK_DW,			0x0		},
+		{DVBT_THD_UP1,				0x14	},
+		{DVBT_THD_DW1,				0xec	},
+
+		{DVBT_INTER_CNT_LEN,		0xc		},
+		{DVBT_GI_PGA_STATE,			0x0		},
+		{DVBT_EN_AGC_PGA,			0x1		},
+
+		{DVBT_REG_GPE,				0x1		},
+		{DVBT_REG_GPO,				0x1		},
+		{DVBT_REG_MONSEL,			0x1		},
+		{DVBT_REG_MON,				0x1		},
+		{DVBT_REG_4MSEL,			0x0		},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	//if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+	//	goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	//if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+	//	goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	//if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+	//	goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_E4000_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_e4000_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+	E4000_EXTRA_MODULE *pTunerExtra;
+	RTL2832_E4000_EXTRA_MODULE *pNimExtra;
+
+	unsigned long TunerBandwidthHz;
+
+	int RfFreqKhz;
+	int BandwidthKhz;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.E4000);
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832E4000);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)//added by annie
+		goto error_status_execute_function;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthHz according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthHz = E4000_BANDWIDTH_6000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthHz = E4000_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthHz = E4000_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth Hz with TunerBandwidthHz.
+	if(pTunerExtra->SetBandwidthHz(pTuner, TunerBandwidthHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set tuner gain mode with normal condition for update procedure.
+	RfFreqKhz = (int)((RfFreqHz + 500) / 1000);
+	BandwidthKhz = (int)((TunerBandwidthHz + 500) / 1000);
+
+	if(E4000_nominal(pTuner, RfFreqKhz, BandwidthKhz) != E4000_1_SUCCESS)
+//	if(E4000_sensitivity(pTuner, RfFreqKhz, BandwidthKhz) != E4000_1_SUCCESS)
+//	if(E4000_linearity(pTuner, RfFreqKhz, BandwidthKhz) != E4000_1_SUCCESS)
+		goto error_status_execute_function;
+
+	pNimExtra->TunerGainMode = RTL2832_E4000_TUNER_GAIN_NORMAL;
+
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+int
+rtl2832_e4000_SetParameters_fm(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+	E4000_EXTRA_MODULE *pTunerExtra;
+	RTL2832_E4000_EXTRA_MODULE *pNimExtra;
+
+	unsigned long TunerBandwidthHz;
+
+	int RfFreqKhz;
+	int BandwidthKhz;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.E4000);
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832E4000);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)//added by annie
+		goto error_status_execute_function;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthHz according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthHz = E4000_BANDWIDTH_6000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthHz = E4000_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthHz = E4000_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth Hz with TunerBandwidthHz.
+	if(pTunerExtra->SetBandwidthHz(pTuner, TunerBandwidthHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set tuner gain mode with normal condition for update procedure.
+	RfFreqKhz = (int)((RfFreqHz + 500) / 1000);
+	BandwidthKhz = (int)((TunerBandwidthHz + 500) / 1000);
+
+	if(E4000_nominal(pTuner, RfFreqKhz, BandwidthKhz) != E4000_1_SUCCESS)//change by annie
+//	if(E4000_sensitivity(pTuner, RfFreqKhz, BandwidthKhz) != E4000_1_SUCCESS)
+//	if(E4000_linearity(pTuner, RfFreqKhz, BandwidthKhz) != E4000_1_SUCCESS)
+		goto error_status_execute_function;
+
+	pNimExtra->TunerGainMode = RTL2832_E4000_TUNER_GAIN_NORMAL;
+
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+/**
+
+@see   DVBT_NIM_FP_UPDATE_FUNCTION
+
+*/
+int
+rtl2832_e4000_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	RTL2832_E4000_EXTRA_MODULE *pNimExtra;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832E4000);
+
+
+	// Update demod particular registers.
+	if(pDemod->UpdateFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Increase tuner mode update waiting time.
+	pNimExtra->TunerModeUpdateWaitTime += 1;
+
+
+	// Check if need to update tuner mode according to update waiting time.
+	if(pNimExtra->TunerModeUpdateWaitTime == pNimExtra->TunerModeUpdateWaitTimeMax)
+	{
+		// Reset update waiting time.
+		pNimExtra->TunerModeUpdateWaitTime = 0;
+
+		// Enable demod DVBT_IIC_REPEAT.
+		if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+
+		// Update tuner mode.
+		if(rtl2832_e4000_UpdateTunerMode(pNim) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		// Disable demod DVBT_IIC_REPEAT.
+		if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Update tuner mode.
+
+One can use rtl2832_e4000_UpdateTunerMode() to update tuner mode.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update tuner mode successfully.
+@retval   FUNCTION_ERROR     Update tuner mode unsuccessfully.
+
+*/
+int
+rtl2832_e4000_UpdateTunerMode(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	static const long LnaGainTable[RTL2832_E4000_LNA_GAIN_TABLE_LEN][RTL2832_E4000_LNA_GAIN_BAND_NUM] =
+	{
+		// VHF Gain,	UHF Gain,		ReadingByte
+		{-50,			-50	},		//	0x0
+		{-25,			-25	},		//	0x1
+		{-50,			-50	},		//	0x2
+		{-25,			-25	},		//	0x3
+		{0,				0	},		//	0x4
+		{25,			25	},		//	0x5
+		{50,			50	},		//	0x6
+		{75,			75	},		//	0x7
+		{100,			100	},		//	0x8
+		{125,			125	},		//	0x9
+		{150,			150	},		//	0xa
+		{175,			175	},		//	0xb
+		{200,			200	},		//	0xc
+		{225,			250	},		//	0xd
+		{250,			280	},		//	0xe
+		{250,			280	},		//	0xf
+
+		// Note: The gain unit is 0.1 dB.
+	};
+
+	static const long LnaGainAddTable[RTL2832_E4000_LNA_GAIN_ADD_TABLE_LEN] =
+	{
+		// Gain,		ReadingByte
+		NO_USE,		//	0x0
+		NO_USE,		//	0x1
+		NO_USE,		//	0x2
+		0,			//	0x3
+		NO_USE,		//	0x4
+		20,			//	0x5
+		NO_USE,		//	0x6
+		70,			//	0x7
+
+		// Note: The gain unit is 0.1 dB.
+	};
+
+	static const long MixerGainTable[RTL2832_E4000_MIXER_GAIN_TABLE_LEN][RTL2832_E4000_MIXER_GAIN_BAND_NUM] =
+	{
+		// VHF Gain,	UHF Gain,		ReadingByte
+		{90,			40	},		//	0x0
+		{170,			120	},		//	0x1
+
+		// Note: The gain unit is 0.1 dB.
+	};
+
+	static const long IfStage1GainTable[RTL2832_E4000_IF_STAGE_1_GAIN_TABLE_LEN] =
+	{
+		// Gain,		ReadingByte
+		-30,		//	0x0
+		60,			//	0x1
+
+		// Note: The gain unit is 0.1 dB.
+	};
+
+	static const long IfStage2GainTable[RTL2832_E4000_IF_STAGE_2_GAIN_TABLE_LEN] =
+	{
+		// Gain,		ReadingByte
+		0,			//	0x0
+		30,			//	0x1
+		60,			//	0x2
+		90,			//	0x3
+
+		// Note: The gain unit is 0.1 dB.
+	};
+
+	static const long IfStage3GainTable[RTL2832_E4000_IF_STAGE_3_GAIN_TABLE_LEN] =
+	{
+		// Gain,		ReadingByte
+		0,			//	0x0
+		30,			//	0x1
+		60,			//	0x2
+		90,			//	0x3
+
+		// Note: The gain unit is 0.1 dB.
+	};
+
+	static const long IfStage4GainTable[RTL2832_E4000_IF_STAGE_4_GAIN_TABLE_LEN] =
+	{
+		// Gain,		ReadingByte
+		0,			//	0x0
+		10,			//	0x1
+		20,			//	0x2
+		20,			//	0x3
+
+		// Note: The gain unit is 0.1 dB.
+	};
+
+	static const long IfStage5GainTable[RTL2832_E4000_IF_STAGE_5_GAIN_TABLE_LEN] =
+	{
+		// Gain,		ReadingByte
+		0,			//	0x0
+		30,			//	0x1
+		60,			//	0x2
+		90,			//	0x3
+		120,		//	0x4
+		120,		//	0x5
+		120,		//	0x6
+		120,		//	0x7
+
+		// Note: The gain unit is 0.1 dB.
+	};
+
+	static const long IfStage6GainTable[RTL2832_E4000_IF_STAGE_6_GAIN_TABLE_LEN] =
+	{
+		// Gain,		ReadingByte
+		0,			//	0x0
+		30,			//	0x1
+		60,			//	0x2
+		90,			//	0x3
+		120,		//	0x4
+		120,		//	0x5
+		120,		//	0x6
+		120,		//	0x7
+
+		// Note: The gain unit is 0.1 dB.
+	};
+
+
+	TUNER_MODULE *pTuner;
+	E4000_EXTRA_MODULE *pTunerExtra;
+	RTL2832_E4000_EXTRA_MODULE *pNimExtra;
+
+	unsigned long RfFreqHz;
+	int RfFreqKhz;
+	unsigned long BandwidthHz;
+	int BandwidthKhz;
+
+	unsigned char ReadingByte;
+	int BandIndex;
+
+	unsigned char TunerBitsLna, TunerBitsLnaAdd, TunerBitsMixer;
+	unsigned char TunerBitsIfStage1, TunerBitsIfStage2, TunerBitsIfStage3, TunerBitsIfStage4;
+	unsigned char TunerBitsIfStage5, TunerBitsIfStage6;
+
+	long TunerGainLna, TunerGainLnaAdd, TunerGainMixer;
+	long TunerGainIfStage1, TunerGainIfStage2, TunerGainIfStage3, TunerGainIfStage4;
+	long TunerGainIfStage5, TunerGainIfStage6;
+
+	long TunerGainTotal;
+	long TunerInputPower;
+
+
+	// Get tuner module.
+	pTuner = pNim->pTuner;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.E4000);
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832E4000);
+
+
+	// Get tuner RF frequency in KHz.
+	// Note: RfFreqKhz = round(RfFreqHz / 1000)
+	if(pTuner->GetRfFreqHz(pTuner, &RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	RfFreqKhz = (int)((RfFreqHz + 500) / 1000);
+
+	// Get tuner bandwidth in KHz.
+	// Note: BandwidthKhz = round(BandwidthHz / 1000)
+	if(pTunerExtra->GetBandwidthHz(pTuner, &BandwidthHz) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	BandwidthKhz = (int)((BandwidthHz + 500) / 1000);
+
+
+	// Determine band index.
+	BandIndex = (RfFreqHz < RTL2832_E4000_RF_BAND_BOUNDARY_HZ) ? 0 : 1;
+
+
+	// Get tuner LNA gain according to reading byte and table.
+	if(pTunerExtra->GetRegByte(pTuner, RTL2832_E4000_LNA_GAIN_ADDR, &ReadingByte) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	TunerBitsLna = (ReadingByte & RTL2832_E4000_LNA_GAIN_MASK) >> RTL2832_E4000_LNA_GAIN_SHIFT;
+	TunerGainLna = LnaGainTable[TunerBitsLna][BandIndex];
+
+
+	// Get tuner LNA additional gain according to reading byte and table.
+	if(pTunerExtra->GetRegByte(pTuner, RTL2832_E4000_LNA_GAIN_ADD_ADDR, &ReadingByte) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	TunerBitsLnaAdd = (ReadingByte & RTL2832_E4000_LNA_GAIN_ADD_MASK) >> RTL2832_E4000_LNA_GAIN_ADD_SHIFT;
+	TunerGainLnaAdd = LnaGainAddTable[TunerBitsLnaAdd];
+
+
+	// Get tuner mixer gain according to reading byte and table.
+	if(pTunerExtra->GetRegByte(pTuner, RTL2832_E4000_MIXER_GAIN_ADDR, &ReadingByte) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	TunerBitsMixer = (ReadingByte & RTL2832_E4000_MIXER_GAIN_MASK) >> RTL2832_E4000_LNA_GAIN_ADD_SHIFT;
+	TunerGainMixer = MixerGainTable[TunerBitsMixer][BandIndex];
+
+
+	// Get tuner IF stage 1 gain according to reading byte and table.
+	if(pTunerExtra->GetRegByte(pTuner, RTL2832_E4000_IF_STAGE_1_GAIN_ADDR, &ReadingByte) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	TunerBitsIfStage1 = (ReadingByte & RTL2832_E4000_IF_STAGE_1_GAIN_MASK) >> RTL2832_E4000_IF_STAGE_1_GAIN_SHIFT;
+	TunerGainIfStage1 = IfStage1GainTable[TunerBitsIfStage1];
+
+
+	// Get tuner IF stage 2 gain according to reading byte and table.
+	if(pTunerExtra->GetRegByte(pTuner, RTL2832_E4000_IF_STAGE_2_GAIN_ADDR, &ReadingByte) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	TunerBitsIfStage2 = (ReadingByte & RTL2832_E4000_IF_STAGE_2_GAIN_MASK) >> RTL2832_E4000_IF_STAGE_2_GAIN_SHIFT;
+	TunerGainIfStage2 = IfStage2GainTable[TunerBitsIfStage2];
+
+
+	// Get tuner IF stage 3 gain according to reading byte and table.
+	if(pTunerExtra->GetRegByte(pTuner, RTL2832_E4000_IF_STAGE_3_GAIN_ADDR, &ReadingByte) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	TunerBitsIfStage3 = (ReadingByte & RTL2832_E4000_IF_STAGE_3_GAIN_MASK) >> RTL2832_E4000_IF_STAGE_3_GAIN_SHIFT;
+	TunerGainIfStage3 = IfStage3GainTable[TunerBitsIfStage3];
+
+
+	// Get tuner IF stage 4 gain according to reading byte and table.
+	if(pTunerExtra->GetRegByte(pTuner, RTL2832_E4000_IF_STAGE_4_GAIN_ADDR, &ReadingByte) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	TunerBitsIfStage4 = (ReadingByte & RTL2832_E4000_IF_STAGE_4_GAIN_MASK) >> RTL2832_E4000_IF_STAGE_4_GAIN_SHIFT;
+	TunerGainIfStage4 = IfStage4GainTable[TunerBitsIfStage4];
+
+
+	// Get tuner IF stage 5 gain according to reading byte and table.
+	if(pTunerExtra->GetRegByte(pTuner, RTL2832_E4000_IF_STAGE_5_GAIN_ADDR, &ReadingByte) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	TunerBitsIfStage5 = (ReadingByte & RTL2832_E4000_IF_STAGE_5_GAIN_MASK) >> RTL2832_E4000_IF_STAGE_5_GAIN_SHIFT;
+	TunerGainIfStage5 = IfStage5GainTable[TunerBitsIfStage5];
+
+
+	// Get tuner IF stage 6 gain according to reading byte and table.
+	if(pTunerExtra->GetRegByte(pTuner, RTL2832_E4000_IF_STAGE_6_GAIN_ADDR, &ReadingByte) != FUNCTION_SUCCESS)
+		goto error_status_get_tuner_registers;
+
+	TunerBitsIfStage6 = (ReadingByte & RTL2832_E4000_IF_STAGE_6_GAIN_MASK) >> RTL2832_E4000_IF_STAGE_6_GAIN_SHIFT;
+	TunerGainIfStage6 = IfStage6GainTable[TunerBitsIfStage6];
+
+
+	// Calculate tuner total gain.
+	// Note: The unit of tuner total gain is 0.1 dB.
+	TunerGainTotal = TunerGainLna + TunerGainLnaAdd + TunerGainMixer + 
+	                 TunerGainIfStage1 + TunerGainIfStage2 + TunerGainIfStage3 + TunerGainIfStage4 +
+	                 TunerGainIfStage5 + TunerGainIfStage6;
+
+	// Calculate tuner input power.
+	// Note: The unit of tuner input power is 0.1 dBm
+	TunerInputPower = RTL2832_E4000_TUNER_OUTPUT_POWER_UNIT_0P1_DBM - TunerGainTotal;
+
+
+	// Determine tuner gain mode according to tuner input power.
+	// Note: The unit of tuner input power is 0.1 dBm
+	switch(pNimExtra->TunerGainMode)
+	{
+		default:
+		case RTL2832_E4000_TUNER_GAIN_SENSITIVE:
+
+			if(TunerInputPower > -650)
+				pNimExtra->TunerGainMode = RTL2832_E4000_TUNER_GAIN_NORMAL;
+
+			break;
+
+
+		case RTL2832_E4000_TUNER_GAIN_NORMAL:
+
+			if(TunerInputPower < -750)
+				pNimExtra->TunerGainMode = RTL2832_E4000_TUNER_GAIN_SENSITIVE;
+
+			if(TunerInputPower > -400)
+				pNimExtra->TunerGainMode = RTL2832_E4000_TUNER_GAIN_LINEAR;
+
+			break;
+
+
+		case RTL2832_E4000_TUNER_GAIN_LINEAR:
+
+			if(TunerInputPower < -500)
+				pNimExtra->TunerGainMode = RTL2832_E4000_TUNER_GAIN_NORMAL;
+
+			break;
+	}
+
+
+	// Set tuner gain mode.
+	switch(pNimExtra->TunerGainMode)
+	{
+		default:
+		case RTL2832_E4000_TUNER_GAIN_SENSITIVE:
+
+			if(E4000_sensitivity(pTuner, RfFreqKhz, BandwidthKhz) != E4000_1_SUCCESS)
+				goto error_status_execute_function;
+
+			break;
+
+
+		case RTL2832_E4000_TUNER_GAIN_NORMAL:
+
+			if(E4000_nominal(pTuner, RfFreqKhz, BandwidthKhz) != E4000_1_SUCCESS)
+				goto error_status_execute_function;
+
+			break;
+
+
+		case RTL2832_E4000_TUNER_GAIN_LINEAR:
+
+			if(E4000_linearity(pTuner, RfFreqKhz, BandwidthKhz) != E4000_1_SUCCESS)
+				goto error_status_execute_function;
+
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_get_tuner_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_e4000.h b/drivers/media/usb/dvb-usb/nim_rtl2832_e4000.h
new file mode 100644
index 0000000..e23c277
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_e4000.h
@@ -0,0 +1,226 @@
+#ifndef __NIM_RTL2832_E4000
+#define __NIM_RTL2832_E4000
+
+/**
+
+@file
+
+@brief   RTL2832 E4000 NIM module declaration
+
+One can manipulate RTL2832 E4000 NIM through RTL2832 E4000 NIM module.
+RTL2832 E4000 NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_e4000.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2832 E4000 NIM module.
+	BuildRtl2832E4000Module(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,									// Maximum I2C reading byte number is 9.
+		8,									// Maximum I2C writing byte number is 8.
+		CustomI2cRead,						// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,						// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,						// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,								// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,			// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,				// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,			// The RTL2832 application mode is STB mode.
+		200,								// The RTL2832 update function reference period is 200 millisecond
+		YES,								// The RTL2832 Function 1 enabling status is YES.
+
+		0xc8,								// The E4000 I2C device address is 0xc8 in 8-bit format.
+		CRYSTAL_FREQ_26000000HZ				// The E4000 crystal frequency is 26 MHz.
+		);
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_e4000.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_E4000_ADDITIONAL_INIT_REG_TABLE_LEN		34
+
+#define RTL2832_E4000_LNA_GAIN_TABLE_LEN				16
+#define RTL2832_E4000_LNA_GAIN_ADD_TABLE_LEN			8
+#define RTL2832_E4000_MIXER_GAIN_TABLE_LEN				2
+#define RTL2832_E4000_IF_STAGE_1_GAIN_TABLE_LEN			2
+#define RTL2832_E4000_IF_STAGE_2_GAIN_TABLE_LEN			4
+#define RTL2832_E4000_IF_STAGE_3_GAIN_TABLE_LEN			4
+#define RTL2832_E4000_IF_STAGE_4_GAIN_TABLE_LEN			4
+#define RTL2832_E4000_IF_STAGE_5_GAIN_TABLE_LEN			8
+#define RTL2832_E4000_IF_STAGE_6_GAIN_TABLE_LEN			8
+
+#define RTL2832_E4000_LNA_GAIN_BAND_NUM					2
+#define RTL2832_E4000_MIXER_GAIN_BAND_NUM				2
+
+#define RTL2832_E4000_RF_BAND_BOUNDARY_HZ				300000000
+
+#define RTL2832_E4000_LNA_GAIN_ADDR						0x14
+#define RTL2832_E4000_LNA_GAIN_MASK						0xf
+#define RTL2832_E4000_LNA_GAIN_SHIFT					0
+
+#define RTL2832_E4000_LNA_GAIN_ADD_ADDR					0x24
+#define RTL2832_E4000_LNA_GAIN_ADD_MASK					0x7
+#define RTL2832_E4000_LNA_GAIN_ADD_SHIFT				0
+
+#define RTL2832_E4000_MIXER_GAIN_ADDR					0x15
+#define RTL2832_E4000_MIXER_GAIN_MASK					0x1
+#define RTL2832_E4000_MIXER_GAIN_SHIFT					0
+
+#define RTL2832_E4000_IF_STAGE_1_GAIN_ADDR				0x16
+#define RTL2832_E4000_IF_STAGE_1_GAIN_MASK				0x1
+#define RTL2832_E4000_IF_STAGE_1_GAIN_SHIFT				0
+
+#define RTL2832_E4000_IF_STAGE_2_GAIN_ADDR				0x16
+#define RTL2832_E4000_IF_STAGE_2_GAIN_MASK				0x6
+#define RTL2832_E4000_IF_STAGE_2_GAIN_SHIFT				1
+
+#define RTL2832_E4000_IF_STAGE_3_GAIN_ADDR				0x16
+#define RTL2832_E4000_IF_STAGE_3_GAIN_MASK				0x18
+#define RTL2832_E4000_IF_STAGE_3_GAIN_SHIFT				3
+
+#define RTL2832_E4000_IF_STAGE_4_GAIN_ADDR				0x16
+#define RTL2832_E4000_IF_STAGE_4_GAIN_MASK				0x60
+#define RTL2832_E4000_IF_STAGE_4_GAIN_SHIFT				5
+
+#define RTL2832_E4000_IF_STAGE_5_GAIN_ADDR				0x17
+#define RTL2832_E4000_IF_STAGE_5_GAIN_MASK				0x7
+#define RTL2832_E4000_IF_STAGE_5_GAIN_SHIFT				0
+
+#define RTL2832_E4000_IF_STAGE_6_GAIN_ADDR				0x17
+#define RTL2832_E4000_IF_STAGE_6_GAIN_MASK				0x38
+#define RTL2832_E4000_IF_STAGE_6_GAIN_SHIFT				3
+
+#define RTL2832_E4000_TUNER_OUTPUT_POWER_UNIT_0P1_DBM	-100
+
+#define RTL2832_E4000_TUNER_MODE_UPDATE_WAIT_TIME_MS	1000
+
+
+// Tuner gain mode
+enum RTL2832_E4000_TUNER_GAIN_MODE
+{
+	RTL2832_E4000_TUNER_GAIN_SENSITIVE,
+	RTL2832_E4000_TUNER_GAIN_NORMAL,
+	RTL2832_E4000_TUNER_GAIN_LINEAR,
+};
+
+
+
+
+
+// Builder
+void
+BuildRtl2832E4000Module(
+	DVBT_NIM_MODULE **ppNim,									// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	);
+
+
+
+
+
+// RTL2832 E4000 NIM manipulaing functions
+int
+rtl2832_e4000_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_e4000_Initialize_fm(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+int
+rtl2832_e4000_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+rtl2832_e4000_SetParameters_fm(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+rtl2832_e4000_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_e4000_UpdateTunerMode(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_fc0012.c b/drivers/media/usb/dvb-usb/nim_rtl2832_fc0012.c
new file mode 100644
index 0000000..0db94c7
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_fc0012.c
@@ -0,0 +1,840 @@
+/**
+
+@file
+
+@brief   RTL2832 FC0012 NIM module definition
+
+One can manipulate RTL2832 FC0012 NIM through RTL2832 FC0012 NIM module.
+RTL2832 FC0012 NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_fc0012.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 FC0012 NIM module builder
+
+Use BuildRtl2832Fc0012Module() to build RTL2832 FC0012 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 FC0012 NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              FC0012 I2C device address
+@param [in]   TunerCrystalFreqHz           FC0012 crystal frequency in Hz
+
+
+@note
+	-# One should call BuildRtl2832Fc0012Module() to build RTL2832 FC0012 NIM module before using it.
+
+*/
+void
+BuildRtl2832Fc0012Module(
+	DVBT_NIM_MODULE **ppNim,								// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+	RTL2832_FC0012_EXTRA_MODULE *pNimExtra;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Fc0012);
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_FC0012;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build FC0012 tuner module.
+	BuildFc0012Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_fc0012_Initialize;
+	pNim->SetParameters  = rtl2832_fc0012_SetParameters;
+	pNim->UpdateFunction = rtl2832_fc0012_UpdateFunction;
+
+
+	// Initialize NIM extra module variables.
+	pNimExtra->LnaUpdateWaitTimeMax = DivideWithCeiling(RTL2832_FC0012_LNA_UPDATE_WAIT_TIME_MS, DemodUpdateFuncRefPeriodMs);
+	pNimExtra->LnaUpdateWaitTime    = 0;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_fc0012_Initialize_fm(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_FC0012_DAB_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x5a	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x5a	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9bf	},
+		{DVBT_EN_GI_PGA,			0x0		},
+		{DVBT_THD_LOCK_UP,			0x0		},
+		{DVBT_THD_LOCK_DW,			0x0		},
+		{DVBT_THD_UP1,				0x11	},
+		{DVBT_THD_DW1,				0xef	},
+		{DVBT_INTER_CNT_LEN,		0xc		},
+		{DVBT_GI_PGA_STATE,			0x0		},
+		{DVBT_EN_AGC_PGA,			0x1		},
+
+		//test
+		{DVBT_AD_EN_REG,			0x1		},
+		{DVBT_AD_EN_REG1,			0x1		},
+//		{DVBT_EN_BK_TRK,			0x0		},
+//		{DVBT_AD_AV_REF,			0x2a	},
+//		{DVBT_REG_PI,				0x3		},
+		//----------
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner registers.
+	if(fc0012_SetRegMaskBits(pTuner, 0xd, 7, 0, 0x2) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner registers.
+	if(fc0012_SetRegMaskBits(pTuner, 0x11, 7, 0, 0x0) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner registers.
+	if(fc0012_SetRegMaskBits(pTuner, 0x15, 7, 0, 0x4) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	//if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+	//	goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	//if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+	//	goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_FC0012_DAB_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Get tuner RSSI value when calibration is on.
+	// Note: Need to execute rtl2832_fc0012_GetTunerRssiCalOn() after demod AD7 is on.
+	if(rtl2832_fc0012_GetTunerRssiCalOn(pNim) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_fc0012_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_FC0012_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x5a	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x5a	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9bf	},
+		{DVBT_EN_GI_PGA,			0x0		},
+		{DVBT_THD_LOCK_UP,			0x0		},
+		{DVBT_THD_LOCK_DW,			0x0		},
+		{DVBT_THD_UP1,				0x11	},
+		{DVBT_THD_DW1,				0xef	},
+		{DVBT_INTER_CNT_LEN,		0xc		},
+		{DVBT_GI_PGA_STATE,			0x0		},
+		{DVBT_EN_AGC_PGA,			0x1		},
+//		{DVBT_REG_GPE,				0x1		},
+//		{DVBT_REG_GPO,				0x0		},
+//		{DVBT_REG_MONSEL,			0x0		},
+//		{DVBT_REG_MON,				0x3		},
+//		{DVBT_REG_4MSEL,			0x0		},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner registers.
+	if(fc0012_SetRegMaskBits(pTuner, 0xd, 7, 0, 0x2) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner registers.
+	if(fc0012_SetRegMaskBits(pTuner, 0x11, 7, 0, 0x0) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner registers.
+	if(fc0012_SetRegMaskBits(pTuner, 0x15, 7, 0, 0x4) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_FC0012_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Get tuner RSSI value when calibration is on.
+	// Note: Need to execute rtl2832_fc0012_GetTunerRssiCalOn() after demod AD7 is on.
+	if(rtl2832_fc0012_GetTunerRssiCalOn(pNim) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_fc0012_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	FC0012_EXTRA_MODULE *pTunerExtra;
+	int TunerBandwidthMode;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc0012);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthMode = FC0012_BANDWIDTH_6000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthMode = FC0012_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthMode = FC0012_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetBandwidthMode(pTuner, TunerBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_fc0012_SetParameters_fm(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	FC0012_EXTRA_MODULE *pTunerExtra;
+	int TunerBandwidthMode;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc0012);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthMode = FC0012_BANDWIDTH_6000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthMode = FC0012_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthMode = FC0012_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetBandwidthMode(pTuner, TunerBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+	
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_UPDATE_FUNCTION
+
+*/
+int
+rtl2832_fc0012_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	RTL2832_FC0012_EXTRA_MODULE *pNimExtra;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Fc0012);
+
+
+	// Update demod particular registers.
+	if(pDemod->UpdateFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Increase tuner LNA_GAIN update waiting time.
+	pNimExtra->LnaUpdateWaitTime += 1;
+
+
+	// Check if need to update tuner LNA_GAIN according to update waiting time.
+	if(pNimExtra->LnaUpdateWaitTime == pNimExtra->LnaUpdateWaitTimeMax)
+	{
+		// Reset update waiting time.
+		pNimExtra->LnaUpdateWaitTime = 0;
+
+		// Enable demod DVBT_IIC_REPEAT.
+		if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+
+		// Update tuner LNA gain with RSSI.
+		if(rtl2832_fc0012_UpdateTunerLnaGainWithRssi(pNim) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		// Disable demod DVBT_IIC_REPEAT.
+		if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Get tuner RSSI value when calibration is on.
+
+One can use rtl2832_fc0012_GetTunerRssiCalOn() to get tuner calibration-on RSSI value.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Get tuner calibration-on RSSI value successfully.
+@retval   FUNCTION_ERROR     Get tuner calibration-on RSSI value unsuccessfully.
+
+*/
+int
+rtl2832_fc0012_GetTunerRssiCalOn(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+	FC0012_EXTRA_MODULE *pTunerExtra;
+	RTL2832_FC0012_EXTRA_MODULE *pNimExtra;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc0012);
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Fc0012);
+
+
+	// Set tuner EN_CAL_RSSI to 0x1.
+	if(fc0012_SetRegMaskBits(pTuner, 0x9, 4, 4, 0x1) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner LNA_POWER_DOWN to 0x1.
+	if(fc0012_SetRegMaskBits(pTuner, 0x6, 0, 0, 0x1) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Get demod RSSI_R when tuner RSSI calibration is on.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RSSI_R, &(pNimExtra->RssiRCalOn)) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Set tuner EN_CAL_RSSI to 0x0.
+	if(fc0012_SetRegMaskBits(pTuner, 0x9, 4, 4, 0x0) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner LNA_POWER_DOWN to 0x0.
+	if(fc0012_SetRegMaskBits(pTuner, 0x6, 0, 0, 0x0) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Update tuner LNA_GAIN with RSSI.
+
+One can use rtl2832_fc0012_UpdateTunerLnaGainWithRssi() to update tuner LNA_GAIN with RSSI.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update tuner LNA_GAIN with RSSI successfully.
+@retval   FUNCTION_ERROR     Update tuner LNA_GAIN with RSSI unsuccessfully.
+
+*/
+int
+rtl2832_fc0012_UpdateTunerLnaGainWithRssi(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+	FC0012_EXTRA_MODULE *pTunerExtra;
+	RTL2832_FC0012_EXTRA_MODULE *pNimExtra;
+
+	unsigned long RssiRCalOff;
+	long RssiRDiff;
+	unsigned char LnaGain;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc0012);
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Fc0012);
+
+
+	// Get demod RSSI_R when tuner RSSI calibration in off.
+	// Note: Tuner EN_CAL_RSSI and LNA_POWER_DOWN are set to 0x0 after rtl2832_fc0012_GetTunerRssiCalOn() executing.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RSSI_R, &RssiRCalOff) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Calculate RSSI_R difference.
+	RssiRDiff = RssiRCalOff - pNimExtra->RssiRCalOn;
+
+	// Get tuner LNA_GAIN.
+	if(fc0012_GetRegMaskBits(pTuner, 0x13, 4, 3, &LnaGain) != FC0012_I2C_SUCCESS)
+		goto error_status_get_registers;
+
+
+	deb_info("%s: current LnaGain = %d\n", __FUNCTION__, LnaGain);
+
+	// Determine next LNA_GAIN according to RSSI_R difference and current LNA_GAIN.
+	switch(LnaGain)
+	{
+		default:
+		case FC0012_LNA_GAIN_LOW:
+
+			if(RssiRDiff <= 0)
+				LnaGain = FC0012_LNA_GAIN_MIDDLE;
+
+			break;
+
+
+		case FC0012_LNA_GAIN_MIDDLE:
+
+			if(RssiRDiff >= 34)
+				LnaGain = FC0012_LNA_GAIN_LOW;
+
+			if(RssiRDiff <= 0)
+				LnaGain = FC0012_LNA_GAIN_HIGH;
+
+			break;
+
+
+		case FC0012_LNA_GAIN_HIGH:
+
+			if(RssiRDiff >= 8)
+				LnaGain = FC0012_LNA_GAIN_MIDDLE;
+
+			break;
+	}
+
+
+	deb_info("%s: next LnaGain = %d\n", __FUNCTION__, LnaGain);
+
+      
+	// Set tuner LNA_GAIN.
+	if(fc0012_SetRegMaskBits(pTuner, 0x13, 4, 3, LnaGain) != FC0012_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_fc0012.h b/drivers/media/usb/dvb-usb/nim_rtl2832_fc0012.h
new file mode 100644
index 0000000..befa45a
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_fc0012.h
@@ -0,0 +1,168 @@
+#ifndef __NIM_RTL2832_FC0012
+#define __NIM_RTL2832_FC0012
+
+/**
+
+@file
+
+@brief   RTL2832 FC0012 NIM module declaration
+
+One can manipulate RTL2832 FC0012 NIM through RTL2832 FC0012 NIM module.
+RTL2832 FC0012 NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_fc0012.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2832 FC0012 NIM module.
+	BuildRtl2832Fc0012Module(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,							// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,		// The RTL2832 application mode is STB mode.
+		200,							// The RTL2832 update function reference period is 200 millisecond
+		YES,							// The RTL2832 Function 1 enabling status is YES.
+
+		0xc6,							// The FC0012 I2C device address is 0xc6 in 8-bit format.
+		CRYSTAL_FREQ_36000000HZ			// The FC0012 crystal frequency is 36.0 MHz.
+		);
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_fc0012.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_FC0012_DAB_ADDITIONAL_INIT_REG_TABLE_LEN		31
+#define RTL2832_FC0012_ADDITIONAL_INIT_REG_TABLE_LEN		29
+#define RTL2832_FC0012_LNA_UPDATE_WAIT_TIME_MS				1000
+
+
+
+
+
+// Builder
+void
+BuildRtl2832Fc0012Module(
+	DVBT_NIM_MODULE **ppNim,									// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	);
+
+
+
+
+
+// RTL2832 FC0012 NIM manipulaing functions
+int
+rtl2832_fc0012_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_fc0012_Initialize_fm(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_fc0012_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+rtl2832_fc0012_SetParameters_fm(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+rtl2832_fc0012_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_fc0012_GetTunerRssiCalOn(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_fc0012_UpdateTunerLnaGainWithRssi(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_fc0013.c b/drivers/media/usb/dvb-usb/nim_rtl2832_fc0013.c
new file mode 100644
index 0000000..16740f3
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_fc0013.c
@@ -0,0 +1,1053 @@
+/**
+
+@file
+
+@brief   RTL2832 FC0013 NIM module definition
+
+One can manipulate RTL2832 FC0013 NIM through RTL2832 FC0013 NIM module.
+RTL2832 FC0013 NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_fc0013.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 FC0013 NIM module builder
+
+Use BuildRtl2832Fc0013Module() to build RTL2832 FC0013 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 FC0013 NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              FC0013 I2C device address
+@param [in]   TunerCrystalFreqHz           FC0013 crystal frequency in Hz
+
+
+@note
+	-# One should call BuildRtl2832Fc0013Module() to build RTL2832 FC0013 NIM module before using it.
+
+*/
+void
+BuildRtl2832Fc0013Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+	RTL2832_FC0013_EXTRA_MODULE *pNimExtra;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Fc0013);
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_FC0013;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build FC0013 tuner module.
+	BuildFc0013Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_fc0013_Initialize;
+	pNim->SetParameters  = rtl2832_fc0013_SetParameters;
+	pNim->UpdateFunction = rtl2832_fc0013_UpdateFunction;
+
+
+	// Initialize NIM extra module variables.
+	pNimExtra->LnaUpdateWaitTimeMax = DivideWithCeiling(RTL2832_FC0013_LNA_UPDATE_WAIT_TIME_MS, DemodUpdateFuncRefPeriodMs);
+	pNimExtra->LnaUpdateWaitTime    = 0;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_fc0013_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_FC0013_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x5a	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x5a	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9bf	},
+		{DVBT_EN_GI_PGA,			0x0		},
+		{DVBT_THD_LOCK_UP,			0x0		},
+		{DVBT_THD_LOCK_DW,			0x0		},
+		{DVBT_THD_UP1,				0x11	},
+		{DVBT_THD_DW1,				0xef	},
+		{DVBT_INTER_CNT_LEN,		0xc		},
+		{DVBT_GI_PGA_STATE,			0x0		},
+		{DVBT_EN_AGC_PGA,			0x1		},
+//		{DVBT_REG_GPE,				0x1		},
+//		{DVBT_REG_GPO,				0x0		},
+//		{DVBT_REG_MONSEL,			0x0		},
+//		{DVBT_REG_MON,				0x3		},
+//		{DVBT_REG_4MSEL,			0x0		},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set FC0013 up-dowm AGC.
+	//(0xFE for master of dual).
+	//(0xFC for slave of dual, and for 2832 mini dongle).
+	if(fc0013_SetRegMaskBits(pTuner, 0x0c, 7, 0, 0xFC) != FC0013_I2C_SUCCESS)
+		goto error_status_set_tuner_registers;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_FC0013_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Get tuner RSSI value when calibration is on.
+	// Note: Need to execute rtl2832_fc0013_GetTunerRssiCalOn() after demod AD7 is on.
+	if(rtl2832_fc0013_GetTunerRssiCalOn(pNim) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+error_status_set_tuner_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_fc0013_Initialize_fm(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_FC0013_DAB_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x5a	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x5a	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9bf	},
+		{DVBT_EN_GI_PGA,			0x0		},
+		{DVBT_THD_LOCK_UP,			0x0		},
+		{DVBT_THD_LOCK_DW,			0x0		},
+		{DVBT_THD_UP1,				0x11	},
+		{DVBT_THD_DW1,				0xef	},
+		{DVBT_INTER_CNT_LEN,		0xc		},
+		{DVBT_GI_PGA_STATE,			0x0		},
+		{DVBT_EN_AGC_PGA,			0x1		},
+		
+		//test
+		{DVBT_AD_EN_REG,			0x1		},
+		{DVBT_AD_EN_REG1,			0x1		},
+//		{DVBT_EN_BK_TRK,			0x0		},
+//		{DVBT_AD_AV_REF,			0x2a	},
+//		{DVBT_REG_PI,				0x3		},
+		//----------
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set FC0013 up-dowm AGC.
+	//(0xFE for master of dual).
+	//(0xFC for slave of dual, and for 2832 mini dongle).
+	if(fc0013_SetRegMaskBits(pTuner, 0x0c, 7, 0, 0xFC) != FC0013_I2C_SUCCESS)
+		goto error_status_set_tuner_registers;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	//if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		//goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	//if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+	//	goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	//if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+	//	goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_FC0013_DAB_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Get tuner RSSI value when calibration is on.
+	// Note: Need to execute rtl2832_fc0013_GetTunerRssiCalOn() after demod AD7 is on.
+	if(rtl2832_fc0013_GetTunerRssiCalOn(pNim) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+error_status_set_tuner_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_fc0013_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	FC0013_EXTRA_MODULE *pTunerExtra;
+	int TunerBandwidthMode;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc0013);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthMode = FC0013_BANDWIDTH_6000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthMode = FC0013_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthMode = FC0013_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetBandwidthMode(pTuner, TunerBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset tuner IQ LPF BW.
+	if(pTunerExtra->RcCalReset(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner IQ LPF BW, val=-2 for D-book ACI test.
+	if(pTunerExtra->RcCalAdd(pTuner, -2) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_fc0013_SetParameters_fm(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	FC0013_EXTRA_MODULE *pTunerExtra;
+	int TunerBandwidthMode;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc0013);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthMode = FC0013_BANDWIDTH_6000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthMode = FC0013_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthMode = FC0013_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetBandwidthMode(pTuner, TunerBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset tuner IQ LPF BW.
+	if(pTunerExtra->RcCalReset(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner IQ LPF BW, val=-2 for D-book ACI test.
+	if(pTunerExtra->RcCalAdd(pTuner, -2) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_UPDATE_FUNCTION
+
+*/
+int
+rtl2832_fc0013_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	RTL2832_FC0013_EXTRA_MODULE *pNimExtra;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Fc0013);
+
+
+	// Update demod particular registers.
+	if(pDemod->UpdateFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Increase tuner LNA_GAIN update waiting time.
+	pNimExtra->LnaUpdateWaitTime += 1;
+
+
+	// Check if need to update tuner LNA_GAIN according to update waiting time.
+	if(pNimExtra->LnaUpdateWaitTime == pNimExtra->LnaUpdateWaitTimeMax)
+	{
+		// Reset update waiting time.
+		pNimExtra->LnaUpdateWaitTime = 0;
+
+		// Enable demod DVBT_IIC_REPEAT.
+		if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+
+		// Update tuner LNA gain with RSSI.
+		if(rtl2832_fc0013_UpdateTunerLnaGainWithRssi(pNim) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		// Disable demod DVBT_IIC_REPEAT.
+		if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Get tuner RSSI value when calibration is on.
+
+One can use rtl2832_fc0013_GetTunerRssiCalOn() to get tuner calibration-on RSSI value.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Get tuner calibration-on RSSI value successfully.
+@retval   FUNCTION_ERROR     Get tuner calibration-on RSSI value unsuccessfully.
+
+*/
+int
+rtl2832_fc0013_GetTunerRssiCalOn(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+	FC0013_EXTRA_MODULE *pTunerExtra;
+	RTL2832_FC0013_EXTRA_MODULE *pNimExtra;
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc0013);
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Fc0013);
+
+	// Get NIM base interface.
+	pBaseInterface = pNim->pBaseInterface;
+
+
+	// Set tuner EN_CAL_RSSI to 0x1.
+	if(fc0013_SetRegMaskBits(pTuner, 0x9, 4, 4, 0x1) != FC0013_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner LNA_POWER_DOWN to 0x1.
+	if(fc0013_SetRegMaskBits(pTuner, 0x6, 0, 0, 0x1) != FC0013_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Wait 100 ms.
+	pBaseInterface->WaitMs(pBaseInterface, 100);
+
+	// Get demod RSSI_R when tuner RSSI calibration is on.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RSSI_R, &(pNimExtra->RssiRCalOn)) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Set tuner EN_CAL_RSSI to 0x0.
+	if(fc0013_SetRegMaskBits(pTuner, 0x9, 4, 4, 0x0) != FC0013_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner LNA_POWER_DOWN to 0x0.
+	if(fc0013_SetRegMaskBits(pTuner, 0x6, 0, 0, 0x0) != FC0013_I2C_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@brief   Update tuner LNA_GAIN with RSSI.
+
+One can use rtl2832_fc0013_UpdateTunerLnaGainWithRssi() to update tuner LNA_GAIN with RSSI.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update tuner LNA_GAIN with RSSI successfully.
+@retval   FUNCTION_ERROR     Update tuner LNA_GAIN with RSSI unsuccessfully.
+
+*/
+int
+rtl2832_fc0013_UpdateTunerLnaGainWithRssi(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+	FC0013_EXTRA_MODULE *pTunerExtra;
+	RTL2832_FC0013_EXTRA_MODULE *pNimExtra;
+
+	unsigned long RssiRCalOff;
+	long RssiRDiff;
+	unsigned char LnaGain;
+	unsigned char ReadValue;
+
+	// added from Fitipower, 2011-2-23, v0.8
+	int boolVhfFlag;      // 0:false,  1:true
+	int boolEnInChgFlag;  // 0:false,  1:true
+	int intGainShift;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc0013);
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Fc0013);
+
+
+	// Get demod RSSI_R when tuner RSSI calibration in off.
+	// Note: Tuner EN_CAL_RSSI and LNA_POWER_DOWN are set to 0x0 after rtl2832_fc0013_GetTunerRssiCalOn() executing.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RSSI_R, &RssiRCalOff) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// To avoid the wrong rssi calibration value in the environment with strong RF pulse signal.
+	if(RssiRCalOff < pNimExtra->RssiRCalOn)
+		pNimExtra->RssiRCalOn = RssiRCalOff;
+
+
+	// Calculate RSSI_R difference.
+	RssiRDiff = RssiRCalOff - pNimExtra->RssiRCalOn;
+
+	// Get tuner LNA_GAIN.
+	if(fc0013_GetRegMaskBits(pTuner, 0x14, 4, 0, &LnaGain) != FC0013_I2C_SUCCESS)
+		goto error_status_get_registers;
+
+
+	// Determine next LNA_GAIN according to RSSI_R difference and current LNA_GAIN.
+	switch(LnaGain)
+	{
+		default:
+
+			boolVhfFlag = 0;		
+			boolEnInChgFlag = 1;
+			intGainShift = 10;
+			LnaGain = FC0013_LNA_GAIN_HIGH_19;
+
+			// Set tuner LNA_GAIN.
+			if(fc0013_SetRegMaskBits(pTuner, 0x14, 4, 0, LnaGain) != FC0013_I2C_SUCCESS)
+				goto error_status_set_registers;
+
+			break;
+
+
+		case FC0013_LNA_GAIN_HIGH_19:
+
+			if(RssiRDiff >= 10)
+			{
+				boolVhfFlag = 1;		
+				boolEnInChgFlag = 0;
+				intGainShift = 10;
+				LnaGain = FC0013_LNA_GAIN_HIGH_17;
+
+				// Set tuner LNA_GAIN.
+				if(fc0013_SetRegMaskBits(pTuner, 0x14, 4, 0, LnaGain) != FC0013_I2C_SUCCESS)
+					goto error_status_set_registers;
+
+				break;
+			}
+			else
+			{
+				goto success_status_Lna_Gain_No_Change;
+			}
+
+
+		case FC0013_LNA_GAIN_HIGH_17:
+			
+			if(RssiRDiff <= 2)
+			{
+				boolVhfFlag = 0;	
+				boolEnInChgFlag = 1;
+				intGainShift = 10;
+				LnaGain = FC0013_LNA_GAIN_HIGH_19;
+
+				// Set tuner LNA_GAIN.
+				if(fc0013_SetRegMaskBits(pTuner, 0x14, 4, 0, LnaGain) != FC0013_I2C_SUCCESS)
+					goto error_status_set_registers;
+
+				break;
+			}
+
+			else if(RssiRDiff >= 24)
+			{
+				boolVhfFlag = 0;	
+				boolEnInChgFlag = 0;
+				intGainShift = 7;
+				LnaGain = FC0013_LNA_GAIN_MIDDLE;
+
+				// Set tuner LNA_GAIN.
+				if(fc0013_SetRegMaskBits(pTuner, 0x14, 4, 0, LnaGain) != FC0013_I2C_SUCCESS)
+					goto error_status_set_registers;
+
+				break;
+			}
+
+			else
+			{
+				goto success_status_Lna_Gain_No_Change;
+			}
+
+
+		case FC0013_LNA_GAIN_MIDDLE:
+
+			if(RssiRDiff >= 38)
+			{
+				boolVhfFlag = 0;	
+				boolEnInChgFlag = 0;
+				intGainShift = 7;
+				LnaGain = FC0013_LNA_GAIN_LOW;
+
+				// Set tuner LNA_GAIN.
+				if(fc0013_SetRegMaskBits(pTuner, 0x14, 4, 0, LnaGain) != FC0013_I2C_SUCCESS)
+					goto error_status_set_registers;
+
+				break;
+			}
+
+			else if(RssiRDiff <= 5)
+			{
+				boolVhfFlag = 1;
+				boolEnInChgFlag = 0;
+				intGainShift = 10;
+				LnaGain = FC0013_LNA_GAIN_HIGH_17;
+
+				// Set tuner LNA_GAIN.
+				if(fc0013_SetRegMaskBits(pTuner, 0x14, 4, 0, LnaGain) != FC0013_I2C_SUCCESS)
+					goto error_status_set_registers;
+
+				break;
+			}
+
+			else
+			{
+				goto success_status_Lna_Gain_No_Change;
+			}
+
+		
+		case FC0013_LNA_GAIN_LOW:
+
+			if(RssiRDiff <= 2)
+			{
+				boolVhfFlag = 0;
+				boolEnInChgFlag = 0;
+				intGainShift = 7;
+				LnaGain = FC0013_LNA_GAIN_MIDDLE;
+
+				// Set tuner LNA_GAIN.
+				if(fc0013_SetRegMaskBits(pTuner, 0x14, 4, 0, LnaGain) != FC0013_I2C_SUCCESS)
+					goto error_status_set_registers;
+
+				break;
+			}
+
+			else
+			{
+				goto success_status_Lna_Gain_No_Change;
+			}
+	}
+
+
+	if(fc0013_GetRegMaskBits(pTuner, 0x14, 7, 0, &ReadValue) != FC0013_I2C_SUCCESS)
+		goto error_status_get_registers;
+
+	if( (ReadValue & 0x60) == 0 )   // disable UHF & GPS ==> lock VHF frequency
+	{
+		boolVhfFlag = 1;
+	}
+
+
+	if( boolVhfFlag == 1 )
+	{
+		//FC0013_Write(0x07, (FC0013_Read(0x07) | 0x10));				// VHF = 1
+		if(fc0013_GetRegMaskBits(pTuner, 0x07, 7, 0, &ReadValue) != FC0013_I2C_SUCCESS)
+			goto error_status_get_registers;
+
+		if(fc0013_SetRegMaskBits(pTuner, 0x07, 7, 0, ReadValue | 0x10) != FC0013_I2C_SUCCESS)
+			goto error_status_set_registers;
+	}
+	else
+	{
+		//FC0013_Write(0x07, (FC0013_Read(0x07) & 0xEF));				// VHF = 0
+		if(fc0013_GetRegMaskBits(pTuner, 0x07, 7, 0, &ReadValue) != FC0013_I2C_SUCCESS)
+			goto error_status_get_registers;
+
+		if(fc0013_SetRegMaskBits(pTuner, 0x07, 7, 0, ReadValue & 0xEF) != FC0013_I2C_SUCCESS)
+			goto error_status_set_registers;
+	}
+		
+
+	if( boolEnInChgFlag == 1 )
+	{
+		//FC0013_Write(0x0A, (FC0013_Read(0x0A) | 0x20));				// EN_IN_CHG = 1
+		if(fc0013_GetRegMaskBits(pTuner, 0x0A, 7, 0, &ReadValue) != FC0013_I2C_SUCCESS)
+			goto error_status_get_registers;
+
+		if(fc0013_SetRegMaskBits(pTuner, 0x0A, 7, 0, ReadValue | 0x20) != FC0013_I2C_SUCCESS)
+			goto error_status_set_registers;
+	}
+	else
+	{
+		//FC0013_Write(0x0A, (FC0013_Read(0x0A) & 0xDF));				// EN_IN_CHG = 0
+		if(fc0013_GetRegMaskBits(pTuner, 0x0A, 7, 0, &ReadValue) != FC0013_I2C_SUCCESS)
+			goto error_status_get_registers;
+
+		if(fc0013_SetRegMaskBits(pTuner, 0x0A, 7, 0, ReadValue & 0xDF) != FC0013_I2C_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	if( intGainShift == 10 )
+	{
+		//FC0013_Write(0x07, (FC0013_Read(0x07) & 0xF0) | 0x0A);		// GS = 10
+		if(fc0013_GetRegMaskBits(pTuner, 0x07, 7, 0, &ReadValue) != FC0013_I2C_SUCCESS)
+			goto error_status_get_registers;
+
+		if(fc0013_SetRegMaskBits(pTuner, 0x07, 7, 0, (ReadValue & 0xF0) | 0x0A) != FC0013_I2C_SUCCESS)
+			goto error_status_set_registers;
+	}
+	else
+	{
+		//FC0013_Write(0x07, (FC0013_Read(0x07) & 0xF0) | 0x07);		// GS = 7
+		if(fc0013_GetRegMaskBits(pTuner, 0x07, 7, 0, &ReadValue) != FC0013_I2C_SUCCESS)
+			goto error_status_get_registers;
+
+		if(fc0013_SetRegMaskBits(pTuner, 0x07, 7, 0, (ReadValue & 0xF0) | 0x07) != FC0013_I2C_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+success_status_Lna_Gain_No_Change:
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_fc0013.h b/drivers/media/usb/dvb-usb/nim_rtl2832_fc0013.h
new file mode 100644
index 0000000..0888d6e
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_fc0013.h
@@ -0,0 +1,170 @@
+#ifndef __NIM_RTL2832_FC0013
+#define __NIM_RTL2832_FC0013
+
+/**
+
+@file
+
+@brief   RTL2832 FC0013 NIM module declaration
+
+One can manipulate RTL2832 FC0013 NIM through RTL2832 FC0013 NIM module.
+RTL2832 FC0013 NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_fc0013.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2832 FC0013 NIM module.
+	BuildRtl2832Fc0013Module(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,							// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,		// The RTL2832 application mode is STB mode.
+		200,							// The RTL2832 update function reference period is 200 millisecond
+		YES,							// The RTL2832 Function 1 enabling status is YES.
+
+		0xc6,							// The FC0013 I2C device address is 0xc6 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ			// The FC0013 crystal frequency is 28.8 MHz.
+		);
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_fc0013.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_FC0013_ADDITIONAL_INIT_REG_TABLE_LEN		29
+#define RTL2832_FC0013_DAB_ADDITIONAL_INIT_REG_TABLE_LEN		31
+#define RTL2832_FC0013_LNA_UPDATE_WAIT_TIME_MS				1000
+
+
+
+
+
+// Builder
+void
+BuildRtl2832Fc0013Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	);
+
+
+
+
+
+// RTL2832 FC0013 NIM manipulaing functions
+int
+rtl2832_fc0013_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+int
+rtl2832_fc0013_Initialize_fm(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+int
+rtl2832_fc0013_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+rtl2832_fc0013_SetParameters_fm(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+rtl2832_fc0013_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_fc0013_GetTunerRssiCalOn(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_fc0013_UpdateTunerLnaGainWithRssi(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_fc2580.c b/drivers/media/usb/dvb-usb/nim_rtl2832_fc2580.c
new file mode 100644
index 0000000..7d12c5f
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_fc2580.c
@@ -0,0 +1,343 @@
+/**
+
+@file
+
+@brief   RTL2832 FC2580 NIM module definition
+
+One can manipulate RTL2832 FC2580 NIM through RTL2832 FC2580 NIM module.
+RTL2832 FC2580 NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_fc2580.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 FC2580 NIM module builder
+
+Use BuildRtl2832Fc2580Module() to build RTL2832 FC2580 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 FC2580 NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              FC2580 I2C device address
+@param [in]   TunerCrystalFreqHz           FC2580 crystal frequency in Hz
+@param [in]   TunerAgcMode                 FC2580 AGC mode
+
+
+@note
+	-# One should call BuildRtl2832Fc2580Module() to build RTL2832 FC2580 NIM module before using it.
+
+*/
+void
+BuildRtl2832Fc2580Module(
+	DVBT_NIM_MODULE **ppNim,								// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerAgcMode
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_FC2580;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build FC2580 tuner module.
+	BuildFc2580Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz,
+		TunerAgcMode
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+	pNim->UpdateFunction    = dvbt_nim_default_UpdateFunction;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_fc2580_Initialize;
+	pNim->SetParameters  = rtl2832_fc2580_SetParameters;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_fc2580_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_FC2580_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x39	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x5a	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x9c	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9f4	},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_FC2580_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_fc2580_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	FC2580_EXTRA_MODULE *pTunerExtra;
+	int TunerBandwidthMode;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc2580);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthMode = FC2580_BANDWIDTH_6000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthMode = FC2580_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthMode = FC2580_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetBandwidthMode(pTuner, TunerBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_fc2580.h b/drivers/media/usb/dvb-usb/nim_rtl2832_fc2580.h
new file mode 100644
index 0000000..a5a7998
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_fc2580.h
@@ -0,0 +1,141 @@
+#ifndef __NIM_RTL2832_FC2580
+#define __NIM_RTL2832_FC2580
+
+/**
+
+@file
+
+@brief   RTL2832 FC2580 NIM module declaration
+
+One can manipulate RTL2832 FC2580 NIM through RTL2832 FC2580 NIM module.
+RTL2832 FC2580 NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_fc2580.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2832 FC2580 NIM module.
+	BuildRtl2832Fc2580Module(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,							// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,		// The RTL2832 application mode is STB mode.
+		200,							// The RTL2832 update function reference period is 200 millisecond
+		YES,							// The RTL2832 Function 1 enabling status is YES.
+
+		0xac,							// The FC2580 I2C device address is 0xac in 8-bit format.
+		CRYSTAL_FREQ_16384000HZ,		// The FC2580 crystal frequency is 16.384 MHz.
+		FC2580_AGC_EXTERNAL				// The FC2580 AGC mode is external AGC mode.
+		);
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_fc2580.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_FC2580_ADDITIONAL_INIT_REG_TABLE_LEN		21
+
+
+
+
+
+// Builder
+void
+BuildRtl2832Fc2580Module(
+	DVBT_NIM_MODULE **ppNim,								// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerAgcMode
+	);
+
+
+
+
+
+// RTL2832 FC2580 NIM manipulaing functions
+int
+rtl2832_fc2580_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_fc2580_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_max3543.c b/drivers/media/usb/dvb-usb/nim_rtl2832_max3543.c
new file mode 100644
index 0000000..6398437
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_max3543.c
@@ -0,0 +1,346 @@
+/**
+
+@file
+
+@brief   RTL2832 MAX3543 NIM module definition
+
+One can manipulate RTL2832 MAX3543 NIM through RTL2832 MAX3543 NIM module.
+RTL2832 MAX3543 NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_max3543.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 MAX3543 NIM module builder
+
+Use BuildRtl2832Max3543Module() to build RTL2832 MAX3543 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 MAX3543 NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              MAX3543 I2C device address
+@param [in]   TunerCrystalFreqHz           MAX3543 crystal frequency in Hz
+
+
+@note
+	-# One should call BuildRtl2832Max3543Module() to build RTL2832 MAX3543 NIM module before using it.
+
+*/
+void
+BuildRtl2832Max3543Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_MAX3543;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build MAX3543 tuner module.
+	BuildMax3543Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz,
+		RTL2832_MAX3543_STANDARD_MODE_DEFAULT,
+		RTL2832_MAX3543_IF_FREQ_HZ_DEFAULT,
+		RTL2832_MAX3543_SAW_INPUT_TYPE_DEFAULT
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+	pNim->UpdateFunction    = dvbt_nim_default_UpdateFunction;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_max3543_Initialize;
+	pNim->SetParameters  = rtl2832_max3543_SetParameters;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_max3543_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_MAX3543_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x39	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x4b	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9d4	},
+		{DVBT_AD_EN_REG1,			0x0		},
+		{DVBT_CKOUT_PWR_PID,		0x0		},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with NIM default.
+	if(pDemod->SetIfFreqHz(pDemod, RTL2832_MAX3543_IF_FREQ_HZ_DEFAULT) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with NIM default.
+	if(pDemod->SetSpectrumMode(pDemod, RTL2832_MAX3543_SPECTRUM_MODE_DEFAULT) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_MAX3543_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_max3543_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	MAX3543_EXTRA_MODULE *pTunerExtra;
+	int TunerBandwidthMode;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Max3543);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	// Note: MAX3543 tuner only has 7 MHz and 8 MHz settings.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthMode = MAX3543_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthMode = MAX3543_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthMode = MAX3543_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetBandwidthMode(pTuner, TunerBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_max3543.h b/drivers/media/usb/dvb-usb/nim_rtl2832_max3543.h
new file mode 100644
index 0000000..b2b61fc
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_max3543.h
@@ -0,0 +1,145 @@
+#ifndef __NIM_RTL2832_MAX3543
+#define __NIM_RTL2832_MAX3543
+
+/**
+
+@file
+
+@brief   RTL2832 MAX3543 NIM module declaration
+
+One can manipulate RTL2832 MAX3543 NIM through RTL2832 MAX3543 NIM module.
+RTL2832 MAX3543 NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_max3543.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2832 MAX3543 NIM module.
+	BuildRtl2832Max3543Module(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,							// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,		// The RTL2832 application mode is STB mode.
+		200,							// The RTL2832 update function reference period is 200 millisecond
+		YES,							// The RTL2832 Function 1 enabling status is YES.
+
+		0xc0,							// The MAX3543 I2C device address is 0xc0 in 8-bit format.
+		CRYSTAL_FREQ_16000000HZ			// The MAX3543 Crystal frequency is 16.0 MHz.
+		);
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_max3543.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_MAX3543_ADDITIONAL_INIT_REG_TABLE_LEN		23
+
+// Default
+#define RTL2832_MAX3543_STANDARD_MODE_DEFAULT				MAX3543_STANDARD_DVBT
+#define RTL2832_MAX3543_IF_FREQ_HZ_DEFAULT					IF_FREQ_36170000HZ
+#define RTL2832_MAX3543_SPECTRUM_MODE_DEFAULT				SPECTRUM_INVERSE
+#define RTL2832_MAX3543_SAW_INPUT_TYPE_DEFAULT				MAX3543_SAW_INPUT_SE
+
+
+
+
+
+// Builder
+void
+BuildRtl2832Max3543Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	);
+
+
+
+
+
+// RTL2832 MAX3543 NIM manipulaing functions
+int
+rtl2832_max3543_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_max3543_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_mt2063.c b/drivers/media/usb/dvb-usb/nim_rtl2832_mt2063.c
new file mode 100644
index 0000000..3c475f9
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_mt2063.c
@@ -0,0 +1,360 @@
+/**
+
+@file
+
+@brief   RTL2832 MT2063 NIM module definition
+
+One can manipulate RTL2832 MT2063 NIM through RTL2832 MT2063 NIM module.
+RTL2832 MT2063 NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_mt2063.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 MT2063 NIM module builder
+
+Use BuildRtl2832Mt2063Module() to build RTL2832 MT2063 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 MT2063 NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              MT2063 I2C device address
+@param [in]   TunerAgcMode                 MT2063 AGC mode
+
+
+@note
+	-# One should call BuildRtl2832Mt2063Module() to build RTL2832 MT2063 NIM module before using it.
+
+*/
+void
+BuildRtl2832Mt2063Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+	unsigned long NimIfFreqHz,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr						// Tuner dependence
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+	RTL2832_MT2063_EXTRA_MODULE *pNimExtra;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Mt2063);
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_MT2063;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build MT2063 tuner module.
+	BuildMt2063Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		MT2063_STANDARD_DVBT,
+		MT2063_VGAGC_0X3
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+	pNim->UpdateFunction    = dvbt_nim_default_UpdateFunction;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_mt2063_Initialize;
+	pNim->SetParameters  = rtl2832_mt2063_SetParameters;
+
+
+	// Set NIM extra module variables.
+	pNimExtra->IfFreqHz = NimIfFreqHz;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_mt2063_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_MT2063_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x39	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+//		{DVBT_AGC_TARG_VAL_8_1,		0x32	},
+		{DVBT_AGC_TARG_VAL_8_1,		0x19	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9d4	},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+	MT2063_EXTRA_MODULE *pTunerExtra;
+	RTL2832_MT2063_EXTRA_MODULE *pNimExtra;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+	pTunerExtra = &(pTuner->Extra.Mt2063);
+	pNimExtra = &(pNim->Extra.Rtl2832Mt2063);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner IF frequency in Hz.
+	if(pTunerExtra->SetIfFreqHz(pTuner, pNimExtra->IfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency in Hz.
+	if(pDemod->SetIfFreqHz(pDemod, pNimExtra->IfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_INVERSE.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_INVERSE) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_MT2063_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_mt2063_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	MT2063_EXTRA_MODULE *pTunerExtra;
+	unsigned long BandwidthHz;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Mt2063);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Determine BandwidthHz according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		BandwidthHz = MT2063_BANDWIDTH_6MHZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		BandwidthHz = MT2063_BANDWIDTH_7MHZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		BandwidthHz = MT2063_BANDWIDTH_8MHZ;		break;
+	}
+
+	// Set tuner bandwidth in Hz with BandwidthHz.
+	// Note: Need to execute SetBandwidthHz() before SetRfFreqHz() for MT2063,
+	//       because MT2063 bandwidth setting API only sets software variables.
+	if(pTunerExtra->SetBandwidthHz(pTuner, BandwidthHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_mt2063.h b/drivers/media/usb/dvb-usb/nim_rtl2832_mt2063.h
new file mode 100644
index 0000000..464d0c6
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_mt2063.h
@@ -0,0 +1,160 @@
+#ifndef __NIM_RTL2832_MT2063
+#define __NIM_RTL2832_MT2063
+
+/**
+
+@file
+
+@brief   RTL2832 MT2063 NIM module declaration
+
+One can manipulate RTL2832 MT2063 NIM through RTL2832 MT2063 NIM module.
+RTL2832 MT2063 NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_mt2063.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+	MT2063_EXTRA_MODULE *pTunerExtra;
+
+	...
+
+
+
+	// Build RTL2832 MT2063 NIM module.
+	BuildRtl2832Mt2063Module(
+		&pNim,
+		&DvbtNimModuleMemory,
+		IF_FREQ_36125000HZ,				// The RTL2832 and MT2063 IF frequency is 36.125 MHz.
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,							// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,		// The RTL2832 application mode is STB mode.
+		200,							// The RTL2832 update function reference period is 200 millisecond
+		YES,							// The RTL2832 Function 1 enabling status is YES.
+
+		0xc0							// The MT2063 I2C device address is 0xc0 in 8-bit format.
+		);
+
+
+
+
+
+	// Get MT2063 tuner extra module.
+	pTuner = pNim->pTuner;
+	pTunerExtra = &(pTuner->Extra.Mt2063);
+
+	// Open MT2063 handle.
+	pTunerExtra->OpenHandle(pTuner);
+
+
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+
+
+
+	// Close MT2063 handle.
+	pTunerExtra->CloseHandle(pTuner);
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_mt2063.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_MT2063_ADDITIONAL_INIT_REG_TABLE_LEN		21
+
+
+
+
+
+// Builder
+void
+BuildRtl2832Mt2063Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+	unsigned long NimIfFreqHz,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr						// Tuner dependence
+	);
+
+
+
+
+
+// RTL2832 MT2063 NIM manipulaing functions
+int
+rtl2832_mt2063_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_mt2063_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_mt2266.c b/drivers/media/usb/dvb-usb/nim_rtl2832_mt2266.c
new file mode 100644
index 0000000..cac01e3
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_mt2266.c
@@ -0,0 +1,1082 @@
+/**
+
+@file
+
+@brief   RTL2832 MT2266 NIM module definition
+
+One can manipulate RTL2832 MT2266 NIM through RTL2832 MT2266 NIM module.
+RTL2832 MT2266 NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_mt2266.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 MT2266 NIM module builder
+
+Use BuildRtl2832Mt2266Module() to build RTL2832 MT2266 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 MT2266 NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              MT2266 I2C device address
+
+
+@note
+	-# One should call BuildRtl2832Mt2266Module() to build RTL2832 MT2266 NIM module before using it.
+
+*/
+void
+BuildRtl2832Mt2266Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr						// Tuner dependence
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+	RTL2832_MT2266_EXTRA_MODULE *pNimExtra;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Mt2266);
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_MT2266;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build MT2266 tuner module.
+	BuildMt2266Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_mt2266_Initialize;
+	pNim->SetParameters  = rtl2832_mt2266_SetParameters;
+	pNim->UpdateFunction = rtl2832_mt2266_UpdateFunction;
+
+
+	// Initialize NIM extra module variables.
+	pNimExtra->LnaConfig       = 0xff;
+	pNimExtra->UhfSens         = 0xff;
+	pNimExtra->AgcCurrentState = 0xff;
+	pNimExtra->LnaGainOld      = 0xffffffff;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_mt2266_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_MT2266_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x39	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x5a	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0xc0	},	// Note: The IF_AGC_MIN value will be set again by demod_pdcontrol_reset().
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x9c	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x1		},
+		{DVBT_POLAR_IF_AGC,			0x1		},
+		{DVBT_AD7_SETTING,			0xe9f4	},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_MT2266_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_mt2266_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	MT2266_EXTRA_MODULE *pTunerExtra;
+	Handle_t Mt2266Handle;
+	unsigned long BandwidthHz;
+
+	RTL2832_MT2266_EXTRA_MODULE *pNimExtra;
+
+	UData_t Status;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Mt2266);
+
+	// Get tuner handle.
+	Mt2266Handle = pTunerExtra->DeviceHandle;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Mt2266);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine BandwidthHz according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		BandwidthHz = MT2266_BANDWIDTH_6MHZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		BandwidthHz = MT2266_BANDWIDTH_7MHZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		BandwidthHz = MT2266_BANDWIDTH_8MHZ;		break;
+	}
+
+	// Set tuner bandwidth in Hz with BandwidthHz.
+	if(pTunerExtra->SetBandwidthHz(pTuner, BandwidthHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Reset MT2266 update procedure.
+	Status = demod_pdcontrol_reset(pDemod, Mt2266Handle, &pNimExtra->AgcCurrentState);
+
+	if(MT_IS_ERROR(Status))
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_UPDATE_FUNCTION
+
+*/
+int
+rtl2832_mt2266_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+	MT2266_EXTRA_MODULE *pTunerExtra;
+	RTL2832_MT2266_EXTRA_MODULE *pNimExtra;
+
+	Handle_t Mt2266Handle;
+	UData_t Status;
+	
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module and tuner handle.
+	pTunerExtra = &(pTuner->Extra.Mt2266);
+	pTunerExtra->GetHandle(pTuner, &Mt2266Handle);
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2832Mt2266);
+
+
+	// Update demod particular registers.
+	if(pDemod->UpdateFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Update demod and tuner register setting.
+	Status = demod_pdcontrol(
+		pDemod,
+		Mt2266Handle,
+		&pNimExtra->LnaConfig,
+		&pNimExtra->UhfSens,
+		&pNimExtra->AgcCurrentState,
+		&pNimExtra->LnaGainOld
+		);
+
+/*
+	handle_t demod_handle,
+	handle_t tuner_handle,
+	unsigned char* lna_config,
+	unsigned char* uhf_sens,
+	unsigned char *agc_current_state,
+	unsigned long *lna_gain_old
+	
+	unsigned char LnaConfig;
+	unsigned char UhfSens;
+	unsigned char AgcCurrentState;
+	unsigned long LnaGainOld;	
+	
+*/
+
+	if(MT_IS_ERROR(Status))
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+// The following context is source code provided by Microtune.
+
+
+
+
+
+// Additional definition for mt_control.c
+UData_t
+demod_get_pd(
+	handle_t demod_handle,
+	unsigned short *pd_value
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	unsigned long RssiR;
+
+
+	// Get demod module.
+	pDemod = (DVBT_DEMOD_MODULE *)demod_handle;
+
+	// Get RSSI_R value.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_RSSI_R, &RssiR) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Set pd_value according to RSSI_R.
+	*pd_value = (unsigned short)RssiR;
+
+
+	return MT_OK;
+
+
+error_status_get_registers:
+	return MT_COMM_ERR;
+}
+
+
+
+UData_t
+demod_get_agc(
+	handle_t demod_handle,
+	unsigned short *rf_level,
+	unsigned short *bb_level
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	unsigned long RfAgc;
+	unsigned long IfAgc;
+
+
+	// Get demod module.
+	pDemod = (DVBT_DEMOD_MODULE *)demod_handle;
+
+	// Get RF and IF AGC value.
+	if(pDemod->GetRfAgc(pDemod, &RfAgc) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->GetIfAgc(pDemod, &IfAgc) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Convert RF and IF AGC value to proper format.
+	*rf_level = (unsigned short)((RfAgc + (1 << (RTL2832_RF_AGC_REG_BIT_NUM - 1))) *
+		(1 << (MT2266_DEMOD_ASSUMED_AGC_REG_BIT_NUM - RTL2832_RF_AGC_REG_BIT_NUM)));
+
+	*bb_level = (unsigned short)((IfAgc + (1 << (RTL2832_IF_AGC_REG_BIT_NUM - 1))) *
+		(1 << (MT2266_DEMOD_ASSUMED_AGC_REG_BIT_NUM - RTL2832_IF_AGC_REG_BIT_NUM)));
+
+
+	return MT_OK;
+
+
+error_status_get_registers:
+	return MT_COMM_ERR;
+}
+
+
+
+UData_t
+demod_set_bbagclim(
+	handle_t demod_handle,
+	int on_off_status
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+	unsigned long IfAgcMinBinary;
+	long IfAgcMinInt;
+
+
+	// Get demod module.
+	pDemod = (DVBT_DEMOD_MODULE *)demod_handle;
+
+	// Get IF_AGC_MIN binary value.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_IF_AGC_MIN, &IfAgcMinBinary) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Convert IF_AGC_MIN binary value to integer.
+	IfAgcMinInt = BinToSignedInt(IfAgcMinBinary, RTL2832_MT2266_IF_AGC_MIN_BIT_NUM);
+
+	// Modify IF_AGC_MIN integer according to on_off_status.
+	switch(on_off_status)
+	{
+		case 1:
+
+			IfAgcMinInt += RTL2832_MT2266_IF_AGC_MIN_INT_STEP;
+
+			if(IfAgcMinInt > RTL2832_MT2266_IF_AGC_MIN_INT_MAX)
+				IfAgcMinInt = RTL2832_MT2266_IF_AGC_MIN_INT_MAX;
+
+			break;
+
+		default:
+		case 0:
+
+			IfAgcMinInt -= RTL2832_MT2266_IF_AGC_MIN_INT_STEP;
+
+			if(IfAgcMinInt < RTL2832_MT2266_IF_AGC_MIN_INT_MIN)
+				IfAgcMinInt = RTL2832_MT2266_IF_AGC_MIN_INT_MIN;
+
+			break;
+	}
+
+	// Convert modified IF_AGC_MIN integer to binary value.
+	IfAgcMinBinary = SignedIntToBin(IfAgcMinInt, RTL2832_MT2266_IF_AGC_MIN_BIT_NUM);
+
+	// Set IF_AGC_MIN with modified binary value.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IF_AGC_MIN, IfAgcMinBinary) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	return MT_OK;
+
+
+error_status_set_registers:
+error_status_get_registers:
+	return MT_COMM_ERR;
+}
+
+
+
+
+
+UData_t
+tuner_set_bw_normal(
+	handle_t tuner_handle,
+	handle_t demod_handle
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int DemodBandwidthMode;
+	unsigned int TunerBandwidthHz;
+	unsigned int TargetTunerBandwidthHz;
+
+
+	// Get demod module.
+	pDemod = (DVBT_DEMOD_MODULE *)demod_handle;
+
+	// Get demod bandwidth mode.
+	if(pDemod->GetBandwidthMode(pDemod, &DemodBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine tuner target bandwidth.
+	switch(DemodBandwidthMode)
+	{
+		case DVBT_BANDWIDTH_6MHZ:	TargetTunerBandwidthHz = MT2266_BANDWIDTH_6MHZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:	TargetTunerBandwidthHz = MT2266_BANDWIDTH_7MHZ;		break;
+		default:
+		case DVBT_BANDWIDTH_8MHZ:	TargetTunerBandwidthHz = MT2266_BANDWIDTH_8MHZ;		break;
+	}
+
+	// Get tuner bandwidth.
+	if(MT_IS_ERROR(MT2266_GetParam(tuner_handle, MT2266_OUTPUT_BW, &TunerBandwidthHz)))
+		goto error_status_get_tuner_bandwidth;
+
+	// Set tuner bandwidth with normal setting according to demod bandwidth mode.
+	if(TunerBandwidthHz != TargetTunerBandwidthHz)
+	{
+		if(MT_IS_ERROR(MT2266_SetParam(tuner_handle, MT2266_OUTPUT_BW, TargetTunerBandwidthHz)))
+			goto error_status_set_tuner_bandwidth;
+	}
+
+
+	return MT_OK;
+
+
+error_status_set_tuner_bandwidth:
+error_status_get_tuner_bandwidth:
+error_status_execute_function:
+	return MT_COMM_ERR;
+}
+
+
+
+
+
+UData_t
+tuner_set_bw_narrow(
+	handle_t tuner_handle,
+	handle_t demod_handle
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int DemodBandwidthMode;
+	unsigned long AciDetInd;
+	unsigned int TunerBandwidthHz;
+	unsigned int TargetTunerBandwidthHz;
+
+
+	// Get demod module.
+	pDemod = (DVBT_DEMOD_MODULE *)demod_handle;
+
+	// Get demod bandwidth mode.
+	if(pDemod->GetBandwidthMode(pDemod, &DemodBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get demod ACI_DET_IND.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_ACI_DET_IND, &AciDetInd) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	// Determine tuner target bandwidth according to ACI_DET_IND.
+	if(AciDetInd == 0x1)
+	{
+		// Choose narrow target bandwidth.
+		switch(DemodBandwidthMode)
+		{
+			case DVBT_BANDWIDTH_6MHZ:	TargetTunerBandwidthHz = MT2266_BANDWIDTH_5MHZ;		break;
+			case DVBT_BANDWIDTH_7MHZ:	TargetTunerBandwidthHz = MT2266_BANDWIDTH_6MHZ;		break;
+			default:
+			case DVBT_BANDWIDTH_8MHZ:	TargetTunerBandwidthHz = MT2266_BANDWIDTH_7MHZ;		break;
+		}
+	}
+	else
+	{
+		// Choose normal target bandwidth.
+		switch(DemodBandwidthMode)
+		{
+			case DVBT_BANDWIDTH_6MHZ:	TargetTunerBandwidthHz = MT2266_BANDWIDTH_6MHZ;		break;
+			case DVBT_BANDWIDTH_7MHZ:	TargetTunerBandwidthHz = MT2266_BANDWIDTH_7MHZ;		break;
+			default:
+			case DVBT_BANDWIDTH_8MHZ:	TargetTunerBandwidthHz = MT2266_BANDWIDTH_8MHZ;		break;
+		}
+	}
+
+	// Get tuner bandwidth.
+	if(MT_IS_ERROR(MT2266_GetParam(tuner_handle, MT2266_OUTPUT_BW, &TunerBandwidthHz)))
+		goto error_status_get_tuner_bandwidth;
+
+	// Set tuner bandwidth with normal setting according to demod bandwidth mode.
+	if(TunerBandwidthHz != TargetTunerBandwidthHz)
+	{
+		if(MT_IS_ERROR(MT2266_SetParam(tuner_handle, MT2266_OUTPUT_BW, TargetTunerBandwidthHz)))
+			goto error_status_set_tuner_bandwidth;
+	}
+
+
+	return MT_OK;
+
+
+error_status_set_tuner_bandwidth:
+error_status_get_tuner_bandwidth:
+error_status_get_registers:
+error_status_execute_function:
+	return MT_COMM_ERR;
+}
+
+
+
+
+
+// Microtune source code - mt_control.c
+
+
+
+UData_t demod_pdcontrol_reset(handle_t demod_handle, handle_t tuner_handle, unsigned char *agc_current_state) {
+
+	DVBT_DEMOD_MODULE *pDemod;
+	unsigned long BinaryValue;
+
+
+	// Get demod module.
+	pDemod = (DVBT_DEMOD_MODULE *)demod_handle;
+
+	// Reset AGC current state.
+	*agc_current_state = AGC_STATE_START;
+
+	// Calculate RTL2832_MT2266_IF_AGC_MIN_INT_MIN binary value.
+	BinaryValue = SignedIntToBin(RTL2832_MT2266_IF_AGC_MIN_INT_MIN, RTL2832_MT2266_IF_AGC_MIN_BIT_NUM);
+
+	// Set IF_AGC_MIN with binary value.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IF_AGC_MIN, BinaryValue) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner bandwidth with normal setting.
+	if(MT_IS_ERROR(tuner_set_bw_normal(tuner_handle, demod_handle)))
+		goto error_status_set_tuner_bandwidth;
+
+
+	return MT_OK;
+
+
+error_status_set_tuner_bandwidth:
+error_status_set_registers:
+	return MT_COMM_ERR;
+}
+
+
+
+UData_t demod_pdcontrol(handle_t demod_handle, handle_t tuner_handle, unsigned char* lna_config, unsigned char* uhf_sens,
+					 unsigned char *agc_current_state, unsigned long *lna_gain_old) {
+
+	unsigned short pd_value;
+	unsigned short rf_level, bb_level;
+	unsigned long lna_gain;
+	unsigned char zin=0;
+	unsigned int tmp_freq=0,tmp_lna_gain=0;
+	
+//	unsigned char temp[2];
+//	unsigned char agc_bb_min;
+//	demod_data_t* local_data;
+
+	
+	unsigned char band=1;  /* band=0: vhf, band=1: uhf low, band=2: uhf high */
+	unsigned long freq;
+
+	// AGC threshold values
+	unsigned short sens_on[]  = {11479, 11479, 32763};
+	unsigned short sens_off[] = {36867, 36867, 44767};
+	unsigned short lin_off[]  = {23619, 23619, 23619};
+	unsigned short lin_on[]   = {38355, 38355, 38355};
+	unsigned short pd_upper[] = {85,    85,    85};
+	unsigned short pd_lower[] = {74,    74,    74};
+	unsigned char next_state;
+
+	// demod_data_t* local_data = (demod_data_t*)demod_handle;	
+
+	if(MT_IS_ERROR(MT2266_GetParam(tuner_handle, MT2266_INPUT_FREQ, &tmp_freq))) goto error_status;
+	if(MT_IS_ERROR(MT2266_GetParam(tuner_handle, MT2266_LNA_GAIN, &tmp_lna_gain))) goto error_status;
+	if(MT_IS_ERROR(MT2266_GetReg(tuner_handle,0x1e,&zin))) goto error_status;
+
+	freq=(unsigned long)(tmp_freq);
+	lna_gain=(unsigned long)(tmp_lna_gain);
+	
+	if (freq <= 250000000) band=0;
+	else if (freq < 660000000) band=1;
+	else band=2;
+	
+	if(MT_IS_ERROR(demod_get_pd(demod_handle, &pd_value))) goto error_status;
+	if(MT_IS_ERROR(demod_get_agc(demod_handle, &rf_level, &bb_level))) goto error_status;
+
+	rf_level=0xffff-rf_level;
+	bb_level=0xffff-bb_level;
+
+/*
+#ifndef _HOST_DLL
+	uart_write_nr("St:");
+	uart_writedez(agc_current_state[num]);
+
+	uart_write_nr(" PD: ");
+	uart_writehex16(pd_value);
+
+	uart_write_nr(" AGC: ");
+	uart_writehex16(rf_level);
+	uart_writehex16(bb_level);	
+#endif
+*/
+
+	next_state = *agc_current_state;
+	
+	switch (*agc_current_state) {
+	
+	case AGC_STATE_START : {
+		if ((int)lna_gain < LNAGAIN_MIN)  
+			next_state=AGC_STATE_LNAGAIN_BELOW_MIN;
+		else if (lna_gain > LNAGAIN_MAX)  
+			next_state=AGC_STATE_LNAGAIN_ABOVE_MAX;
+		else 
+			next_state=AGC_STATE_NORMAL;
+		break;
+		}
+	
+	case AGC_STATE_LNAGAIN_BELOW_MIN : {
+		if ((int)lna_gain < LNAGAIN_MIN ) 
+			next_state=AGC_STATE_LNAGAIN_BELOW_MIN;
+		else next_state=AGC_STATE_NORMAL;
+		
+		break;
+		}
+	
+	case AGC_STATE_LNAGAIN_ABOVE_MAX : {
+		if (lna_gain > LNAGAIN_MAX ) 
+			next_state=AGC_STATE_LNAGAIN_ABOVE_MAX;
+		else next_state=AGC_STATE_NORMAL;
+		break;
+		}
+	
+	case AGC_STATE_NORMAL : {
+		if (rf_level > lin_on[band] ) {
+			*lna_gain_old = lna_gain;
+			next_state = AGC_STATE_MAS_GRANDE_SIGNAL;
+			}
+		else if (pd_value > pd_upper[band]) {
+			next_state = AGC_STATE_GRANDE_INTERFERER;
+			}
+		else if ( (pd_value < pd_lower[band]) && (lna_gain < LNAGAIN_MAX) ) {
+			next_state = AGC_STATE_NO_INTERFERER;
+			}
+		else if ( bb_level < sens_on[band]) {
+			next_state = AGC_STATE_SMALL_SIGNAL;
+			}
+		break;
+		}
+	
+	case AGC_STATE_NO_INTERFERER : {
+		if (pd_value > pd_lower[band] ) 
+			next_state = AGC_STATE_MEDIUM_INTERFERER;
+		else if (pd_value < pd_lower[band] )
+			next_state = AGC_STATE_NORMAL;
+		else if ( lna_gain == LNAGAIN_MAX )
+			next_state = AGC_STATE_NORMAL;
+		break;
+		}
+
+	case AGC_STATE_MEDIUM_INTERFERER : {
+		if (pd_value > pd_upper[band] ) 
+			next_state = AGC_STATE_GRANDE_INTERFERER;
+		else if (pd_value < pd_lower[band] )
+			next_state = AGC_STATE_NO_INTERFERER;
+		break;
+		}
+
+	
+	case AGC_STATE_GRANDE_INTERFERER : {
+		if (pd_value < pd_upper[band] )
+			next_state = AGC_STATE_MEDIUM_INTERFERER;
+		break;
+		}
+	
+	case AGC_STATE_MAS_GRANDE_SIGNAL : {
+		if (rf_level < lin_on[band])
+			next_state = AGC_STATE_GRANDE_SIGNAL;
+		else if (pd_value > pd_upper[band]) {
+			next_state = AGC_STATE_GRANDE_INTERFERER;
+			}
+		break;
+		}
+		
+	case AGC_STATE_MEDIUM_SIGNAL : {
+		if (rf_level > lin_off[band])
+			next_state = AGC_STATE_GRANDE_SIGNAL;
+		else if (lna_gain >= *lna_gain_old) 
+			next_state = AGC_STATE_NORMAL;
+		else if (pd_value > pd_upper[band])
+			next_state = AGC_STATE_GRANDE_INTERFERER;
+		break;
+		}
+	
+	case AGC_STATE_GRANDE_SIGNAL : {
+		if (rf_level > lin_on[band])
+			next_state = AGC_STATE_MAS_GRANDE_SIGNAL;
+		else if (rf_level < lin_off[band]) 
+			next_state = AGC_STATE_MEDIUM_SIGNAL;
+		else if (pd_value > pd_upper[band])
+			next_state = AGC_STATE_GRANDE_INTERFERER;
+		break;
+		}
+	
+	case AGC_STATE_SMALL_SIGNAL : {
+		if (pd_value > pd_upper[band] ) 
+			next_state = AGC_STATE_GRANDE_INTERFERER;
+		else if (bb_level > sens_off[band]) 
+			next_state = AGC_STATE_NORMAL;
+		else if ( (bb_level < sens_on[band]) && (lna_gain == LNAGAIN_MAX) )
+			next_state = AGC_STATE_MAX_SENSITIVITY;
+		break;
+		}
+		
+	case AGC_STATE_MAX_SENSITIVITY : {
+		if (bb_level > sens_off[band]) 
+			next_state = AGC_STATE_SMALL_SIGNAL;
+		break;
+		}
+		
+	}
+			
+	*agc_current_state = next_state;	
+	
+	
+	switch (*agc_current_state) {
+		
+		case AGC_STATE_LNAGAIN_BELOW_MIN : {
+			if(MT_IS_ERROR(MT2266_SetParam(tuner_handle,MT2266_LNA_GAIN_INCR, LNAGAIN_MAX))) goto error_status;
+			break;
+			}
+		
+		case AGC_STATE_LNAGAIN_ABOVE_MAX : {
+			if(MT_IS_ERROR(MT2266_SetParam(tuner_handle,MT2266_LNA_GAIN_DECR, LNAGAIN_MIN))) goto error_status;
+			break;
+			}
+			
+		case AGC_STATE_NORMAL : {
+			if(MT_IS_ERROR(demod_set_bbagclim(demod_handle,0))) goto error_status;
+			if (zin >= 2) {
+				zin -= 2;
+				if(MT_IS_ERROR(MT2266_SetReg(tuner_handle,0x1e,zin))) goto error_status;
+			}
+			break;
+			}
+		
+		case AGC_STATE_NO_INTERFERER : {
+			if(MT_IS_ERROR(MT2266_SetParam(tuner_handle,MT2266_LNA_GAIN_INCR, LNAGAIN_MAX))) goto error_status;
+			if (zin >= 2) {
+				zin -= 2;
+				if(MT_IS_ERROR(MT2266_SetReg(tuner_handle,0x1e,zin))) goto error_status;
+			}
+
+			if(MT_IS_ERROR(demod_set_bbagclim(demod_handle,0))) goto error_status;
+			break;
+			}
+
+		case AGC_STATE_MEDIUM_INTERFERER : {
+			if (zin >= 2) {
+				zin -= 2;
+				if(MT_IS_ERROR(MT2266_SetReg(tuner_handle,0x1e,zin))) goto error_status;
+			}
+
+			// Additional setting
+			// Set tuner with normal bandwidth.
+			if(MT_IS_ERROR(tuner_set_bw_normal(tuner_handle, demod_handle))) goto error_status;
+
+			break;
+			}
+		
+		case AGC_STATE_GRANDE_INTERFERER : {
+			if(MT_IS_ERROR(MT2266_SetParam(tuner_handle,MT2266_LNA_GAIN_DECR, LNAGAIN_MIN))) goto error_status;
+			if(MT_IS_ERROR(demod_set_bbagclim(demod_handle,1))) goto error_status;
+
+			// Additional setting
+			// Set tuner with narrow bandwidth.
+			if(MT_IS_ERROR(tuner_set_bw_narrow(tuner_handle, demod_handle))) goto error_status;
+
+			break;
+			}
+		
+		case AGC_STATE_MEDIUM_SIGNAL : {
+			if(MT_IS_ERROR(MT2266_SetParam(tuner_handle,MT2266_LNA_GAIN_INCR, LNAGAIN_MAX))) goto error_status;
+			if (zin >= 2) {
+				zin -= 2;
+				if(MT_IS_ERROR(MT2266_SetReg(tuner_handle,0x1e,zin))) goto error_status;
+			}
+			if(MT_IS_ERROR(demod_set_bbagclim(demod_handle,0))) goto error_status;
+			break;
+			}
+			
+		case AGC_STATE_GRANDE_SIGNAL : {
+			if(MT_IS_ERROR(demod_set_bbagclim(demod_handle,0))) goto error_status;
+			break;
+			}
+
+		case AGC_STATE_MAS_GRANDE_SIGNAL : {
+			if(MT_IS_ERROR(MT2266_SetParam(tuner_handle,MT2266_LNA_GAIN_DECR, LNAGAIN_MIN))) goto error_status;
+			if (lna_gain==0) {
+				if (zin <= 64) {
+					zin += 2;
+					if(MT_IS_ERROR(MT2266_SetReg(tuner_handle,0x1e,zin))) goto error_status;
+					}
+				}
+			if(MT_IS_ERROR(demod_set_bbagclim(demod_handle,0))) goto error_status;
+			break;
+			}
+		
+		case AGC_STATE_SMALL_SIGNAL : {
+			if(MT_IS_ERROR(MT2266_SetParam(tuner_handle,MT2266_LNA_GAIN_INCR, LNAGAIN_MAX))) goto error_status;
+			if(MT_IS_ERROR(MT2266_SetParam(tuner_handle,MT2266_UHF_NORMAL,1))) goto error_status;
+			if (zin >= 2) {
+				zin -= 2;
+				if(MT_IS_ERROR(MT2266_SetReg(tuner_handle,0x1e,zin))) goto error_status;
+			}
+
+			if(MT_IS_ERROR(demod_set_bbagclim(demod_handle,0))) goto error_status;
+			*uhf_sens=0;
+			break;
+			}
+		
+		case AGC_STATE_MAX_SENSITIVITY : {
+			if(MT_IS_ERROR(MT2266_SetParam(tuner_handle,MT2266_UHF_MAXSENS,1))) goto error_status;
+			if (zin >= 2) {
+				zin -= 2;
+				if(MT_IS_ERROR(MT2266_SetReg(tuner_handle,0x1e,zin))) goto error_status;
+			}
+			if(MT_IS_ERROR(demod_set_bbagclim(demod_handle,0))) goto error_status;
+			*uhf_sens=1;
+			break;
+			}
+	}	
+
+	if(MT_IS_ERROR(MT2266_GetParam(tuner_handle, MT2266_LNA_GAIN,&tmp_lna_gain))) goto error_status;
+	lna_gain=(unsigned long)(tmp_lna_gain);
+
+	*lna_config=(unsigned char)lna_gain;
+
+/*
+#ifndef _HOST_DLL
+	uart_write_nr(" LNA ");	
+	uart_writedez(lna_gain);
+	uart_write_nr(" SENS ");
+	uart_writedez(*uhf_sens);
+	uart_write_nr(" Z ");
+	uart_writedez(zin);
+	uart_write(" ");
+#endif
+*/
+
+
+
+	return MT_OK;
+
+
+error_status:
+	return MT_COMM_ERR;
+}
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_mt2266.h b/drivers/media/usb/dvb-usb/nim_rtl2832_mt2266.h
new file mode 100644
index 0000000..2047220
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_mt2266.h
@@ -0,0 +1,264 @@
+#ifndef __NIM_RTL2832_MT2266
+#define __NIM_RTL2832_MT2266
+
+/**
+
+@file
+
+@brief   RTL2832 MT2266 NIM module declaration
+
+One can manipulate RTL2832 MT2266 NIM through RTL2832 MT2266 NIM module.
+RTL2832 MT2266 NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_mt2266.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+	TUNER_MODULE *pTuner;
+	MT2266_EXTRA_MODULE *pTunerExtra;
+
+	...
+
+
+
+	// Build RTL2832 MT2266 NIM module.
+	BuildRtl2832Mt2266Module(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,									// Maximum I2C reading byte number is 9.
+		8,									// Maximum I2C writing byte number is 8.
+		CustomI2cRead,						// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,						// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,						// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,								// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,			// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,				// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,			// The RTL2832 application mode is STB mode.
+		50,									// The RTL2832 update function reference period is 50 millisecond
+		YES,								// The RTL2832 Function 1 enabling status is YES.
+
+		0xc0								// The MT2266 I2C device address is 0xc0 in 8-bit format.
+		);
+
+
+
+
+
+	// Get MT2266 tuner extra module.
+	pTuner = pNim->pTuner;
+	pTunerExtra = &(pTuner->Extra.Mt2266);
+
+	// Open MT2266 handle.
+	pTunerExtra->OpenHandle(pTuner);
+
+
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+
+
+
+	// Close MT2266 handle.
+	pTunerExtra->CloseHandle(pTuner);
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_mt2266.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_MT2266_ADDITIONAL_INIT_REG_TABLE_LEN		21
+
+#define RTL2832_MT2266_IF_AGC_MIN_BIT_NUM		8
+#define RTL2832_MT2266_IF_AGC_MIN_INT_MAX		36
+#define RTL2832_MT2266_IF_AGC_MIN_INT_MIN		-64
+#define RTL2832_MT2266_IF_AGC_MIN_INT_STEP		0
+
+
+
+
+
+// Builder
+void
+BuildRtl2832Mt2266Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr						// Tuner dependence
+	);
+
+
+
+
+
+// RTL2832 MT2266 NIM manipulaing functions
+int
+rtl2832_mt2266_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_mt2266_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+rtl2832_mt2266_UpdateFunction(
+	DVBT_NIM_MODULE *pNim
+	);
+
+
+
+
+
+// The following context is source code provided by Microtune.
+
+
+
+
+
+// Additional definition for mt_control.c
+typedef void *           handle_t;
+
+#define MT2266_DEMOD_ASSUMED_AGC_REG_BIT_NUM		16
+
+
+
+// Microtune source code - mt_control.c
+
+
+
+/*  $Id: mt_control.c,v 1.6 2008/01/02 12:04:39 tune\tpinz Exp $ */
+/*! 
+ * \file mt_control.c 
+ * \author Thomas Pinz, Microtune GmbH&Co KG
+ * \author Marie-Curie-Str. 1, 85055 Ingolstadt
+ * \author E-Mail: thomas.pinz@microtune.com
+ */
+
+
+#define LNAGAIN_MIN 0
+#define LNAGAIN_MAX 14
+
+#define AGC_STATE_START 0
+#define AGC_STATE_LNAGAIN_BELOW_MIN 1
+#define AGC_STATE_LNAGAIN_ABOVE_MAX 2
+#define AGC_STATE_NORMAL 3
+#define AGC_STATE_NO_INTERFERER 4
+#define AGC_STATE_MEDIUM_INTERFERER 5
+#define AGC_STATE_GRANDE_INTERFERER 6
+#define AGC_STATE_MEDIUM_SIGNAL 7
+#define AGC_STATE_GRANDE_SIGNAL 8
+#define AGC_STATE_MAS_GRANDE_SIGNAL 9
+#define AGC_STATE_MAX_SENSITIVITY 10
+#define AGC_STATE_SMALL_SIGNAL 11
+
+
+UData_t
+demod_get_pd(
+	handle_t demod_handle,
+	unsigned short *pd_value
+	);
+
+UData_t
+demod_get_agc(
+	handle_t demod_handle,
+	unsigned short *rf_level,
+	unsigned short *bb_level
+	);
+
+UData_t
+demod_set_bbagclim(
+	handle_t demod_handle,
+	int on_off_status
+	);
+
+UData_t
+tuner_set_bw_normal(
+	handle_t tuner_handle,
+	handle_t demod_handle
+	);
+
+UData_t
+tuner_set_bw_narrow(
+	handle_t tuner_handle,
+	handle_t demod_handle
+	);
+
+UData_t
+demod_pdcontrol_reset(
+	handle_t demod_handle,
+	handle_t tuner_handle,
+	unsigned char *agc_current_state
+	);
+
+UData_t
+demod_pdcontrol(
+	handle_t demod_handle,
+	handle_t tuner_handle,
+	unsigned char* lna_config,
+	unsigned char* uhf_sens,
+	unsigned char *agc_current_state,
+	unsigned long *lna_gain_old
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_mxl5007t.c b/drivers/media/usb/dvb-usb/nim_rtl2832_mxl5007t.c
new file mode 100644
index 0000000..ef06a95
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_mxl5007t.c
@@ -0,0 +1,517 @@
+/**
+
+@file
+
+@brief   RTL2832 MxL5007T NIM module definition
+
+One can manipulate RTL2832 MxL5007T NIM through RTL2832 MxL5007T NIM module.
+RTL2832 MxL5007T NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_mxl5007t.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 MxL5007T NIM module builder
+
+Use BuildRtl2832Mxl5007tModule() to build RTL2832 MxL5007T NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 MxL5007T NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              MxL5007T I2C device address
+@param [in]   TunerCrystalFreqHz           MxL5007T crystal frequency in Hz
+@param [in]   TunerLoopThroughMode         MxL5007T loop-through mode
+@param [in]   TunerClkOutMode              MxL5007T clock output mode
+@param [in]   TunerClkOutAmpMode           MxL5007T clock output amplitude mode
+
+
+@note
+	-# One should call BuildRtl2832Mxl5007tModule() to build RTL2832 MxL5007T NIM module before using it.
+
+*/
+void
+BuildRtl2832Mxl5007tModule(
+	DVBT_NIM_MODULE **ppNim,								// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerLoopThroughMode,
+	int TunerClkOutMode,
+	int TunerClkOutAmpMode
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_MXL5007T;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build Mxl5007T tuner module.
+	BuildMxl5007tModule(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz,
+		RTL2832_MXL5007T_STANDARD_MODE_DEFAULT,
+		RTL2832_MXL5007T_IF_FREQ_HZ_DEFAULT,
+		RTL2832_MXL5007T_SPECTRUM_MODE_DEFAULT,
+		TunerLoopThroughMode,
+		TunerClkOutMode,
+		TunerClkOutAmpMode,
+		RTL2832_MXL5007T_QAM_IF_DIFF_OUT_LEVEL_DEFAULT
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+	pNim->UpdateFunction    = dvbt_nim_default_UpdateFunction;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_mxl5007t_Initialize;
+	pNim->SetParameters  = rtl2832_mxl5007t_SetParameters;
+
+
+	return;
+}
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_mxl5007t_Initialize_fm(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_MXL5007T_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x39	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x4b	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9d4	},
+		{DVBT_AD_EN_REG1,			0x0		},
+		{DVBT_CKOUT_PWR_PID,		0x0		},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	//if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		//goto error_status_execute_function;
+
+	// Set demod IF frequency with NIM default.
+	//if(pDemod->SetIfFreqHz(pDemod, RTL2832_MXL5007T_IF_FREQ_HZ_DEFAULT) != FUNCTION_SUCCESS)
+	//	goto error_status_execute_function;
+
+	// Set demod spectrum mode with NIM default.
+	//if(pDemod->SetSpectrumMode(pDemod, RTL2832_MXL5007T_SPECTRUM_MODE_DEFAULT) != FUNCTION_SUCCESS)
+	//	goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_MXL5007T_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_mxl5007t_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_MXL5007T_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x39	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x4b	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9d4	},
+		{DVBT_AD_EN_REG1,			0x0		},
+		{DVBT_CKOUT_PWR_PID,		0x0		},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with NIM default.
+	if(pDemod->SetIfFreqHz(pDemod, RTL2832_MXL5007T_IF_FREQ_HZ_DEFAULT) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with NIM default.
+	if(pDemod->SetSpectrumMode(pDemod, RTL2832_MXL5007T_SPECTRUM_MODE_DEFAULT) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_MXL5007T_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_mxl5007t_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	MXL5007T_EXTRA_MODULE *pTunerExtra;
+	int TunerBandwidthMode;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Mxl5007t);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthMode = MXL5007T_BANDWIDTH_6000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthMode = MXL5007T_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthMode = MXL5007T_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetBandwidthMode(pTuner, TunerBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+int
+rtl2832_mxl5007t_SetParameters_fm(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	MXL5007T_EXTRA_MODULE *pTunerExtra;
+	int TunerBandwidthMode;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Mxl5007t);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthMode = MXL5007T_BANDWIDTH_6000000HZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthMode = MXL5007T_BANDWIDTH_7000000HZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthMode = MXL5007T_BANDWIDTH_8000000HZ;		break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetBandwidthMode(pTuner, TunerBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_mxl5007t.h b/drivers/media/usb/dvb-usb/nim_rtl2832_mxl5007t.h
new file mode 100644
index 0000000..bdf43ad
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_mxl5007t.h
@@ -0,0 +1,165 @@
+#ifndef __NIM_RTL2832_MXL5007T
+#define __NIM_RTL2832_MXL5007T
+
+/**
+
+@file
+
+@brief   RTL2832 MxL5007T NIM module declaration
+
+One can manipulate RTL2832 MxL5007T NIM through RTL2832 MxL5007T NIM module.
+RTL2832 MxL5007T NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_mxl5007t.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+	RTL2832_EXTRA_MODULE Rtl2832ExtraModuleMemory;
+	MXL5007T_EXTRA_MODULE Mxl5007tExtraModuleMemory;
+
+	...
+
+
+
+	// Build RTL2832 MxL5007T NIM module.
+	BuildRtl2832Mxl5007tModule(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		&Rtl2832ExtraModuleMemory,		// Employ RTL2832 extra module for RTL2832 module.
+		0x20,							// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2832 crystal frequency is 28.8 MHz.
+		RTL2832_APPLICATION_STB,		// The RTL2832 application mode is STB mode.
+		TS_INTERFACE_SERIAL,			// The RTL2832 TS interface mode is serial.
+		50,								// The RTL2832 update function reference period is 50 millisecond
+		ON,								// The RTL2832 Function 1 enabling status is on.
+
+		&Mxl5007tExtraModuleMemory,		// Employ Mxl5007T extra module for Mxl5007T module.
+		0xc0,							// The MxL5007T I2C device address is 0xc0 in 8-bit format.
+		CRYSTAL_FREQ_16000000HZ,		// The MxL5007T Crystal frequency is 16.0 MHz.
+		MXL5007T_LOOP_THROUGH_DISABLE,	// The MxL5007T loop-through mode is disabled.
+		MXL5007T_CLK_OUT_DISABLE,		// The MxL5007T clock output mode is disabled.
+		MXL5007T_CLK_OUT_AMP_0			// The MxL5007T clock output amplitude is 0.
+		);
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_mxl5007t.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_MXL5007T_ADDITIONAL_INIT_REG_TABLE_LEN		23
+
+// Default
+#define RTL2832_MXL5007T_STANDARD_MODE_DEFAULT				MXL5007T_STANDARD_DVBT
+#define RTL2832_MXL5007T_IF_FREQ_HZ_DEFAULT					IF_FREQ_4570000HZ
+#define RTL2832_MXL5007T_SPECTRUM_MODE_DEFAULT				SPECTRUM_NORMAL
+#define RTL2832_MXL5007T_QAM_IF_DIFF_OUT_LEVEL_DEFAULT		0
+
+
+
+
+
+// Builder
+void
+BuildRtl2832Mxl5007tModule(
+	DVBT_NIM_MODULE **ppNim,								// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerLoopThroughMode,
+	int TunerClkOutMode,
+	int TunerClkOutAmpMode
+	);
+
+
+
+int
+rtl2832_mxl5007t_Initialize_fm(
+	DVBT_NIM_MODULE *pNim
+	);
+
+// RTL2832 MxL5007T NIM manipulaing functions
+int
+rtl2832_mxl5007t_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_mxl5007t_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+rtl2832_mxl5007t_SetParameters_fm(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_r820t.c b/drivers/media/usb/dvb-usb/nim_rtl2832_r820t.c
new file mode 100644
index 0000000..5309ac2
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_r820t.c
@@ -0,0 +1,356 @@
+/**
+
+@file
+
+@brief   RTL2832 R820T NIM module definition
+
+One can manipulate RTL2832 R820T NIM through RTL2832 R820T NIM module.
+RTL2832 R820T NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_r820t.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 R820T NIM module builder
+
+Use BuildRtl2832R820tModule() to build RTL2832 R820T NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 R820T NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              R820T I2C device address
+@param [in]   TunerCrystalFreqHz           R820T crystal frequency in Hz
+
+
+@note
+	-# One should call BuildRtl2832R820tModule() to build RTL2832 R820T NIM module before using it.
+
+*/
+void
+BuildRtl2832R820tModule(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr						// Tuner dependence
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_R820T;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build R820T tuner module.
+	BuildR820tModule(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		R820T
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+	pNim->UpdateFunction    = dvbt_nim_default_UpdateFunction;	
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_r820t_Initialize;
+	pNim->SetParameters  = rtl2832_r820t_SetParameters;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_r820t_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_R820T_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x39	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x40	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x8		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x18	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9f4	},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_INVERSE.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_INVERSE) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_R820T_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+//error_status_set_tuner_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_r820t_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	R820T_EXTRA_MODULE *pTunerExtra;
+	int TunerStandardMode;
+
+	unsigned long IfFreqHz;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.R820t);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		
+			TunerStandardMode = R820T_DVBT_BANDWIDTH_6000000HZ;
+			IfFreqHz = IF_FREQ_3570000HZ;	
+			break;
+		case DVBT_BANDWIDTH_7MHZ:		
+			TunerStandardMode = R820T_DVBT_BANDWIDTH_7000000HZ;
+			IfFreqHz = IF_FREQ_4570000HZ;	
+			break;
+		case DVBT_BANDWIDTH_8MHZ:		
+			TunerStandardMode = R820T_DVBT_BANDWIDTH_8000000HZ;
+			IfFreqHz = IF_FREQ_4570000HZ;	
+			break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetStandardMode(pTuner, TunerStandardMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set demod IF frequency.
+	if(pDemod->SetIfFreqHz(pDemod, IfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_r820t.h b/drivers/media/usb/dvb-usb/nim_rtl2832_r820t.h
new file mode 100644
index 0000000..1addd4e
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_r820t.h
@@ -0,0 +1,143 @@
+#ifndef __NIM_RTL2832_R820T
+#define __NIM_RTL2832_R820T
+
+/**
+
+@file
+
+@brief   RTL2832 R820T NIM module declaration
+
+One can manipulate RTL2832 R820T NIM through RTL2832 R820T NIM module.
+RTL2832 R820T NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_r820t.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2832 R820T NIM module.
+	BuildRtl2832R820tModule(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,							// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,		// The RTL2832 application mode is STB mode.
+		200,							// The RTL2832 update function reference period is 200 millisecond
+		YES,							// The RTL2832 Function 1 enabling status is YES.
+
+		0xc6							// The R820T I2C device address is 0xc6 in 8-bit format.
+		);
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_r820t.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_R820T_ADDITIONAL_INIT_REG_TABLE_LEN		21
+#define RTL2832_R820T_LNA_UPDATE_WAIT_TIME_MS				1000
+
+
+
+#define R820T_DVBT_BANDWIDTH_6000000HZ	DVB_T_6M
+#define R820T_DVBT_BANDWIDTH_7000000HZ	DVB_T_7M_2
+#define R820T_DVBT_BANDWIDTH_8000000HZ	DVB_T_8M
+
+
+
+
+// Builder
+void
+BuildRtl2832R820tModule(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr						// Tuner dependence
+	);
+
+
+
+
+// RTL2832 R820T NIM manipulaing functions
+int
+rtl2832_r820t_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_r820t_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+
+
+
+
+
+
+#endif
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_tda18272.c b/drivers/media/usb/dvb-usb/nim_rtl2832_tda18272.c
new file mode 100644
index 0000000..364ea45
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_tda18272.c
@@ -0,0 +1,408 @@
+/**
+
+@file
+
+@brief   RTL2832 TDA18272 NIM module definition
+
+One can manipulate RTL2832 TDA18272 NIM through RTL2832 TDA18272 NIM module.
+RTL2832 TDA18272 NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_tda18272.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 TDA18272 NIM module builder
+
+Use BuildRtl2832Tda18272Module() to build RTL2832 TDA18272 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 TDA18272 NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              TDA18272 I2C device address
+@param [in]   TunerCrystalFreqHz           TDA18272 crystal frequency in Hz
+@param [in]   TunerUnitNo                  TDA18272 unit number
+@param [in]   TunerIfOutputVppMode         TDA18272 IF output Vp-p mode
+
+
+@note
+	-# One should call BuildRtl2832Tda18272Module() to build RTL2832 TDA18272 NIM module before using it.
+
+*/
+void
+BuildRtl2832Tda18272Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerUnitNo,
+	int TunerIfOutputVppMode
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_TDA18272;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build TDA18272 tuner module.
+	BuildTda18272Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz,
+		TunerUnitNo,
+		TunerIfOutputVppMode
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+	pNim->UpdateFunction    = dvbt_nim_default_UpdateFunction;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize    = rtl2832_tda18272_Initialize;
+	pNim->SetParameters = rtl2832_tda18272_SetParameters;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_tda18272_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_TDA18272_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x39	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x40	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x8		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x18	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x80	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9f4	},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	// Note: TDA18272 tuner uses dynamic IF frequency, so we will set demod IF frequency in SetParameters().
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_INVERSE.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_INVERSE) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_TDA18272_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_tda18272_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	TDA18272_EXTRA_MODULE *pTunerExtra;
+	int TunerStandardBandwidthMode;
+	unsigned long IfFreqHz;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Tda18272);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:	TunerStandardBandwidthMode = TDA18272_STANDARD_BANDWIDTH_DVBT_6MHZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:	TunerStandardBandwidthMode = TDA18272_STANDARD_BANDWIDTH_DVBT_7MHZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:	TunerStandardBandwidthMode = TDA18272_STANDARD_BANDWIDTH_DVBT_8MHZ;		break;
+	}
+
+	// Set tuner standard and bandwidth mode with TunerStandardBandwidthMode.
+	if(pTunerExtra->SetStandardBandwidthMode(pTuner, TunerStandardBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner RF frequency in Hz.
+	// Note: Must run SetRfFreqHz() after SetStandardBandwidthMode(), because SetRfFreqHz() needs some
+	//       SetStandardBandwidthMode() information.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get tuner IF frequency in Hz.
+	// Note: 1. Must run GetIfFreqHz() after SetRfFreqHz(), because GetIfFreqHz() needs some SetRfFreqHz() information.
+	//       2. TDA18272 tuner uses dynamic IF frequency.
+	if(pTunerExtra->GetIfFreqHz(pTuner, &IfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod IF frequency according to IfFreqHz.
+	// Note: TDA18272 tuner uses dynamic IF frequency.
+	if(pDemod->SetIfFreqHz(pDemod, IfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_GET_RF_POWER_LEVEL_DBM
+
+*/
+int
+rtl2832_tda18272_GetRfPowerLevelDbm(
+	DVBT_NIM_MODULE *pNim,
+	long *pRfPowerLevelDbm
+	)
+{
+	DVBT_DEMOD_MODULE *pDemod;
+
+	unsigned long FsmStage;
+	long IfAgc;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get FSM stage and IF AGC value.
+	if(pDemod->GetRegBitsWithPage(pDemod, DVBT_FSM_STAGE, &FsmStage) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+	if(pDemod->GetIfAgc(pDemod, &IfAgc) != FUNCTION_SUCCESS)
+		goto error_status_get_registers;
+
+
+	//  Determine signal strength according to FSM stage and IF AGC value.
+	if(FsmStage < 10)
+		*pRfPowerLevelDbm = -120;
+	else
+	{
+		if(IfAgc > -1250)
+			*pRfPowerLevelDbm = -71 - (IfAgc / 165);
+		else
+			*pRfPowerLevelDbm = -60;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_tda18272.h b/drivers/media/usb/dvb-usb/nim_rtl2832_tda18272.h
new file mode 100644
index 0000000..25c8ef1
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_tda18272.h
@@ -0,0 +1,148 @@
+#ifndef __NIM_RTL2832_TDA18272
+#define __NIM_RTL2832_TDA18272
+
+/**
+
+@file
+
+@brief   RTL2832 TDA18272 NIM module declaration
+
+One can manipulate RTL2832 TDA18272 NIM through RTL2832 TDA18272 NIM module.
+RTL2832 TDA18272 NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_tda18272.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2832 TDA18272 NIM module.
+	BuildRtl2832Tda18272Module(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,							// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,		// The RTL2832 application mode is STB mode.
+		200,							// The RTL2832 update function reference period is 200 millisecond
+		YES,							// The RTL2832 Function 1 enabling status is YES.
+
+		0xc0,							// The TDA18272 I2C device address is 0xc0 in 8-bit format.
+		CRYSTAL_FREQ_16000000HZ,		// The TDA18272 crystal frequency is 16.0 MHz.
+		TDA18272_UNIT_0,				// The TDA18272 unit number is 0.
+		TDA18272_IF_OUTPUT_VPP_0P7V		// The TDA18272 IF output Vp-p is 0.7 V.
+		);
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_tda18272.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_TDA18272_ADDITIONAL_INIT_REG_TABLE_LEN		21
+
+
+
+
+
+// Builder
+void
+BuildRtl2832Tda18272Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerUnitNo,
+	int TunerIfOutputVppMode
+	);
+
+
+
+
+
+// RTL2832 TDA18272 NIM manipulaing functions
+int
+rtl2832_tda18272_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_tda18272_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+int
+rtl2832_tda18272_GetRfPowerLevelDbm(
+	DVBT_NIM_MODULE *pNim,
+	long *pRfPowerLevelDbm
+	);
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_tua9001.c b/drivers/media/usb/dvb-usb/nim_rtl2832_tua9001.c
new file mode 100644
index 0000000..92f2f5f
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_tua9001.c
@@ -0,0 +1,340 @@
+/**
+
+@file
+
+@brief   RTL2832 TUA9001 NIM module definition
+
+One can manipulate RTL2832 TUA9001 NIM through RTL2832 TUA9001 NIM module.
+RTL2832 TUA9001 NIM module is derived from DVB-T NIM module.
+
+*/
+
+
+#include "nim_rtl2832_tua9001.h"
+
+
+
+
+
+/**
+
+@brief   RTL2832 TUA9001 NIM module builder
+
+Use BuildRtl2832Tua9001Module() to build RTL2832 TUA9001 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2832 TUA9001 NIM module pointer
+@param [in]   pDvbtNimModuleMemory         Pointer to an allocated DVB-T NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2832 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2832 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2832 TS interface mode for setting
+@param [in]   DemodAppMode                 RTL2832 application mode for setting
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2832 update function reference period in millisecond for setting
+@param [in]   DemodIsFunc1Enabled          RTL2832 Function 1 enabling status for setting
+@param [in]   TunerDeviceAddr              TUA9001 I2C device address
+
+
+@note
+	-# One should call BuildRtl2832Tua9001Module() to build RTL2832 TUA9001 NIM module before using it.
+
+*/
+void
+BuildRtl2832Tua9001Module(
+	DVBT_NIM_MODULE **ppNim,							// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr						// Tuner dependence
+	)
+{
+	DVBT_NIM_MODULE *pNim;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDvbtNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+
+	// Set NIM type.
+	pNim->NimType = DVBT_NIM_RTL2832_TUA9001;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2832 demod module.
+	BuildRtl2832Module(
+		&pNim->pDemod,
+		&pNim->DvbtDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodAppMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled
+		);
+
+	// Build TUA9001 tuner module.
+	BuildTua9001Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dvbt_nim_default_GetNimType;
+	pNim->GetParameters     = dvbt_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dvbt_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dvbt_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dvbt_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dvbt_nim_default_GetSignalQuality;
+	pNim->GetBer            = dvbt_nim_default_GetBer;
+	pNim->GetSnrDb          = dvbt_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dvbt_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dvbt_nim_default_GetCrOffsetHz;
+	pNim->GetTpsInfo        = dvbt_nim_default_GetTpsInfo;
+	pNim->UpdateFunction    = dvbt_nim_default_UpdateFunction;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2832_tua9001_Initialize;
+	pNim->SetParameters  = rtl2832_tua9001_SetParameters;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2832_tua9001_Initialize(
+	DVBT_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2832_TUA9001_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DVBT_DAGC_TRG_VAL,			0x39	},
+		{DVBT_AGC_TARG_VAL_0,		0x0		},
+		{DVBT_AGC_TARG_VAL_8_1,		0x5a	},
+		{DVBT_AAGC_LOOP_GAIN,		0x16    },
+		{DVBT_LOOP_GAIN2_3_0,		0x6		},
+		{DVBT_LOOP_GAIN2_4,			0x1		},
+		{DVBT_LOOP_GAIN3,			0x16	},
+		{DVBT_VTOP1,				0x35	},
+		{DVBT_VTOP2,				0x21	},
+		{DVBT_VTOP3,				0x21	},
+		{DVBT_KRF1,					0x0		},
+		{DVBT_KRF2,					0x40	},
+		{DVBT_KRF3,					0x10	},
+		{DVBT_KRF4,					0x10	},
+		{DVBT_IF_AGC_MIN,			0x80	},
+		{DVBT_IF_AGC_MAX,			0x7f	},
+		{DVBT_RF_AGC_MIN,			0x9c	},
+		{DVBT_RF_AGC_MAX,			0x7f	},
+		{DVBT_POLAR_RF_AGC,			0x0		},
+		{DVBT_POLAR_IF_AGC,			0x0		},
+		{DVBT_AD7_SETTING,			0xe9f4	},
+		{DVBT_OPT_ADC_IQ,			0x1		},
+		{DVBT_AD_AVI,				0x0		},
+		{DVBT_AD_AVQ,				0x0		},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2832_TUA9001_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DVBT_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2832_tua9001_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	DVBT_DEMOD_MODULE *pDemod;
+
+	TUA9001_EXTRA_MODULE *pTunerExtra;
+	int TunerBandwidthMode;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Tua9001);
+
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Determine TunerBandwidthMode according to bandwidth mode.
+	switch(BandwidthMode)
+	{
+		default:
+		case DVBT_BANDWIDTH_6MHZ:		TunerBandwidthMode = TUA9001_BANDWIDTH_6MHZ;		break;
+		case DVBT_BANDWIDTH_7MHZ:		TunerBandwidthMode = TUA9001_BANDWIDTH_7MHZ;		break;
+		case DVBT_BANDWIDTH_8MHZ:		TunerBandwidthMode = TUA9001_BANDWIDTH_8MHZ;		break;
+	}
+
+	// Set tuner bandwidth mode with TunerBandwidthMode.
+	if(pTunerExtra->SetBandwidthMode(pTuner, TunerBandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod->SetRegBitsWithPage(pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Set demod bandwidth mode.
+	if(pDemod->SetBandwidthMode(pDemod, BandwidthMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2832_tua9001.h b/drivers/media/usb/dvb-usb/nim_rtl2832_tua9001.h
new file mode 100644
index 0000000..5eded7d
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2832_tua9001.h
@@ -0,0 +1,137 @@
+#ifndef __NIM_RTL2832_TUA9001
+#define __NIM_RTL2832_TUA9001
+
+/**
+
+@file
+
+@brief   RTL2832 TUA9001 NIM module declaration
+
+One can manipulate RTL2832 TUA9001 NIM through RTL2832 TUA9001 NIM module.
+RTL2832 TUA9001 NIM module is derived from DVB-T NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dvbt_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2832_tua9001.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DVBT_NIM_MODULE *pNim;
+	DVBT_NIM_MODULE DvbtNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2832 TUA9001 NIM module.
+	BuildRtl2832Tua9001Module(
+		&pNim,
+		&DvbtNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x20,							// The RTL2832 I2C device address is 0x20 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2832 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2832 TS interface mode is serial.
+		RTL2832_APPLICATION_STB,		// The RTL2832 application mode is STB mode.
+		200,							// The RTL2832 update function reference period is 200 millisecond
+		YES,							// The RTL2832 Function 1 enabling status is YES.
+
+		0xc0							// The TUA9001 I2C device address is 0xc0 in 8-bit format.
+		);
+
+
+
+	// See the example for other NIM functions in dvbt_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2832.h"
+#include "tuner_tua9001.h"
+#include "dvbt_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2832_TUA9001_ADDITIONAL_INIT_REG_TABLE_LEN		24
+
+
+
+
+
+// Builder
+void
+BuildRtl2832Tua9001Module(
+	DVBT_NIM_MODULE **ppNim,						// DVB-T NIM dependence
+	DVBT_NIM_MODULE *pDvbtNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,				// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,					// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodAppMode,
+	unsigned long UpdateFuncRefPeriodMs,
+	int IsFunc1Enabled,
+
+	unsigned char TunerDeviceAddr					// Tuner dependence
+	);
+
+
+
+
+
+// RTL2832 TUA9001 NIM manipulaing functions
+int
+rtl2832_tua9001_Initialize(
+	DVBT_NIM_MODULE *pNim
+	);
+
+int
+rtl2832_tua9001_SetParameters(
+	DVBT_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int BandwidthMode
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2836_fc2580.c b/drivers/media/usb/dvb-usb/nim_rtl2836_fc2580.c
new file mode 100644
index 0000000..f501e6e
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2836_fc2580.c
@@ -0,0 +1,308 @@
+/**
+
+@file
+
+@brief   RTL2836 FC2580 NIM module definition
+
+One can manipulate RTL2836 FC2580 NIM through RTL2836 FC2580 NIM module.
+RTL2836 FC2580 NIM module is derived from DTMB NIM module.
+
+*/
+
+
+#include "nim_rtl2836_fc2580.h"
+
+
+
+
+
+/**
+
+@brief   RTL2836 FC2580 NIM module builder
+
+Use BuildRtl2836Fc2580Module() to build RTL2836 FC2580 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2836 FC2580 NIM module pointer
+@param [in]   pDtmbNimModuleMemory         Pointer to an allocated DTMB NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2836 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2836 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2836 TS interface mode
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2836 update function reference period in millisecond
+@param [in]   DemodIsFunc1Enabled          RTL2836 Function 1 enabling status for setting
+@param [in]   DemodIsFunc2Enabled          RTL2836 Function 2 enabling status for setting
+@param [in]   TunerDeviceAddr              FC2580 I2C device address
+@param [in]   TunerCrystalFreqHz           FC2580 crystal frequency in Hz
+@param [in]   TunerAgcMode                 FC2580 AGC mode
+
+
+@note
+	-# One should call BuildRtl2836Fc2580Module() to build RTL2836 FC2580 NIM module before using it.
+
+*/
+void
+BuildRtl2836Fc2580Module(
+	DTMB_NIM_MODULE **ppNim,							// DTMB NIM dependence
+	DTMB_NIM_MODULE *pDtmbNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+	int DemodIsFunc2Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerAgcMode
+	)
+{
+	DTMB_NIM_MODULE *pNim;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDtmbNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+
+	// Set NIM type.
+	pNim->NimType = DTMB_NIM_RTL2836_FC2580;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2836 demod module.
+	BuildRtl2836Module(
+		&pNim->pDemod,
+		&pNim->DtmbDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled,
+		DemodIsFunc2Enabled
+		);
+
+	// Build FC2580 tuner module.
+	BuildFc2580Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz,
+		TunerAgcMode
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dtmb_nim_default_GetNimType;
+	pNim->GetParameters     = dtmb_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dtmb_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dtmb_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dtmb_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dtmb_nim_default_GetSignalQuality;
+	pNim->GetBer            = dtmb_nim_default_GetBer;
+	pNim->GetPer            = dtmb_nim_default_GetPer;
+	pNim->GetSnrDb          = dtmb_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dtmb_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dtmb_nim_default_GetCrOffsetHz;
+	pNim->GetSignalInfo     = dtmb_nim_default_GetSignalInfo;
+	pNim->UpdateFunction    = dtmb_nim_default_UpdateFunction;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2836_fc2580_Initialize;
+	pNim->SetParameters  = rtl2836_fc2580_SetParameters;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2836_fc2580_Initialize(
+	DTMB_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2836_FC2580_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DTMB_TARGET_VAL,			0x38	},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DTMB_DEMOD_MODULE *pDemod;
+	FC2580_EXTRA_MODULE *pTunerExtra;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Fc2580);
+
+
+	// Enable demod DTMB_I2CT_EN_CTRL.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_I2CT_EN_CTRL, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner bandwidth mode with 8 MHz.
+	if(pTunerExtra->SetBandwidthMode(pTuner, FC2580_BANDWIDTH_8000000HZ) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DTMB_I2CT_EN_CTRL.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_I2CT_EN_CTRL, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with 0 Hz.
+	if(pDemod->SetIfFreqHz(pDemod, IF_FREQ_0HZ) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_NORMAL.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_NORMAL) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2836_FC2580_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2836_fc2580_SetParameters(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long RfFreqHz
+	)
+{
+	TUNER_MODULE *pTuner;
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DTMB_I2CT_EN_CTRL.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_I2CT_EN_CTRL, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DTMB_I2CT_EN_CTRL.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_I2CT_EN_CTRL, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2836_fc2580.h b/drivers/media/usb/dvb-usb/nim_rtl2836_fc2580.h
new file mode 100644
index 0000000..cc827ec
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2836_fc2580.h
@@ -0,0 +1,140 @@
+#ifndef __NIM_RTL2836_FC2580
+#define __NIM_RTL2836_FC2580
+
+/**
+
+@file
+
+@brief   RTL2836 FC2580 NIM module declaration
+
+One can manipulate RTL2836 FC2580 NIM through RTL2836 FC2580 NIM module.
+RTL2836 FC2580 NIM module is derived from DTMB NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dtmb_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2836_fc2580.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DTMB_NIM_MODULE *pNim;
+	DTMB_NIM_MODULE DtmbNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2836 FC2580 NIM module.
+	BuildRtl2836Fc2580Module(
+		&pNim,
+		&DtmbNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x3e,							// The RTL2836 I2C device address is 0x3e in 8-bit format.
+		CRYSTAL_FREQ_27000000HZ,		// The RTL2836 crystal frequency is 27.0 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2836 TS interface mode is serial.
+		50,								// The RTL2836 update function reference period is 50 millisecond
+		YES,							// The RTL2836 Function 1 enabling status is YES.
+		YES,							// The RTL2836 Function 2 enabling status is YES.
+
+		0xac,							// The FC2580 I2C device address is 0xac in 8-bit format.
+		CRYSTAL_FREQ_16384000HZ,		// The FC2580 crystal frequency is 16.384 MHz.
+		FC2580_AGC_INTERNAL				// The FC2580 AGC mode is internal AGC mode.
+		);
+
+
+
+	// See the example for other NIM functions in dtmb_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2836.h"
+#include "tuner_fc2580.h"
+#include "dtmb_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2836_FC2580_ADDITIONAL_INIT_REG_TABLE_LEN		1
+
+
+
+
+
+// Builder
+void
+BuildRtl2836Fc2580Module(
+	DTMB_NIM_MODULE **ppNim,							// DTMB NIM dependence
+	DTMB_NIM_MODULE *pDtmbNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+	int DemodIsFunc2Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerAgcMode
+	);
+
+
+
+
+
+// RTL2836 FC2580 NIM manipulaing functions
+int
+rtl2836_fc2580_Initialize(
+	DTMB_NIM_MODULE *pNim
+	);
+
+int
+rtl2836_fc2580_SetParameters(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long RfFreqHz
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2836_mxl5007t.c b/drivers/media/usb/dvb-usb/nim_rtl2836_mxl5007t.c
new file mode 100644
index 0000000..8eaec8b
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2836_mxl5007t.c
@@ -0,0 +1,319 @@
+/**
+
+@file
+
+@brief   RTL2836 MxL5007T NIM module definition
+
+One can manipulate RTL2836 MxL5007T NIM through RTL2836 MxL5007T NIM module.
+RTL2836 MxL5007T NIM module is derived from DTMB NIM module.
+
+*/
+
+
+#include "nim_rtl2836_mxl5007t.h"
+
+
+
+
+
+/**
+
+@brief   RTL2836 MxL5007T NIM module builder
+
+Use BuildRtl2836Mxl5007tModule() to build RTL2836 MxL5007T NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                        Pointer to RTL2836 MxL5007T NIM module pointer
+@param [in]   pDtmbNimModuleMemory         Pointer to an allocated DTMB NIM module memory
+@param [in]   I2cReadingByteNumMax         Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax         Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                      Basic I2C reading function pointer
+@param [in]   I2cWrite                     Basic I2C writing function pointer
+@param [in]   WaitMs                       Basic waiting function pointer
+@param [in]   DemodDeviceAddr              RTL2836 I2C device address
+@param [in]   DemodCrystalFreqHz           RTL2836 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode         RTL2836 TS interface mode
+@param [in]   DemodUpdateFuncRefPeriodMs   RTL2836 update function reference period in millisecond
+@param [in]   DemodIsFunc1Enabled          RTL2836 Function 1 enabling status for setting
+@param [in]   DemodIsFunc2Enabled          RTL2836 Function 2 enabling status for setting
+@param [in]   TunerDeviceAddr              MxL5007T I2C device address
+@param [in]   TunerCrystalFreqHz           MxL5007T crystal frequency in Hz
+@param [in]   TunerLoopThroughMode         MxL5007T loop-through mode
+@param [in]   TunerClkOutMode              MxL5007T clock output mode
+@param [in]   TunerClkOutAmpMode           MxL5007T clock output amplitude mode
+
+
+@note
+	-# One should call BuildRtl2836Mxl5007tModule() to build RTL2836 MxL5007T NIM module before using it.
+
+*/
+void
+BuildRtl2836Mxl5007tModule(
+	DTMB_NIM_MODULE **ppNim,							// DTMB NIM dependence
+	DTMB_NIM_MODULE *pDtmbNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+	int DemodIsFunc2Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerLoopThroughMode,
+	int TunerClkOutMode,
+	int TunerClkOutAmpMode
+	)
+{
+	DTMB_NIM_MODULE *pNim;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pDtmbNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+
+	// Set NIM type.
+	pNim->NimType = DTMB_NIM_RTL2836_MXL5007T;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2836 demod module.
+	BuildRtl2836Module(
+		&pNim->pDemod,
+		&pNim->DtmbDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodUpdateFuncRefPeriodMs,
+		DemodIsFunc1Enabled,
+		DemodIsFunc2Enabled
+		);
+
+	// Build MxL5007T tuner module.
+	BuildMxl5007tModule(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz,
+		RTL2836_MXL5007T_STANDARD_MODE_DEFAULT,
+		RTL2836_MXL5007T_IF_FREQ_HZ_DEFAULT,
+		RTL2836_MXL5007T_SPECTRUM_MODE_DEFAULT,
+		TunerLoopThroughMode,
+		TunerClkOutMode,
+		TunerClkOutAmpMode,
+		RTL2836_MXL5007T_QAM_IF_DIFF_OUT_LEVEL_DEFAULT
+		);
+
+
+	// Set NIM module function pointers with default functions.
+	pNim->GetNimType        = dtmb_nim_default_GetNimType;
+	pNim->GetParameters     = dtmb_nim_default_GetParameters;
+	pNim->IsSignalPresent   = dtmb_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = dtmb_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = dtmb_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = dtmb_nim_default_GetSignalQuality;
+	pNim->GetBer            = dtmb_nim_default_GetBer;
+	pNim->GetPer            = dtmb_nim_default_GetPer;
+	pNim->GetSnrDb          = dtmb_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = dtmb_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = dtmb_nim_default_GetCrOffsetHz;
+	pNim->GetSignalInfo     = dtmb_nim_default_GetSignalInfo;
+	pNim->UpdateFunction    = dtmb_nim_default_UpdateFunction;
+
+	// Set NIM module function pointers with particular functions.
+	pNim->Initialize     = rtl2836_mxl5007t_Initialize;
+	pNim->SetParameters  = rtl2836_mxl5007t_SetParameters;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2836_mxl5007t_Initialize(
+	DTMB_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2836_MXL5007T_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,				Value
+		{DTMB_TARGET_VAL,			0x38	},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	DTMB_DEMOD_MODULE *pDemod;
+
+	MXL5007T_EXTRA_MODULE *pTunerExtra;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+	// Get tuner extra module.
+	pTunerExtra = &(pTuner->Extra.Mxl5007t);
+
+
+	// Enable demod DTMB_I2CT_EN_CTRL.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_I2CT_EN_CTRL, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner bandwidth mode with 8 MHz.
+	if(pTunerExtra->SetBandwidthMode(pTuner, MXL5007T_BANDWIDTH_8000000HZ) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DTMB_I2CT_EN_CTRL.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_I2CT_EN_CTRL, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency with NIM default.
+	if(pDemod->SetIfFreqHz(pDemod, RTL2836_MXL5007T_IF_FREQ_HZ_DEFAULT) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with NIM default.
+	if(pDemod->SetSpectrumMode(pDemod, RTL2836_MXL5007T_SPECTRUM_MODE_DEFAULT) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod registers.
+	for(i = 0; i < RTL2836_MXL5007T_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   DTMB_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2836_mxl5007t_SetParameters(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long RfFreqHz
+	)
+{
+	TUNER_MODULE *pTuner;
+	DTMB_DEMOD_MODULE *pDemod;
+
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Enable demod DTMB_I2CT_EN_CTRL.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_I2CT_EN_CTRL, 0x1) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Disable demod DTMB_I2CT_EN_CTRL.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, DTMB_I2CT_EN_CTRL, 0x0) != FUNCTION_SUCCESS)
+		goto error_status_set_registers;
+
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+error_status_set_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2836_mxl5007t.h b/drivers/media/usb/dvb-usb/nim_rtl2836_mxl5007t.h
new file mode 100644
index 0000000..41e874f
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2836_mxl5007t.h
@@ -0,0 +1,150 @@
+#ifndef __NIM_RTL2836_MXL5007T
+#define __NIM_RTL2836_MXL5007T
+
+/**
+
+@file
+
+@brief   RTL2836 MxL5007T NIM module declaration
+
+One can manipulate RTL2836 MxL5007T NIM through RTL2836 MxL5007T NIM module.
+RTL2836 MxL5007T NIM module is derived from DTMB NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in dtmb_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2836_mxl5007t.h"
+
+
+...
+
+
+
+int main(void)
+{
+	DTMB_NIM_MODULE *pNim;
+	DTMB_NIM_MODULE DtmbNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2836 MxL5007T NIM module.
+	BuildRtl2836Mxl5007tModule(
+		&pNim,
+		&DtmbNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x3e,							// The RTL2836 I2C device address is 0x3e in 8-bit format.
+		CRYSTAL_FREQ_27000000HZ,		// The RTL2836 crystal frequency is 27.0 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2836 TS interface mode is serial.
+		50,								// The RTL2836 update function reference period is 50 millisecond
+		YES,							// The RTL2836 Function 1 enabling status is YES.
+		YES,							// The RTL2836 Function 2 enabling status is YES.
+
+		0xc0,							// The MxL5007T I2C device address is 0xc0 in 8-bit format.
+		CRYSTAL_FREQ_16000000HZ,		// The MxL5007T Crystal frequency is 16.0 MHz.
+		MXL5007T_LOOP_THROUGH_DISABLE,	// The MxL5007T loop-through mode is disabled.
+		MXL5007T_CLK_OUT_DISABLE,		// The MxL5007T clock output mode is disabled.
+		MXL5007T_CLK_OUT_AMP_0			// The MxL5007T clock output amplitude is 0.
+		);
+
+
+
+	// See the example for other NIM functions in dtmb_nim_base.h
+
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2836.h"
+#include "tuner_mxl5007t.h"
+#include "dtmb_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2836_MXL5007T_ADDITIONAL_INIT_REG_TABLE_LEN		1
+
+// Default
+#define RTL2836_MXL5007T_STANDARD_MODE_DEFAULT				MXL5007T_STANDARD_DVBT
+#define RTL2836_MXL5007T_IF_FREQ_HZ_DEFAULT					IF_FREQ_4570000HZ
+#define RTL2836_MXL5007T_SPECTRUM_MODE_DEFAULT				SPECTRUM_NORMAL
+#define RTL2836_MXL5007T_QAM_IF_DIFF_OUT_LEVEL_DEFAULT		0
+
+
+
+
+
+// Builder
+void
+BuildRtl2836Mxl5007tModule(
+	DTMB_NIM_MODULE **ppNim,							// DTMB NIM dependence
+	DTMB_NIM_MODULE *pDtmbNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	unsigned long DemodUpdateFuncRefPeriodMs,
+	int DemodIsFunc1Enabled,
+	int DemodIsFunc2Enabled,
+
+	unsigned char TunerDeviceAddr,						// Tuner dependence
+	unsigned long TunerCrystalFreqHz,
+	int TunerLoopThroughMode,
+	int TunerClkOutMode,
+	int TunerClkOutAmpMode
+	);
+
+
+
+
+
+// RTL2836 MxL5007T NIM manipulaing functions
+int
+rtl2836_mxl5007t_Initialize(
+	DTMB_NIM_MODULE *pNim
+	);
+
+int
+rtl2836_mxl5007t_SetParameters(
+	DTMB_NIM_MODULE *pNim,
+	unsigned long RfFreqHz
+	);
+
+
+
+
+
+
+
+#endif
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2840_max3543.c b/drivers/media/usb/dvb-usb/nim_rtl2840_max3543.c
new file mode 100644
index 0000000..25daa3f
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2840_max3543.c
@@ -0,0 +1,341 @@
+/**
+
+@file
+
+@brief   RTL2840 MAX3543 NIM module definition
+
+One can manipulate RTL2840 MAX3543 NIM through RTL2840 MAX3543 NIM module.
+RTL2840 MAX3543 NIM module is derived from QAM NIM module.
+
+*/
+
+
+#include "nim_rtl2840_max3543.h"
+
+
+
+
+
+/**
+
+@brief   RTL2840 MAX3543 NIM module builder
+
+Use BuildRtl2840Max3543Module() to build RTL2840 MAX3543 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                       Pointer to RTL2840 MAX3543 NIM module pointer
+@param [in]   pQamNimModuleMemory         Pointer to an allocated QAM NIM module memory
+@param [in]   I2cReadingByteNumMax        Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax        Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                     Basic I2C reading function pointer
+@param [in]   I2cWrite                    Basic I2C writing function pointer
+@param [in]   WaitMs                      Basic waiting function pointer
+@param [in]   DemodDeviceAddr             RTL2840 I2C device address
+@param [in]   DemodCrystalFreqHz          RTL2840 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode        RTL2840 TS interface mode for setting
+@param [in]   DemodEnhancementMode        RTL2840 enhancement mode for setting
+@param [in]   TunerDeviceAddr             MAX3543 I2C device address
+@param [in]   TunerCrystalFreqHz          MAX3543 crystal frequency in Hz
+
+
+@note
+	-# One should call BuildRtl2840Max3543Module() to build RTL2840 MAX3543 NIM module before using it.
+
+*/
+void
+BuildRtl2840Max3543Module(
+	QAM_NIM_MODULE **ppNim,							// QAM NIM dependence
+	QAM_NIM_MODULE *pQamNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,				// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,					// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodEnhancementMode,
+
+	unsigned char TunerDeviceAddr,					// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	)
+{
+	QAM_NIM_MODULE *pNim;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pQamNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+	// Set enhancement mode in NIM module.
+	pNim->EnhancementMode = DemodEnhancementMode;
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2840 QAM demod module.
+	BuildRtl2840Module(
+		&pNim->pDemod,
+		&pNim->QamDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodEnhancementMode
+		);
+
+	// Build MAX3543 tuner module.
+	BuildMax3543Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+		TunerCrystalFreqHz,
+		RTL2840_MAX3543_STANDARD_MODE_DEFAULT,
+		RTL2840_MAX3543_IF_FREQ_HZ_DEFAULT,
+		RTL2840_MAX3543_SAW_INPUT_TYPE_DEFAULT
+		);
+
+
+	// Set NIM module manipulating function pointers.
+	pNim->Initialize        = rtl2840_max3543_Initialize;
+	pNim->SetParameters     = rtl2840_max3543_SetParameters;
+
+	// Set NIM module manipulating function pointers with default.
+	pNim->GetNimType        = qam_nim_default_GetNimType;
+	pNim->GetParameters     = qam_nim_default_GetParameters;
+	pNim->IsSignalPresent   = qam_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = qam_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = qam_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = qam_nim_default_GetSignalQuality;
+	pNim->GetErrorRate      = qam_nim_default_GetErrorRate;
+	pNim->GetSnrDb          = qam_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = qam_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = qam_nim_default_GetCrOffsetHz;
+	pNim->UpdateFunction    = qam_nim_default_UpdateFunction;
+
+
+	// Set NIM type.
+	pNim->NimType = QAM_NIM_RTL2840_MAX3543;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2840_max3543_Initialize(
+	QAM_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2840_MAX3543_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,					Value
+		{QAM_OPT_RF_AAGC_DRIVE,			0x1		},
+		{QAM_OPT_IF_AAGC_DRIVE,			0x1		},
+		{QAM_OPT_RF_AAGC_OEN,			0x1		},
+		{QAM_OPT_IF_AAGC_OEN,			0x1		},
+		{QAM_RF_AAGC_MAX,				0xff	},
+		{QAM_RF_AAGC_MIN,				0x0		},
+		{QAM_IF_AAGC_MAX,				0xff	},
+		{QAM_IF_AAGC_MIN,				0x0		},
+		{QAM_AAGC_MODE_SEL,				0x0		},
+	};
+
+
+	QAM_DEMOD_MODULE *pDemod;
+	TUNER_MODULE *pTuner;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+	// Get demod module and tuner module.
+	pDemod = pNim->pDemod;
+	pTuner = pNim->pTuner;
+
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency in Hz with NIM default.
+	if(pDemod->SetIfFreqHz(pDemod, RTL2840_MAX3543_IF_FREQ_HZ_DEFAULT) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with NIM default.
+	if(pDemod->SetSpectrumMode(pDemod, RTL2840_MAX3543_SPECTRUM_MODE_DEFAULT) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod AAGC registers.
+	// Note: SetParameters() will set QAM_AAGC_TARGET and QAM_VTOP according to parameters.
+	for(i = 0; i < RTL2840_MAX3543_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2840_max3543_SetParameters(
+	QAM_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int QamMode,
+	unsigned long SymbolRateHz,
+	int AlphaMode
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	TUNER_MODULE *pTuner;
+
+
+	// Get demod module and tuner module.
+	pDemod = pNim->pDemod;
+	pTuner = pNim->pTuner;
+
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod QAM mode.
+	if(pDemod->SetQamMode(pDemod, QamMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod symbol rate in Hz.
+	if(pDemod->SetSymbolRateHz(pDemod, SymbolRateHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod alpha mode.
+	if(pDemod->SetAlphaMode(pDemod, AlphaMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Set demod QAM_AAGC_TARGET and QAM_VTOP according to QAM mode and enhancement mode.
+	switch(QamMode)
+	{
+		default:
+		case QAM_QAM_4:
+		case QAM_QAM_16:
+		case QAM_QAM_32:
+		case QAM_QAM_64:
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_VTOP, 0x3f) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			switch(pNim->EnhancementMode)
+			{
+				case QAM_DEMOD_EN_NONE:
+
+					if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_AAGC_TARGET, 0x6b) != FUNCTION_SUCCESS)
+						goto error_status_execute_function;
+
+					break;
+
+				default:
+				case QAM_DEMOD_EN_AM_HUM:
+
+					if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_AAGC_TARGET, 0x64) != FUNCTION_SUCCESS)
+						goto error_status_execute_function;
+
+					break;
+			}
+
+			break;
+
+		case QAM_QAM_128:
+		case QAM_QAM_256:
+		case QAM_QAM_512:
+		case QAM_QAM_1024:
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_VTOP, 0x38) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_AAGC_TARGET, 0x6b) != FUNCTION_SUCCESS)
+				goto error_status_execute_function;
+
+			break;
+	}
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2840_max3543.h b/drivers/media/usb/dvb-usb/nim_rtl2840_max3543.h
new file mode 100644
index 0000000..ff4ec2f
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2840_max3543.h
@@ -0,0 +1,146 @@
+#ifndef __NIM_RTL2840_MAX3543_H
+#define __NIM_RTL2840_MAX3543_H
+
+/**
+
+@file
+
+@brief   RTL2840 MAX3543 NIM module definition
+
+One can manipulate RTL2840 MAX3543 NIM through RTL2840 MAX3543 NIM module.
+RTL2840 MAX3543 NIM module is derived from QAM NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in qam_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2840_max3543.h"
+
+
+...
+
+
+
+int main(void)
+{
+	QAM_NIM_MODULE *pNim;
+	QAM_NIM_MODULE QamNimModuleMemory;
+
+	...
+
+
+
+	// Build RTL2840 MAX3543 NIM module.
+	BuildRtl2840Max3543Module(
+		&pNim,
+		&QamNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		0x44,							// The RTL2840 I2C device address is 0x44 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The RTL2840 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The RTL2840 TS interface mode is serial.
+		QAM_DEMOD_EN_AM_HUM,			// Use AM-hum enhancement mode.
+
+		0xc0,							// The MAX3543 I2C device address is 0xc0 in 8-bit format.
+		CRYSTAL_FREQ_16000000HZ			// The MAX3543 Crystal frequency is 16.0 MHz.
+		);
+
+
+
+	// See the example for other NIM functions in qam_nim_base.h
+	...
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2840.h"
+#include "tuner_max3543.h"
+#include "qam_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2840_MAX3543_ADDITIONAL_INIT_REG_TABLE_LEN		9
+
+// Default
+#define RTL2840_MAX3543_STANDARD_MODE_DEFAULT				MAX3543_STANDARD_QAM
+#define RTL2840_MAX3543_IF_FREQ_HZ_DEFAULT					IF_FREQ_36170000HZ
+#define RTL2840_MAX3543_SPECTRUM_MODE_DEFAULT				SPECTRUM_INVERSE
+#define RTL2840_MAX3543_SAW_INPUT_TYPE_DEFAULT				MAX3543_SAW_INPUT_SE
+
+
+
+
+
+// Builder
+void
+BuildRtl2840Max3543Module(
+	QAM_NIM_MODULE **ppNim,							// QAM NIM dependence
+	QAM_NIM_MODULE *pQamNimModuleMemory,
+
+	unsigned long I2cReadingByteNumMax,				// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,					// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodEnhancementMode,
+
+	unsigned char TunerDeviceAddr,					// Tuner dependence
+	unsigned long TunerCrystalFreqHz
+	);
+
+
+
+
+
+// RTL2840 MAX3543 NIM manipulaing functions
+int
+rtl2840_max3543_Initialize(
+	QAM_NIM_MODULE *pNim
+	);
+
+int
+rtl2840_max3543_SetParameters(
+	QAM_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int QamMode,
+	unsigned long SymbolRateHz,
+	int AlphaMode
+	);
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2840_mt2063.c b/drivers/media/usb/dvb-usb/nim_rtl2840_mt2063.c
new file mode 100644
index 0000000..3df31e6
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2840_mt2063.c
@@ -0,0 +1,307 @@
+/**
+
+@file
+
+@brief   RTL2840 MT2063 NIM module definition
+
+One can manipulate RTL2840 MT2063 NIM through RTL2840 MT2063 NIM module.
+RTL2840 MT2063 NIM module is derived from QAM NIM module.
+
+*/
+
+
+#include "nim_rtl2840_mt2063.h"
+
+
+
+
+
+/**
+
+@brief   RTL2840 MT2063 NIM module builder
+
+Use BuildRtl2840Mt2063Module() to build RTL2840 MT2063 NIM module, set all module function pointers with the
+corresponding functions, and initialize module private variables.
+
+
+@param [in]   ppNim                  Pointer to RTL2840 MT2063 NIM module pointer
+@param [in]   pQamNimModuleMemory    Pointer to an allocated QAM NIM module memory
+@param [in]   I2cReadingByteNumMax   Maximum I2C reading byte number for basic I2C reading function
+@param [in]   I2cWritingByteNumMax   Maximum I2C writing byte number for basic I2C writing function
+@param [in]   I2cRead                Basic I2C reading function pointer
+@param [in]   I2cWrite               Basic I2C writing function pointer
+@param [in]   WaitMs                 Basic waiting function pointer
+@param [in]   DemodDeviceAddr        RTL2840 I2C device address
+@param [in]   DemodCrystalFreqHz     RTL2840 crystal frequency in Hz
+@param [in]   DemodTsInterfaceMode   RTL2840 TS interface mode for setting
+@param [in]   DemodEnhancementMode   RTL2840 enhancement mode for setting
+@param [in]   TunerDeviceAddr        MT2063 I2C device address
+
+
+@note
+	-# One should call BuildRtl2840Mt2063Module() to build RTL2840 MT2063 NIM module before using it.
+
+*/
+void
+BuildRtl2840Mt2063Module(
+	QAM_NIM_MODULE **ppNim,								// QAM NIM dependence
+	QAM_NIM_MODULE *pQamNimModuleMemory,
+	unsigned long NimIfFreqHz,
+
+	unsigned long I2cReadingByteNumMax,					// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,						// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodEnhancementMode,
+
+	unsigned char TunerDeviceAddr						// Tuner dependence
+	)
+{
+	QAM_NIM_MODULE *pNim;
+	RTL2840_MT2063_EXTRA_MODULE *pNimExtra;
+
+
+
+	// Set NIM module pointer with NIM module memory.
+	*ppNim = pQamNimModuleMemory;
+	
+	// Get NIM module.
+	pNim = *ppNim;
+
+	// Set I2C bridge module pointer with I2C bridge module memory.
+	pNim->pI2cBridge = &pNim->I2cBridgeModuleMemory;
+
+	// Get NIM extra module.
+	pNimExtra = &(pNim->Extra.Rtl2840Mt2063);
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pNim->pBaseInterface,
+		&pNim->BaseInterfaceModuleMemory,
+		I2cReadingByteNumMax,
+		I2cWritingByteNumMax,
+		I2cRead,
+		I2cWrite,
+		WaitMs
+		);
+
+	// Build RTL2840 QAM demod module.
+	BuildRtl2840Module(
+		&pNim->pDemod,
+		&pNim->QamDemodModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		DemodDeviceAddr,
+		DemodCrystalFreqHz,
+		DemodTsInterfaceMode,
+		DemodEnhancementMode
+		);
+
+	// Build MT2063 tuner module.
+	BuildMt2063Module(
+		&pNim->pTuner,
+		&pNim->TunerModuleMemory,
+		&pNim->BaseInterfaceModuleMemory,
+		&pNim->I2cBridgeModuleMemory,
+		TunerDeviceAddr,
+//		MT2063_STANDARD_QAM,
+		MT2063_STANDARD_DVBT,
+		MT2063_VGAGC_0X1
+		);
+
+
+	// Set NIM module manipulating function pointers.
+	pNim->Initialize        = rtl2840_mt2063_Initialize;
+	pNim->SetParameters     = rtl2840_mt2063_SetParameters;
+
+	// Set NIM module manipulating function pointers with default.
+	pNim->GetNimType        = qam_nim_default_GetNimType;
+	pNim->GetParameters     = qam_nim_default_GetParameters;
+	pNim->IsSignalPresent   = qam_nim_default_IsSignalPresent;
+	pNim->IsSignalLocked    = qam_nim_default_IsSignalLocked;
+	pNim->GetSignalStrength = qam_nim_default_GetSignalStrength;
+	pNim->GetSignalQuality  = qam_nim_default_GetSignalQuality;
+	pNim->GetErrorRate      = qam_nim_default_GetErrorRate;
+	pNim->GetSnrDb          = qam_nim_default_GetSnrDb;
+	pNim->GetTrOffsetPpm    = qam_nim_default_GetTrOffsetPpm;
+	pNim->GetCrOffsetHz     = qam_nim_default_GetCrOffsetHz;
+	pNim->UpdateFunction    = qam_nim_default_UpdateFunction;
+
+
+	// Set NIM type.
+	pNim->NimType = QAM_NIM_RTL2840_MT2063;
+
+	// Set enhancement mode in NIM module.
+	pNim->EnhancementMode = DemodEnhancementMode;
+
+	// Set IF frequency variable in NIM extra module.
+	pNimExtra->IfFreqHz = NimIfFreqHz;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_INITIALIZE
+
+*/
+int
+rtl2840_mt2063_Initialize(
+	QAM_NIM_MODULE *pNim
+	)
+{
+	typedef struct
+	{
+		int RegBitName;
+		unsigned long Value;
+	}
+	REG_VALUE_ENTRY;
+
+
+	static const REG_VALUE_ENTRY AdditionalInitRegValueTable[RTL2840_MT2063_ADDITIONAL_INIT_REG_TABLE_LEN] =
+	{
+		// RegBitName,					Value
+		{QAM_OPT_RF_AAGC_DRIVE,			0x1		},
+		{QAM_OPT_IF_AAGC_DRIVE,			0x1		},
+		{QAM_OPT_RF_AAGC_OEN,			0x1		},
+		{QAM_OPT_IF_AAGC_OEN,			0x1		},
+		{QAM_RF_AAGC_MAX,				0x80	},
+		{QAM_RF_AAGC_MIN,				0x80	},
+		{QAM_IF_AAGC_MAX,				0xff	},
+		{QAM_IF_AAGC_MIN,				0x0		},
+		{QAM_AAGC_MODE_SEL,				0x0		},
+	};
+
+
+	TUNER_MODULE *pTuner;
+	QAM_DEMOD_MODULE *pDemod;
+	MT2063_EXTRA_MODULE *pTunerExtra;
+	RTL2840_MT2063_EXTRA_MODULE *pNimExtra;
+
+	int i;
+
+	int RegBitName;
+	unsigned long Value;
+
+
+	// Get modules.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+	pTunerExtra = &(pTuner->Extra.Mt2063);
+	pNimExtra = &(pNim->Extra.Rtl2840Mt2063);
+
+
+	// Initialize tuner.
+	if(pTuner->Initialize(pTuner) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set tuner IF frequency in Hz.
+	if(pTunerExtra->SetIfFreqHz(pTuner, pNimExtra->IfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Initialize demod.
+	if(pDemod->Initialize(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod IF frequency in Hz.
+	if(pDemod->SetIfFreqHz(pDemod, pNimExtra->IfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod spectrum mode with SPECTRUM_INVERSE.
+	if(pDemod->SetSpectrumMode(pDemod, SPECTRUM_INVERSE) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod AAGC registers.
+	// Note: SetParameters() will set QAM_AAGC_TARGET and QAM_VTOP according to parameters.
+	for(i = 0; i < RTL2840_MT2063_ADDITIONAL_INIT_REG_TABLE_LEN; i++)
+	{
+		// Get register bit name and its value.
+		RegBitName = AdditionalInitRegValueTable[i].RegBitName;
+		Value      = AdditionalInitRegValueTable[i].Value;
+
+		// Set demod registers
+		if(pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, RegBitName, Value) != FUNCTION_SUCCESS)
+			goto error_status_set_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_registers:
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_SET_PARAMETERS
+
+*/
+int
+rtl2840_mt2063_SetParameters(
+	QAM_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int QamMode,
+	unsigned long SymbolRateHz,
+	int AlphaMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module and tuner module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod QAM mode.
+	if(pDemod->SetQamMode(pDemod, QamMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod symbol rate in Hz.
+	if(pDemod->SetSymbolRateHz(pDemod, SymbolRateHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod alpha mode.
+	if(pDemod->SetAlphaMode(pDemod, AlphaMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/nim_rtl2840_mt2063.h b/drivers/media/usb/dvb-usb/nim_rtl2840_mt2063.h
new file mode 100644
index 0000000..0e4e673
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/nim_rtl2840_mt2063.h
@@ -0,0 +1,163 @@
+#ifndef __NIM_RTL2840_MT2063_H
+#define __NIM_RTL2840_MT2063_H
+
+/**
+
+@file
+
+@brief   RTL2840 MT2063 NIM module definition
+
+One can manipulate RTL2840 MT2063 NIM through RTL2840 MT2063 NIM module.
+RTL2840 MT2063 NIM module is derived from QAM NIM module.
+
+
+
+@par Example:
+@code
+
+// The example is the same as the NIM example in qam_nim_base.h except the listed lines.
+
+
+
+#include "nim_rtl2840_mt2063.h"
+
+
+...
+
+
+
+int main(void)
+{
+	QAM_NIM_MODULE *pNim;
+	QAM_NIM_MODULE QamNimModuleMemory;
+	TUNER_MODULE *pTuner;
+	MT2063_EXTRA_MODULE *pTunerExtra;
+
+	...
+
+
+
+	// Build RTL2840 MT2063 NIM module.
+	BuildRtl2840Mt2063Module(
+		&pNim,
+		&QamNimModuleMemory,
+		IF_FREQ_36125000HZ,					// The RTL2840 and MT2063 IF frequency is 36.125 MHz.
+
+		9,									// Maximum I2C reading byte number is 9.
+		8,									// Maximum I2C writing byte number is 8.
+		CustomI2cRead,						// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,						// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,						// Employ CustomWaitMs() as basic waiting function.
+
+		0x44,								// The RTL2840 I2C device address is 0x44 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,			// The RTL2840 crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,				// The RTL2840 TS interface mode is serial.
+		QAM_DEMOD_EN_AM_HUM,				// Use AM-hum enhancement mode.
+
+		0xc0								// The MT2063 I2C device address is 0xc0 in 8-bit format.
+		);
+
+
+
+
+
+	// Get MT2063 tuner extra module.
+	pTuner = pNim->pTuner;
+	pTunerExtra = &(pTuner->Extra.Mt2063);
+
+	// Open MT2063 handle.
+	pTunerExtra->OpenHandle(pTuner);
+
+
+
+
+
+	// See the example for other NIM functions in qam_nim_base.h
+	...
+
+
+
+
+
+	// Close MT2063 handle.
+	pTunerExtra->CloseHandle(pTuner);
+
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "demod_rtl2840.h"
+#include "tuner_mt2063.h"
+#include "qam_nim_base.h"
+
+
+
+
+
+// Definitions
+#define RTL2840_MT2063_ADDITIONAL_INIT_REG_TABLE_LEN		9
+
+
+
+
+
+// Builder
+void
+BuildRtl2840Mt2063Module(
+	QAM_NIM_MODULE **ppNim,							// QAM NIM dependence
+	QAM_NIM_MODULE *pQamNimModuleMemory,
+	unsigned long NimIfFreqHz,
+
+	unsigned long I2cReadingByteNumMax,				// Base interface dependence
+	unsigned long I2cWritingByteNumMax,
+	BASE_FP_I2C_READ I2cRead,
+	BASE_FP_I2C_WRITE I2cWrite,
+	BASE_FP_WAIT_MS WaitMs,
+
+	unsigned char DemodDeviceAddr,					// Demod dependence
+	unsigned long DemodCrystalFreqHz,
+	int DemodTsInterfaceMode,
+	int DemodEnhancementMode,
+
+	unsigned char TunerDeviceAddr					// Tuner dependence
+	);
+
+
+
+
+
+// RTL2840 MT2063 NIM manipulaing functions
+int
+rtl2840_mt2063_Initialize(
+	QAM_NIM_MODULE *pNim
+	);
+
+int
+rtl2840_mt2063_SetParameters(
+	QAM_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int QamMode,
+	unsigned long SymbolRateHz,
+	int AlphaMode
+	);
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/qam_demod_base.c b/drivers/media/usb/dvb-usb/qam_demod_base.c
new file mode 100644
index 0000000..8843ab5
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/qam_demod_base.c
@@ -0,0 +1,1289 @@
+/**
+
+@file
+
+@brief   QAM demod default function definition
+
+QAM demod default functions.
+
+*/
+
+#include "qam_demod_base.h"
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_REG_PAGE
+
+*/
+int
+qam_demod_addr_8bit_default_SetRegPage(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long PageNo
+	)
+{
+#if 0
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBytes[LEN_2_BYTE];
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Set demod register page with page number.
+	// Note: The I2C format of demod register page setting is as follows:
+	//       start_bit + (DeviceAddr | writing_bit) + QAM_DEMOD_PAGE_REG_ADDR + PageNo + stop_bit
+	WritingBytes[0] = QAM_DEMOD_PAGE_REG_ADDR;
+	WritingBytes[1] = (unsigned char)PageNo;
+
+	if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBytes, LEN_2_BYTE) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+#endif
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	struct dvb_usb_device	*d;
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+	
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);  //add by chialing
+
+	if( mutex_lock_interruptible(&d->usb_mutex) )	goto error;
+
+	 pDemod->CurrentPageNo = PageNo;
+
+	mutex_unlock(&d->usb_mutex);
+
+	return FUNCTION_SUCCESS;
+
+error:
+
+	return FUNCTION_ERROR;
+
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_REG_BYTES
+
+*/
+int
+qam_demod_addr_8bit_default_SetRegBytes(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+#if 0
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i, j;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBuffer[I2C_BUFFER_LEN];
+	unsigned long WritingByteNum, WritingByteNumMax, WritingByteNumRem;
+	unsigned char RegWritingAddr;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum writing byte number.
+	WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax - LEN_1_BYTE;
+
+
+	// Set demod register bytes with writing bytes.
+	// Note: Set demod register bytes considering maximum writing byte number.
+	for(i = 0; i < ByteNum; i += WritingByteNumMax)
+	{
+		// Set register writing address.
+		RegWritingAddr = (unsigned char)(RegStartAddr + i);
+
+		// Calculate remainder writing byte number.
+		WritingByteNumRem = ByteNum - i;
+
+		// Determine writing byte number.
+		WritingByteNum = (WritingByteNumRem > WritingByteNumMax) ? WritingByteNumMax : WritingByteNumRem;
+
+
+		// Set writing buffer.
+		// Note: The I2C format of demod register byte setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegWritingAddr + writing_bytes (WritingByteNum bytes) +
+		//       stop_bit
+		WritingBuffer[0] = RegWritingAddr;
+
+		for(j = 0; j < WritingByteNum; j++)
+			WritingBuffer[LEN_1_BYTE + j] = pWritingBytes[i + j];
+
+
+		// Set demod register bytes with writing buffer.
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, WritingByteNum + LEN_1_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+#endif
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned int i, j;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBuffer[I2C_BUFFER_LEN];
+	unsigned char WritingByteNum, WritingByteNumMax, WritingByteNumRem;
+	unsigned char RegWritingAddr;
+	unsigned long PageNo=0;
+
+
+	struct dvb_usb_device	*d;
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+	
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);  //add by chialing
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+	PageNo=pDemod->CurrentPageNo;
+	// Calculate maximum writing byte number.
+	WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax - LEN_1_BYTE;
+
+
+	// Set demod register bytes with writing bytes.
+	// Note: Set demod register bytes considering maximum writing byte number.
+	for(i = 0; i < ByteNum; i += WritingByteNumMax)
+	{
+		// Set register writing address.
+		RegWritingAddr = RegStartAddr + i;
+
+		// Calculate remainder writing byte number.
+		WritingByteNumRem = ByteNum - i;
+
+		// Determine writing byte number.
+		WritingByteNum = (WritingByteNumRem > WritingByteNumMax) ? WritingByteNumMax : WritingByteNumRem;
+
+
+		// Set writing buffer.
+
+		WritingBuffer[0] = RegWritingAddr;
+
+		for(j = 0; j < WritingByteNum; j++)
+			WritingBuffer[LEN_1_BYTE + j] = pWritingBytes[i + j];
+
+		
+		// Set demod register bytes with writing buffer.
+		if(write_demod_register(d, DeviceAddr, PageNo, WritingBuffer[0], WritingBuffer+1, WritingByteNum))
+			goto error_status_set_demod_registers;	
+
+		
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_REG_BYTES
+
+*/
+int
+qam_demod_addr_8bit_default_GetRegBytes(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+#if 0
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i;
+	unsigned char DeviceAddr;
+	unsigned long ReadingByteNum, ReadingByteNumMax, ReadingByteNumRem;
+	unsigned char RegReadingAddr;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum reading byte number.
+	ReadingByteNumMax = pBaseInterface->I2cReadingByteNumMax;
+
+
+	// Get demod register bytes.
+	// Note: Get demod register bytes considering maximum reading byte number.
+	for(i = 0; i < ByteNum; i += ReadingByteNumMax)
+	{
+		// Set register reading address.
+		RegReadingAddr = (unsigned char)(RegStartAddr + i);
+
+		// Calculate remainder reading byte number.
+		ReadingByteNumRem = ByteNum - i;
+
+		// Determine reading byte number.
+		ReadingByteNum = (ReadingByteNumRem > ReadingByteNumMax) ? ReadingByteNumMax : ReadingByteNumRem;
+
+
+		// Set demod register reading address.
+		// Note: The I2C format of demod register reading address setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegReadingAddr + stop_bit
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, &RegReadingAddr, LEN_1_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_register_reading_address;
+
+		// Get demod register bytes.
+		// Note: The I2C format of demod register byte getting is as follows:
+		//       start_bit + (DeviceAddr | reading_bit) + reading_bytes (ReadingByteNum bytes) + stop_bit
+		if(pBaseInterface->I2cRead(pBaseInterface, DeviceAddr, &pReadingBytes[i], ReadingByteNum) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_register_reading_address:
+	return FUNCTION_ERROR;
+#endif
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned int i;
+	unsigned char DeviceAddr;
+	unsigned char ReadingByteNum, ReadingByteNumMax, ReadingByteNumRem;
+	unsigned char RegReadingAddr;
+	unsigned long PageNo;
+
+
+	struct dvb_usb_device	*d;
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+	
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);  //add by chialing
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+	PageNo=pDemod->CurrentPageNo;
+
+
+	// Calculate maximum reading byte number.
+	ReadingByteNumMax = pBaseInterface->I2cReadingByteNumMax;
+
+
+	// Get demod register bytes.
+	// Note: Get demod register bytes considering maximum reading byte number.
+	for(i = 0; i < ByteNum; i += ReadingByteNumMax)
+	{
+		// Set register reading address.
+		RegReadingAddr = RegStartAddr + i;
+
+		// Calculate remainder reading byte number.
+		ReadingByteNumRem = ByteNum - i;
+
+		// Determine reading byte number.
+		ReadingByteNum = (ReadingByteNumRem > ReadingByteNumMax) ? ReadingByteNumMax : ReadingByteNumRem;
+
+		// Get demod register bytes.
+		if(read_demod_register(d, DeviceAddr, PageNo,  RegReadingAddr,  pReadingBytes, ReadingByteNum))
+			goto error_status_get_demod_registers;	
+
+		
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+//error_status_set_demod_register_reading_address:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_REG_MASK_BITS
+
+*/
+int
+qam_demod_addr_8bit_default_SetRegMaskBits(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+	unsigned char WritingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value LSB.
+	//       Put upper address byte on value MSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * i);
+
+
+	// Reserve unsigned integer value unmask bit with mask and inlay writing value into it.
+	Value &= ~Mask;
+	Value |= (WritingValue << Shift) & Mask;
+
+
+	// Separate unsigned integer value into writing bytes.
+	// Note: Pick up lower address byte from value LSB.
+	//       Pick up upper address byte from value MSB.
+	for(i = 0; i < ByteNum; i++)
+		WritingBytes[i] = (unsigned char)((Value >> (BYTE_SHIFT * i)) & BYTE_MASK);
+
+
+	// Write demod register bytes with writing bytes.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBytes(pDemod, RegStartAddr, WritingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_REG_MASK_BITS
+
+*/
+int
+qam_demod_addr_8bit_default_GetRegMaskBits(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value LSB.
+	//       Put upper address byte on value MSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * i);
+
+
+	// Get register bits from unsigned integaer value with mask and shift
+	*pReadingValue = (Value & Mask) >> Shift;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_REG_BITS
+
+*/
+int
+qam_demod_addr_8bit_default_SetRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	)
+{
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->BaseRegTable.Addr8Bit[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from base register table with register bit name key.
+	RegStartAddr = pDemod->BaseRegTable.Addr8Bit[RegBitName].RegStartAddr;
+	Msb          = pDemod->BaseRegTable.Addr8Bit[RegBitName].Msb;
+	Lsb          = pDemod->BaseRegTable.Addr8Bit[RegBitName].Lsb;
+
+
+	// Set register mask bits.
+	if(pDemod->RegAccess.Addr8Bit.SetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, WritingValue) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_REG_BITS
+
+*/
+int
+qam_demod_addr_8bit_default_GetRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->BaseRegTable.Addr8Bit[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from base register table with register bit name key.
+	RegStartAddr = pDemod->BaseRegTable.Addr8Bit[RegBitName].RegStartAddr;
+	Msb          = pDemod->BaseRegTable.Addr8Bit[RegBitName].Msb;
+	Lsb          = pDemod->BaseRegTable.Addr8Bit[RegBitName].Lsb;
+
+
+	// Get register mask bits.
+	if(pDemod->RegAccess.Addr8Bit.GetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, pReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_REG_BITS_WITH_PAGE
+
+*/
+int
+qam_demod_addr_8bit_default_SetRegBitsWithPage(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	)
+{
+	unsigned char PageNo;
+
+
+	// Get register page number from base register table with register bit name key.
+	PageNo = pDemod->BaseRegTable.Addr8Bit[RegBitName].PageNo;
+
+
+	// Set register page number.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Set register mask bits with register bit name key.
+	if(pDemod->RegAccess.Addr8Bit.SetRegBits(pDemod, RegBitName, WritingValue) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_REG_BITS_WITH_PAGE
+
+*/
+int
+qam_demod_addr_8bit_default_GetRegBitsWithPage(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	unsigned char PageNo;
+
+
+	// Get register page number from base register table with register bit name key.
+	PageNo = pDemod->BaseRegTable.Addr8Bit[RegBitName].PageNo;
+
+
+	// Set register page number.
+	if(pDemod->RegAccess.Addr8Bit.SetRegPage(pDemod, PageNo) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	// Get register mask bits with register bit name key.
+	if(pDemod->RegAccess.Addr8Bit.GetRegBits(pDemod, RegBitName, pReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_REG_BYTES
+
+*/
+int
+qam_demod_addr_16bit_default_SetRegBytes(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i, j;
+
+	unsigned char DeviceAddr;
+	unsigned char WritingBuffer[I2C_BUFFER_LEN];
+	unsigned long WritingByteNum, WritingByteNumMax, WritingByteNumRem;
+	unsigned short RegWritingAddr;
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum writing byte number.
+	WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax - LEN_1_BYTE;
+
+
+	// Set demod register bytes with writing bytes.
+	// Note: Set demod register bytes considering maximum writing byte number.
+	for(i = 0; i < ByteNum; i += WritingByteNumMax)
+	{
+		// Set register writing address.
+		RegWritingAddr = (unsigned short)(RegStartAddr + i);
+
+		// Calculate remainder writing byte number.
+		WritingByteNumRem = ByteNum - i;
+
+		// Determine writing byte number.
+		WritingByteNum = (WritingByteNumRem > WritingByteNumMax) ? WritingByteNumMax : WritingByteNumRem;
+
+
+		// Set writing buffer.
+		// Note: The I2C format of demod register byte setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegWritingAddrMsb + RegWritingAddrLsb +
+		//       writing_bytes (WritingByteNum bytes) + stop_bit
+		WritingBuffer[0] = (RegWritingAddr >> BYTE_SHIFT) & BYTE_MASK;
+		WritingBuffer[1] = RegWritingAddr & BYTE_MASK;
+
+		for(j = 0; j < WritingByteNum; j++)
+			WritingBuffer[LEN_2_BYTE + j] = pWritingBytes[i + j];
+
+
+		// Set demod register bytes with writing buffer.
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, WritingByteNum + LEN_2_BYTE) !=
+			FUNCTION_SUCCESS)
+			goto error_status_set_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_REG_BYTES
+
+*/
+int
+qam_demod_addr_16bit_default_GetRegBytes(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+
+	unsigned long i;
+	unsigned char DeviceAddr;
+	unsigned long ReadingByteNum, ReadingByteNumMax, ReadingByteNumRem;
+	unsigned short RegReadingAddr;
+	unsigned char WritingBuffer[LEN_2_BYTE];
+
+
+
+	// Get base interface.
+	pBaseInterface = pDemod->pBaseInterface;
+
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+
+	// Calculate maximum reading byte number.
+	ReadingByteNumMax = pBaseInterface->I2cReadingByteNumMax;
+
+
+	// Get demod register bytes.
+	// Note: Get demod register bytes considering maximum reading byte number.
+	for(i = 0; i < ByteNum; i += ReadingByteNumMax)
+	{
+		// Set register reading address.
+		RegReadingAddr = (unsigned short)(RegStartAddr + i);
+
+		// Calculate remainder reading byte number.
+		ReadingByteNumRem = ByteNum - i;
+
+		// Determine reading byte number.
+		ReadingByteNum = (ReadingByteNumRem > ReadingByteNumMax) ? ReadingByteNumMax : ReadingByteNumRem;
+
+
+		// Set demod register reading address.
+		// Note: The I2C format of demod register reading address setting is as follows:
+		//       start_bit + (DeviceAddr | writing_bit) + RegReadingAddrMsb + RegReadingAddrLsb + stop_bit
+		WritingBuffer[0] = (RegReadingAddr >> BYTE_SHIFT) & BYTE_MASK;
+		WritingBuffer[1] = RegReadingAddr & BYTE_MASK;
+
+		if(pBaseInterface->I2cWrite(pBaseInterface, DeviceAddr, WritingBuffer, LEN_2_BYTE) != FUNCTION_SUCCESS)
+			goto error_status_set_demod_register_reading_address;
+
+		// Get demod register bytes.
+		// Note: The I2C format of demod register byte getting is as follows:
+		//       start_bit + (DeviceAddr | reading_bit) + reading_bytes (ReadingByteNum bytes) + stop_bit
+		if(pBaseInterface->I2cRead(pBaseInterface, DeviceAddr, &pReadingBytes[i], ReadingByteNum) != FUNCTION_SUCCESS)
+			goto error_status_get_demod_registers;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_register_reading_address:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_REG_MASK_BITS
+
+*/
+int
+qam_demod_addr_16bit_default_SetRegMaskBits(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+	unsigned char WritingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->RegAccess.Addr16Bit.GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value LSB.
+	//       Put upper address byte on value MSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * i);
+
+
+	// Reserve unsigned integer value unmask bit with mask and inlay writing value into it.
+	Value &= ~Mask;
+	Value |= (WritingValue << Shift) & Mask;
+
+
+	// Separate unsigned integer value into writing bytes.
+	// Note: Pick up lower address byte from value LSB.
+	//       Pick up upper address byte from value MSB.
+	for(i = 0; i < ByteNum; i++)
+		WritingBytes[i] = (unsigned char)((Value >> (BYTE_SHIFT * i)) & BYTE_MASK);
+
+
+	// Write demod register bytes with writing bytes.
+	if(pDemod->RegAccess.Addr16Bit.SetRegBytes(pDemod, RegStartAddr, WritingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_REG_MASK_BITS
+
+*/
+int
+qam_demod_addr_16bit_default_GetRegMaskBits(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	)
+{
+	int i;
+
+	unsigned char ReadingBytes[LEN_4_BYTE];
+
+	unsigned char ByteNum;
+	unsigned long Mask;
+	unsigned char Shift;
+
+	unsigned long Value;
+
+
+	// Calculate writing byte number according to MSB.
+	ByteNum = Msb / BYTE_BIT_NUM + LEN_1_BYTE;
+
+
+	// Generate mask and shift according to MSB and LSB.
+	Mask = 0;
+
+	for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
+		Mask |= 0x1 << i;
+
+	Shift = Lsb;
+
+
+	// Get demod register bytes according to register start adddress and byte number.
+	if(pDemod->RegAccess.Addr16Bit.GetRegBytes(pDemod, RegStartAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	// Combine reading bytes into an unsigned integer value.
+	// Note: Put lower address byte on value LSB.
+	//       Put upper address byte on value MSB.
+	Value = 0;
+
+	for(i = 0; i < ByteNum; i++)
+		Value |= (unsigned long)ReadingBytes[i] << (BYTE_SHIFT * i);
+
+
+	// Get register bits from unsigned integaer value with mask and shift
+	*pReadingValue = (Value & Mask) >> Shift;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_SET_REG_BITS
+
+*/
+int
+qam_demod_addr_16bit_default_SetRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	)
+{
+	unsigned short RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->BaseRegTable.Addr16Bit[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from base register table with register bit name key.
+	RegStartAddr = pDemod->BaseRegTable.Addr16Bit[RegBitName].RegStartAddr;
+	Msb          = pDemod->BaseRegTable.Addr16Bit[RegBitName].Msb;
+	Lsb          = pDemod->BaseRegTable.Addr16Bit[RegBitName].Lsb;
+
+
+	// Set register mask bits.
+	if(pDemod->RegAccess.Addr16Bit.SetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, WritingValue) != FUNCTION_SUCCESS)
+		goto error_status_set_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_set_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_REG_BITS
+
+*/
+int
+qam_demod_addr_16bit_default_GetRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	)
+{
+	unsigned short RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+
+
+	// Check if register bit name is available.
+	if(pDemod->BaseRegTable.Addr16Bit[RegBitName].IsAvailable == NO)
+		goto error_status_register_bit_name;
+
+
+	// Get register start address, MSB, and LSB from base register table with register bit name key.
+	RegStartAddr = pDemod->BaseRegTable.Addr16Bit[RegBitName].RegStartAddr;
+	Msb          = pDemod->BaseRegTable.Addr16Bit[RegBitName].Msb;
+	Lsb          = pDemod->BaseRegTable.Addr16Bit[RegBitName].Lsb;
+
+
+	// Get register mask bits.
+	if(pDemod->RegAccess.Addr16Bit.GetRegMaskBits(pDemod, RegStartAddr, Msb, Lsb, pReadingValue) != FUNCTION_SUCCESS)
+		goto error_status_get_demod_registers;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_register_bit_name:
+error_status_get_demod_registers:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_DEMOD_TYPE
+
+*/
+void
+qam_demod_default_GetDemodType(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pDemodType
+	)
+{
+	// Get demod type from demod module.
+	*pDemodType = pDemod->DemodType;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_DEVICE_ADDR
+
+*/
+void
+qam_demod_default_GetDeviceAddr(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char *pDeviceAddr
+	)
+{
+	// Get demod I2C device address from demod module.
+	*pDeviceAddr = pDemod->DeviceAddr;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_CRYSTAL_FREQ_HZ
+
+*/
+void
+qam_demod_default_GetCrystalFreqHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pCrystalFreqHz
+	)
+{
+	// Get demod crystal frequency in Hz from demod module.
+	*pCrystalFreqHz = pDemod->CrystalFreqHz;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_QAM_MODE
+
+*/
+int
+qam_demod_default_GetQamMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pQamMode
+	)
+{
+	// Get demod QAM mode from demod module.
+	if(pDemod->IsQamModeSet != YES)
+		goto error_status_get_demod_qam_mode;
+
+	*pQamMode = pDemod->QamMode;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_qam_mode:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_SYMBOL_RATE_HZ
+
+*/
+int
+qam_demod_default_GetSymbolRateHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pSymbolRateHz
+	)
+{
+	// Get demod symbol rate in Hz from demod module.
+	if(pDemod->IsSymbolRateHzSet != YES)
+		goto error_status_get_demod_symbol_rate;
+
+	*pSymbolRateHz = pDemod->SymbolRateHz;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_symbol_rate:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_ALPHA_MODE
+
+*/
+int
+qam_demod_default_GetAlphaMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAlphaMode
+	)
+{
+	// Get demod alpha mode from demod module.
+	if(pDemod->IsAlphaModeSet != YES)
+		goto error_status_get_demod_alpha_mode;
+
+	*pAlphaMode = pDemod->AlphaMode;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_alpha_mode:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_IF_FREQ_HZ
+
+*/
+int
+qam_demod_default_GetIfFreqHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pIfFreqHz
+	)
+{
+	// Get demod IF frequency in Hz from demod module.
+	if(pDemod->IsIfFreqHzSet != YES)
+		goto error_status_get_demod_if_frequency;
+
+	*pIfFreqHz = pDemod->IfFreqHz;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_if_frequency:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_DEMOD_FP_GET_SPECTRUM_MODE
+
+*/
+int
+qam_demod_default_GetSpectrumMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pSpectrumMode
+	)
+{
+	// Get demod spectrum mode from demod module.
+	if(pDemod->IsSpectrumModeSet != YES)
+		goto error_status_get_demod_spectrum_mode;
+
+	*pSpectrumMode = pDemod->SpectrumMode;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_get_demod_spectrum_mode:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/qam_demod_base.h b/drivers/media/usb/dvb-usb/qam_demod_base.h
new file mode 100644
index 0000000..ae292d8
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/qam_demod_base.h
@@ -0,0 +1,2818 @@
+#ifndef __QAM_DEMOD_BASE_H
+#define __QAM_DEMOD_BASE_H
+
+/**
+
+@file
+
+@brief   QAM demod base module definition
+
+QAM demod base module definitions contains demod module structure, demod funciton pointers, and demod definitions.
+
+
+
+@par Example:
+@code
+
+
+#include "demod_xxx.h"
+
+
+
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C reading format:
+	// start_bit + (DeviceAddr | reading_bit) + reading_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+int
+CustomI2cWrite(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C writing format:
+	// start_bit + (DeviceAddr | writing_bit) + writing_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+void
+CustomWaitMs(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned long WaitTimeMs
+	)
+{
+	// Wait WaitTimeMs milliseconds.
+
+	...
+
+	return;
+}
+
+
+
+int main(void)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;
+
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE QamDemodModuleMemory;
+
+	I2C_BRIDGE_MODULE I2cBridgeModuleMemory;
+
+	int QamMode;
+	unsigned long SymbolRateHz;
+	int AlphaMode;
+	unsigned long IfFreqHz;
+	int SpectrumMode;
+
+	int DemodType;
+	unsigned char DeviceAddr;
+	unsigned long CrystalFreqHz;
+
+	long RfAgc, IfAgc;
+	unsigned long DiAgc;
+
+	int Answer;
+	long TrOffsetPpm, CrOffsetHz;
+	unsigned long BerNum, BerDen, PerNum, PerDen;
+	double Ber, Per;
+	long SnrDbNum, SnrDbDen;
+	double SnrDb;
+	unsigned long SignalStrength, SignalQuality;
+
+
+
+	// Build base interface module.
+	BuildBaseInterface(
+		&pBaseInterface,
+		&BaseInterfaceModuleMemory,
+		9,								// Set maximum I2C reading byte number with 9.
+		8,								// Set maximum I2C writing byte number with 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs					// Employ CustomWaitMs() as basic waiting function.
+		);
+
+
+	// Build QAM demod XXX module.
+	BuildXxxModule(
+		&pDemod,
+		&QamDemodModuleMemory,
+		&BaseInterfaceModuleMemory,
+		&I2cBridgeModuleMemory,
+		0x44,							// Demod I2C device address is 0x44 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// Demod crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// Demod TS interface mode is serial.
+		...								// Other arguments by each demod module
+		);
+
+
+
+
+
+	// ==== Initialize QAM demod and set its parameters =====
+
+	// Initialize demod.
+	pDemod->Initialize(pDemod);
+
+
+	// Set demod parameters. (QAM mode, symbol rate, alpha mode, IF frequency, spectrum mode)
+	// Note: In the example:
+	//       1. QAM is 64.
+	//       2. Symbol rate is 6.952 MHz.
+	//       3. Alpha is 0.15.
+	//       4. IF frequency is 36 MHz.
+	//       5. Spectrum mode is SPECTRUM_INVERSE.
+	QamMode      = QAM_QAM_64;
+	SymbolRateHz = 6952000;
+	AlphaMode    = QAM_ALPHA_0P15;
+	IfFreqHz     = IF_FREQ_36000000HZ;
+	SpectrumMode = SPECTRUM_INVERSE;
+
+	pDemod->SetQamMode(pDemod,      QamMode);
+	pDemod->SetSymbolRateHz(pDemod, SymbolRateHz);
+	pDemod->SetAlphaMode(pDemod,    AlphaMode);
+	pDemod->SetIfFreqHz(pDemod,     IfFreqHz);
+	pDemod->SetSpectrumMode(pDemod, SpectrumMode);
+
+
+	// Need to set tuner before demod software reset.
+	// The order to set demod and tuner is not important.
+	// Note: 1. For 8-bit register address demod, one can use
+	//          "pDemod->RegAccess.Addr8Bit.SetRegBitsWithPage(pDemod, QAM_OPT_I2C_RELAY, 0x1);"
+	//          for tuner I2C command forwarding.
+	//       2. For 16-bit register address demod, one can use
+	//          "pDemod->RegAccess.Addr16Bit.SetRegBits(pDemod, QAM_OPT_I2C_RELAY, 0x1);"
+	//       for tuner I2C command forwarding.
+
+
+	// Reset demod by software reset.
+	pDemod->SoftwareReset(pDemod);
+
+
+	// Wait maximum 1000 ms for demod converge.
+	for(i = 0; i < 25; i++)
+	{
+		// Wait 40 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 40);
+
+		// Check signal lock status through frame lock.
+		// Note: If Answer is YES, frame is locked.
+		//       If Answer is NO, frame is not locked.
+		pDemod->IsFrameLocked(pDemod, &Answer);
+
+		if(Answer == YES)
+		{
+			// Signal is locked.
+			break;
+		}
+	}
+
+
+
+
+
+	// ==== Get QAM demod information =====
+
+	// Get demod type.
+	// Note: One can find demod type in MODULE_TYPE enumeration.
+	pDemod->GetDemodType(pDemod, &DemodType);
+
+	// Get demod I2C device address.
+	pDemod->GetDeviceAddr(pDemod, &DeviceAddr);
+
+	// Get demod crystal frequency in Hz.
+	pDemod->GetCrystalFreqHz(pDemod, &CrystalFreqHz);
+
+
+	// Ask demod if it is connected to I2C bus.
+	// Note: If Answer is YES, demod is connected to I2C bus.
+	//       If Answer is NO, demod is not connected to I2C bus.
+	pDemod->IsConnectedToI2c(pDemod, &Answer);
+
+
+	// Get demod parameters. (QAM mode, symbol rate, alpha mode, IF frequency, spectrum mode)
+	pDemod->GetQamMode(pDemod,      &QamMode);
+	pDemod->GetSymbolRateHz(pDemod, &SymbolRateHz);
+	pDemod->GetAlphaMode(pDemod,    &AlphaMode);
+	pDemod->GetIfFreqHz(pDemod,     &IfFreqHz);
+	pDemod->GetSpectrumMode(pDemod, &SpectrumMode);
+
+
+	// Get demod AGC value.
+	// Note: The range of RF AGC and IF AGC value is -1024 ~ 1023.
+	//       The range of digital AGC value is 0 ~ 134217727.
+	pDemod->GetRfAgc(pDemod, &RfAgc);
+	pDemod->GetIfAgc(pDemod, &IfAgc);
+	pDemod->GetDiAgc(pDemod, &DiAgc);
+
+
+	// Get demod lock status.
+	// Note: If Answer is YES, it is locked.
+	//       If Answer is NO, it is not locked.
+	pDemod->IsAagcLocked(pDemod,  &Answer);
+	pDemod->IsEqLocked(pDemod,    &Answer);
+	pDemod->IsFrameLocked(pDemod, &Answer);
+
+
+	// Get TR offset (symbol timing offset) in ppm.
+	pDemod->GetTrOffsetPpm(pDemod, &TrOffsetPpm);
+
+	// Get CR offset (RF frequency offset) in Hz.
+	pDemod->GetCrOffsetHz(pDemod, &CrOffsetHz);
+
+
+	// Get BER and PER.
+	// Note: Test packet number = pow(2, (2 * 5 + 4)) = 16384
+	//       Maximum wait time  = 1000 ms = 1 second
+	pDemod->GetErrorRate(pDemod, 5, 1000, &BerNum, &BerDen, &PerNum, &PerDen);
+	Ber = (double)BerNum / (double)BerDen;
+	Per = (double)PerNum / (double)PerDen;
+
+	// Get SNR in dB.
+	pDemod->GetSnrDb(pDemod, &SnrDbNum, &SnrDbDen);
+	SnrDb = (double)SnrDbNum / (double)SnrDbDen;
+
+
+	// Get signal strength.
+	// Note: 1. The range of SignalStrength is 0~100.
+	//       2. Need to map SignalStrength value to UI signal strength bar manually.
+	pDemod->GetSignalStrength(pDemod, &SignalStrength);
+
+	// Get signal quality.
+	// Note: 1. The range of SignalQuality is 0~100.
+	//       2. Need to map SignalQuality value to UI signal quality bar manually.
+	pDemod->GetSignalQuality(pDemod, &SignalQuality);
+
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "foundation.h"
+
+
+
+
+
+// Definitions
+
+// Page register address
+#define QAM_DEMOD_PAGE_REG_ADDR					0x0
+
+
+/// QAM QAM modes
+enum QAM_QAM_MODE
+{
+	QAM_QAM_4,					///<   QPSK
+	QAM_QAM_16,					///<   16 QAM
+	QAM_QAM_32,					///<   32 QAM
+	QAM_QAM_64,					///<   64 QAM
+	QAM_QAM_128,				///<   128 QAM
+	QAM_QAM_256,				///<   256 QAM
+	QAM_QAM_512,				///<   512 QAM
+	QAM_QAM_1024,				///<   1024 QAM
+};
+#define QAM_QAM_MODE_NUM			8
+
+
+/// QAM alpha modes
+enum QAM_ALPHA_MODE
+{
+	QAM_ALPHA_0P12,				///<   Alpha = 0.12
+	QAM_ALPHA_0P13,				///<   Alpha = 0.13
+	QAM_ALPHA_0P15,				///<   Alpha = 0.15
+	QAM_ALPHA_0P18,				///<   Alpha = 0.18
+	QAM_ALPHA_0P20,				///<   Alpha = 0.20
+};
+#define QAM_ALPHA_MODE_NUM			5
+
+
+/// QAM demod enhancement modes
+enum QAM_DEMOD_EN_MODE
+{
+	QAM_DEMOD_EN_NONE,			///<   None demod enhancement
+	QAM_DEMOD_EN_AM_HUM,		///<   AM-hum demod enhancement
+};
+#define QAM_DEMOD_EN_MODE_NUM		2
+
+
+/// QAM demod configuration mode
+enum QAM_DEMOD_CONFIG_MODE
+{
+	QAM_DEMOD_CONFIG_OC,			///<   OpenCable demod configuration
+	QAM_DEMOD_CONFIG_DVBC,			///<   DVB-C demod configuration
+};
+#define QAM_DEMOD_CONFIG_MODE_NUM		2
+
+
+
+
+
+// Register entry definitions
+
+// Base register entry for 8-bit address
+typedef struct
+{
+	int IsAvailable;
+	unsigned char PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+QAM_BASE_REG_ENTRY_ADDR_8BIT;
+
+
+
+// Primary base register entry for 8-bit address
+typedef struct
+{
+	int RegBitName;
+	unsigned char PageNo;
+	unsigned char RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+QAM_PRIMARY_BASE_REG_ENTRY_ADDR_8BIT;
+
+
+
+// Monitor register entry for 8-bit address
+#define QAM_MONITOR_REG_INFO_TABLE_LEN		2
+typedef struct
+{
+	int IsAvailable;
+	unsigned char      InfoNum;
+
+	struct
+	{
+		unsigned char SelRegAddr;
+		unsigned char SelValue;
+		int           RegBitName;
+		unsigned char Shift;
+	}
+	InfoTable[QAM_MONITOR_REG_INFO_TABLE_LEN];
+}
+QAM_MONITOR_REG_ENTRY_ADDR_8BIT;
+
+
+
+// Primary monitor register entry for 8-bit address
+typedef struct
+{
+	int MonitorRegBitName;
+	unsigned char      InfoNum;
+
+	struct
+	{
+		unsigned char SelRegAddr;
+		unsigned char SelValue;
+		int           RegBitName;
+		unsigned char Shift;
+	}
+	InfoTable[QAM_MONITOR_REG_INFO_TABLE_LEN];
+}
+QAM_PRIMARY_MONITOR_REG_ENTRY_ADDR_8BIT;
+
+
+
+// Base register entry for 16-bit address
+typedef struct
+{
+	int IsAvailable;
+	unsigned short RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+QAM_BASE_REG_ENTRY_ADDR_16BIT;
+
+
+
+// Primary base register entry for 16-bit address
+typedef struct
+{
+	int RegBitName;
+	unsigned short RegStartAddr;
+	unsigned char Msb;
+	unsigned char Lsb;
+}
+QAM_PRIMARY_BASE_REG_ENTRY_ADDR_16BIT;
+
+
+
+// Monitor register entry for 16-bit address
+#define QAM_MONITOR_REG_INFO_TABLE_LEN		2
+typedef struct
+{
+	int IsAvailable;
+	unsigned char InfoNum;
+
+	struct
+	{
+		unsigned short SelRegAddr;
+		unsigned char SelValue;
+		int RegBitName;
+		unsigned char Shift;
+	}
+	InfoTable[QAM_MONITOR_REG_INFO_TABLE_LEN];
+}
+QAM_MONITOR_REG_ENTRY_ADDR_16BIT;
+
+
+
+// Primary monitor register entry for 16-bit address
+typedef struct
+{
+	int MonitorRegBitName;
+	unsigned char InfoNum;
+
+	struct
+	{
+		unsigned short SelRegAddr;
+		unsigned char SelValue;
+		int RegBitName;
+		unsigned char Shift;
+	}
+	InfoTable[QAM_MONITOR_REG_INFO_TABLE_LEN];
+}
+QAM_PRIMARY_MONITOR_REG_ENTRY_ADDR_16BIT;
+
+
+
+
+
+// Register bit name definitions
+
+/// Base register bit name
+enum QAM_REG_BIT_NAME
+{
+	// Generality
+	QAM_SYS_VERSION,
+	QAM_OPT_I2C_RELAY,
+	QAM_I2CT_EN_CTRL,						// for RTL2836B DVB-C only
+	QAM_SOFT_RESET,
+	QAM_SOFT_RESET_FF,
+
+	// Miscellany
+	QAM_OPT_I2C_DRIVE_CURRENT,
+	QAM_GPIO2_OEN,
+	QAM_GPIO3_OEN,
+	QAM_GPIO2_O,
+	QAM_GPIO3_O,
+	QAM_GPIO2_I,
+	QAM_GPIO3_I,
+	QAM_INNER_DATA_STROBE,
+	QAM_INNER_DATA_SEL1,
+	QAM_INNER_DATA_SEL2,
+	QAM_INNER_DATA1,
+	QAM_INNER_DATA2,
+
+	// QAM mode
+	QAM_QAM_MODE,
+
+	// AD
+	QAM_AD_AV,								// for RTL2840 only
+
+	// AAGC
+	QAM_OPT_RF_AAGC_DRIVE_CURRENT,			// for RTL2840, RTD2885 QAM only
+	QAM_OPT_IF_AAGC_DRIVE_CURRENT,			// for RTL2840, RTD2885 QAM only
+	QAM_AGC_DRIVE_LV,						// for RTL2836B DVB-C only
+	QAM_DVBC_RSSI_R,						// for RTL2836B DVB-C only
+	QAM_OPT_RF_AAGC_DRIVE,
+	QAM_OPT_IF_AAGC_DRIVE,
+	QAM_OPT_RF_AAGC_OEN,					// for RTL2840 only
+	QAM_OPT_IF_AAGC_OEN,					// for RTL2840 only
+	QAM_PAR_RF_SD_IB,
+	QAM_PAR_IF_SD_IB,
+	QAM_AAGC_FZ_OPTION,
+	QAM_AAGC_TARGET,
+	QAM_RF_AAGC_MAX,
+	QAM_RF_AAGC_MIN,
+	QAM_IF_AAGC_MAX,
+	QAM_IF_AAGC_MIN,
+	QAM_VTOP,
+	QAM_KRF,								// for RTD2885 QAM only
+	QAM_KRF_MSB,
+	QAM_KRF_LSB,
+	QAM_AAGC_MODE_SEL,
+	QAM_AAGC_LD,
+	QAM_OPT_RF_AAGC_OE,						// for RTL2820 OpenCable, RTD2885 QAM only
+	QAM_OPT_IF_AAGC_OE,						// for RTL2820 OpenCable, RTD2885 QAM only
+	QAM_IF_AGC_DRIVING,						// for RTL2820 OpenCable only
+	QAM_RF_AGC_DRIVING,						// for RTL2820 OpenCable only
+	QAM_AAGC_INIT_LEVEL,
+
+	// DDC
+	QAM_DDC_FREQ,
+	QAM_SPEC_INV,
+
+	// Timing recovery
+	QAM_TR_DECI_RATIO,
+
+	// Carrier recovery
+	QAM_CR_LD,
+
+	// Equalizer
+	QAM_EQ_LD,
+	QAM_MSE,
+
+	// Frame sync. indicator
+	QAM_SYNCLOST,							// for RTL2840, RTD2885 QAM only
+	QAM_FS_SYNC_STROBE,						// for RTL2820 OpenCable, RTD2885 QAM only
+	QAM_FS_SYNC_LOST,						// for RTL2820 OpenCable, RTD2885 QAM only
+	QAM_OC_MPEG_SYNC_MODE,
+
+
+	// BER
+	QAM_BER_RD_STROBE,
+	QAM_BERT_EN,
+	QAM_BERT_HOLD,
+	QAM_DIS_AUTO_MODE,
+	QAM_TEST_VOLUME,
+	QAM_BER_REG0,
+	QAM_BER_REG1,
+	QAM_BER_REG2_15_0,
+	QAM_BER_REG2_18_16,
+
+	QAM_OC_BER_RD_STROBE,					// for RTD2885 QAM only
+	QAM_OC_BERT_EN,							// for RTD2885 QAM only
+	QAM_OC_BERT_HOLD,						// for RTD2885 QAM only
+	QAM_OC_DIS_AUTO_MODE,					// for RTD2885 QAM only
+	QAM_OC_TEST_VOLUME,						// for RTD2885 QAM only
+	QAM_OC_BER_REG0,						// for RTD2885 QAM only
+	QAM_OC_BER_REG1,						// for RTD2885 QAM only
+	QAM_OC_BER_REG2_15_0,					// for RTD2885 QAM only
+	QAM_OC_BER_REG2_18_16,					// for RTD2885 QAM only
+
+	QAM_DVBC_BER_RD_STROBE,					// for RTD2885 QAM only
+	QAM_DVBC_BERT_EN,						// for RTD2885 QAM only
+	QAM_DVBC_BERT_HOLD,						// for RTD2885 QAM only
+	QAM_DVBC_DIS_AUTO_MODE,					// for RTD2885 QAM only
+	QAM_DVBC_TEST_VOLUME,					// for RTD2885 QAM only
+	QAM_DVBC_BER_REG0,						// for RTD2885 QAM only
+	QAM_DVBC_BER_REG1,						// for RTD2885 QAM only
+	QAM_DVBC_BER_REG2_15_0,					// for RTD2885 QAM only
+	QAM_DVBC_BER_REG2_18_16,				// for RTD2885 QAM only
+
+
+	// MPEG TS output interface
+	QAM_OPT_MPEG_OUT_SEL,					// for RTD2648 QAM only
+	QAM_CKOUTPAR,
+	QAM_CKOUT_PWR,
+	QAM_CDIV_PH0,
+	QAM_CDIV_PH1,
+	QAM_MPEG_OUT_EN,						// for RTL2840 only
+	QAM_OPT_MPEG_DRIVE_CURRENT,				// for RTL2840 only
+	QAM_NO_REINVERT,						// for RTL2840 only
+	QAM_FIX_TEI,							// for RTL2840 only
+	QAM_SERIAL,								// for RTL2840 only
+	QAM_OPT_MPEG_IO,						// for RTL2820 OpenCable, RTD2885 QAM only
+	QAM_OPT_M_OEN,							// for RTL2820 OpenCable, RTD2885 QAM only
+	QAM_REPLA_SD_EN,						// for RTL2820 OpenCable only
+	QAM_TEI_SD_ERR_EN,						// for RTL2820 OpenCable only
+	QAM_TEI_RS_ERR_EN,						// for RTL2820 OpenCable only
+	QAM_SET_MPEG_ERR,						// for RTL2820 OpenCable only
+
+	QAM_OC_CKOUTPAR,						// for RTD2885 QAM only
+	QAM_OC_CKOUT_PWR,						// for RTD2885 QAM only
+	QAM_OC_CDIV_PH0,						// for RTD2885 QAM only
+	QAM_OC_CDIV_PH1,						// for RTD2885 QAM only
+	QAM_OC_SERIAL,							// for RTD2885 QAM only
+
+	QAM_DVBC_CKOUTPAR,						// for RTD2885 QAM, RTL2836B DVB-C only
+	QAM_DVBC_CKOUT_PWR,						// for RTD2885 QAM, RTL2836B DVB-C only
+	QAM_DVBC_CDIV_PH0,						// for RTD2885 QAM, RTL2836B DVB-C only
+	QAM_DVBC_CDIV_PH1,						// for RTD2885 QAM, RTL2836B DVB-C only
+	QAM_DVBC_NO_REINVERT,					// for RTD2885 QAM, RTL2836B DVB-C only
+	QAM_DVBC_FIX_TEI,						// for RTD2885 QAM, RTL2836B DVB-C only
+	QAM_DVBC_SERIAL,						// for RTD2885 QAM, RTL2836B DVB-C only
+
+
+	// Monitor
+	QAM_ADC_CLIP_CNT_REC,
+	QAM_DAGC_LEVEL_26_11,
+	QAM_DAGC_LEVEL_10_0,
+	QAM_RF_AAGC_SD_IN,
+	QAM_IF_AAGC_SD_IN,
+	QAM_KI_TR_OUT_30_15,
+	QAM_KI_TR_OUT_14_0,
+	QAM_KI_CR_OUT_15_0,
+	QAM_KI_CR_OUT_31_16,
+
+	// Specific register
+	QAM_SPEC_SIGNAL_INDICATOR,
+	QAM_SPEC_ALPHA_STROBE,
+	QAM_SPEC_ALPHA_SEL,
+	QAM_SPEC_ALPHA_VAL,
+	QAM_SPEC_SYMBOL_RATE_REG_0,
+	QAM_SPEC_SYMBOL_RATE_STROBE,
+	QAM_SPEC_SYMBOL_RATE_SEL,
+	QAM_SPEC_SYMBOL_RATE_VAL,
+	QAM_SPEC_REG_0_STROBE,
+	QAM_SPEC_REG_0_SEL,
+	QAM_SPEC_INIT_A0,						// for RTL2840 only
+	QAM_SPEC_INIT_A1,						// for RTL2840 only
+	QAM_SPEC_INIT_A2,						// for RTL2840 only
+	QAM_SPEC_INIT_B0,						// for RTL2820 OpenCable only
+	QAM_SPEC_INIT_C1,						// for RTL2820 OpenCable only
+	QAM_SPEC_INIT_C2,						// for RTL2820 OpenCable only
+	QAM_SPEC_INIT_C3,						// for RTL2820 OpenCable only
+
+	// GPIO
+	QAM_OPT_GPIOA_OE,						// for RTL2836B DVB-C only
+
+	// Pseudo register for test only
+	QAM_TEST_REG_0,
+	QAM_TEST_REG_1,
+	QAM_TEST_REG_2,
+	QAM_TEST_REG_3,
+
+
+	// Item terminator
+	QAM_REG_BIT_NAME_ITEM_TERMINATOR,
+};
+
+
+/// Monitor register bit name
+enum QAM_MONITOR_REG_BIT_NAME
+{
+	// Generality
+	QAM_ADC_CLIP_CNT,
+	QAM_DAGC_VALUE,
+	QAM_RF_AGC_VALUE,
+	QAM_IF_AGC_VALUE,
+	QAM_TR_OFFSET,
+	QAM_CR_OFFSET,
+
+	// Specific monitor register
+	QAM_SPEC_MONITER_INIT_0,
+
+	// Item terminator
+	QAM_MONITOR_REG_BIT_NAME_ITEM_TERMINATOR,
+};
+
+
+
+// Register table length definitions
+#define QAM_BASE_REG_TABLE_LEN_MAX			QAM_REG_BIT_NAME_ITEM_TERMINATOR
+#define QAM_MONITOR_REG_TABLE_LEN_MAX		QAM_MONITOR_REG_BIT_NAME_ITEM_TERMINATOR
+
+
+
+
+
+/// QAM demod module pre-definition
+typedef struct QAM_DEMOD_MODULE_TAG QAM_DEMOD_MODULE;
+
+
+
+
+
+/**
+
+@brief   QAM demod register page setting function pointer
+
+Demod upper level functions will use QAM_DEMOD_FP_SET_REG_PAGE() to set demod register page.
+
+
+@param [in]   pDemod   The demod module pointer
+@param [in]   PageNo   Page number
+
+
+@retval   FUNCTION_SUCCESS   Set register page successfully with page number.
+@retval   FUNCTION_ERROR     Set register page unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_REG_PAGE() with the corresponding function.
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE DvbcDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbcDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register page with page number 2.
+	pDemod->SetRegPage(pDemod, 2);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_ADDR_8BIT_SET_REG_PAGE)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long PageNo
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod register byte setting function pointer
+
+Demod upper level functions will use QAM_DEMOD_FP_SET_REG_BYTES() to set demod register bytes.
+
+
+@param [in]   pDemod          The demod module pointer
+@param [in]   RegStartAddr    Demod register start address
+@param [in]   pWritingBytes   Pointer to writing bytes
+@param [in]   ByteNum         Writing byte number
+
+
+@retval   FUNCTION_SUCCESS   Set demod register bytes successfully with writing bytes.
+@retval   FUNCTION_ERROR     Set demod register bytes unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_REG_BYTES() with the corresponding function.
+	-# Need to set register page by QAM_DEMOD_FP_SET_REG_PAGE() before using QAM_DEMOD_FP_SET_REG_BYTES().
+
+
+@see   QAM_DEMOD_FP_SET_REG_PAGE, QAM_DEMOD_FP_GET_REG_BYTES
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE DvbcDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned char WritingBytes[10];
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbcDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bytes (page 1, address 0x17 ~ 0x1b) with 5 writing bytes.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->SetRegBytes(pDemod, 0x17, WritingBytes, 5);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_ADDR_8BIT_SET_REG_BYTES)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+typedef int
+(*QAM_DEMOD_FP_ADDR_16BIT_SET_REG_BYTES)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod register byte getting function pointer
+
+Demod upper level functions will use QAM_DEMOD_FP_GET_REG_BYTES() to get demod register bytes.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegStartAddr    Demod register start address
+@param [out]   pReadingBytes   Pointer to an allocated memory for storing reading bytes
+@param [in]    ByteNum         Reading byte number
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bytes successfully with reading byte number.
+@retval   FUNCTION_ERROR     Get demod register bytes unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_REG_BYTES() with the corresponding function.
+	-# Need to set register page by QAM_DEMOD_FP_SET_REG_PAGE() before using QAM_DEMOD_FP_GET_REG_BYTES().
+
+
+@see   QAM_DEMOD_FP_SET_REG_PAGE, QAM_DEMOD_FP_SET_REG_BYTES
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE DvbcDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned char ReadingBytes[10];
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbcDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bytes (page 1, address 0x17 ~ 0x1b) with reading byte number 5.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->GetRegBytes(pDemod, 0x17, ReadingBytes, 5);
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_ADDR_8BIT_GET_REG_BYTES)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+typedef int
+(*QAM_DEMOD_FP_ADDR_16BIT_GET_REG_BYTES)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod register mask bits setting function pointer
+
+Demod upper level functions will use QAM_DEMOD_FP_SET_REG_MASK_BITS() to set demod register mask bits.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   RegStartAddr   Demod register start address
+@param [in]   Msb            Mask MSB with 0-based index
+@param [in]   Lsb            Mask LSB with 0-based index
+@param [in]   WritingValue   The mask bits writing value
+
+
+@retval   FUNCTION_SUCCESS   Set demod register mask bits successfully with writing value.
+@retval   FUNCTION_ERROR     Set demod register mask bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_REG_MASK_BITS() with the corresponding function.
+	-# Need to set register page by QAM_DEMOD_FP_SET_REG_PAGE() before using QAM_DEMOD_FP_SET_REG_MASK_BITS().
+	-# The constraints of QAM_DEMOD_FP_SET_REG_MASK_BITS() function usage are described as follows:
+		-# The mask MSB and LSB must be 0~31.
+		-# The mask MSB must be greater than or equal to LSB.
+
+
+@see   QAM_DEMOD_FP_SET_REG_PAGE, QAM_DEMOD_FP_GET_REG_MASK_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE DvbcDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbcDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bits (page 1, address {0x18, 0x17} [12:5]) with writing value 0x1d.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->SetRegMaskBits(pDemod, 0x17, 12, 5, 0x1d);
+
+
+	// Result:
+	//
+	// Writing value = 0x1d = 0001 1101 b
+	// 
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_ADDR_8BIT_SET_REG_MASK_BITS)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+typedef int
+(*QAM_DEMOD_FP_ADDR_16BIT_SET_REG_MASK_BITS)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod register mask bits getting function pointer
+
+Demod upper level functions will use QAM_DEMOD_FP_GET_REG_MASK_BITS() to get demod register mask bits.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegStartAddr    Demod register start address
+@param [in]    Msb             Mask MSB with 0-based index
+@param [in]    Lsb             Mask LSB with 0-based index
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register mask bits successfully.
+@retval   FUNCTION_ERROR     Get demod register mask bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_REG_MASK_BITS() with the corresponding function.
+	-# Need to set register page by QAM_DEMOD_FP_SET_REG_PAGE() before using QAM_DEMOD_FP_GET_REG_MASK_BITS().
+	-# The constraints of QAM_DEMOD_FP_GET_REG_MASK_BITS() function usage are described as follows:
+		-# The mask MSB and LSB must be 0~31.
+		-# The mask MSB must be greater than or equal to LSB.
+
+
+@see   QAM_DEMOD_FP_SET_REG_PAGE, QAM_DEMOD_FP_SET_REG_MASK_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE DvbcDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned long ReadingValue;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbcDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bits (page 1, address {0x18, 0x17} [12:5]).
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->GetRegMaskBits(pDemod, 0x17, 12, 5, &ReadingValue);
+
+
+	// Result:
+	//
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+	//
+	// Reading value = 0001 1101 b = 0x1d
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_ADDR_8BIT_GET_REG_MASK_BITS)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+typedef int
+(*QAM_DEMOD_FP_ADDR_16BIT_GET_REG_MASK_BITS)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod register bits setting function pointer
+
+Demod upper level functions will use QAM_DEMOD_FP_SET_REG_BITS() to set demod register bits with bit name.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   RegBitName     Pre-defined demod register bit name
+@param [in]   WritingValue   The mask bits writing value
+
+
+@retval   FUNCTION_SUCCESS   Set demod register bits successfully with bit name and writing value.
+@retval   FUNCTION_ERROR     Set demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_REG_BITS() with the corresponding function.
+	-# Need to set register page before using QAM_DEMOD_FP_SET_REG_BITS().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   QAM_DEMOD_FP_SET_REG_PAGE, QAM_DEMOD_FP_GET_REG_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE DvbcDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbcDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bits with bit name PSEUDO_REG_BIT_NAME and writing value 0x1d.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->SetRegBits(pDemod, PSEUDO_REG_BIT_NAME, 0x1d);
+
+
+	// Result:
+	//
+	// Writing value = 0x1d = 0001 1101 b
+	// 
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_ADDR_8BIT_SET_REG_BITS)(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+typedef int
+(*QAM_DEMOD_FP_ADDR_16BIT_SET_REG_BITS)(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod register bits getting function pointer
+
+Demod upper level functions will use QAM_DEMOD_FP_GET_REG_BITS() to get demod register bits with bit name.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegBitName      Pre-defined demod register bit name
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bits successfully with bit name.
+@retval   FUNCTION_ERROR     Get demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_REG_BITS() with the corresponding function.
+	-# Need to set register page before using QAM_DEMOD_FP_GET_REG_BITS().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   QAM_DEMOD_FP_SET_REG_PAGE, QAM_DEMOD_FP_SET_REG_BITS
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE DvbcDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned long ReadingValue;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbcDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bits with bit name PSEUDO_REG_BIT_NAME.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->SetRegPage(pDemod, 1);
+	pDemod->GetRegBits(pDemod, PSEUDO_REG_BIT_NAME, &ReadingValue);
+
+
+	// Result:
+	//
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+	//
+	// Reading value = 0001 1101 b = 0x1d
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_ADDR_8BIT_GET_REG_BITS)(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+typedef int
+(*QAM_DEMOD_FP_ADDR_16BIT_GET_REG_BITS)(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod register bits setting function pointer (with page setting)
+
+Demod upper level functions will use QAM_DEMOD_FP_SET_REG_BITS_WITH_PAGE() to set demod register bits with bit name and
+page setting.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   RegBitName     Pre-defined demod register bit name
+@param [in]   WritingValue   The mask bits writing value
+
+
+@retval   FUNCTION_SUCCESS   Set demod register bits successfully with bit name, page setting, and writing value.
+@retval   FUNCTION_ERROR     Set demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_REG_BITS_WITH_PAGE() with the corresponding function.
+	-# Don't need to set register page before using QAM_DEMOD_FP_SET_REG_BITS_WITH_PAGE().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   QAM_DEMOD_FP_GET_REG_BITS_WITH_PAGE
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE DvbcDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbcDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Set demod register bits with bit name PSEUDO_REG_BIT_NAME and writing value 0x1d.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->SetRegBitsWithPage(pDemod, PSEUDO_REG_BIT_NAME, 0x1d);
+
+
+	// Result:
+	//
+	// Writing value = 0x1d = 0001 1101 b
+	// 
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_ADDR_8BIT_SET_REG_BITS_WITH_PAGE)(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod register bits getting function pointer (with page setting)
+
+Demod upper level functions will use QAM_DEMOD_FP_GET_REG_BITS_WITH_PAGE() to get demod register bits with bit name and
+page setting.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    RegBitName      Pre-defined demod register bit name
+@param [out]   pReadingValue   Pointer to an allocated memory for storing reading value
+
+
+@retval   FUNCTION_SUCCESS   Get demod register bits successfully with bit name and page setting.
+@retval   FUNCTION_ERROR     Get demod register bits unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_REG_BITS_WITH_PAGE() with the corresponding function.
+	-# Don't need to set register page before using QAM_DEMOD_FP_GET_REG_BITS_WITH_PAGE().
+	-# Register bit names are pre-defined keys for bit access, and one can find these in demod header file.
+
+
+@see   QAM_DEMOD_FP_SET_REG_BITS_WITH_PAGE
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE DvbcDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+	unsigned long ReadingValue;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &DvbcDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Get demod register bits with bit name PSEUDO_REG_BIT_NAME.
+	// The corresponding information of PSEUDO_REG_BIT_NAME is address {0x18, 0x17} [12:5] on page 1.
+	pDemod->GetRegBitsWithPage(pDemod, PSEUDO_REG_BIT_NAME, &ReadingValue);
+
+
+	// Result:
+	//
+	// Page 1
+	// Register address   0x18          0x17
+	// Register value     xxx0 0011 b   101x xxxx b
+	//
+	// Reading value = 0001 1101 b = 0x1d
+
+	...
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_ADDR_8BIT_GET_REG_BITS_WITH_PAGE)(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+// Demod register access for 8-bit address
+typedef struct
+{
+	QAM_DEMOD_FP_ADDR_8BIT_SET_REG_PAGE             SetRegPage;
+	QAM_DEMOD_FP_ADDR_8BIT_SET_REG_BYTES            SetRegBytes;
+	QAM_DEMOD_FP_ADDR_8BIT_GET_REG_BYTES            GetRegBytes;
+	QAM_DEMOD_FP_ADDR_8BIT_SET_REG_MASK_BITS        SetRegMaskBits;
+	QAM_DEMOD_FP_ADDR_8BIT_GET_REG_MASK_BITS        GetRegMaskBits;
+	QAM_DEMOD_FP_ADDR_8BIT_SET_REG_BITS             SetRegBits;
+	QAM_DEMOD_FP_ADDR_8BIT_GET_REG_BITS             GetRegBits;
+	QAM_DEMOD_FP_ADDR_8BIT_SET_REG_BITS_WITH_PAGE   SetRegBitsWithPage;
+	QAM_DEMOD_FP_ADDR_8BIT_GET_REG_BITS_WITH_PAGE   GetRegBitsWithPage;
+}
+QAM_DEMOD_REG_ACCESS_ADDR_8BIT;
+
+
+
+
+
+// Demod register access for 16-bit address
+typedef struct
+{
+	QAM_DEMOD_FP_ADDR_16BIT_SET_REG_BYTES       SetRegBytes;
+	QAM_DEMOD_FP_ADDR_16BIT_GET_REG_BYTES       GetRegBytes;
+	QAM_DEMOD_FP_ADDR_16BIT_SET_REG_MASK_BITS   SetRegMaskBits;
+	QAM_DEMOD_FP_ADDR_16BIT_GET_REG_MASK_BITS   GetRegMaskBits;
+	QAM_DEMOD_FP_ADDR_16BIT_SET_REG_BITS        SetRegBits;
+	QAM_DEMOD_FP_ADDR_16BIT_GET_REG_BITS        GetRegBits;
+}
+QAM_DEMOD_REG_ACCESS_ADDR_16BIT;
+
+
+
+
+
+/**
+
+@brief   QAM demod type getting function pointer
+
+One can use QAM_DEMOD_FP_GET_DEMOD_TYPE() to get QAM demod type.
+
+
+@param [in]    pDemod       The demod module pointer
+@param [out]   pDemodType   Pointer to an allocated memory for storing demod type
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_DEMOD_TYPE() with the corresponding function.
+
+
+@see   MODULE_TYPE
+
+*/
+typedef void
+(*QAM_DEMOD_FP_GET_DEMOD_TYPE)(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pDemodType
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod I2C device address getting function pointer
+
+One can use QAM_DEMOD_FP_GET_DEVICE_ADDR() to get QAM demod I2C device address.
+
+
+@param [in]    pDemod        The demod module pointer
+@param [out]   pDeviceAddr   Pointer to an allocated memory for storing demod I2C device address
+
+
+@retval   FUNCTION_SUCCESS   Get demod device address successfully.
+@retval   FUNCTION_ERROR     Get demod device address unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_DEVICE_ADDR() with the corresponding function.
+
+*/
+typedef void
+(*QAM_DEMOD_FP_GET_DEVICE_ADDR)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char *pDeviceAddr
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod crystal frequency getting function pointer
+
+One can use QAM_DEMOD_FP_GET_CRYSTAL_FREQ_HZ() to get QAM demod crystal frequency in Hz.
+
+
+@param [in]    pDemod           The demod module pointer
+@param [out]   pCrystalFreqHz   Pointer to an allocated memory for storing demod crystal frequency in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod crystal frequency successfully.
+@retval   FUNCTION_ERROR     Get demod crystal frequency unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_CRYSTAL_FREQ_HZ() with the corresponding function.
+
+*/
+typedef void
+(*QAM_DEMOD_FP_GET_CRYSTAL_FREQ_HZ)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pCrystalFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod I2C bus connection asking function pointer
+
+One can use QAM_DEMOD_FP_IS_CONNECTED_TO_I2C() to ask QAM demod if it is connected to I2C bus.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_IS_CONNECTED_TO_I2C() with the corresponding function.
+
+*/
+typedef void
+(*QAM_DEMOD_FP_IS_CONNECTED_TO_I2C)(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod software resetting function pointer
+
+One can use QAM_DEMOD_FP_SOFTWARE_RESET() to reset QAM demod by software reset.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset demod by software reset successfully.
+@retval   FUNCTION_ERROR     Reset demod by software reset unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SOFTWARE_RESET() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_SOFTWARE_RESET)(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod initializing function pointer
+
+One can use QAM_DEMOD_FP_INITIALIZE() to initialie QAM demod.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Initialize demod successfully.
+@retval   FUNCTION_ERROR     Initialize demod unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_INITIALIZE() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_INITIALIZE)(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod QAM mode setting function pointer
+
+One can use QAM_DEMOD_FP_SET_QAM_MODE() to set QAM demod QAM mode.
+
+
+@param [in]   pDemod    The demod module pointer
+@param [in]   QamMode   QAM mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod QAM mode successfully.
+@retval   FUNCTION_ERROR     Set demod QAM mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_QAM_MODE() with the corresponding function.
+
+
+@see   QAM_QAM_MODE
+
+*/
+typedef int
+(*QAM_DEMOD_FP_SET_QAM_MODE)(
+	QAM_DEMOD_MODULE *pDemod,
+	int QamMode
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod symbol rate setting function pointer
+
+One can use QAM_DEMOD_FP_SET_SYMBOL_RATE_HZ() to set QAM demod symbol rate in Hz.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   SymbolRateHz   Symbol rate in Hz for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod symbol rate successfully.
+@retval   FUNCTION_ERROR     Set demod symbol rate unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_SYMBOL_RATE_HZ() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_SET_SYMBOL_RATE_HZ)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long SymbolRateHz
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod alpha mode setting function pointer
+
+One can use QAM_DEMOD_FP_SET_ALPHA_MODE() to set QAM demod alpha mode.
+
+
+@param [in]   pDemod      The demod module pointer
+@param [in]   AlphaMode   Alpha mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod alpha mode successfully.
+@retval   FUNCTION_ERROR     Set demod alpha mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_ALPHA_MODE() with the corresponding function.
+
+
+@see   QAM_ALPHA_MODE
+
+*/
+typedef int
+(*QAM_DEMOD_FP_SET_ALPHA_MODE)(
+	QAM_DEMOD_MODULE *pDemod,
+	int AlphaMode
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod IF frequency setting function pointer
+
+One can use QAM_DEMOD_FP_SET_IF_FREQ_HZ() to set QAM demod IF frequency in Hz.
+
+
+@param [in]   pDemod     The demod module pointer
+@param [in]   IfFreqHz   IF frequency in Hz for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod IF frequency successfully.
+@retval   FUNCTION_ERROR     Set demod IF frequency unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_IF_FREQ_HZ() with the corresponding function.
+
+
+@see   IF_FREQ_HZ
+
+*/
+typedef int
+(*QAM_DEMOD_FP_SET_IF_FREQ_HZ)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long IfFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod spectrum mode setting function pointer
+
+One can use QAM_DEMOD_FP_SET_SPECTRUM_MODE() to set QAM demod spectrum mode.
+
+
+@param [in]   pDemod         The demod module pointer
+@param [in]   SpectrumMode   Spectrum mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set demod spectrum mode successfully.
+@retval   FUNCTION_ERROR     Set demod spectrum mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_SET_SPECTRUM_MODE() with the corresponding function.
+
+
+@see   SPECTRUM_MODE
+
+*/
+typedef int
+(*QAM_DEMOD_FP_SET_SPECTRUM_MODE)(
+	QAM_DEMOD_MODULE *pDemod,
+	int SpectrumMode
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod QAM mode getting function pointer
+
+One can use QAM_DEMOD_FP_GET_QAM_MODE() to get QAM demod QAM mode.
+
+
+@param [in]    pDemod     The demod module pointer
+@param [out]   pQamMode   Pointer to an allocated memory for storing demod QAM mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod QAM mode successfully.
+@retval   FUNCTION_ERROR     Get demod QAM mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_QAM_MODE() with the corresponding function.
+
+
+@see   QAM_QAM_MODE
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_QAM_MODE)(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pQamMode
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod symbol rate getting function pointer
+
+One can use QAM_DEMOD_FP_GET_SYMBOL_RATE_HZ() to get QAM demod symbol rate in Hz.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [out]   pSymbolRateHz   Pointer to an allocated memory for storing demod symbol rate in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod symbol rate successfully.
+@retval   FUNCTION_ERROR     Get demod symbol rate unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_SYMBOL_RATE_HZ() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_SYMBOL_RATE_HZ)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pSymbolRateHz
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod alpha mode getting function pointer
+
+One can use QAM_DEMOD_FP_GET_ALPHA_MODE() to get QAM demod alpha mode.
+
+
+@param [in]    pDemod       The demod module pointer
+@param [out]   pAlphaMode   Pointer to an allocated memory for storing demod alpha mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod alpha mode successfully.
+@retval   FUNCTION_ERROR     Get demod alpha mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_ALPHA_MODE() with the corresponding function.
+
+
+@see   QAM_ALPHA_MODE
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_ALPHA_MODE)(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAlphaMode
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod IF frequency getting function pointer
+
+One can use QAM_DEMOD_FP_GET_IF_FREQ_HZ() to get QAM demod IF frequency in Hz.
+
+
+@param [in]    pDemod      The demod module pointer
+@param [out]   pIfFreqHz   Pointer to an allocated memory for storing demod IF frequency in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod IF frequency successfully.
+@retval   FUNCTION_ERROR     Get demod IF frequency unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_IF_FREQ_HZ() with the corresponding function.
+
+
+@see   IF_FREQ_HZ
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_IF_FREQ_HZ)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pIfFreqHz
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod spectrum mode getting function pointer
+
+One can use QAM_DEMOD_FP_GET_SPECTRUM_MODE() to get QAM demod spectrum mode.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [out]   pSpectrumMode   Pointer to an allocated memory for storing demod spectrum mode
+
+
+@retval   FUNCTION_SUCCESS   Get demod spectrum mode successfully.
+@retval   FUNCTION_ERROR     Get demod spectrum mode unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_SPECTRUM_MODE() with the corresponding function.
+
+
+@see   SPECTRUM_MODE
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_SPECTRUM_MODE)(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pSpectrumMode
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod RF AGC getting function pointer
+
+One can use QAM_DEMOD_FP_GET_RF_AGC() to get QAM demod RF AGC value.
+
+
+@param [in]    pDemod   The demod module pointer
+@param [out]   pRfAgc   Pointer to an allocated memory for storing RF AGC value
+
+
+@retval   FUNCTION_SUCCESS   Get demod RF AGC value successfully.
+@retval   FUNCTION_ERROR     Get demod RF AGC value unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_RF_AGC() with the corresponding function.
+	-# The range of RF AGC value is (-pow(2, 10)) ~ (pow(2, 10) - 1).
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_RF_AGC)(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pRfAgc
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod IF AGC getting function pointer
+
+One can use QAM_DEMOD_FP_GET_IF_AGC() to get QAM demod IF AGC value.
+
+
+@param [in]    pDemod   The demod module pointer
+@param [out]   pIfAgc   Pointer to an allocated memory for storing IF AGC value
+
+
+@retval   FUNCTION_SUCCESS   Get demod IF AGC value successfully.
+@retval   FUNCTION_ERROR     Get demod IF AGC value unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_IF_AGC() with the corresponding function.
+	-# The range of IF AGC value is (-pow(2, 10)) ~ (pow(2, 10) - 1).
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_IF_AGC)(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pIfAgc
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod digital AGC getting function pointer
+
+One can use QAM_DEMOD_FP_GET_DI_AGC() to get QAM demod digital AGC value.
+
+
+@param [in]    pDemod   The demod module pointer
+@param [out]   pDiAgc   Pointer to an allocated memory for storing digital AGC value
+
+
+@retval   FUNCTION_SUCCESS   Get demod digital AGC value successfully.
+@retval   FUNCTION_ERROR     Get demod digital AGC value unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_DI_AGC() with the corresponding function.
+	-# The range of digital AGC value is 0 ~ (pow(2, 27) - 1).
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_DI_AGC)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pDiAgc
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod TR offset getting function pointer
+
+One can use QAM_DEMOD_FP_GET_TR_OFFSET_PPM() to get TR offset in ppm.
+
+
+@param [in]    pDemod         The demod module pointer
+@param [out]   pTrOffsetPpm   Pointer to an allocated memory for storing TR offset in ppm
+
+
+@retval   FUNCTION_SUCCESS   Get demod TR offset successfully.
+@retval   FUNCTION_ERROR     Get demod TR offset unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_TR_OFFSET_PPM() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_TR_OFFSET_PPM)(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pTrOffsetPpm
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod CR offset getting function pointer
+
+One can use QAM_DEMOD_FP_GET_CR_OFFSET_HZ() to get CR offset in Hz.
+
+
+@param [in]    pDemod        The demod module pointer
+@param [out]   pCrOffsetHz   Pointer to an allocated memory for storing CR offset in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get demod CR offset successfully.
+@retval   FUNCTION_ERROR     Get demod CR offset unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_CR_OFFSET_HZ() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_CR_OFFSET_HZ)(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pCrOffsetHz
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod AAGC lock asking function pointer
+
+One can use QAM_DEMOD_FP_IS_AAGC_LOCKED() to ask QAM demod if it is AAGC-locked.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform AAGC lock asking to demod successfully.
+@retval   FUNCTION_ERROR     Perform AAGC lock asking to demod unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_IS_AAGC_LOCKED() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_IS_AAGC_LOCKED)(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod EQ lock asking function pointer
+
+One can use QAM_DEMOD_FP_IS_EQ_LOCKED() to ask QAM demod if it is EQ-locked.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform EQ lock asking to demod successfully.
+@retval   FUNCTION_ERROR     Perform EQ lock asking to demod unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_IS_EQ_LOCKED() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_IS_EQ_LOCKED)(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod frame lock asking function pointer
+
+One can use QAM_DEMOD_FP_IS_FRAME_LOCKED() to ask QAM demod if it is frame-locked.
+
+
+@param [in]    pDemod    The demod module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform frame lock asking to demod successfully.
+@retval   FUNCTION_ERROR     Perform frame lock asking to demod unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_IS_FRAME_LOCKED() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_IS_FRAME_LOCKED)(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod error rate value getting function pointer
+
+One can use QAM_DEMOD_FP_GET_ERROR_RATE() to get error rate value.
+
+
+@param [in]    pDemod          The demod module pointer
+@param [in]    TestVolume      Test volume for setting
+@param [in]    WaitTimeMsMax   Maximum waiting time in ms
+@param [out]   pBerNum         Pointer to an allocated memory for storing BER numerator
+@param [out]   pBerDen         Pointer to an allocated memory for storing BER denominator
+@param [out]   pPerNum         Pointer to an allocated memory for storing PER numerator
+@param [out]   pPerDen         Pointer to an allocated memory for storing PER denominator
+
+
+@retval   FUNCTION_SUCCESS   Get demod error rate value successfully.
+@retval   FUNCTION_ERROR     Get demod error rate value unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_ERROR_RATE() with the corresponding function.
+	-# The error test packet number is pow(2, (2 * TestVolume + 4)).
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_ERROR_RATE)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long TestVolume,
+	unsigned int WaitTimeMsMax,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod SNR getting function pointer
+
+One can use QAM_DEMOD_FP_GET_SNR_DB() to get SNR in dB.
+
+
+@param [in]    pDemod      The demod module pointer
+@param [out]   pSnrDbNum   Pointer to an allocated memory for storing SNR dB numerator
+@param [out]   pSnrDbDen   Pointer to an allocated memory for storing SNR dB denominator
+
+
+@retval   FUNCTION_SUCCESS   Get demod SNR successfully.
+@retval   FUNCTION_ERROR     Get demod SNR unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_SNR_DB() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_SNR_DB)(
+	QAM_DEMOD_MODULE *pDemod,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod signal strength getting function pointer
+
+One can use QAM_DEMOD_FP_GET_SIGNAL_STRENGTH() to get signal strength.
+
+
+@param [in]    pDemod            The demod module pointer
+@param [out]   pSignalStrength   Pointer to an allocated memory for storing signal strength (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get demod signal strength successfully.
+@retval   FUNCTION_ERROR     Get demod signal strength unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_SIGNAL_STRENGTH() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_SIGNAL_STRENGTH)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalStrength
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod signal quality getting function pointer
+
+One can use QAM_DEMOD_FP_GET_SIGNAL_QUALITY() to get signal quality.
+
+
+@param [in]    pDemod           The demod module pointer
+@param [out]   pSignalQuality   Pointer to an allocated memory for storing signal quality (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get demod signal quality successfully.
+@retval   FUNCTION_ERROR     Get demod signal quality unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_GET_SIGNAL_QUALITY() with the corresponding function.
+
+*/
+typedef int
+(*QAM_DEMOD_FP_GET_SIGNAL_QUALITY)(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pSignalQuality
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod updating function pointer
+
+One can use QAM_DEMOD_FP_UPDATE_FUNCTION() to update demod register setting.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update demod setting successfully.
+@retval   FUNCTION_ERROR     Update demod setting unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_UPDATE_FUNCTION() with the corresponding function.
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE QamDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &QamDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Execute ResetFunction() before demod software reset.
+	pDemod->ResetFunction(pDemod);
+
+	// Reset demod by software.
+	pDemod->SoftwareReset(pDemod);
+
+	...
+
+	return 0;
+}
+
+
+void PeriodicallyExecutingFunction
+{
+	// Executing UpdateFunction() periodically.
+	pDemod->UpdateFunction(pDemod);
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_UPDATE_FUNCTION)(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/**
+
+@brief   QAM demod reseting function pointer
+
+One can use QAM_DEMOD_FP_RESET_FUNCTION() to reset demod register setting.
+
+
+@param [in]   pDemod   The demod module pointer
+
+
+@retval   FUNCTION_SUCCESS   Reset demod setting successfully.
+@retval   FUNCTION_ERROR     Reset demod setting unsuccessfully.
+
+
+@note
+	-# Demod building function will set QAM_DEMOD_FP_RESET_FUNCTION() with the corresponding function.
+
+
+
+@par Example:
+@code
+
+
+#include "demod_pseudo.h"
+
+
+int main(void)
+{
+	QAM_DEMOD_MODULE *pDemod;
+	QAM_DEMOD_MODULE QamDemodModuleMemory;
+	PSEUDO_EXTRA_MODULE PseudoExtraModuleMemory;
+
+
+	// Build pseudo demod module.
+	BuildPseudoDemodModule(&pDemod, &QamDemodModuleMemory, &PseudoExtraModuleMemory);
+
+	...
+
+	// Execute ResetFunction() before demod software reset.
+	pDemod->ResetFunction(pDemod);
+
+	// Reset demod by software.
+	pDemod->SoftwareReset(pDemod);
+
+	...
+
+	return 0;
+}
+
+
+void PeriodicallyExecutingFunction
+{
+	// Executing UpdateFunction() periodically.
+	pDemod->UpdateFunction(pDemod);
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_DEMOD_FP_RESET_FUNCTION)(
+	QAM_DEMOD_MODULE *pDemod
+	);
+
+
+
+
+
+/// RTD2885 QAM extra module
+typedef struct RTD2885_QAM_EXTRA_MODULE_TAG RTD2885_QAM_EXTRA_MODULE;
+
+// RTD2885 QAM extra module
+struct RTD2885_QAM_EXTRA_MODULE_TAG
+{
+	// Variables
+	int ConfigMode;
+	unsigned char Func1TickNum;
+};
+
+
+
+
+
+/// RTD2840B QAM extra module
+typedef struct RTD2840B_QAM_EXTRA_MODULE_TAG RTD2840B_QAM_EXTRA_MODULE;
+
+// RTD2840B QAM extra module
+struct RTD2840B_QAM_EXTRA_MODULE_TAG
+{
+	// Variables
+	int ConfigMode;
+	unsigned char Func1TickNum;
+};
+
+
+
+
+
+/// RTD2932 QAM extra module alias
+typedef struct RTD2932_QAM_EXTRA_MODULE_TAG RTD2932_QAM_EXTRA_MODULE;
+
+// RTD2932 QAM extra module
+struct RTD2932_QAM_EXTRA_MODULE_TAG
+{
+	// Variables
+	int ConfigMode;
+	unsigned char Func1TickNum;
+};
+
+
+
+
+
+/// RTL2820 OpenCable extra module alias
+typedef struct RTL2820_OC_EXTRA_MODULE_TAG RTL2820_OC_EXTRA_MODULE;
+
+// RTL2820 OpenCable extra module
+struct RTL2820_OC_EXTRA_MODULE_TAG
+{
+	// Variables
+	unsigned char Func1TickNum;
+};
+
+
+
+
+
+/// RTD2648 QAM extra module alias
+typedef struct RTD2648_QAM_EXTRA_MODULE_TAG RTD2648_QAM_EXTRA_MODULE;
+
+// RTD2648 QAM extra module
+struct RTD2648_QAM_EXTRA_MODULE_TAG
+{
+	// Variables
+	int ConfigMode;
+};
+
+
+
+
+
+/// QAM demod module structure
+struct QAM_DEMOD_MODULE_TAG
+{
+	unsigned long CurrentPageNo;
+	// Private variables
+	int           DemodType;
+	unsigned char DeviceAddr;
+	unsigned long CrystalFreqHz;
+	int           TsInterfaceMode;
+
+	int           QamMode;
+	unsigned long SymbolRateHz;
+	int           AlphaMode;
+	unsigned long IfFreqHz;
+	int           SpectrumMode;
+
+	int IsQamModeSet;
+	int IsSymbolRateHzSet;
+	int IsAlphaModeSet;
+	int IsIfFreqHzSet;
+	int IsSpectrumModeSet;
+
+	union											///<   Demod extra module used by driving module
+	{
+		RTD2885_QAM_EXTRA_MODULE  Rtd2885Qam;
+		RTD2840B_QAM_EXTRA_MODULE Rtd2840bQam;
+		RTD2932_QAM_EXTRA_MODULE  Rtd2932Qam;
+		RTL2820_OC_EXTRA_MODULE   Rtl2820Oc;
+		RTD2648_QAM_EXTRA_MODULE  Rtd2648Qam;
+	}
+	Extra;
+
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	I2C_BRIDGE_MODULE *pI2cBridge;
+
+
+	// Register tables
+	union
+	{
+		QAM_BASE_REG_ENTRY_ADDR_8BIT  Addr8Bit[QAM_BASE_REG_TABLE_LEN_MAX];
+		QAM_BASE_REG_ENTRY_ADDR_16BIT Addr16Bit[QAM_BASE_REG_TABLE_LEN_MAX];
+	}
+	BaseRegTable;
+
+	union
+	{
+		QAM_MONITOR_REG_ENTRY_ADDR_8BIT  Addr8Bit[QAM_MONITOR_REG_TABLE_LEN_MAX];
+		QAM_MONITOR_REG_ENTRY_ADDR_16BIT Addr16Bit[QAM_MONITOR_REG_TABLE_LEN_MAX];
+	}
+	MonitorRegTable;
+
+
+	// Demod I2C function pointers
+	union
+	{
+		QAM_DEMOD_REG_ACCESS_ADDR_8BIT  Addr8Bit;
+		QAM_DEMOD_REG_ACCESS_ADDR_16BIT Addr16Bit;
+	}
+	RegAccess;
+
+
+	// Demod manipulating function pointers
+	QAM_DEMOD_FP_GET_DEMOD_TYPE        GetDemodType;
+	QAM_DEMOD_FP_GET_DEVICE_ADDR       GetDeviceAddr;
+	QAM_DEMOD_FP_GET_CRYSTAL_FREQ_HZ   GetCrystalFreqHz;
+
+	QAM_DEMOD_FP_IS_CONNECTED_TO_I2C   IsConnectedToI2c;
+	QAM_DEMOD_FP_SOFTWARE_RESET        SoftwareReset;
+
+	QAM_DEMOD_FP_INITIALIZE            Initialize;
+	QAM_DEMOD_FP_SET_QAM_MODE          SetQamMode;
+	QAM_DEMOD_FP_SET_SYMBOL_RATE_HZ    SetSymbolRateHz;
+	QAM_DEMOD_FP_SET_ALPHA_MODE        SetAlphaMode;
+	QAM_DEMOD_FP_SET_IF_FREQ_HZ        SetIfFreqHz;
+	QAM_DEMOD_FP_SET_SPECTRUM_MODE     SetSpectrumMode;
+	QAM_DEMOD_FP_GET_QAM_MODE          GetQamMode;
+	QAM_DEMOD_FP_GET_SYMBOL_RATE_HZ    GetSymbolRateHz;
+	QAM_DEMOD_FP_GET_ALPHA_MODE        GetAlphaMode;
+	QAM_DEMOD_FP_GET_IF_FREQ_HZ        GetIfFreqHz;
+	QAM_DEMOD_FP_GET_SPECTRUM_MODE     GetSpectrumMode;
+
+	QAM_DEMOD_FP_GET_RF_AGC            GetRfAgc;
+	QAM_DEMOD_FP_GET_IF_AGC            GetIfAgc;
+	QAM_DEMOD_FP_GET_DI_AGC            GetDiAgc;
+	QAM_DEMOD_FP_GET_TR_OFFSET_PPM     GetTrOffsetPpm;
+	QAM_DEMOD_FP_GET_CR_OFFSET_HZ      GetCrOffsetHz;
+
+	QAM_DEMOD_FP_IS_AAGC_LOCKED        IsAagcLocked;
+	QAM_DEMOD_FP_IS_EQ_LOCKED          IsEqLocked;
+	QAM_DEMOD_FP_IS_FRAME_LOCKED       IsFrameLocked;
+
+	QAM_DEMOD_FP_GET_ERROR_RATE        GetErrorRate;
+	QAM_DEMOD_FP_GET_SNR_DB            GetSnrDb;
+
+	QAM_DEMOD_FP_GET_SIGNAL_STRENGTH   GetSignalStrength;
+	QAM_DEMOD_FP_GET_SIGNAL_QUALITY    GetSignalQuality;
+
+	QAM_DEMOD_FP_UPDATE_FUNCTION       UpdateFunction;
+	QAM_DEMOD_FP_RESET_FUNCTION        ResetFunction;
+};
+
+
+
+
+
+
+
+// QAM demod default I2C functions for 8-bit address
+int
+qam_demod_addr_8bit_default_SetRegPage(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long PageNo
+	);
+
+int
+qam_demod_addr_8bit_default_SetRegBytes(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+int
+qam_demod_addr_8bit_default_GetRegBytes(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+int
+qam_demod_addr_8bit_default_SetRegMaskBits(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+int
+qam_demod_addr_8bit_default_GetRegMaskBits(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+int
+qam_demod_addr_8bit_default_SetRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+int
+qam_demod_addr_8bit_default_GetRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+int
+qam_demod_addr_8bit_default_SetRegBitsWithPage(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+int
+qam_demod_addr_8bit_default_GetRegBitsWithPage(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+// QAM demod default I2C functions for 16-bit address
+int
+qam_demod_addr_16bit_default_SetRegBytes(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	);
+
+int
+qam_demod_addr_16bit_default_GetRegBytes(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	);
+
+int
+qam_demod_addr_16bit_default_SetRegMaskBits(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	const unsigned long WritingValue
+	);
+
+int
+qam_demod_addr_16bit_default_GetRegMaskBits(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned short RegStartAddr,
+	unsigned char Msb,
+	unsigned char Lsb,
+	unsigned long *pReadingValue
+	);
+
+int
+qam_demod_addr_16bit_default_SetRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	const unsigned long WritingValue
+	);
+
+int
+qam_demod_addr_16bit_default_GetRegBits(
+	QAM_DEMOD_MODULE *pDemod,
+	int RegBitName,
+	unsigned long *pReadingValue
+	);
+
+
+
+
+
+// QAM demod default manipulating functions
+void
+qam_demod_default_GetDemodType(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pDemodType
+	);
+
+void
+qam_demod_default_GetDeviceAddr(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned char *pDeviceAddr
+	);
+
+void
+qam_demod_default_GetCrystalFreqHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pCrystalFreqHz
+	);
+
+int
+qam_demod_default_GetQamMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pQamMode
+	);
+
+int
+qam_demod_default_GetSymbolRateHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pSymbolRateHz
+	);
+
+int
+qam_demod_default_GetAlphaMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pAlphaMode
+	);
+
+int
+qam_demod_default_GetIfFreqHz(
+	QAM_DEMOD_MODULE *pDemod,
+	unsigned long *pIfFreqHz
+	);
+
+int
+qam_demod_default_GetSpectrumMode(
+	QAM_DEMOD_MODULE *pDemod,
+	int *pSpectrumMode
+	);
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/qam_nim_base.c b/drivers/media/usb/dvb-usb/qam_nim_base.c
new file mode 100644
index 0000000..726eab4
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/qam_nim_base.c
@@ -0,0 +1,496 @@
+/**
+
+@file
+
+@brief   QAM NIM base module definition
+
+QAM NIM base module definitions contains NIM module structure, NIM funciton pointers, NIM definitions, and NIM default
+functions.
+
+*/
+
+
+#include "qam_nim_base.h"
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_GET_NIM_TYPE
+
+*/
+void
+qam_nim_default_GetNimType(
+	QAM_NIM_MODULE *pNim,
+	int *pNimType
+	)
+{
+	// Get NIM type from NIM module.
+	*pNimType = pNim->NimType;
+
+
+	return;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_SET_PARAMETERS
+
+*/
+int
+qam_nim_default_SetParameters(
+	QAM_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int QamMode,
+	unsigned long SymbolRateHz,
+	int AlphaMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Set tuner RF frequency in Hz.
+	if(pTuner->SetRfFreqHz(pTuner, RfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod QAM mode.
+	if(pDemod->SetQamMode(pDemod, QamMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod symbol rate in Hz.
+	if(pDemod->SetSymbolRateHz(pDemod, SymbolRateHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Set demod alpha mode.
+	if(pDemod->SetAlphaMode(pDemod, AlphaMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod particular registers.
+	if(pDemod->ResetFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Reset demod by software reset.
+	if(pDemod->SoftwareReset(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_GET_PARAMETERS
+
+*/
+int
+qam_nim_default_GetParameters(
+	QAM_NIM_MODULE *pNim,
+	unsigned long *pRfFreqHz,
+	int *pQamMode,
+	unsigned long *pSymbolRateHz,
+	int *pAlphaMode
+	)
+{
+	TUNER_MODULE *pTuner;
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get tuner module and demod module.
+	pTuner = pNim->pTuner;
+	pDemod = pNim->pDemod;
+
+
+	// Get tuner RF frequency in Hz.
+	if(pTuner->GetRfFreqHz(pTuner, pRfFreqHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get demod QAM mode.
+	if(pDemod->GetQamMode(pDemod, pQamMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get demod symbol rate in Hz.
+	if(pDemod->GetSymbolRateHz(pDemod, pSymbolRateHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+	// Get demod alpha mode.
+	if(pDemod->GetAlphaMode(pDemod, pAlphaMode) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_IS_SIGNAL_PRESENT
+
+*/
+int
+qam_nim_default_IsSignalPresent(
+	QAM_NIM_MODULE *pNim,
+	int *pAnswer
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	QAM_DEMOD_MODULE *pDemod;
+	int i;
+
+
+	// Get base interface and demod module.
+	pBaseInterface = pNim->pBaseInterface;
+	pDemod         = pNim->pDemod;
+
+
+	// Wait maximum 1000 ms for signal present check.
+	for(i = 0; i < DEFAULT_QAM_NIM_SINGAL_PRESENT_CHECK_TIMES_MAX; i++)
+	{
+		// Wait 20 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 20);
+
+		// Check signal present status on demod.
+		// Note: If frame is locked, stop signal present check.
+		if(pDemod->IsFrameLocked(pDemod, pAnswer) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		if(*pAnswer == YES)
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_IS_SIGNAL_LOCKED
+
+*/
+int
+qam_nim_default_IsSignalLocked(
+	QAM_NIM_MODULE *pNim,
+	int *pAnswer
+	)
+{
+	BASE_INTERFACE_MODULE *pBaseInterface;
+	QAM_DEMOD_MODULE *pDemod;
+	int i;
+
+
+	// Get base interface and demod module.
+	pBaseInterface = pNim->pBaseInterface;
+	pDemod         = pNim->pDemod;
+
+
+	// Wait maximum 1000 ms for signal lock check.
+	for(i = 0; i < DEFAULT_QAM_NIM_SINGAL_LOCK_CHECK_TIMES_MAX; i++)
+	{
+		// Wait 20 ms.
+		pBaseInterface->WaitMs(pBaseInterface, 20);
+
+		// Check frame lock status on demod.
+		// Note: If frame is locked, stop signal lock check.
+		if(pDemod->IsFrameLocked(pDemod, pAnswer) != FUNCTION_SUCCESS)
+			goto error_status_execute_function;
+
+		if(*pAnswer == YES)
+			break;
+	}
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_GET_SIGNAL_STRENGTH
+
+*/
+int
+qam_nim_default_GetSignalStrength(
+	QAM_NIM_MODULE *pNim,
+	unsigned long *pSignalStrength
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get signal strength from demod.
+	if(pDemod->GetSignalStrength(pDemod, pSignalStrength) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_GET_SIGNAL_QUALITY
+
+*/
+int
+qam_nim_default_GetSignalQuality(
+	QAM_NIM_MODULE *pNim,
+	unsigned long *pSignalQuality
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get signal quality from demod.
+	if(pDemod->GetSignalQuality(pDemod, pSignalQuality) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_GET_ERROR_RATE
+
+*/
+int
+qam_nim_default_GetErrorRate(
+	QAM_NIM_MODULE *pNim,
+	unsigned long TestVolume,
+	unsigned int WaitTimeMsMax,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get error rate from demod.
+	if(pDemod->GetErrorRate(pDemod, TestVolume, WaitTimeMsMax, pBerNum, pBerDen, pPerNum, pPerDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_GET_SNR_DB
+
+*/
+int
+qam_nim_default_GetSnrDb(
+	QAM_NIM_MODULE *pNim,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get SNR in dB from demod.
+	if(pDemod->GetSnrDb(pDemod, pSnrDbNum, pSnrDbDen) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_GET_TR_OFFSET_PPM
+
+*/
+int
+qam_nim_default_GetTrOffsetPpm(
+	QAM_NIM_MODULE *pNim,
+	long *pTrOffsetPpm
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get TR offset in ppm from demod.
+	if(pDemod->GetTrOffsetPpm(pDemod, pTrOffsetPpm) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_GET_CR_OFFSET_HZ
+
+*/
+int
+qam_nim_default_GetCrOffsetHz(
+	QAM_NIM_MODULE *pNim,
+	long *pCrOffsetHz
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Get CR offset in Hz from demod.
+	if(pDemod->GetCrOffsetHz(pDemod, pCrOffsetHz) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+/**
+
+@see   QAM_NIM_FP_UPDATE_FUNCTION
+
+*/
+int
+qam_nim_default_UpdateFunction(
+	QAM_NIM_MODULE *pNim
+	)
+{
+	QAM_DEMOD_MODULE *pDemod;
+
+
+	// Get demod module.
+	pDemod = pNim->pDemod;
+
+
+	// Update demod particular registers.
+	if(pDemod->UpdateFunction(pDemod) != FUNCTION_SUCCESS)
+		goto error_status_execute_function;
+
+
+	return FUNCTION_SUCCESS;
+
+
+error_status_execute_function:
+	return FUNCTION_ERROR;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/media/usb/dvb-usb/qam_nim_base.h b/drivers/media/usb/dvb-usb/qam_nim_base.h
new file mode 100644
index 0000000..143f6d4
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/qam_nim_base.h
@@ -0,0 +1,879 @@
+#ifndef __QAM_NIM_BASE_H
+#define __QAM_NIM_BASE_H
+
+/**
+
+@file
+
+@brief   QAM NIM base module definition
+
+QAM NIM base module definitions contains NIM module structure, NIM funciton pointers, NIM definitions, and NIM default
+functions.
+
+
+
+@par Example:
+@code
+
+
+#include "nim_demodx_tunery.h"
+
+
+
+int
+CustomI2cRead(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	unsigned char *pReadingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C reading format:
+	// start_bit + (DeviceAddr | reading_bit) + reading_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+int
+CustomI2cWrite(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned char DeviceAddr,
+	const unsigned char *pWritingBytes,
+	unsigned long ByteNum
+	)
+{
+	// I2C writing format:
+	// start_bit + (DeviceAddr | writing_bit) + writing_byte * ByteNum + stop_bit
+
+	...
+
+	return FUNCTION_SUCCESS;
+
+error_status:
+	return FUNCTION_ERROR;
+}
+
+
+
+void
+CustomWaitMs(
+	BASE_INTERFACE_MODULE *pBaseInterface,
+	unsigned long WaitTimeMs
+	)
+{
+	// Wait WaitTimeMs milliseconds.
+
+	...
+
+	return;
+}
+
+
+
+int main(void)
+{
+	QAM_NIM_MODULE *pNim;
+	QAM_NIM_MODULE QamNimModuleMemory;
+	DEMODX_EXTRA_MODULE DemodxExtraModuleMemory;
+	TUNERY_EXTRA_MODULE TuneryExtraModuleMemory;
+
+	unsigned long RfFreqHz;
+	int QamMode;
+	unsigned long SymbolRateHz;
+	int AlphaMode;
+
+	int Answer;
+	unsigned long SignalStrength, SignalQuality;
+	unsigned long BerNum, BerDen, PerNum, PerDen;
+	double Ber, Per;
+	unsigned long SnrDbNum, SnrDbDen;
+	double SnrDb;
+	long TrOffsetPpm, CrOffsetHz;
+
+
+
+	// Build Demod-X Tuner-Y NIM module.
+	BuildDemodxTuneryModule(
+		&pNim,
+		&QamNimModuleMemory,
+
+		9,								// Maximum I2C reading byte number is 9.
+		8,								// Maximum I2C writing byte number is 8.
+		CustomI2cRead,					// Employ CustomI2cRead() as basic I2C reading function.
+		CustomI2cWrite,					// Employ CustomI2cWrite() as basic I2C writing function.
+		CustomWaitMs,					// Employ CustomWaitMs() as basic waiting function.
+
+		&DemodxExtraModuleMemory,		// Employ Demod-X extra module.
+		0x44,							// The Demod-X I2C device address is 0x44 in 8-bit format.
+		CRYSTAL_FREQ_28800000HZ,		// The Demod-X crystal frequency is 28.8 MHz.
+		TS_INTERFACE_SERIAL,			// The Demod-X TS interface mode is serial.
+		...								// Other arguments for Demod-X
+
+		&TunerxExtraModuleMemory,		// Employ Tuner-Y extra module.
+		0xc0,							// The Tuner-Y I2C device address is 0xc0 in 8-bit format.
+		...								// Other arguments for Tuner-Y
+		);
+
+
+
+	// Get NIM type.
+	// Note: NIM types are defined in the MODULE_TYPE enumeration.
+	pNim->GetNimType(pNim, &NimType);
+
+
+
+
+
+
+
+	// ==== Initialize NIM and set its parameters =====
+
+	// Initialize NIM.
+	pNim->Initialize(pNim);
+
+	// Set NIM parameters. (RF frequency, QAM mode, symbol rate, alpha mode)
+	// Note: In the example:
+	//       1. RF frequency is 738 MHz.
+	//       2. QAM is 64.
+	//       3. Symbol rate is 6.952 MHz.
+	//       4. Alpha is 0.15.
+	RfFreqHz     = 738000000;
+	QamMode      = QAM_QAM_64;
+	SymbolRateHz = 6952000;
+	AlphaMode    = QAM_ALPHA_0P15;
+	pNim->SetParameters(pNim, RfFreqHz, QamMode, SymbolRateHz, AlphaMode);
+
+
+
+	// Wait 1 second for demod convergence.
+
+
+
+
+
+	// ==== Get NIM information =====
+
+	// Get NIM parameters. (RF frequency, QAM mode, symbol rate, alpha mode)
+	pNim->GetParameters(pNim, &RfFreqHz, &QamMode, &SymbolRateHz, &AlphaMode);
+
+
+	// Get signal present status.
+	// Note: 1. The argument Answer is YES when the NIM module has found QAM signal in the RF channel.
+	//       2. The argument Answer is NO when the NIM module does not find QAM signal in the RF channel.
+	// Recommendation: Use the IsSignalPresent() function for channel scan.
+	pNim->IsSignalPresent(pNim, &Answer);
+
+	// Get signal lock status.
+	// Note: 1. The argument Answer is YES when the NIM module has locked QAM signal in the RF channel.
+	//          At the same time, the NIM module sends TS packets through TS interface hardware pins.
+	//       2. The argument Answer is NO when the NIM module does not lock QAM signal in the RF channel.
+	// Recommendation: Use the IsSignalLocked() function for signal lock check.
+	pNim->IsSignalLocked(pNim, &Answer);
+
+
+	// Get signal strength.
+	// Note: 1. The range of SignalStrength is 0~100.
+	//       2. Need to map SignalStrength value to UI signal strength bar manually.
+	pNim->GetSignalStrength(pNim, &SignalStrength);
+
+	// Get signal quality.
+	// Note: 1. The range of SignalQuality is 0~100.
+	//       2. Need to map SignalQuality value to UI signal quality bar manually.
+	pNim->GetSignalQuality(pNim, &SignalQuality);
+
+
+	// Get BER and PER.
+	// Note: Test packet number = pow(2, (2 * 4 + 4)) = 4096
+	//       Maximum wait time  = 1000 ms = 1 second
+	pNim->GetErrorRate(pNim, 4, 1000, &BerNum, &BerDen, &PerNum, &PerDen);
+	Ber = (double)BerNum / (double)BerDen;
+	Per = (double)PerNum / (double)PerDen;
+
+	// Get SNR in dB.
+	pNim->GetSnrDb(pNim, &SnrDbNum, &SnrDbDen);
+	SnrDb = (double)SnrDbNum / (double)SnrDbDen;
+
+
+	// Get TR offset (symbol timing offset) in ppm.
+	pNim->GetTrOffsetPpm(pNim, &TrOffsetPpm);
+
+	// Get CR offset (RF frequency offset) in Hz.
+	pNim->GetCrOffsetHz(pNim, &CrOffsetHz);
+
+
+
+	return 0;
+}
+
+
+@endcode
+
+*/
+
+
+#include "foundation.h"
+#include "tuner_base.h"
+#include "qam_demod_base.h"
+
+
+
+
+
+// Definitions
+#define DEFAULT_QAM_NIM_SINGAL_PRESENT_CHECK_TIMES_MAX		1
+#define DEFAULT_QAM_NIM_SINGAL_LOCK_CHECK_TIMES_MAX			1
+
+
+
+
+
+/// QAM NIM module pre-definition
+typedef struct QAM_NIM_MODULE_TAG QAM_NIM_MODULE;
+
+
+
+
+
+/**
+
+@brief   QAM demod type getting function pointer
+
+One can use QAM_NIM_FP_GET_NIM_TYPE() to get QAM NIM type.
+
+
+@param [in]    pNim       The NIM module pointer
+@param [out]   pNimType   Pointer to an allocated memory for storing NIM type
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_GET_NIM_TYPE() with the corresponding function.
+
+
+@see   MODULE_TYPE
+
+*/
+typedef void
+(*QAM_NIM_FP_GET_NIM_TYPE)(
+	QAM_NIM_MODULE *pNim,
+	int *pNimType
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM initializing function pointer
+
+One can use QAM_NIM_FP_INITIALIZE() to initialie QAM NIM.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Initialize NIM successfully.
+@retval   FUNCTION_ERROR     Initialize NIM unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_INITIALIZE() with the corresponding function.
+
+*/
+typedef int
+(*QAM_NIM_FP_INITIALIZE)(
+	QAM_NIM_MODULE *pNim
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM parameter setting function pointer
+
+One can use QAM_NIM_FP_SET_PARAMETERS() to set QAM NIM parameters.
+
+
+@param [in]   pNim           The NIM module pointer
+@param [in]   RfFreqHz       RF frequency in Hz for setting
+@param [in]   QamMode        QAM mode for setting
+@param [in]   SymbolRateHz   Symbol rate in Hz for setting
+@param [in]   AlphaMode      Alpha mode for setting
+
+
+@retval   FUNCTION_SUCCESS   Set NIM parameters successfully.
+@retval   FUNCTION_ERROR     Set NIM parameters unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_SET_PARAMETERS() with the corresponding function.
+
+
+@see   QAM_QAM_MODE, QAM_ALPHA_MODE
+
+*/
+typedef int
+(*QAM_NIM_FP_SET_PARAMETERS)(
+	QAM_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int QamMode,
+	unsigned long SymbolRateHz,
+	int AlphaMode
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM parameter getting function pointer
+
+One can use QAM_NIM_FP_GET_PARAMETERS() to get QAM NIM parameters.
+
+
+@param [in]    pNim            The NIM module pointer
+@param [out]   pRfFreqHz       Pointer to an allocated memory for storing NIM RF frequency in Hz
+@param [out]   pQamMode        Pointer to an allocated memory for storing NIM QAM mode
+@param [out]   pSymbolRateHz   Pointer to an allocated memory for storing NIM symbol rate in Hz
+@param [out]   pAlphaMode      Pointer to an allocated memory for storing NIM alpha mode
+
+
+@retval   FUNCTION_SUCCESS   Get NIM parameters successfully.
+@retval   FUNCTION_ERROR     Get NIM parameters unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_GET_PARAMETERS() with the corresponding function.
+
+
+@see   QAM_QAM_MODE, QAM_ALPHA_MODE
+
+*/
+typedef int
+(*QAM_NIM_FP_GET_PARAMETERS)(
+	QAM_NIM_MODULE *pNim,
+	unsigned long *pRfFreqHz,
+	int *pQamMode,
+	unsigned long *pSymbolRateHz,
+	int *pAlphaMode
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM signal present asking function pointer
+
+One can use QAM_NIM_FP_IS_SIGNAL_PRESENT() to ask QAM NIM if signal is present.
+
+
+@param [in]    pNim      The NIM module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform signal present asking to NIM successfully.
+@retval   FUNCTION_ERROR     Perform signal present asking to NIM unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_IS_SIGNAL_PRESENT() with the corresponding function.
+
+*/
+typedef int
+(*QAM_NIM_FP_IS_SIGNAL_PRESENT)(
+	QAM_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM signal lock asking function pointer
+
+One can use QAM_NIM_FP_IS_SIGNAL_LOCKED() to ask QAM NIM if signal is locked.
+
+
+@param [in]    pNim      The NIM module pointer
+@param [out]   pAnswer   Pointer to an allocated memory for storing answer
+
+
+@retval   FUNCTION_SUCCESS   Perform signal lock asking to NIM successfully.
+@retval   FUNCTION_ERROR     Perform signal lock asking to NIM unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_IS_SIGNAL_LOCKED() with the corresponding function.
+
+*/
+typedef int
+(*QAM_NIM_FP_IS_SIGNAL_LOCKED)(
+	QAM_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM signal strength getting function pointer
+
+One can use QAM_NIM_FP_GET_SIGNAL_STRENGTH() to get signal strength.
+
+
+@param [in]    pNim              The NIM module pointer
+@param [out]   pSignalStrength   Pointer to an allocated memory for storing signal strength (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get NIM signal strength successfully.
+@retval   FUNCTION_ERROR     Get NIM signal strength unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_GET_SIGNAL_STRENGTH() with the corresponding function.
+
+*/
+typedef int
+(*QAM_NIM_FP_GET_SIGNAL_STRENGTH)(
+	QAM_NIM_MODULE *pNim,
+	unsigned long *pSignalStrength
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM signal quality getting function pointer
+
+One can use QAM_NIM_FP_GET_SIGNAL_QUALITY() to get signal quality.
+
+
+@param [in]    pNim             The NIM module pointer
+@param [out]   pSignalQuality   Pointer to an allocated memory for storing signal quality (value = 0 ~ 100)
+
+
+@retval   FUNCTION_SUCCESS   Get NIM signal quality successfully.
+@retval   FUNCTION_ERROR     Get NIM signal quality unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_GET_SIGNAL_QUALITY() with the corresponding function.
+
+*/
+typedef int
+(*QAM_NIM_FP_GET_SIGNAL_QUALITY)(
+	QAM_NIM_MODULE *pNim,
+	unsigned long *pSignalQuality
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM error rate value getting function pointer
+
+One can use QAM_NIM_FP_GET_ERROR_RATE() to get error rate value.
+
+
+@param [in]    pNim            The NIM module pointer
+@param [in]    TestVolume      Test volume for setting
+@param [in]    WaitTimeMsMax   Maximum waiting time in ms
+@param [out]   pBerNum         Pointer to an allocated memory for storing BER numerator
+@param [out]   pBerDen         Pointer to an allocated memory for storing BER denominator
+@param [out]   pPerNum         Pointer to an allocated memory for storing PER numerator
+@param [out]   pPerDen         Pointer to an allocated memory for storing PER denominator
+
+
+@retval   FUNCTION_SUCCESS   Get NIM error rate value successfully.
+@retval   FUNCTION_ERROR     Get NIM error rate value unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_GET_ERROR_RATE() with the corresponding function.
+	-# The error test packet number is pow(2, (2 * TestVolume + 4)).
+
+*/
+typedef int
+(*QAM_NIM_FP_GET_ERROR_RATE)(
+	QAM_NIM_MODULE *pNim,
+	unsigned long TestVolume,
+	unsigned int WaitTimeMsMax,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM SNR getting function pointer
+
+One can use QAM_NIM_FP_GET_SNR_DB() to get SNR in dB.
+
+
+@param [in]    pNim        The NIM module pointer
+@param [out]   pSnrDbNum   Pointer to an allocated memory for storing SNR dB numerator
+@param [out]   pSnrDbDen   Pointer to an allocated memory for storing SNR dB denominator
+
+
+@retval   FUNCTION_SUCCESS   Get NIM SNR successfully.
+@retval   FUNCTION_ERROR     Get NIM SNR unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_GET_SNR_DB() with the corresponding function.
+
+*/
+typedef int
+(*QAM_NIM_FP_GET_SNR_DB)(
+	QAM_NIM_MODULE *pNim,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM TR offset getting function pointer
+
+One can use QAM_NIM_FP_GET_TR_OFFSET_PPM() to get TR offset in ppm.
+
+
+@param [in]    pNim           The NIM module pointer
+@param [out]   pTrOffsetPpm   Pointer to an allocated memory for storing TR offset in ppm
+
+
+@retval   FUNCTION_SUCCESS   Get NIM TR offset successfully.
+@retval   FUNCTION_ERROR     Get NIM TR offset unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_GET_TR_OFFSET_PPM() with the corresponding function.
+
+*/
+typedef int
+(*QAM_NIM_FP_GET_TR_OFFSET_PPM)(
+	QAM_NIM_MODULE *pNim,
+	long *pTrOffsetPpm
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM CR offset getting function pointer
+
+One can use QAM_NIM_FP_GET_CR_OFFSET_HZ() to get CR offset in Hz.
+
+
+@param [in]    pNim          The NIM module pointer
+@param [out]   pCrOffsetHz   Pointer to an allocated memory for storing CR offset in Hz
+
+
+@retval   FUNCTION_SUCCESS   Get NIM CR offset successfully.
+@retval   FUNCTION_ERROR     Get NIM CR offset unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_GET_CR_OFFSET_HZ() with the corresponding function.
+
+*/
+typedef int
+(*QAM_NIM_FP_GET_CR_OFFSET_HZ)(
+	QAM_NIM_MODULE *pNim,
+	long *pCrOffsetHz
+	);
+
+
+
+
+
+/**
+
+@brief   QAM NIM updating function pointer
+
+One can use QAM_NIM_FP_UPDATE_FUNCTION() to update NIM register setting.
+
+
+@param [in]   pNim   The NIM module pointer
+
+
+@retval   FUNCTION_SUCCESS   Update NIM setting successfully.
+@retval   FUNCTION_ERROR     Update NIM setting unsuccessfully.
+
+
+@note
+	-# NIM building function will set QAM_NIM_FP_UPDATE_FUNCTION() with the corresponding function.
+
+
+
+@par Example:
+@code
+
+
+#include "nim_demodx_tunery.h"
+
+
+int main(void)
+{
+	QAM_NIM_MODULE *pNim;
+	QAM_NIM_MODULE QamNimModuleMemory;
+	DEMODX_EXTRA_MODULE DemodxExtraModuleMemory;
+	TUNERY_EXTRA_MODULE TuneryExtraModuleMemory;
+
+
+	// Build Demod-X Tuner-Y NIM module.
+	BuildDemodxTuneryModule(
+		...
+		);
+
+	...
+
+
+	return 0;
+}
+
+
+void PeriodicallyExecutingFunction
+{
+	// Executing UpdateFunction() periodically.
+	pNim->UpdateFunction(pNim);
+}
+
+
+@endcode
+
+*/
+typedef int
+(*QAM_NIM_FP_UPDATE_FUNCTION)(
+	QAM_NIM_MODULE *pNim
+	);
+
+
+
+
+
+// RTL2840 MT2062 extra module
+typedef struct RTL2840_MT2062_EXTRA_MODULE_TAG RTL2840_MT2062_EXTRA_MODULE;
+struct RTL2840_MT2062_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long IfFreqHz;
+};
+
+
+
+
+
+// RTL2840 MT2063 extra module
+typedef struct RTL2840_MT2063_EXTRA_MODULE_TAG RTL2840_MT2063_EXTRA_MODULE;
+struct RTL2840_MT2063_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long IfFreqHz;
+};
+
+
+
+
+
+// RTD2840B QAM MT2062 extra module
+typedef struct RTD2840B_QAM_MT2062_EXTRA_MODULE_TAG RTD2840B_QAM_MT2062_EXTRA_MODULE;
+struct RTD2840B_QAM_MT2062_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long IfFreqHz;
+};
+
+
+
+
+
+// RTL2836B DVBC FC0013B extra module
+typedef struct RTL2836B_DVBC_FC0013B_EXTRA_MODULE_TAG RTL2836B_DVBC_FC0013B_EXTRA_MODULE;
+struct RTL2836B_DVBC_FC0013B_EXTRA_MODULE_TAG
+{
+	// Extra variables
+	unsigned long LnaUpdateWaitTimeMax;
+	unsigned long LnaUpdateWaitTime;
+	unsigned long RssiRCalOn;
+};
+
+
+
+
+
+/// QAM NIM module structure
+struct QAM_NIM_MODULE_TAG
+{
+	// Private variables
+	int NimType;
+	int EnhancementMode;
+	int ConfigMode;
+
+	union														///<   NIM extra module used by driving module
+	{
+		RTL2840_MT2062_EXTRA_MODULE Rtl2840Mt2062;
+		RTL2840_MT2063_EXTRA_MODULE Rtl2840Mt2063;
+		RTD2840B_QAM_MT2062_EXTRA_MODULE  Rtd2840bQamMt2062;
+		RTL2836B_DVBC_FC0013B_EXTRA_MODULE  Rtl2836bDvbcFc0013b;
+	}
+	Extra;
+
+
+	// Modules
+	BASE_INTERFACE_MODULE *pBaseInterface;						///<   Base interface module pointer
+	BASE_INTERFACE_MODULE BaseInterfaceModuleMemory;			///<   Base interface module memory
+
+	I2C_BRIDGE_MODULE *pI2cBridge;								///<   I2C bridge module pointer
+	I2C_BRIDGE_MODULE I2cBridgeModuleMemory;					///<   I2C bridge module memory
+
+	TUNER_MODULE *pTuner;										///<   Tuner module pointer
+	TUNER_MODULE TunerModuleMemory;								///<   Tuner module memory
+
+	QAM_DEMOD_MODULE *pDemod;									///<   QAM demod module pointer
+	QAM_DEMOD_MODULE QamDemodModuleMemory;						///<   QAM demod module memory
+
+
+	// NIM manipulating functions
+	QAM_NIM_FP_GET_NIM_TYPE          GetNimType;
+	QAM_NIM_FP_INITIALIZE            Initialize;
+	QAM_NIM_FP_SET_PARAMETERS        SetParameters;
+	QAM_NIM_FP_GET_PARAMETERS        GetParameters;
+	QAM_NIM_FP_IS_SIGNAL_PRESENT     IsSignalPresent;
+	QAM_NIM_FP_IS_SIGNAL_LOCKED      IsSignalLocked;
+	QAM_NIM_FP_GET_SIGNAL_STRENGTH   GetSignalStrength;
+	QAM_NIM_FP_GET_SIGNAL_QUALITY    GetSignalQuality;
+	QAM_NIM_FP_GET_ERROR_RATE        GetErrorRate;
+	QAM_NIM_FP_GET_SNR_DB            GetSnrDb;
+	QAM_NIM_FP_GET_TR_OFFSET_PPM     GetTrOffsetPpm;
+	QAM_NIM_FP_GET_CR_OFFSET_HZ      GetCrOffsetHz;
+	QAM_NIM_FP_UPDATE_FUNCTION       UpdateFunction;
+};
+
+
+
+
+
+
+
+// QAM NIM default manipulaing functions
+void
+qam_nim_default_GetNimType(
+	QAM_NIM_MODULE *pNim,
+	int *pNimType
+	);
+
+int
+qam_nim_default_SetParameters(
+	QAM_NIM_MODULE *pNim,
+	unsigned long RfFreqHz,
+	int QamMode,
+	unsigned long SymbolRateHz,
+	int AlphaMode
+	);
+
+int
+qam_nim_default_GetParameters(
+	QAM_NIM_MODULE *pNim,
+	unsigned long *pRfFreqHz,
+	int *pQamMode,
+	unsigned long *pSymbolRateHz,
+	int *pAlphaMode
+	);
+
+int
+qam_nim_default_IsSignalPresent(
+	QAM_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+int
+qam_nim_default_IsSignalLocked(
+	QAM_NIM_MODULE *pNim,
+	int *pAnswer
+	);
+
+int
+qam_nim_default_GetSignalStrength(
+	QAM_NIM_MODULE *pNim,
+	unsigned long *pSignalStrength
+	);
+
+int
+qam_nim_default_GetSignalQuality(
+	QAM_NIM_MODULE *pNim,
+	unsigned long *pSignalQuality
+	);
+
+int
+qam_nim_default_GetErrorRate(
+	QAM_NIM_MODULE *pNim,
+	unsigned long TestVolume,
+	unsigned int WaitTimeMsMax,
+	unsigned long *pBerNum,
+	unsigned long *pBerDen,
+	unsigned long *pPerNum,
+	unsigned long *pPerDen
+	);
+
+int
+qam_nim_default_GetSnrDb(
+	QAM_NIM_MODULE *pNim,
+	long *pSnrDbNum,
+	long *pSnrDbDen
+	);
+
+int
+qam_nim_default_GetTrOffsetPpm(
+	QAM_NIM_MODULE *pNim,
+	long *pTrOffsetPpm
+	);
+
+int
+qam_nim_default_GetCrOffsetHz(
+	QAM_NIM_MODULE *pNim,
+	long *pCrOffsetHz
+	);
+
+int
+qam_nim_default_UpdateFunction(
+	QAM_NIM_MODULE *pNim
+	);
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/media/usb/dvb-usb/rtl2832u.c b/drivers/media/usb/dvb-usb/rtl2832u.c
new file mode 100644
index 0000000..4d0b710
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/rtl2832u.c
@@ -0,0 +1,1745 @@
+
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include "rtl2832u.h"
+#include "rtl2832u_io.h"
+#include "rtl2832u_audio.h"
+//#include "rtl2832u_ioctl.h"
+
+int dvb_usb_rtl2832u_debug=0;
+module_param_named(debug,dvb_usb_rtl2832u_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Set debugging level (1=info,xfer=2 (or-able),rc=3)." DVB_USB_DEBUG_STATUS);
+
+int demod_default_type=0;
+module_param_named(demod, demod_default_type, int, 0644);
+MODULE_PARM_DESC(demod, "Set default demod type(0=dvb-t, 1=dtmb, 2=dvb-c)"DVB_USB_DEBUG_STATUS);
+
+int dtmb_error_packet_discard;
+module_param_named(dtmb_err_discard, dtmb_error_packet_discard, int, 0644);
+MODULE_PARM_DESC(dtmb_err_discard, "Set error packet discard type(0=not discard, 1=discard)"DVB_USB_DEBUG_STATUS);
+
+int dvb_use_rtl2832u_rc_mode=2;
+module_param_named(rtl2832u_rc_mode, dvb_use_rtl2832u_rc_mode, int, 0644);
+MODULE_PARM_DESC(rtl2832u_rc_mode, "Set default rtl2832u_rc_mode(0=rc6, 1=rc5, 2=nec, 3=disable rc, default=2)."DVB_USB_DEBUG_STATUS);
+
+int dvb_use_rtl2832u_card_type=0;
+module_param_named(rtl2832u_card_type, dvb_use_rtl2832u_card_type, int, 0644);
+MODULE_PARM_DESC(rtl2832u_card_type, "Set default rtl2832u_card_type type(0=dongle, 1=mini card, default=0)."DVB_USB_DEBUG_STATUS);
+
+int dvb_usb_rtl2832u_snrdb=0;
+module_param_named(snrdb,dvb_usb_rtl2832u_snrdb, int, 0644);
+MODULE_PARM_DESC(snrdb, "SNR type output (0=16bit, 1=dB decibel), default=0");
+
+
+
+
+//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+//#endif
+
+#define	USB_EPA_CTL	0x0148
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define RT_RC_POLLING_INTERVAL_TIME_MS			287
+#define MAX_RC_PROTOCOL_NUM				3			
+
+/* original realtek remote control key map */
+/*
+static struct dvb_usb_rc_key rtl2832u_rc_keys_map_table[] = {// realtek Key map   	
+		{ 0x0400, KEY_0 },           // 0 
+		{ 0x0401, KEY_1 },           // 1 
+		{ 0x0402, KEY_2 },           // 2 
+		{ 0x0403, KEY_3 },           // 3 
+		{ 0x0404, KEY_4 },           // 4 
+		{ 0x0405, KEY_5 },           // 5 
+		{ 0x0406, KEY_6 },           // 6 
+		{ 0x0407, KEY_7 },           // 7 
+		{ 0x0408, KEY_8 },           // 8 
+		{ 0x0409, KEY_9 },           // 9 
+		{ 0x040c, KEY_POWER },       // POWER 
+		{ 0x040e, KEY_MUTE },        // MUTE 
+		{ 0x0410, KEY_VOLUMEUP },    // VOL UP 
+		{ 0x0411, KEY_VOLUMEDOWN },  // VOL DOWN 
+		{ 0x0412, KEY_CHANNELUP },   // CH UP 
+		{ 0x0413, KEY_CHANNELDOWN }, // CH DOWN 
+		{ 0x0416, KEY_PLAY },        // PLAY 
+		{ 0x0417, KEY_RECORD },      // RECORD 
+		{ 0x0418, KEY_PLAYPAUSE },   // PAUSE 
+		{ 0x0419, KEY_STOP },        // STOP 
+		{ 0x041e, KEY_UP},	     // UP
+		{ 0x041f, KEY_DOWN},	     // DOWN
+		{ 0x0420, KEY_LEFT },        // LEFT
+		{ 0x0421, KEY_RIGHT },       // RIGHT
+		{ 0x0422, KEY_ZOOM },        // FULL SCREEN  -->OK 
+		{ 0x0447, KEY_AUDIO },       // MY AUDIO 
+		{ 0x045b, KEY_MENU},         // RED 
+		{ 0x045c, KEY_EPG },         // GREEN 
+		{ 0x045d, KEY_FIRST },       // YELLOW
+		{ 0x045e, KEY_LAST },        // BLUE
+		{ 0x045a, KEY_TEXT },        // TEXT TV
+	 	{ 0x0423, KEY_BACK },        // <- BACK
+		{ 0x0414, KEY_FORWARD }    // >> 
+	};
+*/
+
+/* Xgazza remote control Ubuntu 11.10 key map */
+static struct rc_map_table rtl2832u_rc_keys_map_table[] = {
+	{ 0x40bf, KEY_POWER2 },        // TV POWER
+	{ 0x08f7, KEY_POWER },         // PC POWER
+	{ 0x58a7, KEY_REWIND },        // REWIND
+	{ 0xd827, KEY_PLAY },          // PLAY
+	{ 0x22dd, KEY_FASTFORWARD },   // FAST FORWARD
+	{ 0x02fd, KEY_STOP },          // STOP
+	{ 0x5aa5, KEY_PREVIOUS },      // SKIP BACK
+	{ 0x42bd, KEY_PLAYPAUSE },     // PAUSE
+	{ 0xa25d, KEY_NEXT },          // SKIP FOWARD
+	{ 0x12ed, KEY_RECORD },        // RECORD
+	{ 0x28d7, KEY_BACK },          // BACK
+	{ 0xa857, KEY_INFO },          // MORE
+//	{ 0x28d7, BTN_LEFT },          // MOUSE LEFT BUTTON
+//	{ 0xa857, BTN_RIGHT },         // MOUSE RIGHT BUTTON
+	{ 0x6897, KEY_UP},             // UP
+	{ 0x48b7, KEY_DOWN},           // DOWN
+	{ 0xe817, KEY_LEFT },          // LEFT
+	{ 0x30cf, KEY_RIGHT },         // RIGHT
+	{ 0x18e7, KEY_OK },            // OK 
+	{ 0xc23d, KEY_ZOOM },          // ASPECT
+//	{ 0xea15, KEY_??? },           // MOUSE
+	{ 0x708f, KEY_RED },           // RED 
+	{ 0xc837, KEY_GREEN },         // GREEN 
+	{ 0x8877, KEY_YELLOW },        // YELLOW
+	{ 0x9867, KEY_BLUE },          // BLUE
+	{ 0x807f, KEY_VOLUMEUP },      // VOL UP 
+	{ 0x7887, KEY_VOLUMEDOWN },    // VOL DOWN 
+	{ 0xb04f, KEY_HOME },          // HOME
+	{ 0x00ff, KEY_MUTE },          // MUTE 
+	{ 0xd22d, KEY_CHANNELUP },     // CH UP 
+	{ 0xf20d, KEY_CHANNELDOWN },   // CH DOWN 
+	{ 0x50af, KEY_0 },             // 0 
+	{ 0xf807, KEY_1 },             // 1 
+	{ 0xc03f, KEY_2 },             // 2 
+	{ 0x20df, KEY_3 },             // 3 
+	{ 0xa05f, KEY_4 },             // 4 
+	{ 0x38c7, KEY_5 },             // 5 
+	{ 0x609f, KEY_6 },             // 6 
+	{ 0xe01f, KEY_7 },             // 7 
+	{ 0x10ef, KEY_8 },             // 8 
+	{ 0xb847, KEY_9 },             // 9
+	{ 0x906f, KEY_NUMERIC_STAR },  // *
+	{ 0xd02f, KEY_NUMERIC_POUND }, // #
+	{ 0x52ad, KEY_EPG },           // GUIDE
+	{ 0x926d, KEY_VIDEO },         // RTV
+	{ 0x32cd, KEY_HELP },          // HELP
+	{ 0xca35, KEY_CYCLEWINDOWS },  // PIP(?)
+	{ 0xb24d, KEY_RADIO },         // RADIO
+	{ 0x0af5, KEY_DVD },           // DVD
+	{ 0x8a75, KEY_AUDIO },         // AUDIO
+	{ 0x4ab5, KEY_TITLE }          // TITLE
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+enum   rc_status_define{
+	RC_FUNCTION_SUCCESS =0,
+	RC_FUNCTION_UNSUCCESS
+};
+
+int rtl2832u_remote_control_state=0;
+static int SampleNum2TNum[] = 
+{
+	0,0,0,0,0,				
+	1,1,1,1,1,1,1,1,1,			
+	2,2,2,2,2,2,2,2,2,			
+	3,3,3,3,3,3,3,3,3,			
+	4,4,4,4,4,4,4,4,4,			
+	5,5,5,5,5,5,5,5,			
+	6,6,6,6,6,6,6,6,6,			
+	7,7,7,7,7,7,7,7,7,			
+	8,8,8,8,8,8,8,8,8,			
+	9,9,9,9,9,9,9,9,9,			
+	10,10,10,10,10,10,10,10,10,	
+	11,11,11,11,11,11,11,11,11,	
+	12,12,12,12,12,12,12,12,12,	
+	13,13,13,13,13,13,13,13,13,	
+	14,14,14,14,14,14,14		
+};
+//IRRC register table 
+static const RT_rc_set_reg_struct p_rtl2832u_rc_initial_table[]= 
+{
+		{RTD2832U_SYS,RC_USE_DEMOD_CTL1		,0x00,OP_AND,0xfb},
+		{RTD2832U_SYS,RC_USE_DEMOD_CTL1		,0x00,OP_AND,0xf7}, 
+		{RTD2832U_USB,USB_CTRL			,0x00,OP_OR ,0x20}, 
+		{RTD2832U_SYS,SYS_GPD			,0x00,OP_AND,0xf7}, 
+		{RTD2832U_SYS,SYS_GPOE			,0x00,OP_OR ,0x08}, 
+		{RTD2832U_SYS,SYS_GPO			,0x00,OP_OR ,0x08}, 		
+		{RTD2832U_RC,IR_RX_CTRL			,0x20,OP_NO ,0xff},
+		{RTD2832U_RC,IR_RX_BUFFER_CTRL		,0x80,OP_NO ,0xff},
+		{RTD2832U_RC,IR_RX_IF			,0xff,OP_NO ,0xff},
+		{RTD2832U_RC,IR_RX_IE			,0xff,OP_NO ,0xff},
+		{RTD2832U_RC,IR_MAX_DURATION0		,0xd0,OP_NO ,0xff},
+		{RTD2832U_RC,IR_MAX_DURATION1		,0x07,OP_NO ,0xff},
+		{RTD2832U_RC,IR_IDLE_LEN0		,0xc0,OP_NO ,0xff},
+		{RTD2832U_RC,IR_IDLE_LEN1		,0x00,OP_NO ,0xff},
+		{RTD2832U_RC,IR_GLITCH_LEN		,0x03,OP_NO ,0xff},
+		{RTD2832U_RC,IR_RX_CLK			,0x09,OP_NO ,0xff},
+		{RTD2832U_RC,IR_RX_CONFIG		,0x1c,OP_NO ,0xff},
+		{RTD2832U_RC,IR_MAX_H_Tolerance_LEN	,0x1e,OP_NO ,0xff},
+		{RTD2832U_RC,IR_MAX_L_Tolerance_LEN	,0x1e,OP_NO ,0xff},        
+		{RTD2832U_RC,IR_RX_CTRL			,0x80,OP_NO ,0xff} 
+		
+};
+	
+int rtl2832u_remoto_control_initial_setting(struct dvb_usb_device *d)
+{ 
+	
+
+
+	//begin setting
+	int ret = RC_FUNCTION_SUCCESS;
+	u8 data=0,i=0,NumberOfRcInitialTable=0;
+
+
+	deb_rc("+rc_%s\n", __FUNCTION__);
+
+	NumberOfRcInitialTable = sizeof(p_rtl2832u_rc_initial_table)/sizeof(RT_rc_set_reg_struct);
+	
+
+	for (i=0;i<NumberOfRcInitialTable;i++)
+	{	
+		switch(p_rtl2832u_rc_initial_table[i].type)
+		{
+			case RTD2832U_SYS:
+			case RTD2832U_USB:
+				data=p_rtl2832u_rc_initial_table[i].data;
+				if (p_rtl2832u_rc_initial_table[i].op != OP_NO)
+				{
+					if ( read_usb_sys_char_bytes( d , 
+								      p_rtl2832u_rc_initial_table[i].type , 
+								      p_rtl2832u_rc_initial_table[i].address,
+								      &data , 
+								      LEN_1) ) 
+					{
+						deb_rc("+%s : rc- usb or sys register read error! \n", __FUNCTION__);
+						ret=RC_FUNCTION_UNSUCCESS;
+						goto error;
+					}					
+				
+					if (p_rtl2832u_rc_initial_table[i].op == OP_AND){
+					        data &=  p_rtl2832u_rc_initial_table[i].op_mask;	
+					}
+					else{//OP_OR
+						data |=  p_rtl2832u_rc_initial_table[i].op_mask;
+					}			
+				}
+				
+				if ( write_usb_sys_char_bytes( d , 
+							      p_rtl2832u_rc_initial_table[i].type , 
+							      p_rtl2832u_rc_initial_table[i].address,
+							      &data , 
+							      LEN_1) ) 
+				{
+						deb_rc("+%s : rc- usb or sys register write error! \n", __FUNCTION__);
+						ret= RC_FUNCTION_UNSUCCESS;
+						goto error;
+				}
+		
+			break;
+			case RTD2832U_RC:
+				data= p_rtl2832u_rc_initial_table[i].data;
+				if (p_rtl2832u_rc_initial_table[i].op != OP_NO)
+				{
+					if ( read_rc_char_bytes( d , 
+								 p_rtl2832u_rc_initial_table[i].type , 
+								 p_rtl2832u_rc_initial_table[i].address,
+								 &data , 
+								 LEN_1) ) 
+					{
+						deb_rc("+%s : rc -ir register read error! \n", __FUNCTION__);
+						ret=RC_FUNCTION_UNSUCCESS;
+						goto error;
+					}					
+				
+					if (p_rtl2832u_rc_initial_table[i].op == OP_AND){
+					        data &=  p_rtl2832u_rc_initial_table[i].op_mask;	
+					}
+					else{//OP_OR
+					    data |=  p_rtl2832u_rc_initial_table[i].op_mask;
+					}			
+				}
+				if ( write_rc_char_bytes( d , 
+							      p_rtl2832u_rc_initial_table[i].type , 
+							      p_rtl2832u_rc_initial_table[i].address,
+							      &data , 
+							      LEN_1) ) 
+				{
+					deb_rc("+%s : rc -ir register write error! \n", __FUNCTION__);
+					ret=RC_FUNCTION_UNSUCCESS;
+					goto error;
+				}
+
+			break;
+			default:
+				deb_rc("+%s : rc table error! \n", __FUNCTION__);
+				ret=RC_FUNCTION_UNSUCCESS;
+				goto error;			     	
+			break;	
+		}	
+	}
+	rtl2832u_remote_control_state=RC_INSTALL_OK;
+	ret=RC_FUNCTION_SUCCESS;
+error: 
+	deb_rc("-rc_%s ret = %d \n", __FUNCTION__, ret);
+	return ret;
+
+	
+}
+
+
+static int frt0(u8* rt_uccode,u8 byte_num,u8 *p_uccode)
+{
+	u8 *pCode = rt_uccode;
+	int TNum =0;
+	u8   ucBits[frt0_bits_num];
+	u8  i=0,state=WAITING_6T;
+	int  LastTNum = 0,CurrentBit = 0;
+	int ret=RC_FUNCTION_SUCCESS;
+	u8 highestBit = 0,lowBits=0;
+	u32 scancode=0;
+	
+	if(byte_num < frt0_para1){
+		deb_rc("Bad rt uc code received, byte_num is error\n");
+		ret= RC_FUNCTION_UNSUCCESS;
+		goto error;
+	}
+	while(byte_num > 0)
+	{
+
+		highestBit = (*pCode)&0x80;
+		lowBits = (*pCode) & 0x7f;
+		TNum=SampleNum2TNum[lowBits];
+		
+		if(highestBit != 0)	TNum = -TNum;
+
+		pCode++;
+		byte_num--;
+
+		if(TNum <= -6)	 state = WAITING_6T;
+
+		if(WAITING_6T == state)
+		{
+			if(TNum <= -6)	state = WAITING_2T_AFTER_6T;
+		}
+		else if(WAITING_2T_AFTER_6T == state)
+		{
+			if(2 == TNum)	
+			{
+				state = WAITING_NORMAL_BITS;
+				LastTNum   = 0;
+				CurrentBit = 0;
+			}
+			else 	state = WAITING_6T;
+		} 
+		else if(WAITING_NORMAL_BITS == state)
+		{
+			if(0 == LastTNum)	LastTNum = TNum;
+			else	{
+				if(LastTNum < 0)	ucBits[CurrentBit]=1;
+				else			ucBits[CurrentBit]=0;
+
+				CurrentBit++;
+
+				if(CurrentBit >= frt0_bits_num)	{
+ 					deb_rc("Bad frame received, bits num is error\n");
+					CurrentBit = frt0_bits_num -1 ;
+
+				}
+				if(TNum > 3)	{
+						for(i=0;i<frt0_para2;i++){
+							if (ucBits[i+frt0_para4])	scancode  |= (0x01 << (frt0_para2-i-1));
+						}	
+				}
+				else{
+					LastTNum += TNum;	
+				}							
+			}			
+		}	
+
+	}
+	p_uccode[0]=(u8)((scancode>>24)  &  frt0_BITS_mask0);
+	p_uccode[1]=(u8)((scancode>>16)  &  frt0_BITS_mask1);
+	p_uccode[2]=(u8)((scancode>>8)  & frt0_BITS_mask2);
+	p_uccode[3]=(u8)((scancode>>0)  & frt0_BITS_mask3);
+	
+	deb_rc("-rc_%s 3::rc6:%x %x %x %x \n", __FUNCTION__,p_uccode[0],p_uccode[1],p_uccode[2],p_uccode[3]);
+	ret= RC_FUNCTION_SUCCESS;
+error:
+
+	return ret;
+}
+
+
+static int frt1(u8* rt_uccode,u8 byte_num,u8 *p_uccode)
+{
+	u8 *pCode = rt_uccode;
+	u8  ucBits[frt1_bits_num];
+	u8 i=0,CurrentBit=0,index=0;
+	u32 scancode=0;
+	int ret= RC_FUNCTION_SUCCESS;
+
+	deb_rc("+rc_%s \n", __FUNCTION__);
+	if(byte_num < frt1_para1)	{
+		deb_rc("Bad rt uc code received, byte_num = %d is error\n",byte_num);
+		ret = RC_FUNCTION_UNSUCCESS;
+		goto error;
+	}
+	
+	memset(ucBits,0,frt1_bits_num);		
+
+	for(i = 0; i < byte_num; i++)	{
+		if ((pCode[i] & frt1_para2)< frt1_para3)    index=frt1_para5 ;   
+		else 					    index=frt1_para6 ;  
+
+		ucBits[i]= (pCode[i] & 0x80) + index;
+	}
+	if(ucBits[0] !=frt1_para_uc_1 && ucBits[0] !=frt1_para_uc_2 )   {ret= RC_FUNCTION_UNSUCCESS; goto error;}
+
+	if(ucBits[1] !=frt1_para5  && ucBits[1] !=frt1_para6)   	{ret= RC_FUNCTION_UNSUCCESS;goto error;}
+
+	if(ucBits[2] >= frt1_para_uc_1)  				ucBits[2] -= 0x01;
+	else			 					{ret= RC_FUNCTION_UNSUCCESS;goto error;}
+
+	
+   	i = 0x02;
+	CurrentBit = 0x00;
+
+	while(i < byte_num-1)
+	{
+		if(CurrentBit >= 32)	{
+			break;
+		}	
+
+		if((ucBits[i] & 0x0f) == 0x0)	{
+			i++;
+			continue;
+		}
+		if(ucBits[i++] == 0x81)	{
+						if(ucBits[i] >=0x01)	{
+							scancode |= 0x00 << (31 - CurrentBit++);
+						}	 							
+		}
+		else	{
+				if(ucBits[i] >=0x81)	{
+					scancode |= 0x01 << (31 - CurrentBit++); 
+				}
+		}
+				
+		ucBits[i] -= 0x01;
+		continue;
+	}
+	p_uccode[3]=(u8)((scancode>>16)  &  frt1_bits_mask3);
+	p_uccode[2]=(u8)((scancode>>24)  &  frt1_bits_mask2);
+	p_uccode[1]=(u8)((scancode>>8)   &  frt1_bits_mask1);
+	p_uccode[0]=(u8)((scancode>>0)   &  frt1_bits_mask0);
+
+	
+	deb_rc("-rc_%s rc5:%x %x %x %x -->scancode =%x\n", __FUNCTION__,p_uccode[0],p_uccode[1],p_uccode[2],p_uccode[3],scancode);
+	ret= RC_FUNCTION_SUCCESS;
+error:
+	return ret;
+}
+
+static int frt2(u8* rt_uccode,u8 byte_num,u8 *p_uccode)
+{
+	u8 *pCode = rt_uccode;
+	u8  i=0;
+	u32 scancode=0;
+	u8  out_io=0;
+			
+	int ret= RC_FUNCTION_SUCCESS;
+
+	deb_rc("+rc_%s \n", __FUNCTION__);
+
+	if(byte_num < frt2_para1)  				goto error;
+    	if(pCode[0] != frt2_para2) 				goto error;
+	if((pCode[1] <frt2_para3 )||(pCode[1] >frt2_para4))	goto error;	
+
+
+	if( (pCode[2] <frt2_para5 ) && (pCode[2] >frt2_para6) )   
+	{ 
+
+		if( (pCode[3] <frt2_para7 ) && (pCode[3] >frt2_para8 ) &&(pCode[4]==frt2_para9 ))  scancode=0xffff;
+		else goto error;
+
+	}
+	else if( (pCode[2] <frt2_para10  ) && (pCode[2] >frt2_para11 ) ) 
+	{
+
+	 	for (i = 3; i <68; i++)
+		{  
+                        if ((i% 2)==1)
+			{
+				if( (pCode[i]>frt2_para7 ) || (pCode[i] <frt2_para8 ) )  
+				{ 
+					deb_rc("Bad rt uc code received[4]\n");
+					ret= RC_FUNCTION_UNSUCCESS;
+					goto error;
+				}			
+			}
+			else
+			{
+				if(pCode[i]<frt2_para12  )  out_io=0;
+				else			    out_io=1;
+				scancode |= (out_io << (31 -(i-4)/2) );
+			}
+		} 
+
+
+
+	}
+	else  	goto error;
+	deb_rc("-rc_%s nec:%x\n", __FUNCTION__,scancode);
+	p_uccode[0]=(u8)((scancode>>24)  &  frt2_bits_mask0);
+	p_uccode[1]=(u8)((scancode>>16)  &  frt2_bits_mask1);
+	p_uccode[2]=(u8)((scancode>>8)   &  frt2_bits_mask2);
+	p_uccode[3]=(u8)((scancode>>0)   &  frt2_bits_mask3);
+	ret= RC_FUNCTION_SUCCESS;
+error:	
+
+	return ret;
+}
+#define receiveMaskFlag1  0x80
+#define receiveMaskFlag2  0x03
+#define flush_step_Number 0x05
+#define rt_code_len       0x80  
+
+static int rtl2832u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+
+	static const RT_rc_set_reg_struct p_flush_table1[]={
+		{RTD2832U_RC,IR_RX_CTRL			,0x20,OP_NO ,0xff},
+		{RTD2832U_RC,IR_RX_BUFFER_CTRL		,0x80,OP_NO ,0xff},
+		{RTD2832U_RC,IR_RX_IF			,0xff,OP_NO ,0xff},
+		{RTD2832U_RC,IR_RX_IE			,0xff,OP_NO ,0xff},        
+		{RTD2832U_RC,IR_RX_CTRL			,0x80,OP_NO ,0xff} 
+
+	};
+	static const RT_rc_set_reg_struct p_flush_table2[]={
+		{RTD2832U_RC,IR_RX_IF			,0x03,OP_NO ,0xff},
+		{RTD2832U_RC,IR_RX_BUFFER_CTRL		,0x80,OP_NO ,0xff},	
+		{RTD2832U_RC,IR_RX_CTRL			,0x80,OP_NO ,0xff} 
+
+	};
+
+
+	u8  data=0,i=0,byte_count=0;
+	int ret=0;
+	u8  rt_u8_code[rt_code_len];
+	u8  ucode[4];
+	u16 scancode=0;
+
+	deb_rc("+%s \n", __FUNCTION__);
+	if (dvb_use_rtl2832u_rc_mode >= MAX_RC_PROTOCOL_NUM) 	
+	{
+		
+		deb_rc("%s : dvb_use_rtl2832u_rc_mode=%d \n", __FUNCTION__,dvb_use_rtl2832u_rc_mode);		
+		return 0;
+	}
+
+	if(rtl2832u_remote_control_state == RC_NO_SETTING)
+	{
+                deb_rc("%s : IrDA Initial Setting rtl2832u_remote_control_state=%d\n", __FUNCTION__,rtl2832u_remote_control_state);
+		ret=rtl2832u_remoto_control_initial_setting(d);	
+
+	}
+	if ( read_rc_char_bytes( d ,RTD2832U_RC, IR_RX_IF,&data ,LEN_1) ) 
+	{
+		ret=-1;
+		deb_rc("%s : Read IrDA IF is failed\n", __FUNCTION__);	
+		goto error;
+	}
+	/* debug */
+	if (data != 0)
+	{
+		deb_rc("%s : IR_RX_IF= 0x%x\n", __FUNCTION__,data);	
+	}
+
+
+	if (!(data & receiveMaskFlag1))
+	{
+		ret =0 ;
+		goto error;
+	}	
+	
+	if (data & receiveMaskFlag2)
+	{		
+			/* delay */
+			msleep(287);
+
+			if ( read_rc_char_bytes( d ,RTD2832U_RC,IR_RX_BC,&byte_count ,LEN_1) ) 
+			{
+				deb_rc("%s : rc -ir register read error! \n", __FUNCTION__);
+				ret=-1;
+				goto error;
+			}		
+			if (byte_count == 0 )  
+			{	
+				//ret=0;
+				goto error;
+			}
+				
+			if ((byte_count%LEN_2) == 1)   byte_count+=LEN_1;	
+			if (byte_count > rt_code_len)  byte_count=rt_code_len;	
+					
+			memset(rt_u8_code,0,rt_code_len);
+			deb_rc("%s : byte_count= %d type = %d \n", __FUNCTION__,byte_count,dvb_use_rtl2832u_rc_mode);
+			if ( read_rc_char_bytes( d ,RTD2832U_RC,IR_RX_BUF,rt_u8_code ,0x80) ) 
+			{
+				deb_rc("%s : rc -ir register read error! \n", __FUNCTION__);
+				ret=-1;
+				goto error;
+			}
+				
+			memset(ucode,0,4);
+		
+			
+			ret=0;
+			if (dvb_use_rtl2832u_rc_mode == 0)		ret =frt0(rt_u8_code,byte_count,ucode);
+			else if (dvb_use_rtl2832u_rc_mode == 1)		ret =frt1(rt_u8_code,byte_count,ucode);
+			else if (dvb_use_rtl2832u_rc_mode== 2)		ret =frt2(rt_u8_code,byte_count,ucode);	
+			else  
+			{
+					//deb_rc("%s : rc - unknow rc protocol set ! \n", __FUNCTION__);
+					ret=-1;
+					goto error;	
+			}
+			
+			if((ret != RC_FUNCTION_SUCCESS) || (ucode[0] ==0 && ucode[1] ==0 && ucode[2] ==0 && ucode[3] ==0))   
+ 			{
+					//deb_rc("%s : rc-rc is error scan code ! %x %x %x %x \n", __FUNCTION__,ucode[0],ucode[1],ucode[2],ucode[3]);
+					ret=-1;
+					goto error;	
+			}
+			scancode=(ucode[2]<<8) | ucode[3] ;
+			deb_info("-%s scan code %x %x %x %x,(0x%x) -- len=%d\n", __FUNCTION__,ucode[0],ucode[1],ucode[2],ucode[3],scancode,byte_count);
+			////////// map/////////////////////////////////////////////////////////////////////////////////////////////////////
+			for (i = 0; i < ARRAY_SIZE(rtl2832u_rc_keys_map_table); i++) {
+				if(rtl2832u_rc_keys_map_table[i].scancode == scancode ){
+#ifdef V4L2_REFACTORED_RC_CODE
+					*event = rtl2832u_rc_keys_map_table[i].keycode;
+#else
+					*event = rtl2832u_rc_keys_map_table[i].event;
+#endif
+					*state = REMOTE_KEY_PRESSED;
+					deb_rc("%s : map number = %d \n", __FUNCTION__,i);	
+					break;
+				}		
+				
+			}
+
+			memset(rt_u8_code,0,rt_code_len);
+			byte_count=0;
+			for (i=0;i<3;i++){
+				data= p_flush_table2[i].data;
+				if ( write_rc_char_bytes( d ,RTD2832U_RC, p_flush_table2[i].address,&data,LEN_1) ) {
+					deb_rc("+%s : rc -ir register write error! \n", __FUNCTION__);
+					ret=-1;
+					goto error;
+				}		
+
+			}
+
+			ret =0;	
+			return ret;
+	}
+error:
+			memset(rt_u8_code,0,rt_code_len);
+			byte_count=0;
+			for (i=0;i<flush_step_Number;i++){
+				data= p_flush_table1[i].data;
+				if ( write_rc_char_bytes( d ,RTD2832U_RC, p_flush_table1[i].address,&data,LEN_1) ) {
+					deb_rc("+%s : rc -ir register write error! \n", __FUNCTION__);
+					ret=-1;
+					break;
+				}		
+
+			}			   			
+			ret =0;    //must return 0   
+			return ret;
+
+}
+
+static int rtl2832u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
+{
+	u8 data[2];	
+	//3 to avoid  scanning  channels loss
+	if(onoff)
+	{
+		data[0] = data[1] = 0;		
+		if ( write_usb_sys_char_bytes( adap->dev , RTD2832U_USB , USB_EPA_CTL , data , 2) ) goto error;				
+	}
+	else
+	{
+		data[0] = 0x10;	//3stall epa, set bit 4 to 1
+		data[1] = 0x02;	//3reset epa, set bit 9 to 1
+		if ( write_usb_sys_char_bytes( adap->dev , RTD2832U_USB , USB_EPA_CTL , data , 2) ) goto error;		
+	}
+
+	return 0;
+error: 
+	return -1;
+}
+
+
+static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
+{
+#ifdef V4L2_REFACTORED_MFE_CODE
+	adap->fe_adap[0].fe = rtl2832u_fe_attach(adap->dev);
+#else
+	adap->fe = rtl2832u_fe_attach(adap->dev);
+#endif
+	return 0;
+}
+
+
+static void rtl2832u_usb_disconnect(struct usb_interface *intf)
+{
+	try_module_get(THIS_MODULE);
+	dvb_usb_device_exit(intf);	
+}
+
+
+static struct dvb_usb_device_properties rtl2832u_1st_properties;
+static struct dvb_usb_device_properties rtl2832u_2nd_properties;
+static struct dvb_usb_device_properties rtl2832u_3th_properties;
+static struct dvb_usb_device_properties rtl2832u_4th_properties;
+static struct dvb_usb_device_properties rtl2832u_5th_properties;
+static struct dvb_usb_device_properties rtl2832u_6th_properties;
+static struct dvb_usb_device_properties rtl2832u_7th_properties;
+static struct dvb_usb_device_properties rtl2832u_8th_properties;
+static struct dvb_usb_device_properties rtl2832u_9th_properties;
+
+
+//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static int rtl2832u_usb_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	/* Thats avoids bugs with 2 instances of driver that operate same hardware */
+	/* https://gitorious.org/rtl2832/rtl2832/commit/5495b3fda9e2c3bf4feef5d5751f6f2343380ea9 */
+	if (!intf->altsetting->desc.bNumEndpoints)
+		return -ENODEV;
+
+	if ( ( 0== dvb_usb_device_init(intf,&rtl2832u_1st_properties,THIS_MODULE,NULL,adapter_nr) )||
+		( 0== dvb_usb_device_init(intf,&rtl2832u_2nd_properties,THIS_MODULE,NULL,adapter_nr) ) ||
+		( 0== dvb_usb_device_init(intf,&rtl2832u_3th_properties,THIS_MODULE,NULL,adapter_nr) ) ||
+		( 0== dvb_usb_device_init(intf,&rtl2832u_4th_properties,THIS_MODULE,NULL,adapter_nr) ) ||
+		( 0== dvb_usb_device_init(intf,&rtl2832u_5th_properties,THIS_MODULE,NULL,adapter_nr) ) ||
+		( 0== dvb_usb_device_init(intf,&rtl2832u_6th_properties,THIS_MODULE,NULL,adapter_nr) ) ||
+		( 0== dvb_usb_device_init(intf,&rtl2832u_7th_properties,THIS_MODULE,NULL,adapter_nr) ) ||
+		( 0== dvb_usb_device_init(intf,&rtl2832u_8th_properties,THIS_MODULE,NULL,adapter_nr) ) ||
+		( 0== dvb_usb_device_init(intf,&rtl2832u_9th_properties,THIS_MODULE,NULL,adapter_nr) ) )
+		return 0;
+
+	return -ENODEV;
+}
+
+static struct usb_device_id rtl2832u_usb_table [] = {								
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2832_WARM) },		// 0			
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2838_WARM) },		// 1
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2836_WARM) },		// 2
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2839_WARM) },		// 3
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2840_WARM) },		// 4
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2841_WARM) },		// 5
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2834_WARM) },		// 6
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2837_WARM) },		// 7
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2820_WARM) },		// 8
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2821_WARM) },		// 9
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2822_WARM) },		// 10
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2823_WARM) },		// 11
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2810_WARM) },		// 12
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2811_WARM) },		// 13
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2824_WARM) },		// 14
+	{ USB_DEVICE(USB_VID_REALTEK, USB_PID_RTL2825_WARM) },		// 15
+
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1101) },		// 16	
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1102) },		// 17
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1103) },		// 18	
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1104) },		// 19
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1105) },		// 20	
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1106) },		// 21
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1107) },		// 22	
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_1108) },		// 23
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_2101) },		// 24	
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_8202) },		// 25
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_9201) },		// 26	
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_3103) },		// 27
+	{ USB_DEVICE(USB_VID_DEXATEK, USB_PID_DEXATEK_9202) },		// 28
+
+	{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_00A9)},	// 29
+	{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_00B3)},	// 30
+
+	{ USB_DEVICE(USB_VID_AZUREWAVE_2, USB_PID_AZUREWAVE_3234) },	// 31
+	{ USB_DEVICE(USB_VID_AZUREWAVE_2, USB_PID_AZUREWAVE_3274) },	// 32
+	{ USB_DEVICE(USB_VID_AZUREWAVE_2, USB_PID_AZUREWAVE_3282) },	// 33
+
+	{ USB_DEVICE(USB_VID_THP, USB_PID_THP_5013)},				// 34
+	{ USB_DEVICE(USB_VID_THP, USB_PID_THP_5020)},				// 35
+	{ USB_DEVICE(USB_VID_THP, USB_PID_THP_5026)},				// 36
+
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D393) },	// 37
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D394) },	// 38
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D395) },	// 39
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D396) },	// 40
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D397) },	// 41
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D398) },	// 42
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D39A) },	// 43
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D39B) },	// 44
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D39C) },	// 45
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D39E) },	// 46
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_E77B) },	// 47
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D3A1) },	// 48
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_D3A4) },	// 49
+	{ USB_DEVICE(USB_VID_KWORLD_1ST, USB_PID_KWORLD_E41D) },	// 50
+	
+	{ USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK_WARM_0837)},		// 51
+	{ USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK_WARM_A803)},		// 52
+	{ USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK_WARM_B803)},		// 53
+	{ USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK_WARM_C803)},		// 54
+	{ USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK_WARM_D803)},		// 55
+	{ USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK_WARM_C280)},		// 56
+	{ USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK_WARM_D286)},		// 57
+	{ USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK_WARM_0139)},		// 58
+	{ USB_DEVICE(USB_VID_GTEK, USB_PID_GTEK_WARM_A683)},		// 59
+
+	{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_LEADTEK_WARM_1)},		// 60			
+	{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_LEADTEK_WARM_2)},		// 61
+
+	{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_WARM)},			//62
+        { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_WARM80)},		//63
+	{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_WARM84)},	 	//64
+
+	{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_WARM_0620)},	// 65			
+	{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_WARM_0630)},	// 66			
+	{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_WARM_0640)},	// 67			
+	{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_WARM_0650)},	// 68			
+	{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_WARM_0680)},	// 69			
+	{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_WARM_9580)},	// 70			
+	{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_WARM_9550)},	// 71			
+	{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_WARM_9540)},	// 72			
+	{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_WARM_9530)},	// 73  71																						//------rtl2832u_6th_properties(6)
+	{ USB_DEVICE(USB_VID_COMPRO,  USB_PID_COMPRO_WARM_9520)},	// 74
+		
+	{ USB_DEVICE(USB_VID_GOLDENBRIDGE, USB_PID_GOLDENBRIDGE_WARM)},	//75
+
+	{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_MINI)},	// 76
+
+	{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_00D3)},		// 77
+	{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_00D4)},		// 78
+	{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_00E0)},		// 79
+
+	{ 0 },
+};
+
+
+MODULE_DEVICE_TABLE(usb, rtl2832u_usb_table);
+
+static struct dvb_usb_device_properties rtl2832u_1st_properties = {
+
+	.num_adapters = 1,
+	.adapter = 
+	{
+		{
+#ifndef NO_FE_IOCTL_OVERRIDE
+			.fe_ioctl_override = rtl2832_fe_ioctl_override,
+#endif
+#ifdef V4L2_REFACTORED_MFE_CODE
+			.num_frontends = 1,
+			.fe = {{
+#endif
+			.streaming_ctrl = rtl2832u_streaming_ctrl,
+			.frontend_attach = rtl2832u_frontend_attach,
+			//parameter for the MPEG2-data transfer 
+			.stream = 
+			{
+				.type = USB_BULK,
+				.count = RTD2831_URB_NUMBER,
+				.endpoint = 0x01,		//data pipe
+				.u = 
+				{
+					.bulk = 
+					{
+						.buffersize = RTD2831_URB_SIZE,
+					}
+				}
+			},
+#ifdef V4L2_REFACTORED_MFE_CODE
+			}},
+#endif
+		}
+	},
+	
+	//remote control
+	.rc.legacy = {
+#ifdef V4L2_REFACTORED_RC_CODE
+		.rc_map_table = rtl2832u_rc_keys_map_table,             //user define key map
+		.rc_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table), //user define key map size	
+#else
+		.rc_key_map       = rtl2832u_rc_keys_map_table,			//user define key map
+		.rc_key_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table),	//user define key map size	
+#endif	
+		.rc_query         = rtl2832u_rc_query,				//use define quary function
+		.rc_interval      = RT_RC_POLLING_INTERVAL_TIME_MS,		
+	},
+	
+	.num_device_descs = 9,
+	.devices = {
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[0], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[1], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[2], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[3], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[4], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[5], NULL },
+		},		
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[6], NULL },
+		},		
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[7], NULL },
+		},		
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[8], NULL },
+		},
+		{ NULL },
+	}
+};
+
+
+static struct dvb_usb_device_properties rtl2832u_2nd_properties = {
+
+	.num_adapters = 1,
+	.adapter = 
+	{
+		{
+#ifndef NO_FE_IOCTL_OVERRIDE
+			.fe_ioctl_override = rtl2832_fe_ioctl_override,
+#endif
+#ifdef V4L2_REFACTORED_MFE_CODE
+			.num_frontends = 1,
+			.fe = {{
+#endif
+			.streaming_ctrl = rtl2832u_streaming_ctrl,
+			.frontend_attach = rtl2832u_frontend_attach,
+			//parameter for the MPEG2-data transfer 
+			.stream = 
+			{
+				.type = USB_BULK,
+				.count = RTD2831_URB_NUMBER,
+				.endpoint = 0x01,		//data pipe
+				.u = 
+				{
+					.bulk = 
+					{
+						.buffersize = RTD2831_URB_SIZE,
+					}
+				}
+			},
+#ifdef V4L2_REFACTORED_MFE_CODE
+			}},
+#endif
+		}
+	},
+	//remote control
+	.rc.legacy = {
+#ifdef V4L2_REFACTORED_RC_CODE
+		.rc_map_table = rtl2832u_rc_keys_map_table,             //user define key map
+		.rc_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table), //user define key map size	
+#else
+		.rc_key_map       = rtl2832u_rc_keys_map_table,			//user define key map
+		.rc_key_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table),	//user define key map size	
+#endif	
+		.rc_query         = rtl2832u_rc_query,				//use define query function
+		.rc_interval      = RT_RC_POLLING_INTERVAL_TIME_MS,		
+	},
+	
+	.num_device_descs = 9,
+	.devices = {
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[9], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[10], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[11], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[12], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[13], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[14], NULL },
+		},
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[15], NULL },
+		},
+		{ .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[16], NULL },
+		},
+		{ .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[17], NULL },
+		},
+		{ NULL },
+	}
+};
+
+
+
+static struct dvb_usb_device_properties rtl2832u_3th_properties = {
+
+	.num_adapters = 1,
+	.adapter = 
+	{
+		{
+#ifndef NO_FE_IOCTL_OVERRIDE
+			.fe_ioctl_override = rtl2832_fe_ioctl_override,
+#endif
+#ifdef V4L2_REFACTORED_MFE_CODE
+			.num_frontends = 1,
+			.fe = {{
+#endif
+			.streaming_ctrl = rtl2832u_streaming_ctrl,
+			.frontend_attach = rtl2832u_frontend_attach,
+			//parameter for the MPEG2-data transfer 
+			.stream = 
+			{
+				.type = USB_BULK,
+				.count = RTD2831_URB_NUMBER,
+				.endpoint = 0x01,		//data pipe
+				.u = 
+				{
+					.bulk = 
+					{
+						.buffersize = RTD2831_URB_SIZE,
+					}
+				}
+			},
+#ifdef V4L2_REFACTORED_MFE_CODE
+			}},
+#endif
+		}
+	},
+
+	//remote control
+	.rc.legacy = {
+#ifdef V4L2_REFACTORED_RC_CODE
+		.rc_map_table = rtl2832u_rc_keys_map_table,             //user define key map
+		.rc_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table), //user define key map size	
+#else
+		.rc_key_map       = rtl2832u_rc_keys_map_table,			//user define key map
+		.rc_key_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table),	//user define key map size	
+#endif	
+		.rc_query         = rtl2832u_rc_query,				//use define query function
+		.rc_interval      = RT_RC_POLLING_INTERVAL_TIME_MS,		
+	},
+
+	.num_device_descs = 9,
+	.devices = {
+		{ .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[18], NULL },
+		},
+		{ .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[19], NULL },
+		},
+		{ .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[20], NULL },
+		},
+		{
+		  .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[21], NULL },
+		},
+		{
+		  .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[22], NULL },
+		},
+		{
+		  .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[23], NULL },
+		},
+		{
+		  .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[24], NULL },
+		},
+		{
+		  .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[25], NULL },
+		},
+		{
+		  .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[26], NULL },
+		}
+	}
+};
+
+
+static struct dvb_usb_device_properties rtl2832u_4th_properties = {
+
+	.num_adapters = 1,
+	.adapter = 
+	{
+		{
+#ifndef NO_FE_IOCTL_OVERRIDE
+			.fe_ioctl_override = rtl2832_fe_ioctl_override,
+#endif
+#ifdef V4L2_REFACTORED_MFE_CODE
+			.num_frontends = 1,
+			.fe = {{
+#endif
+			.streaming_ctrl = rtl2832u_streaming_ctrl,
+			.frontend_attach = rtl2832u_frontend_attach,
+			//parameter for the MPEG2-data transfer 
+			.stream = 
+			{
+				.type = USB_BULK,
+				.count = RTD2831_URB_NUMBER,
+				.endpoint = 0x01,		//data pipe
+				.u = 
+				{
+					.bulk = 
+					{
+						.buffersize = RTD2831_URB_SIZE,
+					}
+				}
+			},
+#ifdef V4L2_REFACTORED_MFE_CODE
+			}},
+#endif
+		}
+	},
+
+	//remote control
+	.rc.legacy = {
+#ifdef V4L2_REFACTORED_RC_CODE
+		.rc_map_table = rtl2832u_rc_keys_map_table,             //user define key map
+		.rc_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table), //user define key map size	
+#else
+		.rc_key_map       = rtl2832u_rc_keys_map_table,			//user define key map
+		.rc_key_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table),	//user define key map size	
+#endif	
+		.rc_query         = rtl2832u_rc_query,				//use define query function
+		.rc_interval      = RT_RC_POLLING_INTERVAL_TIME_MS,		
+	},
+
+	.num_device_descs = 12,
+	.devices = {
+		{ .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[27], NULL },
+		},
+		{ .name = "DK DONGLE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[28], NULL },
+		},
+		{ .name = "Terratec Cinergy T Stick Black",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[29], NULL },
+		},
+		{
+		  .name = "Terratec Cinergy T Stick Black",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[30], NULL },
+		},
+		{
+		  .name = "USB DVB-T Device",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[31], NULL },
+		},
+		{
+		  .name = "USB DVB-T Device",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[32], NULL },
+		},
+		
+		{
+		  .name = "USB DVB-T Device",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[33], NULL },
+		},
+				
+		{
+		  .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[34], NULL },
+		},
+		
+		{
+		  .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[35], NULL },
+		},				
+		
+		{
+		  .name = "Terratec Cinergy T Stick RC (Rev.3)",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[77], NULL },
+		},
+
+		{
+		  .name = "Terratec Cinergy T Stick BLACK (Rev.2)",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[78], NULL },
+		},
+
+		{
+		  .name = "Terratec Noxon DAB Stick (Rev.2)",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[79], NULL },
+		},
+	}
+};
+
+static struct dvb_usb_device_properties rtl2832u_5th_properties = {
+
+	.num_adapters = 1,
+	.adapter = 
+	{
+		{
+#ifndef NO_FE_IOCTL_OVERRIDE
+			.fe_ioctl_override = rtl2832_fe_ioctl_override,
+#endif
+#ifdef V4L2_REFACTORED_MFE_CODE
+			.num_frontends = 1,
+			.fe = {{
+#endif
+			.streaming_ctrl = rtl2832u_streaming_ctrl,
+			.frontend_attach = rtl2832u_frontend_attach,
+			//parameter for the MPEG2-data transfer 
+			.stream = 
+			{
+				.type = USB_BULK,
+				.count = RTD2831_URB_NUMBER,
+				.endpoint = 0x01,		//data pipe
+				.u = 
+				{
+					.bulk = 
+					{
+						.buffersize = RTD2831_URB_SIZE,
+					}
+				}
+			},
+#ifdef V4L2_REFACTORED_MFE_CODE
+			}},
+#endif
+		}
+	},
+
+	//remote control
+	.rc.legacy = {
+#ifdef V4L2_REFACTORED_RC_CODE
+		.rc_map_table = rtl2832u_rc_keys_map_table,             //user define key map
+		.rc_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table), //user define key map size	
+#else
+		.rc_key_map       = rtl2832u_rc_keys_map_table,			//user define key map
+		.rc_key_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table),	//user define key map size	
+#endif	
+		.rc_query         = rtl2832u_rc_query,				//use define query function
+		.rc_interval      = RT_RC_POLLING_INTERVAL_TIME_MS,		
+	},
+
+	.num_device_descs = 9,
+	.devices = {
+		{ .name = "RTL2832U DVB-T USB DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[36], NULL },
+		},
+		{ .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[37], NULL },
+		},
+		{ .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[38], NULL },
+		},
+		{
+		  .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[39], NULL },
+		},
+		{
+		  .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[40], NULL },
+		},
+		{
+		  .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[41], NULL },
+		},
+		
+		{
+		  .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[42], NULL },
+		},
+				
+		{
+		  .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[43], NULL },
+		},
+		
+		{
+		  .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[44], NULL },
+		},				
+		
+		
+	}
+};
+
+static struct dvb_usb_device_properties rtl2832u_6th_properties = {
+
+	.num_adapters = 1,
+	.adapter = 
+	{
+		{
+#ifndef NO_FE_IOCTL_OVERRIDE
+			.fe_ioctl_override = rtl2832_fe_ioctl_override,
+#endif
+#ifdef V4L2_REFACTORED_MFE_CODE
+			.num_frontends = 1,
+			.fe = {{
+#endif
+			.streaming_ctrl = rtl2832u_streaming_ctrl,
+			.frontend_attach = rtl2832u_frontend_attach,
+			//parameter for the MPEG2-data transfer 
+			.stream = 
+			{
+				.type = USB_BULK,
+				.count = RTD2831_URB_NUMBER,
+				.endpoint = 0x01,		//data pipe
+				.u = 
+				{
+					.bulk = 
+					{
+						.buffersize = RTD2831_URB_SIZE,
+					}
+				}
+			},
+#ifdef V4L2_REFACTORED_MFE_CODE
+			}},
+#endif
+		}
+	},
+
+	 /*remote control*/
+	.rc.legacy = {
+#ifdef V4L2_REFACTORED_RC_CODE
+		.rc_map_table = rtl2832u_rc_keys_map_table,             //user define key map
+		.rc_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table), //user define key map size	
+#else
+		.rc_key_map       = rtl2832u_rc_keys_map_table,			//user define key map
+		.rc_key_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table),	//user define key map size	
+#endif	
+		.rc_query         = rtl2832u_rc_query,				//use define query function
+		.rc_interval      = RT_RC_POLLING_INTERVAL_TIME_MS,		
+	},
+
+	.num_device_descs = 9,
+	.devices = {
+		{ .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[45], NULL },
+		},
+		{ .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[46], NULL },
+		},
+		{ .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[47], NULL },
+		},
+		{
+		  .name ="USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[48], NULL },
+		},
+		{
+		  .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[49], NULL },
+		},
+		{
+		  .name = "USB DVB-T DEVICE",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[50], NULL },
+		},
+		{
+		  .name ="DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[51], NULL },
+		},
+		{
+		  .name = "DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[52], NULL },
+		},
+		{
+		  .name = "DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[53], NULL },
+		},
+		
+		{ NULL },				
+
+		
+	}
+};
+
+static struct dvb_usb_device_properties rtl2832u_7th_properties = {
+
+	.num_adapters = 1,
+	.adapter = 
+	{
+		{
+#ifndef NO_FE_IOCTL_OVERRIDE
+			.fe_ioctl_override = rtl2832_fe_ioctl_override,
+#endif
+#ifdef V4L2_REFACTORED_MFE_CODE
+			.num_frontends = 1,
+			.fe = {{
+#endif
+			.streaming_ctrl = rtl2832u_streaming_ctrl,
+			.frontend_attach = rtl2832u_frontend_attach,
+			//parameter for the MPEG2-data transfer 
+			.stream = 
+			{
+				.type = USB_BULK,
+				.count = RTD2831_URB_NUMBER,
+				.endpoint = 0x01,		//data pipe
+				.u = 
+				{
+					.bulk = 
+					{
+						.buffersize = RTD2831_URB_SIZE,
+					}
+				}
+			},
+#ifdef V4L2_REFACTORED_MFE_CODE
+			}},
+#endif
+		}
+	},
+
+	//remote control
+	.rc.legacy = {
+#ifdef V4L2_REFACTORED_RC_CODE
+		.rc_map_table = rtl2832u_rc_keys_map_table,             //user define key map
+		.rc_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table), //user define key map size	
+#else
+		.rc_key_map       = rtl2832u_rc_keys_map_table,			//user define key map
+		.rc_key_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table),	//user define key map size	
+#endif	
+		.rc_query         = rtl2832u_rc_query,				//use define query function
+		.rc_interval      = RT_RC_POLLING_INTERVAL_TIME_MS,		
+	},
+
+	.num_device_descs = 10,
+	.devices = {
+		{ .name = "DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[54], NULL },
+		},
+		{ .name = "DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[55], NULL },
+		},
+		{ .name = "DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[56], NULL },
+		},
+		{
+		  .name ="DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[57], NULL },
+		},
+		{ .name = "DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[58], NULL },
+		},
+		{ .name = "DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[59], NULL },
+		},
+		{ .name = "USB DVB-T Device",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[60], NULL },
+		},
+		{
+		  .name = "USB DVB-T Device",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[61], NULL },
+		},
+		{
+		  .name = "USB DVB-T Device",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[62], NULL },
+		},
+		{ .name = "Leadtek WinFast DTV Dongle Mini",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[76], NULL },
+		},
+		{ NULL },				
+	}
+};
+
+static struct dvb_usb_device_properties rtl2832u_8th_properties = {
+
+	.num_adapters = 1,
+	.adapter =
+	{
+		{
+#ifndef NO_FE_IOCTL_OVERRIDE
+			.fe_ioctl_override = rtl2832_fe_ioctl_override,
+#endif
+#ifdef V4L2_REFACTORED_MFE_CODE
+			.num_frontends = 1,
+			.fe = {{
+#endif
+			.streaming_ctrl = rtl2832u_streaming_ctrl,
+			.frontend_attach = rtl2832u_frontend_attach,
+			//parameter for the MPEG2-data transfer 
+			.stream = 
+			{
+				.type = USB_BULK,
+				.count = RTD2831_URB_NUMBER,
+				.endpoint = 0x01,		//data pipe
+				.u = 
+				{
+					.bulk = 
+					{
+						.buffersize = RTD2831_URB_SIZE,
+					}
+				}
+			},
+#ifdef V4L2_REFACTORED_MFE_CODE
+			}},
+#endif
+		}
+	},
+
+	//remote control
+	.rc.legacy = {
+#ifdef V4L2_REFACTORED_RC_CODE
+		.rc_map_table = rtl2832u_rc_keys_map_table,             //user define key map
+		.rc_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table), //user define key map size	
+#else
+		.rc_key_map       = rtl2832u_rc_keys_map_table,			//user define key map
+		.rc_key_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table),	//user define key map size	
+#endif	
+		.rc_query         = rtl2832u_rc_query,				//use define query function
+		.rc_interval      = RT_RC_POLLING_INTERVAL_TIME_MS,		
+	},
+
+	.num_device_descs = 9,
+	.devices = {
+		{ .name = "USB DVB-T Device",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[63], NULL },
+		},
+		{ .name = "USB DVB-T Device",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[64], NULL },
+		},
+		{ .name = "VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[65], NULL },
+		},
+		{
+		  .name ="VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[66], NULL },
+		},
+		{ .name = "VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[67], NULL },
+		},
+		{ .name = "VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[68], NULL },
+		},
+		{ .name = "VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[69], NULL },
+		},
+		{
+		  .name ="VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[70], NULL },
+		},
+		{
+		  .name ="VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[71], NULL },
+		},
+
+		{ NULL },				
+	}
+};
+
+static struct dvb_usb_device_properties rtl2832u_9th_properties = {
+
+	.num_adapters = 1,
+	.adapter = 
+	{
+		{
+#ifndef NO_FE_IOCTL_OVERRIDE
+			.fe_ioctl_override = rtl2832_fe_ioctl_override,
+#endif
+#ifdef V4L2_REFACTORED_MFE_CODE
+			.num_frontends = 1,
+			.fe = {{
+#endif
+			.streaming_ctrl = rtl2832u_streaming_ctrl,
+			.frontend_attach = rtl2832u_frontend_attach,
+			//parameter for the MPEG2-data transfer 
+			.stream = 
+			{
+				.type = USB_BULK,
+				.count = RTD2831_URB_NUMBER,
+				.endpoint = 0x01,		//data pipe
+				.u = 
+				{
+					.bulk = 
+					{
+						.buffersize = RTD2831_URB_SIZE,
+					}
+				}
+			},
+#ifdef V4L2_REFACTORED_MFE_CODE
+			}},
+#endif
+		}
+	},
+
+	//remote control
+	.rc.legacy = {
+#ifdef V4L2_REFACTORED_RC_CODE
+		.rc_map_table = rtl2832u_rc_keys_map_table,             //user define key map
+		.rc_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table), //user define key map size	
+#else
+		.rc_key_map       = rtl2832u_rc_keys_map_table,			//user define key map
+		.rc_key_map_size  = ARRAY_SIZE(rtl2832u_rc_keys_map_table),	//user define key map size	
+#endif	
+		.rc_query         = rtl2832u_rc_query,				//use define query function
+		.rc_interval      = RT_RC_POLLING_INTERVAL_TIME_MS,		
+	},
+
+	.num_device_descs = 4,
+	.devices = {
+		{
+		  .name ="VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[72], NULL },
+		},
+		{
+		  .name ="VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[73], NULL },
+		},
+		{ .name = "VideoMate DTV",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[74], NULL },
+		},
+		{ .name = "DVB-T TV Stick",
+		  .cold_ids = { NULL, NULL },
+		  .warm_ids = { &rtl2832u_usb_table[75], NULL },
+		},
+		{ NULL },
+	}
+};
+
+
+
+
+static struct usb_driver rtl2832u_usb_driver = {
+	.name		= "dvb_usb_rtl2832u",
+	.probe		= rtl2832u_usb_probe,
+	.disconnect	= rtl2832u_usb_disconnect,
+	.id_table		= rtl2832u_usb_table,
+};
+
+
+static int __init rtl2832u_usb_module_init(void)
+{
+	int result =0 ;
+
+	deb_info("+info debug open_%s\n", __FUNCTION__);
+	if ((result = usb_register(&rtl2832u_usb_driver))) {
+		err("usb_register failed. (%d)",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit rtl2832u_usb_module_exit(void)
+{
+	usb_deregister(&rtl2832u_usb_driver);
+
+	return ;	
+}
+
+
+
+module_init(rtl2832u_usb_module_init);
+module_exit(rtl2832u_usb_module_exit);
+
+
+MODULE_AUTHOR("Realtek");
+MODULE_AUTHOR("Chialing Lu <chialing@realtek.com>");
+MODULE_AUTHOR("Dean Chung<DeanChung@realtek.com>");
+MODULE_DESCRIPTION("Driver for the RTL2832U DVB-T / RTL2836 DTMB USB2.0 device");
+MODULE_VERSION("2.2.2");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/usb/dvb-usb/rtl2832u.h b/drivers/media/usb/dvb-usb/rtl2832u.h
new file mode 100644
index 0000000..16ad113
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/rtl2832u.h
@@ -0,0 +1,277 @@
+
+#ifndef _RTL2832U_H_
+#define _RTL2832U_H_
+
+
+
+#include "dvb-usb.h"
+
+#ifndef USB_VID_REALTEK
+	#define	USB_VID_REALTEK						0x0BDA
+#endif
+#define	USB_PID_RTL2832_WARM					0x2832 
+#define	USB_PID_RTL2838_WARM					0x2838 
+#define	USB_PID_RTL2836_WARM					0x2836
+#define	USB_PID_RTL2839_WARM					0x2839
+#define	USB_PID_RTL2840_WARM					0x2840
+#define	USB_PID_RTL2841_WARM					0x2841
+#define	USB_PID_RTL2834_WARM					0x2834 
+#define	USB_PID_RTL2837_WARM          			0x2837
+#define	USB_PID_RTL2820_WARM					0x2820 
+#define	USB_PID_RTL2821_WARM          			0x2821
+#define	USB_PID_RTL2822_WARM					0x2822 
+#define	USB_PID_RTL2823_WARM          			0x2823
+#define	USB_PID_RTL2810_WARM					0x2810 
+#define	USB_PID_RTL2811_WARM          			0x2811
+#define	USB_PID_RTL2824_WARM					0x2824 
+#define	USB_PID_RTL2825_WARM          			0x2825
+
+#ifndef USB_VID_DEXATEK
+	#define	USB_VID_DEXATEK						0x1D19
+#endif
+#define	USB_PID_DEXATEK_1101					0x1101
+#define	USB_PID_DEXATEK_1102					0x1102
+#define	USB_PID_DEXATEK_1103					0x1103
+#define	USB_PID_DEXATEK_1104					0x1104
+#define	USB_PID_DEXATEK_1105					0x1105
+#define	USB_PID_DEXATEK_1106					0x1106
+#define	USB_PID_DEXATEK_1107					0x1107
+#define	USB_PID_DEXATEK_1108					0x1108
+#define	USB_PID_DEXATEK_2101					0x2101
+#define	USB_PID_DEXATEK_8202					0x8202
+#define	USB_PID_DEXATEK_9201					0x9201
+#define	USB_PID_DEXATEK_3103					0x3103
+#define	USB_PID_DEXATEK_9202					0x9202
+
+#ifndef USB_VID_TERRATEC
+	#define USB_VID_TERRATEC					0x0CCD
+#endif
+#define	USB_PID_TERRATEC_00A9					0x00A9
+#define	USB_PID_TERRATEC_00B3					0x00B3
+#define	USB_PID_TERRATEC_00D3					0x00D3
+#define	USB_PID_TERRATEC_00D4					0x00D4
+#define	USB_PID_TERRATEC_00E0					0x00E0
+
+#ifndef USB_VID_AZUREWAVE_2
+	#define	USB_VID_AZUREWAVE_2					0x13D3
+#endif
+	#define	USB_PID_AZUREWAVE_3234				0x3234
+	#define	USB_PID_AZUREWAVE_3274				0x3274
+	#define	USB_PID_AZUREWAVE_3282				0x3282
+
+
+#ifndef USB_VID_THP
+	#define	USB_VID_THP							0x1554
+#endif
+#define	USB_PID_THP_5013						0x5013
+#define	USB_PID_THP_5020						0x5020	
+#define	USB_PID_THP_5026						0x5026	
+
+#ifndef USB_VID_KWORLD_1ST
+	#define	USB_VID_KWORLD_1ST					0x1B80
+#endif
+#define	USB_PID_KWORLD_D393						0xD393
+#define	USB_PID_KWORLD_D394						0xD394
+#define	USB_PID_KWORLD_D395						0xD395
+#define	USB_PID_KWORLD_D396						0xD396
+#define	USB_PID_KWORLD_D397						0xD397
+#define	USB_PID_KWORLD_D398						0xD398
+#define	USB_PID_KWORLD_D39A						0xD39A
+#define	USB_PID_KWORLD_D39B						0xD39B
+#define	USB_PID_KWORLD_D39C						0xD39C
+#define	USB_PID_KWORLD_D39E						0xD39E
+#define	USB_PID_KWORLD_E77B						0xE77B
+#define	USB_PID_KWORLD_D3A1						0xD3A1
+#define	USB_PID_KWORLD_D3A4						0xD3A4
+#define	USB_PID_KWORLD_E41D						0xE41D
+
+#ifndef USB_VID_GOLDENBRIDGE
+	#define	USB_VID_GOLDENBRIDGE				0x1680
+#endif
+#define	USB_PID_GOLDENBRIDGE_WARM				0xA332
+
+#ifndef USB_VID_YUAN
+	#define	USB_VID_YUAN						0x1164
+#endif
+#define	USB_PID_YUAN_WARM						0x6601
+#define USB_PID_YUAN_WARM80						0x3280
+#define USB_PID_YUAN_WARM84	                    0x3284
+
+#ifndef USB_PID_GTEK_WARM_0837
+	#define	USB_PID_GTEK_WARM_0837				0x0837	
+#endif
+#define	USB_PID_GTEK_WARM_A803					0xA803
+#define	USB_PID_GTEK_WARM_B803					0xB803
+#define	USB_PID_GTEK_WARM_C803					0xC803
+#define	USB_PID_GTEK_WARM_D803					0xD803
+#define	USB_PID_GTEK_WARM_C280					0xC280
+#define	USB_PID_GTEK_WARM_D286					0xD286
+#define	USB_PID_GTEK_WARM_0139					0x0139
+#define	USB_PID_GTEK_WARM_A683					0xA683
+
+#ifndef USB_VID_LEADTEK
+	#define	USB_VID_LEADTEK						0x0413
+#endif
+#define	USB_PID_LEADTEK_WARM_1					0x6680
+#define	USB_PID_LEADTEK_WARM_2					0x6F11
+#define	USB_PID_WINFAST_DTV_DONGLE_MINI				0x6a03
+
+#ifndef  USB_VID_COMPRO
+	#define USB_VID_COMPRO						0x185B
+#endif 
+#define USB_PID_COMPRO_WARM_0620				0x0620
+#define USB_PID_COMPRO_WARM_0630				0x0630
+#define USB_PID_COMPRO_WARM_0640				0x0640
+#define USB_PID_COMPRO_WARM_0650				0x0650
+#define USB_PID_COMPRO_WARM_0680				0x0680
+#define USB_PID_COMPRO_WARM_9580				0x9580
+#define USB_PID_COMPRO_WARM_9550				0x9550
+#define USB_PID_COMPRO_WARM_9540				0x9540
+#define USB_PID_COMPRO_WARM_9530				0x9530
+#define USB_PID_COMPRO_WARM_9520				0x9520
+
+
+#define RTD2831_URB_SIZE				4096// 39480
+#define RTD2831_URB_NUMBER				10 //  4
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+//			remote control 
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+//define rtl283u rc register address
+#define IR_RX_BUF			0xFC00
+#define IR_RX_IE			0xFD00
+#define IR_RX_IF			0xFD01
+#define IR_RX_CTRL			0xFD02
+#define IR_RX_CONFIG			0xFD03
+#define IR_MAX_DURATION0		0xFD04
+#define IR_MAX_DURATION1		0xFD05
+#define IR_IDLE_LEN0			0xFD06
+#define IR_IDLE_LEN1			0xFD07
+#define IR_GLITCH_LEN			0xFD08
+#define IR_RX_BUFFER_CTRL		0xFD09
+#define IR_RX_BUFFER_DATA		0xFD0A
+#define IR_RX_BC			0xFD0B
+#define IR_RX_CLK			0xFD0C
+#define IR_RX_C_COUNT_L			0xFD0D
+#define IR_RX_C_COUNT_H			0xFD0E
+
+#define IR_SUSPEND_CTRL			0xFD10
+#define IR_Err_Tolerance_CTRL		0xFD11
+#define IR_UNIT_LEN			0xFD12
+#define IR_Err_Tolerance_LEN		0xFD13
+#define IR_MAX_H_Tolerance_LEN		0xFD14
+#define IR_MAX_L_Tolerance_LEN		0xFD15
+#define IR_MASK_CTRL			0xFD16
+#define IR_MASK_DATA			0xFD17
+#define IR_RESUME_MASK_ADDR		0xFD18
+#define IR_RESUME_MASK_T_LEN		0xFD19
+
+#define USB_CTRL			0x0010
+#define SYS_GPD				0x0004
+#define SYS_GPOE			0x0003
+#define SYS_GPO				0x0001
+#define RC_USE_DEMOD_CTL1		0x000B
+
+//define use len 
+#define LEN_1				0x01
+#define LEN_2				0x02
+#define LEN_3				0x03
+#define LEN_4				0x04
+
+
+
+//function
+int rtl2832u_remoto_control_initial_setting(struct dvb_usb_device *d);
+#define	USB_EPA_CTL			0x0148
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+//decode control para define
+#define frt0_para1 			0x3c
+#define frt0_para2 			0x20
+#define frt0_para3			0x7f
+#define frt0_para4      		0x05
+#define frt0_bits_num 			0x80
+#define frt0_BITS_mask 			0x01
+#define frt0_BITS_mask0			0x00
+#define frt0_BITS_mask1			0x00
+#define frt0_BITS_mask2			0x0f
+#define frt0_BITS_mask3			0xff
+
+#define frt1_para1 			0x12
+#define frt1_para3 			0x1a
+#define frt1_para2 			0x7f
+#define frt1_para4 			0x80
+#define frt1_para5 			0x01
+#define frt1_para6 			0x02
+#define frt1_bits_num 			0x80
+#define frt1_para_uc_1			0x81
+#define frt1_para_uc_2 			0x82
+#define frt1_bits_mask0			0x00
+#define frt1_bits_mask1			0x00
+#define frt1_bits_mask2			0x7f
+#define frt1_bits_mask3			0xff
+
+#define frt2_para1  			0x0a
+#define frt2_para2  			0xFF
+#define frt2_para3 			0xb0
+#define frt2_para4 			0xc6
+#define frt2_para5  			0x30
+#define frt2_para6  			0x1b
+#define frt2_para7  			0x8f
+#define frt2_para8  			0x89
+#define frt2_para9  			0x7f
+#define frt2_para10 			0x60
+#define frt2_para11 			0x38
+#define frt2_para12  			0x15
+#define frt2_bits_num			0x80
+#define frt2_bits_mask0			0x00
+#define frt2_bits_mask1			0x00
+#define frt2_bits_mask2			0xff
+#define frt2_bits_mask3			0xff
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+//			remote control 
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+enum protocol_type_for_RT{
+				RT_RC6=0,
+				RT_RC5,
+				RT_NEC,
+				RT_TEST
+};
+// op define	
+enum OP{
+	OP_NO	=0,
+	OP_AND	  ,
+	OP_OR
+};
+
+typedef enum RT_UC_CODE_STATE{
+	WAITING_6T,
+	WAITING_2T_AFTER_6T,
+	WAITING_NORMAL_BITS
+}RT_UC_CODE_STATE;
+
+//struct define
+typedef struct RT_rc_set_reg_struct{	
+		u8	type;	
+		u16 	address;
+		u8      data;
+		u8	op;
+		u8	op_mask;	
+}RT_rc_set_reg_struct;
+
+enum RTL2832U_RC_STATE{
+	RC_NO_SETTING=0,
+	RC_INSTALL_OK,
+	RC__POLLING_OK,
+	RC_STOP_OK
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+extern struct dvb_frontend * rtl2832u_fe_attach(struct dvb_usb_device *d);
+
+#endif
+
+
+
diff --git a/drivers/media/usb/dvb-usb/rtl2832u_audio.c b/drivers/media/usb/dvb-usb/rtl2832u_audio.c
new file mode 100644
index 0000000..b569d3a
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/rtl2832u_audio.c
@@ -0,0 +1,926 @@
+
+
+#include "rtl2832u_audio.h"
+//#include "rtl2832u_ioctl.h"
+
+#ifndef NO_FE_IOCTL_OVERRIDE
+
+#define RTK_Demod_Byte_Write(page, offset, length, data) \
+	((write_demod_register(p_state->d, RTL2832_DEMOD_ADDR, page, offset, data, length)) ? 0 : 1 )
+
+
+#define RTK_Demod_Byte_Read(page, offset, length, data) \
+	((read_demod_register(p_state->d, RTL2832_DEMOD_ADDR, page, offset, data, length)) ? 0 : 1 )
+
+
+int Set1(struct rtl2832_state*	p_state)
+{	
+	unsigned char data[1];
+	unsigned short	length = 1;
+	int hr = 1;
+	
+	data[0] = 202;
+	hr &= RTK_Demod_Byte_Write(1, 0x1C, length, data);
+		
+	data[0] = 220;
+	hr &= RTK_Demod_Byte_Write(1, 0x1D, length, data);
+		
+	data[0] = 215;
+	hr &= RTK_Demod_Byte_Write(1, 0x1E, length, data);
+		
+	data[0] = 216;
+	hr &= RTK_Demod_Byte_Write(1, 0x1F, length, data);
+		
+	data[0] = 224;
+	hr &= RTK_Demod_Byte_Write(1, 0x20, length, data);
+		
+	data[0] = 242;
+	hr &= RTK_Demod_Byte_Write(1, 0x21, length, data);
+		
+	data[0] = 14;
+	hr &= RTK_Demod_Byte_Write(1, 0x22, length, data);
+	
+	data[0] = 53;
+	hr &= RTK_Demod_Byte_Write(1, 0x23, length, data);
+	
+	data[0] = 6;
+	hr &= RTK_Demod_Byte_Write(1, 0x24, length, data);
+		
+	data[0] = 80;
+	hr &= RTK_Demod_Byte_Write(1, 0x25, length, data);
+		
+	data[0] = 156;
+	hr &= RTK_Demod_Byte_Write(1, 0x26, length, data);
+		
+	data[0] = 13;
+	hr &= RTK_Demod_Byte_Write(1, 0x27, length, data);
+		
+	data[0] = 113;
+	hr &= RTK_Demod_Byte_Write(1, 0x28, length, data);
+		
+	data[0] = 17;
+	hr &= RTK_Demod_Byte_Write(1, 0x29, length, data);
+		
+	data[0] = 20;
+	hr &= RTK_Demod_Byte_Write(1, 0x2A, length, data);
+		
+	data[0] = 113;
+	hr &= RTK_Demod_Byte_Write(1, 0x2B, length, data);
+		
+	data[0] = 116;
+	hr &= RTK_Demod_Byte_Write(1, 0x2C, length, data);
+		
+	data[0] = 25;
+	hr &= RTK_Demod_Byte_Write(1, 0x2D, length, data);
+		
+	data[0] = 65;
+	hr &= RTK_Demod_Byte_Write(1, 0x2E, length, data);
+		
+	data[0] = 165;
+	hr &= RTK_Demod_Byte_Write(1, 0x2F, length, data);
+
+	return hr;	
+}
+
+int Set2(struct rtl2832_state*	p_state)
+{
+	UCHAR FM_coe2[6] = {-1, 1, 6, 13, 22, 27}; 	
+	unsigned char data[1];
+    	unsigned short addr = 0x1F;
+
+	int i;
+	BOOL rst = 1;
+	for(i=0; i<6; i++)
+	{
+		data[0] = FM_coe2[i];
+	
+		rst &= RTK_Demod_Byte_Write(0, addr, 1, data);
+		addr--;
+	}
+
+	return rst;
+}   
+
+ int RTL2832_SWReset(struct rtl2832_state*	p_state)
+{
+	unsigned char data[1];
+	int hr = 1;
+
+	hr &= RTK_Demod_Byte_Read(1, 0x01, 1, data);
+	data[0] = data[0] | 0x04;
+	hr &= RTK_Demod_Byte_Write(1, 0x01, 1, data);
+	data[0] = data[0] & 0xFB;
+	hr &= RTK_Demod_Byte_Write(1, 0x01, 1, data);
+
+	return hr; 
+}	
+
+ int RTL2832_SWReset_2(struct rtl2832_state* p_state)
+{
+	unsigned char data[1];
+	unsigned char tmp;
+	int hr = 1;
+
+	// disable
+	hr &= RTK_Demod_Byte_Read(0, 0x19, 1, data);
+	data[0] = data[0] & 0xFE;
+	tmp = data[0];
+	hr &= RTK_Demod_Byte_Write(0, 0x19, 1, data);
+
+
+	// sw reset
+	hr &= RTK_Demod_Byte_Read(1, 0x01, 1, data);
+	data[0] = data[0] | 0x04;
+	hr &= RTK_Demod_Byte_Write(1, 0x01, 1, data);
+	data[0] = data[0] & 0xFB;
+	hr &= RTK_Demod_Byte_Write(1, 0x01, 1, data);
+
+	//enable
+	tmp = tmp | 0x1;
+	hr &= RTK_Demod_Byte_Write(0, 0x19, 1, &tmp);
+
+	return hr; 
+}
+
+
+
+int Initial_2832_fm(struct rtl2832_state*	p_state)
+{
+	unsigned char data[4];
+	unsigned short length;
+	int hr = 1;
+
+ 	length = 2;
+	data[0] = 0x00;
+	data[1] = 0x00;
+	hr &= RTK_Demod_Byte_Write(1, 0x3E, length, data);
+	
+    	length = 1;
+	data[0] = 0x00;
+	hr &= RTK_Demod_Byte_Write(1, 0x15, length, data);
+
+	length = 3;
+	data[0] = 0x00;
+	data[1] = 0x00;
+	data[2] = 0x00;
+	hr &= RTK_Demod_Byte_Write(1, 0x16, length, data);
+
+	if(p_state->tuner_type == RTL2832_TUNER_TYPE_MXL5007T)
+	{
+		data[0] = 0x35;
+		data[1] = 0xD8;
+		data[2] = 0x2E;
+		hr &= RTK_Demod_Byte_Write(1, 0x19, 3, data);
+	}
+	else if(p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)
+	{
+        	data[0] = 0x00;
+		data[1] = 0x00;
+		data[2] = 0x00;	
+		hr &= RTK_Demod_Byte_Write(1, 0x19, 3, data);
+	}
+	else if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012)
+	{
+		data[0] = 0x00;
+		data[1] = 0x00;
+		data[2] = 0x00;	
+		hr &= RTK_Demod_Byte_Write(1, 0x19, 3, data);
+	}
+
+   	length = 4;
+	data[0] = 0x03;
+	data[1] = 0x84;
+	data[2] = 0x00;
+	data[3] = 0x00;
+    	hr &= RTK_Demod_Byte_Write(1, 0x9F, length, data);
+
+    	hr &= Set1(p_state);
+
+ 	length = 1;
+	data[0] = 0x11;
+	hr &= RTK_Demod_Byte_Write(0, 0x17, length, data);
+    
+	length = 1;
+	data[0] = 0x10;
+	hr &= RTK_Demod_Byte_Write(0, 0x18, length, data);
+    
+	length = 1;
+	data[0] = 0x21;
+   	hr &= RTK_Demod_Byte_Write(0, 0x19, length, data);
+    
+ 	hr &= Set2(p_state);
+
+      length = 1;
+	data[0] = 0x00;
+	hr &= RTK_Demod_Byte_Write(1, 0x92, length, data);
+
+	length = 1;
+	data[0] = 0xF0;
+	hr &= RTK_Demod_Byte_Write(1, 0x93, length, data);
+
+   	length = 1;
+	data[0] = 0x0F;
+	hr &= RTK_Demod_Byte_Write(1, 0x94, length, data);
+   
+	length = 1;
+	data[0] = 0x60;
+	hr &= RTK_Demod_Byte_Write(0, 0x61, length, data);//output of PID filter
+
+	length = 1;
+	data[0] = 0x80;
+	hr &= RTK_Demod_Byte_Write(0, 0x06, length, data);
+
+	if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012  || p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)
+	{
+		data[0] = 0xCD;
+    		hr &= RTK_Demod_Byte_Write(0, 0x08, 1, data);
+
+		data[0] = 0x1;
+		hr &= RTK_Demod_Byte_Write(1, 0xB1, 1, data);
+	}
+
+     	hr &= RTL2832_SWReset(p_state);
+ 	if(!hr)
+	{
+		deb_info("FM Func: Initial 2832 register failed\n");
+	}
+
+	if(hr != 1)
+		return  -1;
+	
+	return 0;
+}
+
+
+int Initial_2832_dab(struct rtl2832_state*	p_state)
+{
+	unsigned char data[4];
+	unsigned short length;	
+	BOOL hr = 1;
+	
+	if( p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)
+	{
+		length = 1;
+		data[0] = 0xCD;//enable ADC_I, ADC_Q for zero-IF
+		//data[0] = 0x8D;//enable ADC_I 
+		hr &= RTK_Demod_Byte_Write(0, 0x08, length, data);
+		
+		//bit 0, enable en_bbin
+		//bit 2,1  DC offset
+		//bit 4,3  IQ mismatch
+		length = 1;
+		data[0] = 0x1F;//ZeroIF //?? data[0] = 0x1E;
+		hr &= RTK_Demod_Byte_Write(1, 0xB1, length, data);
+	}
+   
+	//----------------------------------------------
+	//set each time change 
+	//en_sfreq_sync = 0   page 1, 0x3E, bit6
+	//pset_sfreq_off default = 0  page 1, 0x{3E, 3F}
+	length = 2;
+	data[0] = 0x00;
+	data[1] = 0x00;
+	hr &= RTK_Demod_Byte_Write(1, 0x3E, length, data);
+	//-----------------------------------------------
+
+	//spec_inv = 0; en_aci = 0; en_cfreq_sync = 0
+	length = 1;
+	data[0] = 0x00;
+	hr &= RTK_Demod_Byte_Write(1, 0x15, length, data);
+	
+	//pset_cfreq_off = 0    Pre-set value of carrier frequency offset. 
+	length = 3;
+	data[0] = 0x00;
+	data[1] = 0x00;
+	data[2] = 0x00;
+	hr &= RTK_Demod_Byte_Write(1, 0x16, length, data);
+
+	//---- DDC Setting ------
+	//pset_iffreq   IF frequency //36.125M  0x2F; 0xB8; 0xE4;
+	if(p_state->tuner_type == RTL2832_TUNER_TYPE_MXL5007T)
+	{//IF 4.57M
+		length = 3;
+		data[0] = 0x35;
+		data[1] = 0xD8;
+		data[2] = 0x2E;
+		hr &= RTK_Demod_Byte_Write(1, 0x19, length, data);
+	}
+	else if(p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)
+	{//ZERO IF
+		length = 3;
+		data[0] = 0x00;
+		data[1] = 0x00;
+		data[2] = 0x00;
+		hr &= RTK_Demod_Byte_Write(1, 0x19, length, data);
+	}
+	else if(p_state->tuner_type ==  RTL2832_TUNER_TYPE_FC0012)
+	{//FC0012_TUNER is zero IF, but can set tunner to other frequency to avoid DC cancellation, frequency noise...
+		
+		//length = 3;
+		//data[0] = 0x00;
+		//data[1] = 0x00;
+		//data[2] = 0x00;
+		//hr &= RTK_Demod_Byte_Write(1, 0x19, length, data);
+	
+		// Set pset_iffreg of 2832
+		length = 3;
+		data[0] = 0x00;
+		data[1] = 0x00;
+		data[2] = 0x00;
+		hr &= RTK_Demod_Byte_Write(1, 0x19, length, data);
+	}
+	//20110413 add by alan
+	else if(p_state->tuner_type ==  RTL2832_TUNER_TYPE_FC0013)
+	{//FC0013_TUNER is zero IF, but can set tunner to other frequency to avoid DC cancellation, frequency noise...
+		
+		//length = 3;
+		//data[0] = 0x00;
+		//data[1] = 0x00;
+		//data[2] = 0x00;
+		//hr &= RTK_Demod_Byte_Write(1, 0x19, length, data);
+	
+		// Set pset_iffreg of 2832
+		length = 3;
+		data[0] = 0x00;
+		data[1] = 0x00;
+		data[2] = 0x00;
+		hr &= RTK_Demod_Byte_Write(1, 0x19, length, data);
+	}
+	//end	
+	//------ Resampler Setting -------
+	//resample ratio 28.8M --> 8.192M
+	length = 4;
+	data[0] = 0x03;
+	data[1] = 0x84;
+	data[2] = 0x00;
+	data[3] = 0x00;
+	hr &= RTK_Demod_Byte_Write(1, 0x9F, length, data);
+
+ 	//------- DDC LPF coe -------------
+	// used in OpenDevice? more possible setFreq  
+	length = 1;
+	data[0] = 202;
+	hr &= RTK_Demod_Byte_Write(1, 0x1C, length, data);
+
+	length = 1;
+	data[0] = 220;
+	hr &= RTK_Demod_Byte_Write(1, 0x1D, length, data);
+
+	length = 1;
+	data[0] = 215;
+	hr &= RTK_Demod_Byte_Write(1, 0x1E, length, data);
+
+	length = 1;
+	data[0] = 216;
+	hr &= RTK_Demod_Byte_Write(1, 0x1F, length, data);
+
+	length = 1;
+	data[0] = 224;
+	hr &= RTK_Demod_Byte_Write(1, 0x20, length, data);
+
+	length = 1;
+	data[0] = 242;
+	hr &= RTK_Demod_Byte_Write(1, 0x21, length, data);
+
+	length = 1;
+	data[0] = 14;
+	hr &= RTK_Demod_Byte_Write(1, 0x22, length, data);
+
+	length = 1;
+	data[0] = 53;
+	hr &= RTK_Demod_Byte_Write(1, 0x23, length, data);
+  
+	length = 1;
+	data[0] = 6;
+	hr &= RTK_Demod_Byte_Write(1, 0x24, length, data);
+
+	length = 1;
+	data[0] = 80;
+	hr &= RTK_Demod_Byte_Write(1, 0x25, length, data);
+
+	length = 1;
+	data[0] = 156;
+	hr &= RTK_Demod_Byte_Write(1, 0x26, length, data);
+
+	length = 1;
+	data[0] = 13;
+	hr &= RTK_Demod_Byte_Write(1, 0x27, length, data);
+
+	length = 1;
+	data[0] = 113;
+	hr &= RTK_Demod_Byte_Write(1, 0x28, length, data);
+
+	length = 1;
+	data[0] = 17;
+	hr &= RTK_Demod_Byte_Write(1, 0x29, length, data);
+
+	length = 1;
+	data[0] = 20;
+	hr &= RTK_Demod_Byte_Write(1, 0x2A, length, data);
+ 
+	length = 1;
+	data[0] = 113;
+	hr &= RTK_Demod_Byte_Write(1, 0x2B, length, data);
+
+	length = 1;
+	data[0] = 116;
+	hr &= RTK_Demod_Byte_Write(1, 0x2C, length, data);
+
+	length = 1;
+	data[0] = 25;
+	hr &= RTK_Demod_Byte_Write(1, 0x2D, length, data);
+
+	length = 1;
+	data[0] = 65;
+	hr &= RTK_Demod_Byte_Write(1, 0x2E, length, data);
+
+	length = 1;
+	data[0] = 165;
+	hr &= RTK_Demod_Byte_Write(1, 0x2F, length, data);
+
+	//-------- DAB Setting ---------
+	//dab dagc_target;     (S,8,7f) when dagc on 
+	length = 1;
+	data[0] = 0x11;//default: 0x13
+	hr &= RTK_Demod_Byte_Write(0, 0x17, length, data);
+    
+	//dagc_gain_set;  (S,8,1f) when dagc off
+	length = 1;
+	data[0] = 0x10;//default: 0x10
+	hr &= RTK_Demod_Byte_Write(0, 0x18, length, data);
+    
+	//0x19 [0]   0x01    1 for dab_enable;     0 for soft reset or module disable;       
+	//0x19 [2:1] 0x02    mode  10 for DAB , 00 for FM , 01/11 for pattern
+ 	//0x19 [4:3] 0x00    dagc_loop_gain; 0~3 for 2^-10 ~ 2^-7:                     
+	//0x19 [5]   0x01    dagc_on;        0 for off , 1 for on                    
+	length = 1;
+	data[0] = 0x25;//0x25;//0x27;
+	hr &= RTK_Demod_Byte_Write(0, 0x19, length, data);
+	//-------------------------------
+
+	//------- hold stage ------------
+	// stage 11 is possible
+	// hold stage 4 now !
+	length = 1;
+	data[0] = 0x00;//0x7F;//
+	hr &= RTK_Demod_Byte_Write(1, 0x92, length, data);
+
+	length = 1;
+	data[0] = 0xF0;//0xF7;//
+	hr &= RTK_Demod_Byte_Write(1, 0x93, length, data);
+
+ 	length = 1;
+	data[0] = 0x0F;//0xFF;//
+	hr &= RTK_Demod_Byte_Write(1, 0x94, length, data);
+	//----------------------------------
+
+	// DAB input from PIP ?
+	length = 1;
+	data[0] = 0x60;
+	hr &= RTK_Demod_Byte_Write(0, 0x61, length, data);//output of PID filter
+ 
+	//if(currentTunner == MT2266_TUNER || currentTunner == FC2580_TUNER || currentTunner == TUA9001_TUNER || currentTunner == FC0012_TUNER)
+	{//???
+		length = 1;
+		data[0] = 0x40;//08.03.10
+		hr &= RTK_Demod_Byte_Write(0, 0x20, length, data);
+	}
+	
+	length = 1;
+	//if(p_state->tuner_type == TUA9001_TUNER)// pay attention: for infineon tunner, exchange I and Q
+	//{
+	//	data[0] = 0x90;
+	//}
+	//else
+	{	
+		data[0] = 0x80;
+	}
+	hr &= RTK_Demod_Byte_Write(0, 0x06, length, data);
+
+	//end
+	//---- software reset -----
+	//page 1, 0x01, bit 2, first 1 then zero
+	length = 1;
+	hr &= RTK_Demod_Byte_Read(1, 0x01, length, data);
+	data[0] = data[0] | 0x04;
+	hr &= RTK_Demod_Byte_Write(1, 0x01, length, data);
+	data[0] = data[0] & 0xFB;
+	hr &= RTK_Demod_Byte_Write(1, 0x01, length, data);
+
+	if(!hr)
+	{
+		deb_info("DAB DLL: initial 2832 register fail\n");
+	}
+
+	if(hr != 1)
+		return  -1;
+	
+	return 0;
+}
+
+
+
+int switch_mode(struct rtl2832_state* p_state, int audio_mdoe)
+{
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )	goto mutex_error;
+
+	if(p_state->tuner_type != RTL2832_TUNER_TYPE_FC0012 && 
+				p_state->tuner_type != RTL2832_TUNER_TYPE_MXL5007T &&
+				p_state->tuner_type != RTL2832_TUNER_TYPE_E4000 &&
+				p_state->tuner_type != RTL2832_TUNER_TYPE_FC0013)
+	{
+		deb_info("Illegal tuner type\n");
+		goto error;
+	}
+	
+	deb_info("+switch_mode\n");
+
+	if(p_state->demod_support_type & SUPPORT_DVBT_MODE)
+	{
+		// if current state is 2832
+		if(p_state->demod_type == RTL2832)
+		{
+	      		// Demod  H/W Reset
+           		if(rtl2832_hw_reset( p_state))
+					goto error;
+					
+			if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012)
+			{
+				if(rtl2832_fc0012_Initialize_fm(p_state->pNim))
+					goto error;
+			}
+			else if(p_state->tuner_type == RTL2832_TUNER_TYPE_MXL5007T)
+			{
+				if(rtl2832_mxl5007t_Initialize_fm(p_state->pNim))
+					goto error;
+			}
+			else if(p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)
+			{	
+				if(rtl2832_e4000_Initialize_fm(p_state->pNim))
+					goto error;
+			}
+			else if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0013)
+			{	
+				if(rtl2832_fc0013_Initialize_fm(p_state->pNim))
+					goto error;
+			}
+
+
+			switch(audio_mdoe)
+			{
+				case FM_MODE:
+					if (Initial_2832_fm(p_state)) 
+					{
+						deb_info("%s: fail to initial fm\n",__FUNCTION__);
+						goto error;
+					}
+					deb_info("%s: switch to fm.....\n",__FUNCTION__);	
+				break;
+
+				case DAB_MODE:
+					if (Initial_2832_dab(p_state)) 
+					{
+						deb_info("%s: fail to initial dab\n",__FUNCTION__);
+						goto error;
+					}
+					deb_info("%s: switch to dab.....\n",__FUNCTION__);	
+				break;	
+			}
+		}
+	}
+
+	deb_info("-switch_mode\n");
+
+       mutex_unlock(&p_state->i2c_repeater_mutex);
+	return 0;
+
+error:
+	mutex_unlock(&p_state->i2c_repeater_mutex);
+mutex_error:
+	return -1;
+}
+
+
+//3 Related to urb behavior
+struct usb_data_stream stream_cp;
+struct  fm_stream_ctrl_struct
+{
+	u8  fm_stream_buf[24064];
+	int  fm_stream_index;
+};
+struct fm_stream_ctrl_struct fm_struct;
+struct fm_stream_ctrl_struct* fm_stream;
+
+static void dvb_dmx_fm_filter(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+
+       struct dvb_demux_feed *feed;
+	int p,i,j;
+
+	spin_lock(&demux->lock);
+
+       list_for_each_entry(feed, &demux->feed_list, list_head) {
+		if(feed->pid != 0x2000)
+			continue;
+
+	p = 0;
+	if (fm_stream->fm_stream_index) {
+		i = fm_stream->fm_stream_index;
+		j = 24064 - i;
+
+		if (count < j) {
+			memcpy(&fm_stream->fm_stream_buf[i], buf, count);
+			fm_stream->fm_stream_index += count; 
+			goto bailout;
+		}
+		
+		memcpy(&fm_stream->fm_stream_buf[i], buf, j);
+		feed->cb.ts(fm_stream->fm_stream_buf, 24064, NULL, 0, &feed->feed.ts, DMX_OK);
+		fm_stream->fm_stream_index = 0;
+		p += j;
+	}
+
+	while (p < count) {
+		if (count - p >= 24064) {
+				feed->cb.ts(&buf[p], 24064, NULL, 0, &feed->feed.ts, DMX_OK);
+				p += 24064;
+		} else {
+				i = count - p;
+				memcpy(fm_stream->fm_stream_buf, &buf[p], i);
+				fm_stream->fm_stream_index = i;
+				goto bailout;
+		}
+	}
+
+	}
+
+bailout:
+	spin_unlock(&demux->lock);
+}
+
+
+//3--> dvb_usb_data_complete
+static void fm_usb_data_complete(struct usb_data_stream *stream, u8 *buffer, size_t length)
+{
+	struct dvb_usb_adapter *adap = stream->user_priv;
+	
+	//deb_info("%s: length %d\n ", __func__, length);//debug
+	if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
+		dvb_dmx_fm_filter(&adap->demux, buffer, length);
+}
+
+#ifdef V4L2_REFACTORED_MFE_CODE
+void fm_stream_ctrl(int f,  struct dvb_usb_adapter*  adapter)
+{
+	if(f)
+	{//store  usb_data_stream part
+		memcpy(&stream_cp, &adapter->fe_adap[0].stream, sizeof(struct usb_data_stream));
+		adapter->fe_adap[0].stream.complete = fm_usb_data_complete;
+	}
+	else
+	{//resume dvb-t usb_data_stream part
+		memcpy(&adapter->fe_adap[0].stream, &stream_cp, sizeof(struct usb_data_stream));
+	}
+}
+#else
+void fm_stream_ctrl(int f,  struct dvb_usb_adapter*  adapter)
+{
+	if(f)
+	{//store  usb_data_stream part
+		memcpy(&stream_cp, &adapter->stream, sizeof(struct usb_data_stream));
+		adapter->stream.complete = fm_usb_data_complete;
+	}
+	else
+	{//resume dvb-t usb_data_stream part
+		memcpy(&adapter->stream, &stream_cp, sizeof(struct usb_data_stream));
+	}
+}
+#endif
+
+int fe_fm_cmd_ctrl(struct dvb_frontend *fe, void *parg)
+{
+	struct rtl2832_state*	p_state = fe->demodulator_priv;
+	struct dvb_usb_adapter*  adapter = p_state->d->adapter;//ptr to adapter[0]
+	struct fm_cmd_struct*  fm_ctrl = (struct fm_cmd_struct*)parg;
+	int fm_cmd = fm_ctrl->cmd_num;
+	unsigned int tmp2;
+	unsigned char data[4];
+	int hr;
+	struct fm_cmd_struct  tmp_str;
+	unsigned int orgValue;
+	unsigned int psetValue;
+
+	deb_info("+fe_fm_cmd_ctrl\n");
+
+	switch(fm_cmd)
+	{
+		case FE_ENABLE_FM:
+
+			deb_info("FE_OPEN_FM\n");
+
+			if(p_state->rtl2832_audio_video_mode == RTK_AUDIO)
+			{
+				deb_info("It has been FM mode\n");
+				return 1;
+			}
+
+			//check whether it is legal, no dvb-t, no fm
+					
+			//switch to fm mode
+			if(switch_mode(p_state, FM_MODE))
+				return -1;
+			
+			//change usb_data_stream part
+			//fm_stream = vmalloc(sizeof(struct fm_stream_ctrl_struct));
+			fm_stream = &fm_struct;
+			fm_stream_ctrl(1, adapter);
+		
+			p_state->rtl2832_audio_video_mode = RTK_AUDIO;//FM or DAB
+
+			tmp_str.tuner= p_state->tuner_type;//tuner type
+			memcpy(parg, &tmp_str, sizeof(struct fm_cmd_struct));//will be copy to user
+	
+			return 1;//break;
+
+		case FE_ENABLE_DAB:
+
+			deb_info("FE_OPEN_DAB\n");
+
+			if(p_state->rtl2832_audio_video_mode == RTK_AUDIO)
+			{
+				deb_info("It has been DAB mode\n");
+				return 1;
+			}
+
+			//check whether it is legal, no dvb-t, no fm
+					
+			//switch to fm mode
+			if(switch_mode(p_state, DAB_MODE))
+				return -1;
+			
+			//change usb_data_stream part
+			//fm_stream = vmalloc(sizeof(struct fm_stream_ctrl_struct));
+			fm_stream = &fm_struct;
+			fm_stream_ctrl(1, adapter);
+		
+			p_state->rtl2832_audio_video_mode = RTK_AUDIO;//FM or DAB
+
+			tmp_str.tuner= p_state->tuner_type;//tuner type
+			memcpy(parg, &tmp_str, sizeof(struct fm_cmd_struct));//will be copy to user
+	
+			return 1;//break;
+
+			
+		case FE_DISABLE_FM:
+		case FE_DISABLE_DAB:
+			
+			deb_info("FE_CLOSE_FM or DAB\n");
+
+			if(p_state->rtl2832_audio_video_mode != RTK_AUDIO)
+			{
+				deb_info("It is not start from FM or DAB mode\n");
+				return 1;
+			}
+			
+			fm_stream_ctrl(0, adapter);
+			p_state->rtl2832_audio_video_mode = RTK_VIDEO;
+			return 1;//break;
+
+		case CR_D:
+
+			deb_info("CR_d\n");
+
+			tmp2 = (fm_ctrl->cr)  & 0x3FFFFF;
+	    		data[0] = (tmp2>>16) & 0x3F;
+	    		data[1] = (tmp2>>8) & 0xFF;
+			data[2] = tmp2 & 0xFF;
+	    		hr = RTK_Demod_Byte_Write(1, 0x16, 3, data);
+			if(!hr)
+				return -1;
+
+			hr = RTL2832_SWReset_2(p_state);
+			if(!hr)
+				return -1;
+
+			deb_info("CR_d done\n");
+			return 1;
+
+		case CR_A:
+
+			deb_info("CR_a\n");
+
+			hr = RTK_Demod_Byte_Read(1, 0x16, 3, data);
+			if(!hr)
+			{
+				return -1;
+			}
+
+			tmp2 = (fm_ctrl->cr)  & 0x3FFFFF;
+
+			orgValue =  (((unsigned int)data[0]&0x3F)<<16) | (((unsigned int)data[1])<<8) | (unsigned short)data[2];
+			psetValue = tmp2 + orgValue; 
+			
+			data[0] = (psetValue>>16) & 0x3F;
+			data[1] = (psetValue>>8) & 0xFF;
+			data[2] = psetValue & 0xFF;
+			hr = RTK_Demod_Byte_Write(1, 0x16, 3, data);
+			if(!hr)
+				return -1;
+
+			hr = RTL2832_SWReset_2(p_state);
+			if(!hr)
+				return -1;	
+
+			deb_info("CR_a done\n");
+			return 1;
+
+		case TR_D:   
+
+			deb_info("TR_d \n");
+
+			tmp2 = (fm_ctrl->cr);
+			data[0] = (tmp2>>8) & 0x3F;
+			data[1] = tmp2 & 0xFF;
+			hr = RTK_Demod_Byte_Write(1, 0x3E, 2, data);//0x3E 0x3F
+			if(!hr)
+				return -1;
+
+			//hr = RTL2832_SWReset(p_state);
+			//if(!hr)
+			//	return -1;
+
+			deb_info("TR_d done\n");
+			return 1;
+
+		case TR_A:    //increasing value
+
+			deb_info("TR_a\n");
+
+			hr = RTK_Demod_Byte_Read(1, 0x3E, 2, data);//0x3E, 0x3F
+			if(!hr)
+				return -1;
+
+			tmp2 = (fm_ctrl->cr);
+			orgValue =  (((unsigned int)data[0] & 0x3F) << 8) | (unsigned int)data[1];
+			psetValue = (tmp2 & 0x3FFF) + orgValue; 
+	
+			data[0] = (psetValue>>8) & 0x3F;
+			data[1] = psetValue & 0xFF;
+
+			hr = RTK_Demod_Byte_Write(1, 0x3E, 2, data);//0x3E, 0x3F
+			if(!hr)
+				return -1;			
+			
+			//hr = RTL2832_SWReset(p_state);
+			//if(!hr)
+			//	return -1;
+
+			deb_info("TR_a done\n");
+			return 1;
+
+		case SW_RESET:
+
+			hr = RTL2832_SWReset(p_state);
+			if(!hr)
+				return -1;
+
+			deb_info("RTL2832_SWReset\n");
+			return 1;
+
+		default:
+			return -1;			
+	}
+
+	return 0;		
+}
+
+int rtl2832_fe_ioctl_override(struct dvb_frontend *fe,unsigned int cmd, void *parg, unsigned int stage)
+{
+	
+	//deb_info("rtl2832_fe_ioctl_override : cmd =%d\n", cmd);
+	
+	int ret = 0;
+
+	if(stage == DVB_FE_IOCTL_PRE)
+	{
+		switch(cmd)
+		{
+			case FE_FM_CMD:
+
+				ret = fe_fm_cmd_ctrl(fe, parg);
+			break;
+	
+		}
+	}
+	//else
+	//{
+	//deb_info("rtl2832_fe_ioctl_override : xxxxx\n");
+	//}	
+
+	return ret;
+}
+
+#endif
+
+
+
diff --git a/drivers/media/usb/dvb-usb/rtl2832u_audio.h b/drivers/media/usb/dvb-usb/rtl2832u_audio.h
new file mode 100644
index 0000000..58168f6
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/rtl2832u_audio.h
@@ -0,0 +1,67 @@
+
+#ifndef __RTL2832U_AUDIO_H__
+#define __RTL2832U_AUDIO_H__
+
+#include "rtl2832u_fe.h"
+#include "rtl2832u_io.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb-usb.h"
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0)) || (defined V4L2_VERSION)
+#define V4L2_REFACTORED_RC_CODE
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)) || (defined V4L2_VERSION)
+#define V4L2_REFACTORED_MFE_CODE
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) || (defined V4L2_VERSION)
+#define NO_FE_IOCTL_OVERRIDE
+#endif
+
+#define UCHAR  unsigned char
+
+
+#ifndef NO_FE_IOCTL_OVERRIDE
+struct fm_cmd_struct
+{
+	int cmd_num;
+	int cr;
+	int tuner;	
+	int tr;
+};
+
+
+#define FE_FM_CMD    _IOWR('o', 90,  struct fm_cmd_struct)
+
+enum
+{
+	FE_ENABLE_FM=0,
+	FE_DISABLE_FM,
+	CR_D,
+	CR_A,
+	CR_S,
+	READ_BYTE,
+	WRITE_BYTE,
+	FE_ENABLE_DAB,
+	FE_DISABLE_DAB,
+	TR_D,
+	TR_A,
+	SW_RESET,
+};
+
+enum
+{
+	FM_MODE = 0,
+	DAB_MODE,
+};
+
+
+
+int rtl2832_fe_ioctl_override(struct dvb_frontend *fe,unsigned int cmd, void *parg, unsigned int stage);
+void fm_stream_ctrl(int f,  struct dvb_usb_adapter*  adapter);
+
+#endif
+#endif
diff --git a/drivers/media/usb/dvb-usb/rtl2832u_fe.c b/drivers/media/usb/dvb-usb/rtl2832u_fe.c
new file mode 100644
index 0000000..ba4a9a5
--- /dev/null
+++ b/drivers/media/usb/dvb-usb/rtl2832u_fe.c
@@ -0,0 +1,4746 @@
+
+#include "rtl2832u_fe.h"
+#include "rtl2832u_io.h"
+#include "rtl2832u.h"
+#include "rtl2832u_audio.h"
+//#include "rtl2832u_ioctl.h"
+
+extern int demod_default_type;
+extern int dtmb_error_packet_discard;
+extern int dvb_use_rtl2832u_card_type;
+extern int dvb_use_rtl2832u_rc_mode;
+extern int rtl2832u_remote_control_state;
+
+static struct rtl2832_reg_addr rtl2832_reg_map[]= {
+	/* RTD2831_RMAP_INDEX_USB_CTRL_BIT5*/			{ RTD2832U_USB, USB_CTRL, 5, 5		},
+	/* RTD2831_RMAP_INDEX_USB_STAT*/				{ RTD2832U_USB, USB_STAT, 0, 7		},
+	/* RTD2831_RMAP_INDEX_USB_EPA_CTL*/			{ RTD2832U_USB, USB_EPA_CTL, 0, 31	},
+	/* RTD2831_RMAP_INDEX_USB_SYSCTL*/				{ RTD2832U_USB, USB_SYSCTL, 0, 31		},
+	/* RTD2831_RMAP_INDEX_USB_EPA_CFG*/			{ RTD2832U_USB, USB_EPA_CFG, 0, 31	},
+	/* RTD2831_RMAP_INDEX_USB_EPA_MAXPKT*/		{ RTD2832U_USB, USB_EPA_MAXPKT, 0, 31},
+	/* RTD2831_RMAP_INDEX_USB_EPA_FIFO_CFG*/		{ RTD2832U_USB, USB_EPA_FIFO_CFG, 0, 31},
+
+	/* RTD2831_RMAP_INDEX_SYS_DEMOD_CTL*/			{ RTD2832U_SYS, DEMOD_CTL, 0, 7	       },
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL*/	{ RTD2832U_SYS, GPIO_OUTPUT_VAL, 0, 7	},
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_EN_BIT3*/{ RTD2832U_SYS, GPIO_OUTPUT_EN, 3, 3	},
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_DIR_BIT3*/		{ RTD2832U_SYS, GPIO_DIR, 3, 3		},
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_CFG0_BIT67*/	{ RTD2832U_SYS, GPIO_CFG0, 6, 7		},
+	/* RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1*/		{ RTD2832U_SYS, DEMOD_CTL1, 0, 7	       },	
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_EN_BIT1*/{ RTD2832U_SYS, GPIO_OUTPUT_EN, 1, 1	},
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_DIR_BIT1*/		{ RTD2832U_SYS, GPIO_DIR, 1, 1		},
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_EN_BIT6*/{ RTD2832U_SYS, GPIO_OUTPUT_EN, 6, 6	},	
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_DIR_BIT6*/		{ RTD2832U_SYS, GPIO_DIR, 6, 6		},
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_EN_BIT5*/{ RTD2832U_SYS, GPIO_OUTPUT_EN, 5, 5},
+	/* RTD2831_RMAP_INDEX_SYS_GPIO_DIR_BIT5*/      { RTD2832U_SYS, GPIO_DIR, 5, 5},
+
+#if 0
+	/* RTD2831_RMAP_INDEX_SYS_GPD*/			{ RTD2832U_SYS, GPD, 0, 7		},
+	/* RTD2831_RMAP_INDEX_SYS_GPOE*/			{ RTD2832U_SYS, GPOE, 0, 7	},
+	/* RTD2831_RMAP_INDEX_SYS_GPO*/			{ RTD2832U_SYS, GPO, 0, 7		},
+	/* RTD2831_RMAP_INDEX_SYS_SYS_0*/			{ RTD2832U_SYS, SYS_0, 0, 7	},
+#endif
+
+	/* DTMB related */
+
+   
+};                                          
+
+static int rtl2832_reg_mask[32]= {
+    0x00000001,
+    0x00000003,
+    0x00000007,
+    0x0000000f,
+    0x0000001f,
+    0x0000003f,
+    0x0000007f,
+    0x000000ff,
+    0x000001ff,
+    0x000003ff,
+    0x000007ff,
+    0x00000fff,
+    0x00001fff,
+    0x00003fff,
+    0x00007fff,
+    0x0000ffff,
+    0x0001ffff,
+    0x0003ffff,
+    0x0007ffff,
+    0x000fffff,
+    0x001fffff,
+    0x003fffff,
+    0x007fffff,
+    0x00ffffff,
+    0x01ffffff,
+    0x03ffffff,
+    0x07ffffff,
+    0x0fffffff,
+    0x1fffffff,
+    0x3fffffff,
+    0x7fffffff,
+    0xffffffff
+};
+
+typedef struct FC0012_LNA_REG_MAP
+{
+	unsigned char	Lna_regValue;
+	long			LnaGain;
+}FC0012_LNA_REG_MAP;
+
+FC0012_LNA_REG_MAP  FC0012_LNA_GAIN_TABLE[]= {
+	{0x00 , -63},{0x01 , -58},{0x02 , -99},{0x03 , -73},{0x04 , -63},{0x05 , -65}
+	,{0x06 , -54},{0x07 , -60},{0x08 , 71 },{0x09 , 70 },{0x0a , 68 },{0x0b , 67 }
+	,{0x0c , 65 },{0x0d , 63 },{0x0e , 61 },{0x0f , 58 },{0x10 , 197},{0x11 , 191}
+	,{0x12 , 188},{0x13 , 186},{0x14 , 184},{0x15 , 182},{0x16 , 181},{0x17 , 179}
+};
+
+static int check_dtmb_support(struct rtl2832_state* p_state);
+
+static int 	check_dvbc_support(struct rtl2832_state* p_state);
+
+static int
+set_demod_2836_power(
+		struct rtl2832_state* p_state, 
+		int  onoff);
+
+static int
+rtl2840_on_hwreset(
+		struct rtl2832_state* p_state);
+
+
+static int
+set_demod_2840_power(
+		struct rtl2832_state* p_state, 
+		int  onoff);
+
+
+static int
+demod_init_setting(
+	struct rtl2832_state * p_state);
+
+static int
+build_nim_module(
+	struct rtl2832_state*  p_state);
+
+static int 
+rtl2836_scan_procedure(
+		struct rtl2832_state * p_state);
+static int 
+fc0012_get_signal_strength(
+	struct rtl2832_state	*p_state,
+	unsigned long *strength);
+static int 
+rtl2832_sleep_mode(struct rtl2832_state* p_state);
+
+static void 	
+custom_wait_ms(
+	BASE_INTERFACE_MODULE*	pBaseInterface,
+	unsigned long				WaitTimeMs)
+{
+	platform_wait(WaitTimeMs);
+	return;	
+}
+
+
+static int
+custom_i2c_read(
+	BASE_INTERFACE_MODULE*	pBaseInterface,
+	unsigned char				DeviceAddr,
+	unsigned char*			pReadingBytes,
+	unsigned long				ByteNum
+	)
+{
+	struct dvb_usb_device *d;
+
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);
+	if ( read_rtl2832_stdi2c( d, DeviceAddr , pReadingBytes , ByteNum ) ) goto error;
+	
+	return 0;
+error:
+	return 1;
+}
+
+
+
+static int
+custom_i2c_write(
+	BASE_INTERFACE_MODULE*	pBaseInterface,
+	unsigned char				DeviceAddr,
+	const unsigned char*			pWritingBytes,
+	unsigned long				ByteNum)
+{
+	struct dvb_usb_device *d;
+
+	pBaseInterface->GetUserDefinedDataPointer(pBaseInterface, (void **)&d);
+	if ( write_rtl2832_stdi2c( d, DeviceAddr , (unsigned char*)pWritingBytes , ByteNum ) ) goto error;
+	
+	return 0;
+error:
+	return 1;
+}
+
+
+
+static int
+read_usb_sys_register(
+	struct rtl2832_state*		p_state,
+	rtl2832_reg_map_index		reg_map_index,
+	int*						p_val)
+{
+	RegType			reg_type=	rtl2832_reg_map[reg_map_index].reg_type;
+	unsigned short	reg_addr=	rtl2832_reg_map[reg_map_index].reg_addr;
+	int				bit_low=	rtl2832_reg_map[reg_map_index].bit_low;
+	int				bit_high=	rtl2832_reg_map[reg_map_index].bit_high;
+
+	int	n_byte_read=(bit_high>> 3)+ 1;
+
+	*p_val= 0;
+	if (read_usb_sys_int_bytes(p_state->d, reg_type, reg_addr, n_byte_read, p_val)) goto error;
+
+	*p_val= ((*p_val>> bit_low) & rtl2832_reg_mask[bit_high- bit_low]);
+ 
+	return 0;
+
+error:
+	return 1;
+}
+
+
+
+
+static int
+write_usb_sys_register(
+	struct rtl2832_state*		p_state,
+	rtl2832_reg_map_index		reg_map_index,
+	int						val_write)
+{
+	RegType			reg_type=	rtl2832_reg_map[reg_map_index].reg_type;
+	unsigned short	reg_addr=	rtl2832_reg_map[reg_map_index].reg_addr;
+	int				bit_low=	rtl2832_reg_map[reg_map_index].bit_low;
+	int				bit_high=	rtl2832_reg_map[reg_map_index].bit_high;
+	
+	int	n_byte_write=	(bit_high>> 3)+ 1;
+	int	val_read= 0;
+	int	new_val_write;
+
+	if (read_usb_sys_int_bytes(p_state->d, reg_type, reg_addr, n_byte_write, &val_read)) goto error;
+
+	new_val_write= (val_read & (~(rtl2832_reg_mask[bit_high- bit_low]<< bit_low))) | (val_write<< bit_low);
+
+	if (write_usb_sys_int_bytes(p_state->d, reg_type, reg_addr, n_byte_write, new_val_write)) goto error;
+	return 0;
+	
+error:
+	return 1;
+}
+
+
+
+
+static int 
+max3543_set_power(
+	struct rtl2832_state*	p_state,
+	unsigned char			onoff
+	)
+{
+	unsigned char	data;
+	unsigned char	i2c_repeater;	
+
+	
+	if( p_state->tuner_type != RTL2832_TUNER_TYPE_MAX3543)		return 0;
+
+	deb_info(" %s : onoff =%d\n", __FUNCTION__, onoff);
+
+	read_demod_register(p_state->d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 );
+	i2c_repeater |= BIT3;	
+	write_demod_register(p_state->d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 );	
+
+	if(onoff)
+	{
+		//turn on BIT7=0
+		read_rtl2832_tuner_register(p_state->d, MAX3543_TUNER_ADDR, MAX3543_SHUTDOWN_OFFSET, &data, LEN_1_BYTE);
+		data &=(~BIT_7_MASK);
+		write_rtl2832_tuner_register(p_state->d, MAX3543_TUNER_ADDR, MAX3543_SHUTDOWN_OFFSET, &data, LEN_1_BYTE);
+	}
+	else
+	{
+		//turn off  BIT7=1
+		read_rtl2832_tuner_register(p_state->d, MAX3543_TUNER_ADDR, MAX3543_SHUTDOWN_OFFSET, &data, LEN_1_BYTE);
+		data |=BIT_7_MASK;
+		write_rtl2832_tuner_register(p_state->d, MAX3543_TUNER_ADDR, MAX3543_SHUTDOWN_OFFSET, &data, LEN_1_BYTE);
+	}
+
+	read_demod_register(p_state->d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 );
+	i2c_repeater &= (~BIT3);	
+	write_demod_register(p_state->d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 );
+
+
+	return 0;	
+
+}
+
+
+static int 
+set_tuner_power(
+	struct rtl2832_state*	p_state,
+	unsigned char			b_gpio4, 
+	unsigned char			onoff)
+{
+
+	int			data;
+
+	if(onoff==0)		max3543_set_power(p_state, onoff);
+
+	deb_info(" +%s \n", __FUNCTION__);
+	
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &data) ) goto error;		
+
+	if(b_gpio4)
+	{
+		if(onoff)		data &= ~(BIT4);   //set bit4 to 0
+		else			data |= BIT4;		//set bit4 to 1		
+
+	}
+	else
+	{
+		if(onoff)		data &= ~(BIT3);   //set bit3 to 0
+		else			data |= BIT3;		//set bit3 to 1		
+	}
+	
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL,data) ) goto error;
+
+
+	if(onoff==1)		max3543_set_power(p_state, onoff);
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	return 0;
+error:
+	return 1;
+}
+
+
+static int 
+set_demod_power(
+	struct rtl2832_state*	p_state,
+	unsigned char			onoff)
+{
+
+	int			data;
+
+	deb_info(" +%s \n", __FUNCTION__);
+	
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &data) ) goto error;		
+	if(onoff)		data &= ~(BIT0);   //set bit0 to 0
+	else			data |= BIT0;		//set bit0 to 1	
+	data &= ~(BIT0);   //3 Demod Power always ON => hw issue.	
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL,data) ) goto error;
+
+	deb_info(" -%s \n", __FUNCTION__);
+	return 0;
+error:
+	return 1;
+}
+
+
+//3//////// Set GPIO3 "OUT"  => Turn ON/OFF Tuner Power
+//3//////// Set GPIO3 "IN"      => Button  Wake UP (USB IF) , NO implement in rtl2832u linux driver
+
+static int 
+gpio3_out_setting(
+	struct rtl2832_state*	p_state)
+{
+	int			data;
+
+	deb_info(" +%s \n", __FUNCTION__);
+
+	// GPIO3_PAD Pull-HIGH, BIT76
+	data = 2;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_CFG0_BIT67,data) ) goto error;
+
+	// GPO_GPIO3 = 1, GPIO3 output value = 1 
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &data) ) goto error;		
+	data |= BIT3;		//set bit3 to 1
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL,data) ) goto error;
+
+	// GPD_GPIO3=0, GPIO3 output direction
+	data = 0;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_DIR_BIT3,data) ) goto error;
+
+	// GPOE_GPIO3=1, GPIO3 output enable
+	data = 1;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_EN_BIT3,data) ) goto error;
+
+	//BTN_WAKEUP_DIS = 1
+	data = 1;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_CTRL_BIT5,data) ) goto error;
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	return 0;
+error:
+	return 1;
+}
+
+
+
+
+
+
+static int 
+usb_epa_fifo_reset(
+	struct rtl2832_state*	p_state)
+{
+
+	int					data;
+
+	deb_info(" +%s \n", __FUNCTION__);
+	
+	//3 reset epa fifo:
+	//3[9] Reset EPA FIFO
+	//3 [5] FIFO Flush,Write 1 to flush the oldest TS packet (a 188 bytes block)
+
+	data = 0x0210;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_CTL,data) ) goto error;
+
+	data = 0xffff;
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_CTL,&data) ) goto error;
+
+	if( (data & 0xffff) != 0x0210)
+	{
+		deb_info("Write error RTD2831_RMAP_INDEX_USB_EPA_CTL = 0x%x\n",data);
+	 	goto error;	
+	}
+
+	data=0x0000;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_CTL,data) ) goto error;
+
+	data = 0xffff;
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_CTL,&data) ) goto error;
+
+	if( ( data  & 0xffff) != 0x0000)
+	{
+		deb_info("Write error RTD2831_RMAP_INDEX_USB_EPA_CTL = 0x%x\n",data);
+	 	goto error;	
+	}
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	return 0;
+
+error:
+	return 1;
+
+}
+
+
+
+static int 
+usb_init_bulk_setting(
+	struct rtl2832_state*	p_state)
+{
+
+	int					data;
+	
+	deb_info(" +%s \n", __FUNCTION__);
+	
+	//3 1.FULL packer mode(for bulk)
+	//3 2.DMA enable.
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_SYSCTL, &data) ) goto error;
+
+	data &=0xffffff00;
+	data |= 0x09;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_SYSCTL, data) ) goto error;
+
+	data=0;
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_SYSCTL, &data) ) goto error;
+      
+	if((data&0xff)!=0x09)  
+	{
+		deb_info("Open bulk FULL packet mode error!!\n");
+	 	goto error;
+	}
+
+	//3check epa config,
+	//3[9-8]:00, 1 transaction per microframe
+	//3[7]:1, epa enable
+	//3[6-5]:10, bulk mode
+	//3[4]:1, device to host
+	//3[3:0]:0001, endpoint number
+	data = 0;
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_CFG, &data) ) goto error;                
+	if((data&0x0300)!=0x0000 || (data&0xff)!=0xd1)
+	{
+		deb_info("Open bulk EPA config error! data=0x%x \n" , data);
+	 	goto error;	
+	}
+
+	//3 EPA maxsize packet 
+	//3 512:highspeedbulk, 64:fullspeedbulk. 
+	//3 940:highspeediso,  940:fullspeediso.
+
+	//3 get info :HIGH_SPEED or FULL_SPEED
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_STAT, &data) ) goto error;	
+	if(data&0x01)  
+	{
+		data = 0x00000200;
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_MAXPKT, data) ) goto error;
+
+		data=0;
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_MAXPKT, &data) ) goto error;
+	                      
+		if((data&0xffff)!=0x0200)
+		{
+			deb_info("Open bulk EPA max packet size error!\n");
+		 	goto error;
+		}
+
+		deb_info("HIGH SPEED\n");
+	}
+	else 
+    	{
+		data = 0x00000040;
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_MAXPKT, data) ) goto error;
+
+		data=0;
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_MAXPKT, &data) ) goto error;
+	                      
+		if((data&0xffff)!=0x0200)
+		{
+			deb_info("Open bulk EPA max packet size error!\n");
+		 	goto error;
+		}
+		
+		deb_info("FULL SPEED\n");
+	}	
+
+	deb_info(" -%s \n", __FUNCTION__);
+	
+	return 0;
+
+error:	
+	return 1;
+}
+
+
+static int 
+usb_init_setting(
+	struct rtl2832_state*	p_state)
+{
+
+	int					data;
+
+	deb_info(" +%s \n", __FUNCTION__);
+
+	if ( usb_init_bulk_setting(p_state) ) goto error;
+
+	//3 change fifo length of EPA 
+	data = 0x00000014;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_FIFO_CFG, data) ) goto error;
+	data = 0xcccccccc;
+	if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_USB_EPA_FIFO_CFG, &data) ) goto error;
+	if( (data & 0xff) != 0x14)
+	{
+		deb_info("Write error RTD2831_RMAP_INDEX_USB_EPA_FIFO_CFG =0x%x\n",data);
+	 	goto error;
+	}
+
+	if ( usb_epa_fifo_reset(p_state) ) goto error;
+
+	deb_info(" -%s \n", __FUNCTION__);
+	
+	return 0;
+
+error: 
+	return 1;	
+}
+
+
+
+static int 
+suspend_latch_setting(
+	struct rtl2832_state*	p_state,
+	unsigned char			resume)
+{
+
+	int					data;
+	deb_info(" +%s \n", __FUNCTION__);
+
+	if (resume)
+	{
+		//3 Suspend_latch_en = 0  => Set BIT4 = 0 
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1, &data) ) goto error;		
+		data &= (~BIT4);	//set bit4 to 0
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1,data) ) goto error;
+	}
+	else
+	{
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1, &data) ) goto error;		
+		data |= BIT4;		//set bit4 to 1
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1,data) ) goto error;
+	}
+
+	deb_info(" -%s \n", __FUNCTION__);	
+
+	return 0;
+error:
+	return 1;
+
+}
+
+
+
+
+
+//3////// DEMOD_CTL1  => IR Setting , IR wakeup from suspend mode
+//3////// if resume =1, resume
+//3////// if resume = 0, suspend
+
+
+static int 
+demod_ctl1_setting(
+	struct rtl2832_state*	p_state,
+	unsigned char			resume)
+{
+
+	int					data;
+
+	deb_info(" +%s \n", __FUNCTION__);
+	
+	if(resume)
+	{
+		// IR_suspend	
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1, &data) ) goto error;		
+		data &= (~BIT2);		//set bit2 to 0
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1,data) ) goto error;
+
+		//Clk_400k
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1, &data) ) goto error;		
+		data &= (~BIT3);		//set bit3 to 0
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1,data) ) goto error;
+	}
+	else
+	{
+		//Clk_400k
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1, &data) ) goto error;		
+		data |= BIT3;		//set bit3 to 1
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1,data) ) goto error;
+
+		// IR_suspend		
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1, &data) ) goto error;		
+		data |= BIT2;		//set bit2 to 1
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL1,data) ) goto error;
+	}
+
+	deb_info(" -%s \n", __FUNCTION__);
+	
+	return 0;
+error:
+	return 1;
+
+}
+
+
+
+
+static int 
+demod_ctl_setting(
+	struct rtl2832_state*	p_state,
+	unsigned char			resume,
+	unsigned char               on)
+{
+
+	int					data;
+	unsigned char			tmp;
+	
+	deb_info(" +%s \n", __FUNCTION__);
+		
+	if(resume)
+	{
+		// PLL setting
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+		data |= BIT7;		//set bit7 to 1
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;
+		
+		
+
+
+
+		//2 + Begin LOCK
+		// Demod  H/W Reset
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+		data &= (~BIT5);	//set bit5 to 0
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;
+
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+		data |= BIT5;		//set bit5 to 1
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;
+		
+		//3 reset page chache to 0 		
+		if ( read_demod_register(p_state->d, RTL2832_DEMOD_ADDR, 0, 1, &tmp, 1 ) ) goto error;	
+		//2 -End LOCK
+
+		// delay 5ms
+		platform_wait(5);
+
+
+		if(on)
+		{
+			// ADC_Q setting on
+			if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+			data |= BIT3;		//set bit3 to 1
+			if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;
+
+			// ADC_I setting on
+			if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+			data |= BIT6;		//set bit3 to 1
+			if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;
+		}
+		else
+		{
+			// ADC_I setting off
+			if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+			data &= (~BIT6);		//set bit3 to 0
+			if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;
+
+			// ADC_Q setting off
+			if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+			data &= (~BIT3);		//set bit3 to 0
+			if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;		
+		}
+	}
+	else
+	{
+
+		// ADC_I setting
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+		data &= (~BIT6);		//set bit3 to 0
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;
+
+		// ADC_Q setting
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+		data &= (~BIT3);		//set bit3 to 0
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;
+
+		// PLL setting
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL, &data) ) goto error;		
+		data &= (~BIT7);		//set bit7 to 0
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_DEMOD_CTL,data) ) goto error;
+
+	}
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	return 0;
+error: 
+	return 1;	
+
+}
+
+
+static int
+read_tuner_id_register(
+	struct rtl2832_state*	p_state,
+	unsigned char			tuner_addr,
+	unsigned char			tuner_offset,
+	unsigned char*		id_data,
+	unsigned char			length)
+{
+	unsigned char				i2c_repeater;	
+	struct dvb_usb_device*	d = p_state->d;
+
+	//2 + Begin LOCK
+	if(read_demod_register(d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 )) goto error;
+	i2c_repeater |= BIT3;	
+	if(write_demod_register(d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 )) goto error;
+	
+	if(read_rtl2832_tuner_register(d, tuner_addr, tuner_offset, id_data, length)) goto error;
+
+	if(read_demod_register(d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 )) goto error;
+	i2c_repeater &= (~BIT3);	
+	if(write_demod_register(d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 )) goto error;
+	//2 - End LOCK
+	return 0;
+	
+error:
+	return 1;
+}
+
+
+
+static int
+check_mxl5007t_chip_version(
+	struct rtl2832_state*	p_state,
+	unsigned char			*chipversion)
+{
+
+	unsigned char Buffer[LEN_2_BYTE];
+	unsigned char	i2c_repeater;	
+
+	struct dvb_usb_device*	d = p_state->d;	
+
+
+	Buffer[0] = (unsigned char)MXL5007T_I2C_READING_CONST;
+	Buffer[1] = (unsigned char)MXL5007T_CHECK_ADDRESS;
+
+
+	if(read_demod_register(d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 )) goto error;
+	i2c_repeater |= BIT3;	
+	if(write_demod_register(d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 )) goto error;
+
+
+	write_rtl2832_stdi2c(d, MXL5007T_BASE_ADDRESS , Buffer, LEN_2_BYTE);
+
+	read_rtl2832_stdi2c(d, MXL5007T_BASE_ADDRESS, Buffer, LEN_1_BYTE);
+
+	if(read_demod_register(d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 )) goto error;
+	i2c_repeater &= (~BIT3);
+	if(write_demod_register(d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 )) goto error;
+
+
+
+	switch(Buffer[0])
+	{
+		case MXL5007T_CHECK_VALUE: 
+			*chipversion = MxL_5007T_V4;
+			break;
+		default: 
+			*chipversion = MxL_UNKNOWN_ID;
+			break;
+	}	
+
+	return 0;
+
+error:
+
+	return 1;
+
+}
+
+
+
+
+
+
+static int 
+check_tuner_type(
+	struct rtl2832_state	*p_state)
+{
+
+	unsigned char				tuner_id_data[2];
+	unsigned char				chip_version;
+
+       deb_info(" +%s\n", __FUNCTION__);
+	if ((!read_tuner_id_register(p_state, MT2266_TUNER_ADDR, MT2266_OFFSET,  tuner_id_data, LEN_1_BYTE)) && 
+		( tuner_id_data[0] == MT2266_CHECK_VAL ))
+	{
+	 	p_state->tuner_type = RTL2832_TUNER_TYPE_MT2266;
+
+		deb_info(" -%s : MT2266 tuner on board...\n", __FUNCTION__);
+	}
+	else if ((!read_tuner_id_register(p_state, FC2580_TUNER_ADDR, FC2580_OFFSET,  tuner_id_data, LEN_1_BYTE)) &&
+			((tuner_id_data[0]&(~BIT7)) == FC2580_CHECK_VAL ))
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_FC2580;
+
+		deb_info(" -%s : FC2580 tuner on board...\n", __FUNCTION__);
+	}
+	else if(( !read_tuner_id_register(p_state, MT2063_TUNER_ADDR, MT2063_CHECK_OFFSET,  tuner_id_data, LEN_1_BYTE)) &&
+			( tuner_id_data[0]==MT2063_CHECK_VALUE || tuner_id_data[0]==MT2063_CHECK_VALUE_2))
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_MT2063;
+
+		deb_info(" -%s : MT2063 tuner on board...\n", __FUNCTION__);
+
+	}
+	else if(( !read_tuner_id_register(p_state, MAX3543_TUNER_ADDR, MAX3543_CHECK_OFFSET,  tuner_id_data, LEN_1_BYTE)) &&
+			( tuner_id_data[0]==MAX3543_CHECK_VALUE))
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_MAX3543;
+
+		deb_info(" -%s : MAX3543 tuner on board...\n", __FUNCTION__);
+
+	}
+	else if ((!read_tuner_id_register(p_state, TUA9001_TUNER_ADDR, TUA9001_OFFSET,  tuner_id_data, LEN_2_BYTE)) &&
+				(((tuner_id_data[0]<<8)|tuner_id_data[1]) == TUA9001_CHECK_VAL ))
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_TUA9001;
+			
+		deb_info(" -%s : TUA9001 tuner on board...\n", __FUNCTION__);
+	}
+	else	 if ((!check_mxl5007t_chip_version(p_state, &chip_version)) &&
+			(chip_version == MXL5007T_CHECK_VALUE) )
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_MXL5007T;
+
+		deb_info(" -%s : MXL5007T tuner on board...\n", __FUNCTION__);
+	}
+	else if ((!read_tuner_id_register(p_state, FC0012_BASE_ADDRESS , FC0012_CHECK_ADDRESS,  tuner_id_data, LEN_1_BYTE)) &&
+			(tuner_id_data[0] == FC0012_CHECK_VALUE))
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_FC0012;
+				
+		deb_info(" -%s : FC0012 tuner on board...\n", __FUNCTION__);	
+	}
+	else	if((!read_tuner_id_register(p_state, E4000_BASE_ADDRESS, E4000_CHECK_ADDRESS, tuner_id_data, LEN_1_BYTE)) && 
+			(tuner_id_data[0] == E4000_CHECK_VALUE))	
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_E4000;
+		deb_info(" -%s : E4000 tuner on board...\n", __FUNCTION__);
+	}
+	else if(( !read_tuner_id_register(p_state, TDA18272_TUNER_ADDR, TDA18272_CHECK_OFFSET,  tuner_id_data, LEN_2_BYTE)) &&
+			( (tuner_id_data[0]==TDA18272_CHECK_VALUE1) && (tuner_id_data[1]==TDA18272_CHECK_VALUE2)))
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_TDA18272;
+
+		deb_info(" -%s : Tda18272 tuner on board...\n", __FUNCTION__);
+
+	}	
+	else if ((!read_tuner_id_register(p_state, FC0013_BASE_ADDRESS , FC0013_CHECK_ADDRESS,  tuner_id_data, LEN_1_BYTE)) &&
+			(tuner_id_data[0] == FC0013_CHECK_VALUE))
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_FC0013;
+				
+		deb_info(" -%s : FC0013 tuner on board...\n", __FUNCTION__);	
+	}
+	else if ((!read_tuner_id_register(p_state, R820T_BASE_ADDRESS , R820T_CHECK_ADDRESS,  tuner_id_data, LEN_1_BYTE)) &&
+			(tuner_id_data[0] == R820T_CHECK_VALUE))
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_R820T;
+				
+		deb_info(" -%s : R820T tuner on board...\n", __FUNCTION__);	
+	}	
+	else
+	{
+		p_state->tuner_type = RTL2832_TUNER_TYPE_UNKNOWN;
+			
+		deb_info(" -%s : Unknown tuner on board...\n", __FUNCTION__);	
+		goto error;
+	}
+
+	return 0;
+error:
+	return -1;
+}
+
+static int 
+gpio1_output_enable_direction(
+	struct rtl2832_state*	p_state)
+{
+	int data;
+	// GPD_GPIO1=0, GPIO1 output direction
+	data = 0;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_DIR_BIT1,data) ) goto error;
+
+	// GPOE_GPIO1=1, GPIO1 output enable
+	data = 1;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_EN_BIT1,data) ) goto error;
+
+	return 0;
+error:
+	return 1;
+}
+
+
+static int 
+gpio6_output_enable_direction(
+	struct rtl2832_state*	p_state)
+{
+	int data;
+	// GPD_GPIO6=0, GPIO6 output direction
+	data = 0;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_DIR_BIT6,data) ) goto error;
+
+	// GPOE_GPIO6=1, GPIO6 output enable
+	data = 1;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_EN_BIT6,data) ) goto error;
+
+	return 0;
+error:
+	return 1;
+}
+
+
+static int 
+gpio5_output_enable_direction(
+	struct rtl2832_state*	p_state)
+{
+	int data;
+	// GPD_GPIO5=0, GPIO5 output direction
+	data = 0;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_DIR_BIT5,data) ) goto error;
+
+	// GPOE_GPIO5=1, GPIO5 output enable
+	data = 1;
+	if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_EN_BIT5,data) ) goto error;
+
+	return 0;
+error:
+	return 1;
+}
+
+
+static int 
+check_dvbt_reset_parameters(
+
+	struct rtl2832_state*	p_state,
+	unsigned long			frequency,
+#ifdef V4L2_ONLY_DVB_V5
+	unsigned long		bandwidth_hz,
+#else
+	enum fe_bandwidth	bandwidth,
+#endif	
+	int*					reset_needed)
+{
+
+	int							is_lock;	
+	unsigned int					diff_ms;
+
+	deb_info(" +%s \n", __FUNCTION__);
+
+	*reset_needed = 1;	 //3initialize "reset_needed"
+
+#ifdef V4L2_ONLY_DVB_V5
+	if( (p_state->current_frequency == frequency) && (p_state->current_bandwidth_hz == bandwidth_hz) )
+#else
+	if( (p_state->current_frequency == frequency) && (p_state->current_bandwidth == bandwidth) )
+#endif
+	{
+		if( p_state->pNim->IsSignalLocked(p_state->pNim, &is_lock) ) goto error;
+		diff_ms = 0;		
+		
+		while( !(is_lock == LOCKED || diff_ms > 200) )
+		{
+			platform_wait(40);
+			diff_ms += 40;
+			if( p_state->pNim->IsSignalLocked(p_state->pNim, &is_lock) ) goto error;
+		}
+
+	       if (is_lock==YES)		
+	       {
+		   *reset_needed = 0;		 //3 set "reset_needed" = 0
+		   deb_info("%s : The same frequency = %d setting\n", __FUNCTION__, (int)frequency);
+	       }
+	}	   
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	return 0;
+
+error:
+	
+	*reset_needed = 1; 	//3 set "reset_needed" = 1
+	return 1;
+}
+
+
+#if UPDATE_FUNC_ENABLE_2832
+void
+rtl2832_update_functions(struct work_struct *work)
+{
+	struct rtl2832_state* p_state = container_of( work,  struct rtl2832_state,  update2832_procedure_work.work); 
+	//unsigned  long ber_num, ber_dem;
+	//long snr_num = 0;
+	//long snr_dem = 0;
+	//long _snr= 0;
+
+	if(p_state->pNim == NULL)
+	{
+		//deb_info("%s error\n", __FUNCTION__);
+		goto mutex_error;
+	}
+
+
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )	goto mutex_error;
+
+	deb_info(" +%s\n", __FUNCTION__);	
+
+	if(!p_state->is_frequency_valid)
+	{
+		//deb_info("  %s no need \n", __FUNCTION__);
+		goto advance_exit;
+	}
+
+	// Update tuner mode
+	deb_info(" +%s run update\n", __FUNCTION__);
+	if( p_state->pNim->UpdateFunction(p_state->pNim)){
+		deb_info(" --->%s run update fail\n", __FUNCTION__);	
+		goto advance_exit;
+	}
+	
+	/* p_state->pNim->UpdateFunction(p_state->pNim);
+	p_state->pNim->GetBer( p_state->pNim , &ber_num , &ber_dem);
+	p_state->pNim->GetSnrDb(p_state->pNim, &snr_num, &snr_dem) ;
+
+	_snr = snr_num / snr_dem;
+	if( _snr < 0 ) _snr = 0;
+
+	deb_info("%s : ber = %lu, snr = %lu\n", __FUNCTION__,ber_num,_snr);
+	*/
+
+advance_exit:
+	mutex_unlock(&p_state->i2c_repeater_mutex);
+	
+	schedule_delayed_work(&p_state->update2832_procedure_work, UPDATE_PROCEDURE_PERIOD_2832);
+
+	deb_info(" -%s\n", __FUNCTION__);
+	
+	return;
+
+mutex_error:
+	return;
+	
+}
+#endif
+
+#if UPDATE_FUNC_ENABLE_2836
+void 
+rtl2836_update_function(struct work_struct *work)
+{
+	struct rtl2832_state* p_state; 
+	unsigned long Per1, Per2;
+	long Data1,Data2;
+	unsigned char data;
+	DTMB_DEMOD_MODULE * pDtmbDemod;
+
+	p_state = container_of(work , struct rtl2832_state , update2836_procedure_work.work); 
+	if(p_state->pNim2836 == NULL)
+	{
+		deb_info("%s error\n", __FUNCTION__);
+		goto mutex_error;
+	}
+	pDtmbDemod = p_state->pNim2836->pDemod;
+
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )	goto mutex_error;
+
+	deb_info(" +%s\n", __FUNCTION__);
+	if(!p_state->is_frequency_valid)
+	{
+		deb_info(" %s no need \n", __FUNCTION__);
+		goto advance_exit;
+	}
+
+	if(pDtmbDemod->UpdateFunction(pDtmbDemod))	
+	{
+		deb_info("%s -- UpdateFunction failed\n", __FUNCTION__);
+	}
+
+	pDtmbDemod->GetPer(pDtmbDemod,&Per1,&Per2);
+	deb_info("%s -- ***GetPer= %d***\n", __FUNCTION__, (int)Per1);
+
+	pDtmbDemod->GetSnrDb(pDtmbDemod,&Data1,&Data2);            
+	deb_info("%s -- ***SNR = %d***\n",__FUNCTION__, (int)(Data1>>2));
+
+	read_rtl2836_demod_register(p_state->d, RTL2836_DEMOD_ADDR, PAGE_6, 0xc0, &data, LEN_1_BYTE);
+	deb_info("%s --***FSM = %d***\n", __FUNCTION__, (data&0x1f));
+
+advance_exit:
+	
+	mutex_unlock(&p_state->i2c_repeater_mutex);
+	
+	schedule_delayed_work(&p_state->update2836_procedure_work,  UPDATE_PROCEDURE_PERIOD_2836);
+
+	deb_info(" -%s\n", __FUNCTION__);	
+	return;
+
+mutex_error:
+	return;
+
+}
+#endif
+
+static int 
+rtl2832_init(
+	struct dvb_frontend*	fe)
+{
+	struct rtl2832_state*	p_state = fe->demodulator_priv;
+
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )	goto mutex_error;
+
+	deb_info(" +%s\n", __FUNCTION__);
+	
+	//usb_reset_device(p_state->d->udev);
+
+	if( usb_init_setting(p_state) ) goto error;
+	
+	if( gpio3_out_setting(p_state) ) goto error;				//3Set GPIO3 OUT	
+	
+	if( demod_ctl1_setting(p_state , 1) ) goto error;		//3	DEMOD_CTL1, resume = 1
+
+	if (dvb_use_rtl2832u_card_type)
+	{
+		if( set_demod_power(p_state , 1) ) goto error;			//3	turn ON demod power
+	}
+
+	if( suspend_latch_setting(p_state , 1) ) goto error;		//3 suspend_latch_en = 0, resume = 1 					
+
+	if( demod_ctl_setting(p_state , 1,  1) ) goto error;		//3 DEMOD_CTL, resume =1; ADC on
+
+	if( set_tuner_power(p_state, 1, 1) ) goto error;		//3	turn ON tuner power
+
+	if( p_state->tuner_type == RTL2832_TUNER_TYPE_TUA9001)
+	{	
+		if( gpio1_output_enable_direction(p_state) )	goto error;	
+	}
+	else if( p_state->tuner_type == RTL2832_TUNER_TYPE_MXL5007T)
+	{
+		//3 MXL5007T : Set GPIO6 OUTPUT_EN & OUTPUT_DIR & OUTPUT_VAL for YUAN
+		int	data;		
+		if( gpio6_output_enable_direction(p_state) )	goto error;	
+
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &data) ) goto error;		
+		data |= BIT6;
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL,data) ) goto error;
+
+	}
+	else if( p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012)
+	{
+		int data;
+		if( gpio5_output_enable_direction(p_state))		goto error;
+
+		if( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &data) ) goto error;
+		data |= BIT5; // set GPIO5 high
+		if( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, data) ) goto error;
+		data &= ~(BIT5); // set GPIO5 low
+		if( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, data) ) goto error;
+	}
+
+	switch(p_state->demod_type)
+	{
+		case RTL2836:
+		{
+			if ( set_demod_2836_power(p_state,  1))  goto error;//32836 on
+
+			// RTL2832 ADC_I& ADC_Q OFF
+			if( demod_ctl_setting(p_state,  1,  0)) goto error;// ADC off
+
+		}
+		break;
+
+		case RTL2840:
+		{
+			if ( set_demod_2840_power(p_state,  1))  goto error;//2840 on
+
+			// RTL2832 ADC_I& ADC_Q OFF
+			if( demod_ctl_setting(p_state,  1,  0)) goto error;//ADC off
+		}
+		break;
+	}
+	
+	//3 Nim initial
+	switch(p_state->demod_type)
+	{	
+		case RTL2832:
+		{
+			// Nim initialize for 2832
+			if ( p_state->pNim->Initialize(p_state->pNim) ) goto error;
+		}
+		break;
+
+		case RTL2836:
+		{
+			// Enable demod DVBT_IIC_REPEAT.
+		       if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x1) )   goto error;
+
+	             // Nim initialize for 2836
+			if ( p_state->pNim2836->Initialize(p_state->pNim2836)) goto error;
+
+			// Disable demod DVBT_IIC_REPEAT.
+		       if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x0))  goto error;
+
+			if(dtmb_error_packet_discard)
+			{
+				unsigned char val=0;
+				if(read_demod_register(p_state->d,  RTL2832_DEMOD_ADDR, PAGE_0, 0x21, &val,  LEN_1_BYTE)) goto error;
+				val &= ~(BIT5);
+				if(write_demod_register(p_state->d,  RTL2832_DEMOD_ADDR, PAGE_0, 0x21, &val,  LEN_1_BYTE)) goto error;
+		
+				if(read_rtl2836_demod_register(p_state->d,  RTL2836_DEMOD_ADDR, PAGE_4, 0x26, &val,  LEN_1_BYTE)) goto error;
+				val &= ~(BIT0);
+				if(write_rtl2836_demod_register(p_state->d,  RTL2836_DEMOD_ADDR, PAGE_4, 0x26, &val,  LEN_1_BYTE)) goto error;
+
+				deb_info(" dtmb discard error packets\n");
+			}
+			else
+			{
+				deb_info(" dtmb NOT discard error packets\n");
+			}
+		}
+		break;	
+
+		case RTL2840:
+		{
+			// Enable demod DVBT_IIC_REPEAT.
+			if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x1) )   goto error;
+
+			// Nim initialize for 2840
+			if ( p_state->pNim2840->Initialize(p_state->pNim2840)) goto error;
+
+			// Disable demod DVBT_IIC_REPEAT.
+			if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x0))  goto error;
+		}			
+		break;
+	}
+
+	//3  RTL2832U AGC Setting, Serial Mode Switch Setting, PIP Setting based on demod_type
+	if(demod_init_setting(p_state)) goto error;
+	
+	p_state->is_initial = 1; 
+	//if(p_state->rtl2832_audio_video_mode == RTK_AUDIO)
+	//{
+	//	  deb_info("%s: previous mode is audio? \n", __func__);
+	//      fm_stream_ctrl(0, p_state->d->adapter);			
+	//}
+	p_state->rtl2832_audio_video_mode = RTK_VIDEO;
+	
+	deb_info(" -%s \n", __FUNCTION__);
+
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+
+#if UPDATE_FUNC_ENABLE_2840
+       if(p_state->demod_type == RTL2840)
+	   	schedule_delayed_work(&(p_state->update2840_procedure_work), 0);//3 Initialize update function
+#endif
+
+#if UPDATE_FUNC_ENABLE_2836
+       if(p_state->demod_type == RTL2836)
+	   	schedule_delayed_work(&(p_state->update2836_procedure_work),  0);
+#endif
+
+#if UPDATE_FUNC_ENABLE_2832
+       if(p_state->demod_type == RTL2832)
+	   	schedule_delayed_work(&(p_state->update2832_procedure_work), 0);//3 Initialize update function
+#endif
+
+	return 0;
+error:
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+	
+mutex_error:
+	deb_info(" -%s  error end\n", __FUNCTION__);
+
+	p_state->rtl2832_audio_video_mode = RTK_UNKNOWN;
+
+	return -1;
+}
+
+
+static void
+rtl2832_release(
+	struct dvb_frontend*	fe)
+{
+	struct rtl2832_state* p_state = fe->demodulator_priv;
+	MT2266_EXTRA_MODULE*	p_mt2266_extra=NULL;	
+	MT2063_EXTRA_MODULE*	p_mt2063_extra=NULL;	
+
+	TUNER_MODULE*		pTuner=NULL;
+
+	deb_info("  +%s \n", __FUNCTION__);	
+
+	if( p_state->pNim== NULL)
+	{
+		deb_info(" %s pNim = NULL \n", __FUNCTION__);
+		return;
+	}
+
+	if( (p_state->is_mt2266_nim_module_built) && (p_state->demod_type==RTL2832) )
+	{
+		pTuner = p_state->pNim->pTuner;
+		p_mt2266_extra = &(pTuner->Extra.Mt2266);
+		p_mt2266_extra->CloseHandle(pTuner);
+		p_state->is_mt2266_nim_module_built = 0;
+	}
+
+	if( p_state->is_mt2063_nim_module_built)
+	{
+
+		switch(p_state->demod_type)
+		{
+		case RTL2832:
+			pTuner=p_state->pNim->pTuner;
+		break;
+
+		case RTL2840:
+			pTuner=p_state->pNim2840->pTuner;
+		break;
+
+		}
+		p_mt2063_extra=&(pTuner->Extra.Mt2063);
+		p_mt2063_extra->CloseHandle(pTuner);
+		p_state->is_mt2063_nim_module_built = 0;
+		
+	}
+
+	if(p_state->is_initial)
+	{
+#if UPDATE_FUNC_ENABLE_2840
+              if(p_state->demod_type == RTL2840)
+              {
+			cancel_delayed_work_sync( &(p_state->update2840_procedure_work) );//cancel_rearming_delayed_work
+			flush_scheduled_work();
+              }
+#endif
+	
+#if UPDATE_FUNC_ENABLE_2836
+		if(p_state->demod_type == RTL2836)
+		{
+			cancel_delayed_work_sync( &(p_state->update2836_procedure_work));
+			flush_scheduled_work();
+		}
+#endif
+
+#if UPDATE_FUNC_ENABLE_2832
+              if(p_state->demod_type == RTL2832)
+              {
+			cancel_delayed_work_sync( &(p_state->update2832_procedure_work) );
+			flush_scheduled_work();
+              }
+#endif
+		p_state->is_initial = 0;
+	}
+	p_state->is_frequency_valid = 0;
+	p_state->rtl2832_audio_video_mode = RTK_UNKNOWN;
+	//IrDA	
+	rtl2832u_remote_control_state = RC_NO_SETTING;
+
+	kfree(p_state);
+
+	deb_info(" -%s \n", __FUNCTION__);	
+
+	return;
+}
+
+
+
+
+static int 
+rtl2832_sleep_mode(struct rtl2832_state* p_state)
+{
+	int data=0;
+
+	
+	if(p_state->tuner_type == RTL2832_TUNER_TYPE_MAX3543)
+	{
+		//+set MAX3543_CHECK_VALUE to Default value
+		unsigned char	i2c_repeater;	
+		unsigned char	data = MAX3543_CHECK_VALUE;
+
+		read_demod_register(p_state->d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 );
+		i2c_repeater |= BIT3;	
+		write_demod_register(p_state->d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 );
+	
+		write_rtl2832_tuner_register(p_state->d, MAX3543_TUNER_ADDR, MAX3543_CHECK_OFFSET, &data, LEN_1_BYTE);
+
+		read_demod_register(p_state->d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 );
+		i2c_repeater &= (~BIT3);	
+		write_demod_register(p_state->d, RTL2832_DEMOD_ADDR, 1, 1, &i2c_repeater, 1 );
+		//-set MAX3543_CHECK_VALUE to Default value
+	}
+
+
+	if( p_state->is_initial )
+	{
+
+#if UPDATE_FUNC_ENABLE_2840
+		if(p_state->demod_type == RTL2840)
+		{
+			cancel_delayed_work_sync( &(p_state->update2840_procedure_work));
+			flush_scheduled_work();
+		}
+#endif
+
+#if UPDATE_FUNC_ENABLE_2836
+		if(p_state->demod_type == RTL2836)
+		{
+			cancel_delayed_work_sync( &(p_state->update2836_procedure_work));
+			flush_scheduled_work();
+		}
+#endif
+
+#if UPDATE_FUNC_ENABLE_2832
+              if(p_state->demod_type == RTL2832)
+              {
+	             cancel_delayed_work_sync( &(p_state->update2832_procedure_work));
+		       flush_scheduled_work();
+              }
+#endif		
+		p_state->is_initial = 0;
+	}
+	p_state->is_frequency_valid = 0;
+
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )	goto mutex_error;
+
+	deb_info(" +%s \n", __FUNCTION__);
+
+#if 0
+	//2 For debug
+	/* for( page_no = 0; page_no < 3; page_no++ )//2832 
+	{
+		pDemod->SetRegPage(pDemod, page_no);
+		for( addr_no = 0; addr_no < 256; addr_no++ )
+		{
+			pDemod->GetRegBytes(pDemod, addr_no, &reg_value, 1);
+			printk("0x%x, 0x%x, 0x%x\n", page_no, addr_no, reg_value);
+		}
+	}*/
+      for( page_no = 0; page_no < 10; page_no++ )//2836 
+	{
+		pDemod2836->SetRegPage(pDemod2836, page_no);
+		for( addr_no = 0; addr_no < 256; addr_no++ )
+		{
+			pDemod2836->GetRegBytes(pDemod2836, addr_no, &reg_value, 1);
+			printk("0x%x, 0x%x, 0x%x\n", page_no, addr_no, reg_value);
+		}
+	}
+#endif
+
+	 if( p_state->tuner_type == RTL2832_TUNER_TYPE_MXL5007T)
+	{
+		//3 MXL5007T : Set GPIO6 OUTPUT_VAL  OFF for YUAN
+		if ( read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &data) ) goto error;		
+		data &= (~BIT6);
+		if ( write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL,data) ) goto error;
+
+	}
+
+
+	if( demod_ctl1_setting(p_state , 0) ) goto error;		//3	DEMOD_CTL1, resume = 0
+
+	if( set_tuner_power(p_state, 1, 0) ) goto error;		//3	turn OFF tuner power
+
+	if( demod_ctl_setting(p_state , 0,  0) ) goto error;		//3 	DEMOD_CTL, resume =0	
+
+	if (p_state->demod_type != RTL2832){
+	set_demod_2836_power(p_state,  0);   //3 RTL2836 power OFF
+	deb_info(" ->%s::RTL2836 power OFF\n", __FUNCTION__);
+	set_demod_2840_power(p_state,  0);   //3 RTL2840 power OFF
+	deb_info(" ->%s ::RTL2840 power OFF\n", __FUNCTION__);
+	}
+	//2 for H/W reason
+	//if( suspend_latch_setting(p_state , 0) ) goto error;		//3 suspend_latch_en = 1, resume = 0					
+	if (dvb_use_rtl2832u_card_type)
+	{
+		deb_info(" -%s ::mini card mode gpio0 set high ,demod power off\n", __FUNCTION__);
+		if( set_demod_power(p_state , 0) ) goto error;		//3	turn OFF demod power
+	}
+
+#ifndef NO_FE_IOCTL_OVERRIDE
+	if(p_state->rtl2832_audio_video_mode == RTK_AUDIO)
+	{
+		fm_stream_ctrl(0,  p_state->d->adapter);
+	}
+#endif
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	mutex_unlock(&p_state->i2c_repeater_mutex);
+
+	return 0;
+	
+error:
+	mutex_unlock(&p_state->i2c_repeater_mutex);
+	
+mutex_error:
+	deb_info(" -%s fail\n", __FUNCTION__);	
+	return 1;
+
+
+}
+static int 
+rtl2832_sleep(
+	struct dvb_frontend*	fe)
+{
+	struct rtl2832_state* p_state = fe->demodulator_priv;
+
+	return rtl2832_sleep_mode(p_state);
+}
+
+
+
+#ifdef V4L2_ONLY_DVB_V5
+static int
+rtl2840_set_parameters(
+	struct dvb_frontend*	fe)
+{
+	struct dtv_frontend_properties		*param = &fe->dtv_property_cache;
+	struct rtl2832_state				*p_state = fe->demodulator_priv;
+	unsigned long						frequency = param->frequency;
+
+	DVBT_DEMOD_MODULE				*pDemod2832;
+	int								QamMode;
+
+	deb_info(" +%s \n", __FUNCTION__);
+
+	if(p_state->demod_type == RTL2840 && p_state->pNim2840 == NULL )
+	{
+		deb_info(" %s pNim2840 = NULL \n", __FUNCTION__);
+
+		return -1;
+	 }
+
+
+	deb_info(" +%s Freq=%lu , Symbol rate=%u, QAM=%u\n", __FUNCTION__, frequency, param->symbol_rate, param->modulation);
+
+	pDemod2832 = p_state->pNim->pDemod;
+
+	switch(param->modulation)
+	{
+		case QPSK :		QamMode = QAM_QAM_4;		break;
+		case QAM_16 :	QamMode = QAM_QAM_16;		break;
+		case QAM_32 :	QamMode = QAM_QAM_32;		break;
+		case QAM_64 :	QamMode = QAM_QAM_64;		break;
+		case QAM_128 :	QamMode = QAM_QAM_128;		break;
+		case QAM_256 :	QamMode = QAM_QAM_256;		break;		
+
+		case QAM_AUTO :
+		default:
+		deb_info(" XXX %s  : unknown QAM \n", __FUNCTION__);
+		goto  mutex_error;
+		break;
+			
+	}
+
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )	goto mutex_error;
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod2832->SetRegBitsWithPage(pDemod2832,  DVBT_IIC_REPEAT, 0x1) )   goto error;	
+	
+	p_state->pNim2840->SetParameters(p_state->pNim2840, frequency, QamMode, param->symbol_rate, QAM_ALPHA_0P15);
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod2832->SetRegBitsWithPage(pDemod2832, DVBT_IIC_REPEAT, 0x0))  goto error;
+
+	if(pDemod2832->SoftwareReset(pDemod2832))//2832 swreset
+		goto error;
+
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	return 0;
+
+error:
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+
+mutex_error:
+
+	deb_info(" -XXX %s \n", __FUNCTION__);
+
+	return 1;
+
+}
+#else
+static int
+rtl2840_set_parameters(
+	struct dvb_frontend*	fe,
+	struct dvb_frontend_parameters*	param)
+{
+
+	struct rtl2832_state				*p_state = fe->demodulator_priv;
+	struct dvb_qam_parameters 		*p_qam_param= &param->u.qam;
+	unsigned long						frequency = param->frequency;
+
+	DVBT_DEMOD_MODULE				*pDemod2832;
+	int								QamMode;
+
+	deb_info(" +%s \n", __FUNCTION__);
+
+	if(p_state->demod_type == RTL2840 && p_state->pNim2840 == NULL )
+	{
+		deb_info(" %s pNim2840 = NULL \n", __FUNCTION__);
+
+		return -1;
+	 }
+
+
+	deb_info(" +%s Freq=%lu , Symbol rate=%u, QAM=%u\n", __FUNCTION__, frequency, p_qam_param->symbol_rate, p_qam_param->modulation);
+
+	pDemod2832 = p_state->pNim->pDemod;
+
+	switch(p_qam_param->modulation)
+	{
+		case QPSK :		QamMode = QAM_QAM_4;		break;
+		case QAM_16 :	QamMode = QAM_QAM_16;		break;
+		case QAM_32 :	QamMode = QAM_QAM_32;		break;
+		case QAM_64 :	QamMode = QAM_QAM_64;		break;
+		case QAM_128 :	QamMode = QAM_QAM_128;		break;
+		case QAM_256 :	QamMode = QAM_QAM_256;		break;		
+
+		case QAM_AUTO :
+		default:
+		deb_info(" XXX %s  : unknown QAM \n", __FUNCTION__);
+		goto  mutex_error;
+		break;
+			
+	}
+
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )	goto mutex_error;
+
+	// Enable demod DVBT_IIC_REPEAT.
+	if(pDemod2832->SetRegBitsWithPage(pDemod2832,  DVBT_IIC_REPEAT, 0x1) )   goto error;	
+	
+	p_state->pNim2840->SetParameters(p_state->pNim2840, frequency, QamMode, p_qam_param->symbol_rate, QAM_ALPHA_0P15);
+
+	// Disable demod DVBT_IIC_REPEAT.
+	if(pDemod2832->SetRegBitsWithPage(pDemod2832, DVBT_IIC_REPEAT, 0x0))  goto error;
+	
+	if(pDemod2832->SoftwareReset(pDemod2832))//2832 swreset
+		goto error;		
+
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	return 0;
+
+error:
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+
+mutex_error:
+
+	deb_info(" -XXX %s \n", __FUNCTION__);
+
+	return 1;
+
+}
+#endif
+
+
+
+#ifdef V4L2_ONLY_DVB_V5
+static int
+rtl2832_set_parameters(
+	struct dvb_frontend*	fe)
+{
+	struct dtv_frontend_properties	*param = &fe->dtv_property_cache;
+	struct rtl2832_state			*p_state = fe->demodulator_priv;
+
+	unsigned long					frequency = param->frequency;
+	int							bandwidth_mode;
+	int							is_signal_present;
+	int							reset_needed;
+	unsigned char                             data;
+	int							int_data; 
+
+       
+       DTMB_DEMOD_MODULE *           pDemod2836;
+	DVBT_DEMOD_MODULE *           pDemod2832;
+
+
+
+       if( p_state->pNim == NULL)
+       {
+		deb_info(" %s pNim = NULL \n", __FUNCTION__);
+		return -1;
+       }
+
+	if(p_state->demod_type == RTL2836 && p_state->pNim2836 == NULL )
+	{
+		deb_info(" %s pNim2836 = NULL \n", __FUNCTION__);
+		return -1;
+	 }
+
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )	goto mutex_error;
+	
+	deb_info(" +%s frequency = %lu , bandwidth = %u\n", __FUNCTION__, frequency , param->bandwidth_hz);
+
+	if(p_state->demod_type == RTL2832)
+	{
+		if ( check_dvbt_reset_parameters( p_state , frequency , param->bandwidth_hz, &reset_needed) ) goto error;
+
+		if( reset_needed == 0 )
+		{
+			mutex_unlock(&p_state->i2c_repeater_mutex);		
+			return 0;
+		}
+
+		switch (param->bandwidth_hz) 
+	      {
+		case 6000000:
+		bandwidth_mode = DVBT_BANDWIDTH_6MHZ; 	
+		break;
+		
+		case 7000000:
+		bandwidth_mode = DVBT_BANDWIDTH_7MHZ;
+		break;
+		
+		case 8000000:
+		default:
+		bandwidth_mode = DVBT_BANDWIDTH_8MHZ;	
+		break;
+	       }
+	       
+	       	//add by Dean
+	        if (p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012 )
+	        {
+	        
+	   		if( gpio6_output_enable_direction(p_state) )	goto error;	    
+	   		
+	   			
+			if (frequency > 300000000)
+			{
+				
+				read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &int_data);
+				int_data |= BIT6; // set GPIO6 high
+				write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, int_data);	
+				deb_info("  %s : Tuner :FC0012 V-band (GPIO6 high)\n", __FUNCTION__);		
+			}
+			else
+			{
+	
+				read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &int_data);
+				int_data &= (~BIT6); // set GPIO6 low	
+				write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, int_data);	
+				deb_info("  %s : Tuner :FC0012 U-band (GPIO6 low)\n", __FUNCTION__);	
+				
+			}
+		}
+		
+
+	
+			
+		
+		if ( p_state->pNim->SetParameters( p_state->pNim,  frequency , bandwidth_mode ) ) goto error; 
+
+		if ( p_state->pNim->IsSignalPresent( p_state->pNim, &is_signal_present) ) goto error;
+		deb_info("  %s : ****** Signal Present = %d ******\n", __FUNCTION__, is_signal_present);
+		
+		
+
+
+		p_state->is_frequency_valid = 1;
+
+		
+	}
+	else if(p_state->demod_type == RTL2836)
+	{
+		pDemod2836 =  p_state->pNim2836->pDemod;
+		pDemod2832 = p_state->pNim->pDemod;
+
+		//if ( check_dtmb_reset_parameters( p_state , frequency ,  &reset_needed) ) goto error;
+		//if( reset_needed == 0 )
+		//{
+		//	mutex_unlock(&p_state->i2c_repeater_mutex);		
+		//	return 0;
+		//}
+		
+		deb_info("%s:  RTL2836 Hold Stage=9\n",__FUNCTION__);
+		if(read_rtl2836_demod_register(p_state->d, RTL2836_DEMOD_ADDR,  PAGE_3,  0xf8,  &data, LEN_1_BYTE))  goto error;
+		data &=(~BIT_0_MASK);  //reset Reg_present
+		data &=(~BIT_1_MASK);  //reset Reg_lock
+		if(write_rtl2836_demod_register(p_state->d, RTL2836_DEMOD_ADDR,  PAGE_3,  0xf8,  &data, LEN_1_BYTE))  goto error;
+		
+		//3 + RTL2836 Hold Stage=9
+		data = 0x29;
+		if(write_rtl2836_demod_register(p_state->d, RTL2836_DEMOD_ADDR,  PAGE_3,  0x4d,  &data, LEN_1_BYTE))  goto error;
+		
+		data = 0xA5;
+		if(write_rtl2836_demod_register(p_state->d, RTL2836_DEMOD_ADDR,  PAGE_3,  0x4e,  &data, LEN_1_BYTE))  goto error;
+		
+		data = 0x94;
+		if(write_rtl2836_demod_register(p_state->d, RTL2836_DEMOD_ADDR,  PAGE_3,  0x4f,  &data, LEN_1_BYTE))  goto error;
+		//3 -RTL2836 Hold Stage=9
+	
+
+		// Enable demod DVBT_IIC_REPEAT.
+	       if(pDemod2832->SetRegBitsWithPage(pDemod2832,  DVBT_IIC_REPEAT, 0x1) )   goto error;
+
+		if ( p_state->pNim2836->SetParameters( p_state->pNim2836,  frequency)) 	goto error; //no bandwidth setting	
+
+		// Disable demod DVBT_IIC_REPEAT.
+	       if(pDemod2832->SetRegBitsWithPage(pDemod2832, DVBT_IIC_REPEAT, 0x0))  goto error;
+
+		if(pDemod2832->SoftwareReset(pDemod2832))//2832 swreset
+			goto error;
+
+		p_state->is_frequency_valid = 1;
+		if( rtl2836_scan_procedure(p_state))  goto error; 
+	}
+
+
+//#if(UPDATE_FUNC_ENABLE_2832 == 0)
+	//3 FC0012/E4000 update begin --
+	if(p_state->demod_type == RTL2832 && (p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012 
+										|| p_state->tuner_type == RTL2832_TUNER_TYPE_E4000
+										|| p_state->tuner_type == RTL2832_TUNER_TYPE_FC0013))
+	{
+              // Enable demod DVBT_IIC_REPEAT.
+		if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+			goto error;
+ 
+		if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012)//fc0012
+		{
+			if(rtl2832_fc0012_UpdateTunerLnaGainWithRssi(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		else if(p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)//e4000
+		{
+			if(rtl2832_e4000_UpdateTunerMode(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		else if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0013) //fc0013
+		{
+			if(rtl2832_fc0013_UpdateTunerLnaGainWithRssi(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		
+		// Disable demod DVBT_IIC_REPEAT.
+		if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+			goto error;
+                
+
+		deb_info("%s : fc0012/e4000 update first\n", __FUNCTION__);
+
+		msleep(50);
+ 
+		if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+			goto error;
+
+		// Update tuner LNA gain with RSSI.
+		if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012)//fc0012
+		{
+			if(rtl2832_fc0012_UpdateTunerLnaGainWithRssi(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		else if (p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)//e4000
+		{
+			if(rtl2832_e4000_UpdateTunerMode(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		else if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0013) //fc0013
+		{
+			if(rtl2832_fc0013_UpdateTunerLnaGainWithRssi(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+			
+		// Disable demod DVBT_IIC_REPEAT.
+		if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+			goto error;
+
+		deb_info("%s : fc0012/e4000 update 2nd\n", __FUNCTION__);
+	}
+	//3 FC0012/E4000 update end --
+      
+//#endif
+	
+	p_state->current_frequency = frequency;	
+	p_state->current_bandwidth_hz = param->bandwidth_hz;
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+
+	return 0;
+
+error:	
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+	
+mutex_error:	
+	p_state->current_frequency = 0;
+	p_state->current_bandwidth_hz = 0;
+	p_state->is_frequency_valid = 0;
+	deb_info(" -%s  error end\n", __FUNCTION__);
+
+	return -1;
+	
+}
+
+static int
+rtl2832_set_parameters_fm(
+	struct dvb_frontend*	fe)
+{
+	struct dtv_frontend_properties	*param = &fe->dtv_property_cache;
+	struct rtl2832_state* p_state = fe->demodulator_priv;
+	unsigned long					frequency = param->frequency;
+	int							bandwidth_mode;
+	int	int_data;
+       
+      //DTMB_DEMOD_MODULE *           pDemod2836;
+	//DVBT_DEMOD_MODULE *           pDemod2832;
+   
+       if( p_state->pNim == NULL)
+       {
+		deb_info(" %s pNim = NULL \n", __FUNCTION__);
+		return -1;
+       }
+
+	/* if(p_state->demod_type == RTL2836 && p_state->pNim2836 == NULL )
+	{
+		deb_info(" %s pNim2836 = NULL \n", __FUNCTION__);
+		return -1;
+	 } */
+
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )	goto mutex_error;
+	
+	deb_info(" +%s frequency = %lu , bandwidth = %u\n", __FUNCTION__, frequency , param->bandwidth_hz);
+
+	if(p_state->demod_type == RTL2832)
+	{
+		bandwidth_mode = DVBT_BANDWIDTH_6MHZ; 	
+	
+		if(p_state->tuner_type ==  RTL2832_TUNER_TYPE_FC0012)
+		{
+	   		if( gpio6_output_enable_direction(p_state) )	goto error;	    
+	   			   			
+			if (frequency > 300000000)
+			{
+				
+				read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &int_data);
+				int_data |= BIT6; // set GPIO6 high
+				write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, int_data);	
+				deb_info("  %s : Tuner :FC0012 V-band (GPIO6 high)\n", __FUNCTION__);		
+			}
+			else
+			{
+	
+				read_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, &int_data);
+				int_data &= (~BIT6); // set GPIO6 low	
+				write_usb_sys_register(p_state, RTD2831_RMAP_INDEX_SYS_GPIO_OUTPUT_VAL, int_data);	
+				deb_info("  %s : Tuner :FC0012 U-band (GPIO6 low)\n", __FUNCTION__);	
+				
+			}
+
+			if(rtl2832_fc0012_SetParameters_fm( p_state->pNim,  frequency , bandwidth_mode ))
+				goto error;
+		}
+		else if(p_state->tuner_type == RTL2832_TUNER_TYPE_MXL5007T)
+		{
+			if(rtl2832_mxl5007t_SetParameters_fm(p_state->pNim, frequency , bandwidth_mode ))
+				goto error;
+		}
+		else if(p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)
+		{
+			if(rtl2832_e4000_SetParameters_fm( p_state->pNim,  frequency , bandwidth_mode ))
+				goto error;
+		}
+		else if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0013)
+		{
+			if(rtl2832_fc0013_SetParameters_fm( p_state->pNim,  frequency , bandwidth_mode ))
+				goto error;
+		}
+
+		p_state->is_frequency_valid = 1;
+
+		
+	}
+	/*else if(p_state->demod_type == RTL2836)
+	{		
+	}*/
+
+
+//#if(UPDATE_FUNC_ENABLE_2832 == 0)
+	//3 FC0012/E4000 update begin --
+	if(p_state->demod_type == RTL2832 && (p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012 || p_state->tuner_type == RTL2832_TUNER_TYPE_E4000))
+	{
+              // Enable demod DVBT_IIC_REPEAT.
+		if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+			goto error;
+
+		// Update tuner LNA gain with RSSI.
+		// if( p_state->pNim->UpdateFunction(p_state->pNim))
+		//	goto error;
+		if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012)//fc0012
+		{
+			if(rtl2832_fc0012_UpdateTunerLnaGainWithRssi(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		else if (p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)//e4000
+		{
+			if(rtl2832_e4000_UpdateTunerMode(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		else if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0013) //fc0013
+		{
+			if(rtl2832_fc0013_UpdateTunerLnaGainWithRssi(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		
+		// Disable demod DVBT_IIC_REPEAT.
+		if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+			goto error;
+                
+
+		deb_info("%s : fc0012/e4000 update first\n", __FUNCTION__);
+
+		msleep(50);
+
+		// if( p_state->pNim->UpdateFunction(p_state->pNim)) goto error;
+		if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x1) != FUNCTION_SUCCESS)
+			goto error;
+
+		// Update tuner LNA gain with RSSI.
+		if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0012)//fc0012
+		{
+			if(rtl2832_fc0012_UpdateTunerLnaGainWithRssi(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		else if (p_state->tuner_type == RTL2832_TUNER_TYPE_E4000)//e4000
+		{
+			if(rtl2832_e4000_UpdateTunerMode(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		else if(p_state->tuner_type == RTL2832_TUNER_TYPE_FC0013) //fc0013
+		{
+			if(rtl2832_fc0013_UpdateTunerLnaGainWithRssi(p_state->pNim) != FUNCTION_SUCCESS)
+				goto error;
+		}
+		
+		// Disable demod DVBT_IIC_REPEAT.
+		if(p_state->pNim->pDemod->SetRegBitsWithPage(p_state->pNim->pDemod, DVBT_IIC_REPEAT, 0x0) != FUNCTION_SUCCESS)
+			goto error;
+
+		deb_info("%s : fc0012/e4000 update 2nd\n", __FUNCTION__);
+	}
+	//3 FC0012/E4000 update end --
+      
+//#endif
+	
+	//p_state->current_frequency = frequency;	
+	//p_state->current_bandwidth = p_ofdm_param->bandwidth;	
+
+	deb_info(" -%s \n", __FUNCTION__);
+
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+
+	return 0;
+
+error:	
+	mutex_unlock(&p_state->i2c_repeater_mutex);	
+	
+mutex_error:	
+	//p_state->current_frequency = 0;
+	//p_state->current_bandwidth = -1;
+	p_state->is_frequency_valid = 0;
+	deb_info(" -%s  error end\n", __FUNCTION__);
+
+	return -1;
+	
+}
+
+static int 
+rtl2832_get_parameters(
+	struct dvb_frontend*	fe,
+	struct dtv_frontend_properties  *param)
+{
+	struct rtl2832_state* p_state = fe->demodulator_priv;
+	int pConstellation;
+	int pHierarchy;
+	int pCodeRateLp;
+	int pCodeRateHp;
+	int pGuardInterval;
+	int pFftMode;
+
+	if( p_state->pNim== NULL)
+	{
+		deb_info(" %s pNim = NULL \n", __FUNCTION__);
+		return -1;
+	}
+
+	if( mutex_lock_interruptible(&p_state->i2c_repeater_mutex) )
+		return -1;
+
+	if(p_state->demod_type == RTL2832)
+	{
+		p_state->pNim->GetTpsInfo(p_state->pNim, &pConstellation, &pHierarchy, &pCodeRateLp, &pCodeRateHp, &pGuardInterval, &pFftMode);
+
+		switch (pConstellation) {
+		case DVBT_CONSTELLATION_QPSK:
+			param->modulation = QPSK;
+			break;
+		case DVBT_CONSTELLATION_16QAM:
+			param->modulation = QAM_16;
+			break;
+		case DVBT_CONSTELLATION_64QAM:
+			param->modulation = QAM_64;
+			break;
+