/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
 *
 * Copyright (C) 2009 NXP B.V.
 * All Rights Reserved.
 *
 * NXP based DVB adapter driver.
 * Based on the bt8xx driver by Florian Schirmer <jolt@tuxbox.org>
 *
*//*

Rev Date        Author              Comments
--------------------------------------------------------------------------------
001 20090304    Christophe Grosse   First version.
    For consistency and standardisation retain the Section Separators.
*/

/***********************************************
* INCLUDE FILES                                *
************************************************/
#define DVBT
#include <linux/i2c.h>
#include <linux/delay.h>

// For tuner configuration
#include <prjconfig.h>

#include "tda18218.h"

/***********************************************
* LOCAL MACROS                                 *
************************************************/
#define NUM_TDA18218_REG (59)

// For initialisation tables
#define dimof(a) (sizeof(a)/sizeof(a[0]))

#define TDA18218_THERMOMETER_MAP_NB_ROWS  (16)
#define TDA18218_MAIN_PLL_MAP_NB_ROWS (40)

#define dprintk( args... ) \
 do { \
  if (debug) printk(KERN_DEBUG args); \
 } while (0)

// Porting definitions
#define TMBSL_ERR_IIC_ERR -1
#define TM_FALSE 0
#define TM_OK 1
#define TRUE 1
#define True 1
#define False 0

/******************************************************************
* LOCAL TYPEDEFS                                                  *
* recommendation only:                     [p]phStbDbg_<Word>+_t  *
*******************************************************************/

/******************************************************************
* LOCAL TYPEDEFS                                                  *
*******************************************************************/

// Porting definitions
typedef unsigned int UInt32;
typedef int Int32;
typedef unsigned char UInt8;
typedef signed char Int8;
typedef unsigned char Bool;
typedef int tmErrorCode_t;

enum TDA18218RFIOConfig {
    tmTDA18218RFIOConfigNotUsed,
    tmTDA18218Single_HZin_noLTO,
    tmTDA18218Single_HZin_LTOonMTO,
    tmTDA18218Single_HZin_LTOonLT_test,
    tmTDA18218Single_RFin_noLTO,
    tmTDA18218Single_RFin_LTOonLT,
    tmTDA18218Single_Rfin_LTOonMTO_test,
    tmTDA18218Master_HZin_noLTO,
    tmTDA18218Master_HZin_LTOonMTO,
    tmTDA18218Master_HZin_LTOonLT_test,
    tmTDA18218Master_RFin_noLTO,
    tmTDA18218Master_RFin_LTOonLT,
    tmTDA18218Master_Rfin_LTOonMTO_test,
    tmTDA18218Slave_M_HZin_noLTO,
    tmTDA18218Slave_M_HZin_LTOonMTO,
    tmTDA18218Slave_M_HZin_LTOonLT_test,
    tmTDA18218Slave_M_RFin_noLTO,
    tmTDA18218Slave_M_RFin_LTOonLT,
    tmTDA18218Slave_M_Rfin_LTOonMTO_test,
};

enum TDA18218StandardMode {
    tmTDA18218DigitalChannel_6MHz,
    tmTDA18218DigitalChannel_7MHz,
    tmTDA18218DigitalChannel_8MHz,
    tmTDA18218DigitalChannel_9MHz,
    tmTDA18218StandardNotSupported,
};

enum TDA18218ChannelType {
    tmTDA18218AnalogChannel = 0,
    tmTDA18218DigitalChannel
};

enum TDA18218DeviceType {
    tmTDA18218MasterDeviceWithoutLT = 0,
    tmTDA18218MasterDeviceWithLT,
};

// For Caen code's 'static variables'
typedef struct {
    enum TDA18218RFIOConfig   RFIOConfig;
    enum TDA18218StandardMode StandardMode;
    enum TDA18218ChannelType  ChannelType;
    enum TDA18218DeviceType   DeviceType;
    UInt32 uRF;
    UInt32 uIF;
    UInt32 uBW;
    UInt32 uRF_IF_Det;
    UInt32 uAGC1_Init;
    UInt32 uNominalIRFound;
    UInt32 IRCoefHighF[4];
} tmTDA182I1Config_t;

struct tda18218_priv {
    u8 i2c_addr;
    struct i2c_adapter *i2c_adapt;
    unsigned char tda18218_regs[NUM_TDA18218_REG];
    short init;
    u32 frequency;
    u32 bandwidth;
    tmTDA182I1Config_t Config_Instance; // to hold 'static data' for Caen code
};

static Bool TDA18218Write (struct dvb_frontend * tuner_card, UInt8 uSubAddress, UInt8 uNbData);
static Bool TDA18218WriteMAINPLL (struct dvb_frontend * tuner_card, UInt32 uLO, Bool bI2CEnabled);
static Bool TDA18218WriteAGC2_TOP (struct dvb_frontend * tuner_card, UInt8 uBPIndex);
static Bool TDA18218ResetAGC (struct dvb_frontend * tuner_card);
static Bool TDA18218IRCalibration (struct dvb_frontend * tuner_card);
static Bool TDA18218Read (struct dvb_frontend * tuner_card, UInt8 uSubAddress, UInt8 uNbData);

/******************************************************************
* STATIC DATA                  g[k|p|kp|pk|kpk]<Module>_<Word>+   *
*******************************************************************/

// @todo Remove default setting to '1'
static int debug;  // module param

static const struct {
    UInt32 uRF_Max;
    UInt32 uBP_Filter;
} BP_FILTER_Map[] =
{    // BP_FILTER_Map uRF_Max, uBP_Filter
    {62000000, 0x00},
    {84000000, 0x01},
    {100000000, 0x02},
    {140000000, 0x03},
    {170000000, 0x04},
    {180000000, 0x05},
    {865000000, 0x06},
};

static const struct {
    UInt32 uRF_Max;
    UInt32 uRF_Band;
} RF_BAND_Map[] =
{    // RF_BAND_Map uRF_Max, uRF_Band
    {47900000, 0x00},
    {61100000, 0x01},
    {152600000, 0x02},
    {164700000, 0x03},
    {203500000, 0x04},
    {457800000, 0x05},
    {865000000, 0x06},
};

static const struct {
    UInt32 uRF_Max;
    UInt32 uGain_Taper;
} GAIN_TAPER_Map[] =
{    // GAIN_TAPER_Map uRF_Max, uGain_Taper
    {45400000, 0x1F},
    {45800000, 0x1E},
    {46200000, 0x1D},
    {46700000, 0x1C},
    {47100000, 0x1B},
    {47500000, 0x1A},
    {47900000, 0x19},
    {49600000, 0x17},
    {51200000, 0x16},
    {52900000, 0x15},
    {54500000, 0x14},
    {56200000, 0x13},
    {57800000, 0x12},
    {59500000, 0x11},
    {61100000, 0x10},
    {67600000, 0x0D},
    {74200000, 0x0C},
    {80700000, 0x0B},
    {87200000, 0x0A},
    {93800000, 0x09},
    {100300000, 0x08},
    {106900000, 0x07},
    {113400000, 0x06},
    {119900000, 0x05},
    {126500000, 0x04},
    {133000000, 0x03},
    {139500000, 0x02},
    {146100000, 0x01},
    {152600000, 0x00},
    {154300000, 0x1F},
    {156100000, 0x1E},
    {157800000, 0x1D},
    {159500000, 0x1C},
    {161200000, 0x1B},
    {163000000, 0x1A},
    {164700000, 0x19},
    {170200000, 0x17},
    {175800000, 0x16},
    {181300000, 0x15},
    {186900000, 0x14},
    {192400000, 0x13},
    {198000000, 0x12},
    {203500000, 0x11},
    {216200000, 0x14},
    {228900000, 0x13},
    {241600000, 0x12},
    {254400000, 0x11},
    {267100000, 0x10},
    {279800000, 0x0F},
    {292500000, 0x0E},
    {305200000, 0x0D},
    {317900000, 0x0C},
    {330700000, 0x0B},
    {343400000, 0x0A},
    {356100000, 0x09},
    {368800000, 0x08},
    {381500000, 0x07},
    {394200000, 0x06},
    {406900000, 0x05},
    {419700000, 0x04},
    {432400000, 0x03},
    {445100000, 0x02},
    {457800000, 0x01},
    {476300000, 0x19},
    {494800000, 0x18},
    {513300000, 0x17},
    {531800000, 0x16},
    {550300000, 0x15},
    {568900000, 0x14},
    {587400000, 0x13},
    {605900000, 0x12},
    {624400000, 0x11},
    {642900000, 0x10},
    {661400000, 0x0F},
    {679900000, 0x0E},
    {698400000, 0x0D},
    {716900000, 0x0C},
    {735400000, 0x0B},
    {753900000, 0x0A},
    {772500000, 0x09},
    {791000000, 0x08},
    {809500000, 0x07},
    {828000000, 0x06},
    {846500000, 0x05},
    {865000000, 0x04},
};

static const struct {
    UInt32 uRF_Max;
    UInt32 uRFC_Cprog;
} RF_CAL_Map[] =
{    // RF_CAL_Map uRF_Max, uRFC_Cprog
    {41000000, 0x1E},
    {43000000, 0x30},
    {45000000, 0x43},
    {46000000, 0x4D},
    {47000000, 0x54},
    {47900000, 0x64},
    {49100000, 0x20},
    {50000000, 0x22},
    {51000000, 0x2A},
    {53000000, 0x32},
    {55000000, 0x35},
    {56000000, 0x3C},
    {57000000, 0x3F},
    {58000000, 0x48},
    {59000000, 0x4D},
    {60000000, 0x58},
    {61100000, 0x5F},
};

static const struct {
    UInt32 uRF_Max;
    UInt32 uK;
    UInt32 uM;
    UInt32 uCOAmpl;
} RF_CAL_KMCO_Map[] =
{    // RF_CAL_KMCO_Map uRF_Max uK, uM, UCOAmp
    {152600000, 2,  0,  1},
    {164700000, 1,  0,  1},
  //{203500000, 2,  1,  3},
    {203500000, 2,  1,  1},
    {457800000, 4,  0,  3},
    {865000000, 2,  2,  3},
};

 static const struct {
        UInt32 uTM_D;
        UInt32 uTM_60_92;
        UInt32 uTM_92_122;
} THERMOMETER_Map[] =
{    // THERMOMETER_Map uTM_D, uTM_60_92, uTM_92_122
    {0x00, 0x3C, 0x5C},
    {0x01, 0x3E, 0x5E},
    {0x02, 0x42, 0x62},
    {0x03, 0x40, 0x60},
    {0x04, 0x4A, 0x6A},
    {0x05, 0x48, 0x68},
    {0x06, 0x44, 0x64},
    {0x07, 0x46, 0x66},
    {0x08, 0x5A, 0x7A},
    {0x09, 0x58, 0x78},
    {0x0A, 0x54, 0x74},
    {0x0B, 0x56, 0x76},
    {0x0C, 0x4C, 0x6C},
    {0x0D, 0x4E, 0x6E},
    {0x0E, 0x52, 0x72},
    {0x0F, 0x50, 0x70},
};

static const struct {
    UInt32 uLO_Max;
    UInt8 uPost_Div;
    UInt8 uDiv;
} MAIN_PLL_Map[] =
{    // MAIN_PLL_Map uLO_Max, uPost_Div, uDiv
    {33000000, 0x57, 0xF0},
    {36000000, 0x56, 0xE0},
    {38000000, 0x55, 0xD0},
    {42000000, 0x54, 0xC0},
    {45000000, 0x53, 0xB0},
    {50000000, 0x52, 0xA0},
    {56000000, 0x51, 0x90},
    {63000000, 0x50, 0x80},
    {67000000, 0x47, 0x78},
    {72000000, 0x46, 0x70},
    {77000000, 0x45, 0x68},
    {84000000, 0x44, 0x60},
    {91000000, 0x43, 0x58},
    {100000000, 0x42, 0x50},
    {112000000, 0x41, 0x48},
    {126000000, 0x40, 0x40},
    {134000000, 0x37, 0x3C},
    {144000000, 0x36, 0x38},
    {155000000, 0x35, 0x34},
    {168000000, 0x34, 0x30},
    {183000000, 0x33, 0x2C},
    {201000000, 0x32, 0x28},
    {224000000, 0x31, 0x24},
    {252000000, 0x30, 0x20},
    {268000000, 0x27, 0x1E},
    {288000000, 0x26, 0x1C},
    {310000000, 0x25, 0x1A},
    {336000000, 0x24, 0x18},
    {366000000, 0x23, 0x16},
    {403000000, 0x22, 0x14},
    {448000000, 0x21, 0x12},
    {504000000, 0x20, 0x10},
    {537000000, 0x17, 0x0F},
    {576000000, 0x16, 0x0E},
    {620000000, 0x15, 0x0D},
    {672000000, 0x14, 0x0C},
    {733000000, 0x13, 0x0B},
    {806000000, 0x12, 0x0A},
    {896000000, 0x11, 0x09},
    {1008000000, 0x10, 0x08},
};

static const struct {
    UInt32 uLO_Max;
    UInt8 uPost_Div;
    UInt8 uDiv;
} CAL_PLL_Map[] =
{    // CAL_PLL_Map uLO_Max, uPost_Div, uDiv
    {33000000, 0x5D, 0xD0},
    {36000000, 0x5C, 0xC0},
    {40000000, 0x5B, 0xB0},
    {44000000, 0x5A, 0xA0},
    {49000000, 0x59, 0x90},
    {55000000, 0x58, 0x80},
    {63000000, 0x53, 0x70},
    {67000000, 0x4D, 0x68},
    {73000000, 0x4C, 0x60},
    {80000000, 0x4B, 0x58},
    {88000000, 0x4A, 0x50},
    {98000000, 0x49, 0x48},
    {110000000, 0x48, 0x40},
    {126000000, 0x43, 0x38},
    {135000000, 0x3D, 0x34},
    {147000000, 0x3C, 0x30},
    {160000000, 0x3B, 0x2C},
    {176000000, 0x3A, 0x28},
    {196000000, 0x39, 0x24},
    {220000000, 0x38, 0x20},
    {252000000, 0x33, 0x1C},
    {271000000, 0x2D, 0x1A},
    {294000000, 0x2C, 0x18},
    {320000000, 0x2B, 0x16},
    {352000000, 0x2A, 0x14},
    {392000000, 0x29, 0x12},
    {441000000, 0x28, 0x10},
    {504000000, 0x23, 0x0E},
    {542000000, 0x1D, 0x0D},
    {588000000, 0x1C, 0x0C},
    {641000000, 0x1B, 0x0B},
    {705000000, 0x1A, 0x0A},
    {784000000, 0x19, 0x09},
    {882000000, 0x18, 0x08},
    {1008000000, 0x13, 0x07},
};

static const struct {
    UInt8 uGu;
    UInt8 uGd;
    UInt8 uAd15;
    UInt8 uAd12;
    UInt8 uAd9;
    UInt8 uAd6; //for ES3
    UInt8 uAu3; //for ES3
    UInt8 uAu6;
    UInt8 uAu9;
    UInt8 uAu12;
} AGC1_TOP_Map[] =
{    // AGC1_TOP_Map uGu, uGd, uAd15, uAd12, uAd9, uAd6, uAu3, uAu6, uAu9, uAu12
    {0x0C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // hybrid
};

static const struct {
        UInt8 uGu2;
        UInt8 uGd2;
        UInt8 uGu3;
        UInt8 uGd3;
        UInt8 uGu4;
        UInt8 uGd4;
} AGC2_TOP_Map[] =
{    // AGC2_TOP_Map uGu2, uGd2, uGu3, uGd3, uGu4, uGd4
    {0x02, 0x01, 0x17, 0x16, 0x0C, 0x0B}, // Filter 0
    {0x02, 0x01, 0x17, 0x16, 0x0C, 0x0B}, // Filter 1
    {0x02, 0x01, 0x17, 0x16, 0x0C, 0x0B}, // Filter 2
    {0x02, 0x01, 0x15, 0x14, 0x0C, 0x0B}, // Filter 3
    {0x02, 0x01, 0x15, 0x14, 0x0C, 0x0B}, // Filter 4
    {0x02, 0x01, 0x13, 0x12, 0x0C, 0x0B}, // Filter 5
    {0x02, 0x01, 0x09, 0x08, 0x0C, 0x0B}, // Filter 6
    {0x02, 0x01, 0x09, 0x08, 0x0C, 0x0B}, // Filter 7
};

static const struct {
    UInt32 uAGC1Gain;
    UInt32 uRFAGCTOP;
} RFAGC_TOP_Map[] =
{    // RFAGC_TOP_Map uAGC1Gain, uRFAGCTOP
    {0x03, 0x00},
    {0x06, 0x03},
    {0x09, 0x03},
    {0x0F, 0x03},
};

static const struct {
    UInt32 uRF_Max;
} IR_Map[] =
{    // IR_Map uRF_Max
    {123000},
    {380000},
    {780000},
    {1100000},
};

static const struct {
    UInt32 uR2I;
    UInt32 uR2Q;
    UInt32 uR3IQ;
    UInt32 uR3InQ;
} IR_Rx_Map[] =
    // IR_Rx_Map uR2I, uR2Q, uR3IQ, uR3InQ
{
    {0x00, 0x00, 0x00, 0x00},
};

static const struct {
    UInt32 uFcal_Interval;
} RAM_FCAL_Map[] =
{    // RAM_FCAL_Map uFcal
    {0x08},
    {0x07},
    {0x0B},
    {0x0A},
    {0x0E},
    {0x14},
    {0x1A},
    {0x24},
    {0x2A},
};

static const struct {
    UInt32 uCtap;
    UInt32 uCad;
    UInt32 uCo;
    UInt32 uCtapColor;
    UInt32 uCadColor;
    UInt32 uCoColor;
    Int32 uRAMCtap;
    Int32 uRAMCad;
    Int32 uRAMCo;
} CAPBANK_LF_Map[] =
{    // CAPBANK_LF_Map uCtap, uCad, uCo, uCtapColor, uCadColor, uCoColor
    {0x17, 0x64, 0x78, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00},
    {0x18, 0x5A, 0x5A, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00},
    {0x1A, 0x44, 0x50, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00},
    {0x0E, 0x38, 0x38, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},
    {0x0E, 0x30, 0x34, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},
    {0x0F, 0x22, 0x2E, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},
    {0x0B, 0x1E, 0x28, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},
    {0x09, 0x1C, 0x1E, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},
    {0x09, 0x16, 0x1C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},
    {0x0A, 0x12, 0x1A, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},
    {0x08, 0x0E, 0x18, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00},
    {0x09, 0x0C, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x09, 0x0A, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x06, 0x0C, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x06, 0x0A, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x06, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x06, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x05, 0x07, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x05, 0x07, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x06, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x06, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x05, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x05, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x06, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x04, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x05, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x04, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x05, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
};

static const struct {
    UInt32 uCtap;
    UInt32 uCad;
    UInt32 uCo;
    UInt32 uCtapColor;
    UInt32 uCadColor;
    UInt32 uCoColor;
    Int32 uRAMCtap;
    Int32 uRAMCad;
    Int32 uRAMCo;
} CAPBANK_HF_Map[] =
{    // CAPBANK_HF_Map uCtap, uCad, uCo, uCtapColor, uCadColor, uCoColor
    {0x50, 0x1E, 0x72, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00},
    {0x46, 0x1E, 0x6A, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00},
    {0x46, 0x1E, 0x64, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00},
    {0x46, 0x1A, 0x5E, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00},
    {0x46, 0x14, 0x54, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00},
    {0x46, 0x14, 0x4A, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00},
    {0x5A, 0x10, 0x44, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00},
    {0x28, 0x10, 0x3E, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00},
    {0x1E, 0x0E, 0x36, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x1E, 0x0C, 0x32, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x1E, 0x0C, 0x2E, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x1C, 0x0C, 0x2A, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x1A, 0x0C, 0x26, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x1A, 0x0C, 0x22, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x1E, 0x0A, 0x20, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x14, 0x0A, 0x1E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x14, 0x09, 0x1C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x16, 0x08, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x16, 0x08, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x16, 0x08, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
    {0x16, 0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x14, 0x06, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x14, 0x06, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0D, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0D, 0x06, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0D, 0x06, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0D, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0D, 0x05, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0C, 0x05, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0C, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0B, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0B, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0B, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0B, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0B, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0B, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0D, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0B, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x0A, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x10, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x09, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    {0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
};

static const struct {
    Int32 uDeltaIndex;
} DELTA_INDEX_Map[] =
{    // DELTA_INDEX_Map uCtap, uCad, uCo, uCtapColor, uCadColor, uCoColor
    {0},
    {0},
    {0},
    {0},
    {0},
    {0},
};

typedef struct
{
    union
    {
        UInt8 ID_byte;                    // address  0x00
        struct
        {
            UInt8 ID            :7;        // Chip identification number
            UInt8 UNUSED_0x00    :1;        // Reserved, must be written as 1
        }bF;
    }uBx00;

    union
    {
        UInt8 THERMO_BYTE;   // address 0x01
        // Thermometer byte
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 POR            :1;
            UInt8 LO_Lock        :1;
            UInt8 CAL_Lock       :1;
            UInt8 LT_2           :1;
            UInt8 TM_D           :4;
#else
            UInt8 TM_D           :4;
            UInt8 LT_2           :1;
            UInt8 CAL_Lock       :1;
            UInt8 LO_Lock        :1;
            UInt8 POR            :1;
#endif
        }bF;
    }uBx01;

    union
    {
        UInt8 Read_byte_2;                // address 0x02
        UInt8 RSSI;
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 RSSI_7        :1;
            UInt8 RSSI_6        :1;
            UInt8 RSSI_5        :1;
            UInt8 RSSI_4        :1;
            UInt8 RSSI_3        :1;
            UInt8 RSSI_2        :1;
            UInt8 RSSI_1        :1;
            UInt8 RSSI_0        :1;
#else
            UInt8 RSSI_0        :1;
            UInt8 RSSI_1        :1;
            UInt8 RSSI_2        :1;
            UInt8 RSSI_3        :1;
            UInt8 RSSI_4        :1;
            UInt8 RSSI_5        :1;
            UInt8 RSSI_6        :1;
            UInt8 RSSI_7        :1;
#endif
        }bF;
    }uBx02;

    union
    {
        UInt8 Read_byte_3;                // address 0x03
        UInt8 Power_Level_15_to_8;
        UInt8 AGC2;
    }uBx03;

    union
    {
        UInt8 Read_byte_4;                // address 0x04
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 Power_Level_AGC1_2        :1;
            UInt8 PB_IRCAL                  :1;
            UInt8 IR_CAL_OK                 :1;
            UInt8 RSSI_Alarm                :1;
            UInt8 LT                        :2;
            UInt8 Power_Level_AGC1          :2;
#else
            UInt8 Power_Level_AGC1          :2;
            UInt8 LT                        :2;
            UInt8 RSSI_Alarm                :1;
            UInt8 IR_CAL_OK                 :1;
            UInt8 PB_IRCAL                  :1;
            UInt8 Power_Level_AGC1_2        :1;
#endif
        }bF;
    }uBx04;

    union
    {
        UInt8 Read_byte_5;                // address 0x05
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 msm_rst                   :1;
            UInt8 FlagClear                 :1;
            UInt8 launch_msm                :1;
            UInt8 FlagMSM_OK                :1;
            UInt8 RSSI_Sense_OK             :1;
            UInt8 FlagSuperpos              :1;
            UInt8 FlagRFcal_AV_End          :1;
            UInt8 FlagRFcal_POR_End         :1;
#else
            UInt8 FlagRFcal_POR_End         :1;
            UInt8 FlagRFcal_AV_End          :1;
            UInt8 FlagSuperpos              :1;
            UInt8 RSSI_Sense_OK             :1;
            UInt8 FlagMSM_OK                :1;
            UInt8 launch_msm                :1;
            UInt8 FlagClear                 :1;
            UInt8 msm_rst                   :1;
#endif
        }bF;
    }uBx05;

    union
    {
        UInt8 Read_byte_6;                // address 0x06
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x06               :2;
            UInt8 DataRAM                   :6;
#else
            UInt8 DataRAM                   :6;
            UInt8 UNUSED_0x06               :2;
#endif
        }bF;
    }uBx06;

    union
    {
        UInt8 PSM_byte_1;                // address 0x07
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x07               :1;
            UInt8 Freq_prog_En              :1;
            UInt8 PSM_LOVCO                 :2;
            UInt8 PSM_Mixer                 :2;
            UInt8 PSM_Lodriver              :2;
#else
            UInt8 PSM_Lodriver              :2;
            UInt8 PSM_Mixer                 :2;
            UInt8 PSM_LOVCO                 :2;
            UInt8 Freq_prog_En              :1;
            UInt8 UNUSED_0x07               :1;
#endif
        }bF;
    }uBx07;

    union
    {
        UInt8 Main_Divider_byte_1;        // address 0x08
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x08_0             :1;
            UInt8 LOPostDiv                 :3;
            UInt8 UNUSED_0x08_1             :1;
            UInt8 LOPresc                   :3;
#else
            UInt8 LOPresc                   :3;
            UInt8 UNUSED_0x08_1             :1;
            UInt8 LOPostDiv                 :3;
            UInt8 UNUSED_0x08_0             :1;
#endif
        }bF;
    }uBx08;

    union
    {
        UInt8 Main_Divider_byte_2;        // address 0x09
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x09               :1;
            UInt8 LO_Int                    :7;
#else
            UInt8 LO_Int                    :7;
            UInt8 UNUSED_0x09               :1;
#endif
        }bF;
    }uBx09;

    union
    {
        UInt8 Main_Divider_byte_3;        // address 0x0A
        UInt8 LO_Frac_31_to_24;
    }uBx0A;

    union
    {
        UInt8 Main_Divider_byte_4;        // address 0x0B
        UInt8 LO_Frac_23_to_16;
    }uBx0B;

    union
    {
        UInt8 Main_Divider_byte_5;        // address 0x0C
        UInt8 LO_Frac_15_to_8;
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 LO_Frac_15_to_12          :4;
            UInt8 LO_Frac_11_to_8           :4;
#else
            UInt8 LO_Frac_11_to_8           :4;
            UInt8 LO_Frac_15_to_12          :4;
#endif
        }bF;
    }uBx0C;

    union
    {
        UInt8 Main_Divider_byte_6;        // address 0x0D
        UInt8 LO_Frac_7_to_0;
    }uBx0D;

    union
    {
        UInt8 Main_Divider_byte_7;        // address 0x0E
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 LOSD_clock                :1;
            UInt8 LOSD_Static_N             :1;
            UInt8 LOSD_BascD                :1;
            UInt8 LOSD_dpa2                 :1;
            UInt8 LOSD_dpa1                 :1;
            UInt8 LOSDrstN                  :1;
            UInt8 LOSD_test_En              :1;
            UInt8 UNUSED_0x0E               :1;
#else
            UInt8 UNUSED_0x0E               :1;
            UInt8 LOSD_test_En              :1;
            UInt8 LOSDrstN                  :1;
            UInt8 LOSD_dpa1                 :1;
            UInt8 LOSD_dpa2                 :1;
            UInt8 LOSD_BascD                :1;
            UInt8 LOSD_Static_N             :1;
            UInt8 LOSD_clock                :1;
#endif
        }bF;
    }uBx0E;

    union
    {
        UInt8 Main_Divider_byte_8;        // address 0x0F
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 state_pll_out_2           :1;
            UInt8 Freq_prog_Start           :1;
            UInt8 state_pll_out_0           :1;
            UInt8 LO_Sn05                   :1;
            UInt8 LO_Sn05b                  :1;
            UInt8 LO_ForceSrce              :1;
            UInt8 LO_ForceSink              :1;
            UInt8 LO_Auto_src               :1;
#else
            UInt8 LO_Auto_src               :1;
            UInt8 LO_ForceSink              :1;
            UInt8 LO_ForceSrce              :1;
            UInt8 LO_Sn05b                  :1;
            UInt8 LO_Sn05                   :1;
            UInt8 state_pll_out_0           :1;
            UInt8 Freq_prog_Start           :1;
            UInt8 state_pll_out_2           :1;
#endif
        }bF;
    }uBx0F;

    union
    {
        UInt8 Cal_Divider_byte_1;        // address 0x10
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 state_pll_out_1           :1;
            UInt8 CALPostDiv                :3;
            UInt8 CALPrescSW                :1;
            UInt8 CALPresc                  :3;
#else
            UInt8 CALPresc                  :3;
            UInt8 CALPrescSW                :1;
            UInt8 CALPostDiv                :3;
            UInt8 state_pll_out_1           :1;
#endif
        }bF;
    }uBx10;

    union
    {
        Int8 Cal_Divider_byte_2;        // address 0x11
        Int8 CAL_Int;
    }uBx11;

    union
    {
        UInt8 Cal_Divider_byte_3;        // address 0x12
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x12               :1;
            UInt8 CAL_Frac_22_to_16         :7;
#else
            UInt8 CAL_Frac_22_to_16         :7;
            UInt8 UNUSED_0x12               :1;
#endif
        }bF;
    }uBx12;

    union
    {
        UInt8 Cal_Divider_byte_4;        // address 0x13
        UInt8 CAL_Frac_15_to_8;
    }uBx13;

    union
    {
        UInt8 Cal_Divider_byte_5;        // address 0x14
        UInt8 CAL_Frac_7_to_0;
    }uBx14;

    union
    {
        UInt8 Cal_Divider_byte_6;        // address 0x15
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 CALSD_clock               :1;
            UInt8 CALSD_Static_N            :1;
            UInt8 CALSD_BascD               :1;
            UInt8 CALSD_dpa2                :1;
            UInt8 CALSD_dpa1                :1;
            UInt8 CALSDrstN                 :1;
            UInt8 CALSD_test_En             :1;
            UInt8 PD_CALvco_Testn           :1;
#else
            UInt8 PD_CALvco_Testn           :1;
            UInt8 CALSD_test_En             :1;
            UInt8 CALSDrstN                 :1;
            UInt8 CALSD_dpa1                :1;
            UInt8 CALSD_dpa2                :1;
            UInt8 CALSD_BascD               :1;
            UInt8 CALSD_Static_N            :1;
            UInt8 CALSD_clock               :1;
#endif
        }bF;
    }uBx15;

    union
    {
        UInt8 Cal_Divider_byte_7;        // address 0x16
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 MixGateDC                 :2;
            UInt8 UNUSED_0x16               :1;
            UInt8 CAL_Sn05                  :1;
            UInt8 CAL_Sn05b                 :1;
            UInt8 CAL_ForceSrce             :1;
            UInt8 CAL_ForceSink             :1;
            UInt8 CAL_Auto_src              :1;
#else
            UInt8 CAL_Auto_src              :1;
            UInt8 CAL_ForceSink             :1;
            UInt8 CAL_ForceSrce             :1;
            UInt8 CAL_Sn05b                 :1;
            UInt8 CAL_Sn05                  :1;
            UInt8 UNUSED_0x16               :1;
            UInt8 MixGateDC                 :2;
#endif
        }bF;
    }uBx16;

    union
    {
        UInt8 Power_Down_byte_1;        // address 0x17
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x17               :1;
            UInt8 pdLT                      :1;
            UInt8 pdAGC1a                   :1;
            UInt8 pdHZlna                   :1;
            UInt8 pdAGC1b                   :1;
            UInt8 PD_RFAGC_Ifout            :1;
            UInt8 PD_LO_Synthe              :1;
            UInt8 SM                        :1;
#else
            UInt8 SM                        :1;
            UInt8 PD_LO_Synthe              :1;
            UInt8 PD_RFAGC_Ifout            :1;
            UInt8 pdAGC1b                   :1;
            UInt8 pdHZlna                   :1;
            UInt8 pdAGC1a                   :1;
            UInt8 pdLT                      :1;
            UInt8 UNUSED_0x17               :1;
#endif
        }bF;
    }uBx17;

    union
    {
        UInt8 Power_Down_byte_2;        // address 0x18
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 RFSW_MTO_LT_Hzin          :1;
            UInt8 RFSW_MTO_LT_RFin          :1;
            UInt8 RFSW_Buf1_out             :1;
            UInt8 RFSW_AGC1b_out            :1;
            UInt8 PD_RFAGC_Det              :1;
            UInt8 pdDETECT1                 :1;
            UInt8 pdAGC2b                   :1;
            UInt8 PD_LOtest                 :1;
#else
            UInt8 PD_LOtest                 :1;
            UInt8 pdAGC2b                   :1;
            UInt8 pdDETECT1                 :1;
            UInt8 PD_RFAGC_Det              :1;
            UInt8 RFSW_AGC1b_out            :1;
            UInt8 RFSW_Buf1_out             :1;
            UInt8 RFSW_MTO_LT_RFin          :1;
            UInt8 RFSW_MTO_LT_Hzin          :1;
#endif
        }bF;
    }uBx18;

    union
    {
        UInt8 Xtout_Byte;                // address 0x19
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 hc_mode                   :4;
            UInt8 XtOut                     :4;
#else
            UInt8 XtOut                     :4;
            UInt8 hc_mode                   :4;
#endif
        }bF;
    }uBx19;

    union
    {
        UInt8 IF_Byte_1;                    // address 0x1A
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 IF_notch                  :1;
            UInt8 IF_level                  :3;
            UInt8 H3H5_Gain_3dB             :1;
            UInt8 BP_Filter                 :3;
#else
            UInt8 BP_Filter                 :3;
            UInt8 H3H5_Gain_3dB             :1;
            UInt8 IF_level                  :3;
            UInt8 IF_notch                  :1;
#endif
        }bF;
    }uBx1A;

    union
    {
        UInt8 IF_Byte_2;                    // address 0x1B
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 RFAGC_OpenLoop            :1;
            UInt8 RF_IF_Det                 :1;
            UInt8 pdAGC2a                   :1;
            UInt8 AGC_Low_BW                :1;
            UInt8 UNUSED_0x1B               :2;
            UInt8 LP_Fc                     :2;
#else
            UInt8 LP_Fc                     :2;
            UInt8 UNUSED_0x1B               :2;
            UInt8 AGC_Low_BW                :1;
            UInt8 pdAGC2a                   :1;
            UInt8 RF_IF_Det                 :1;
            UInt8 RFAGC_OpenLoop            :1;
#endif
        }bF;
    }uBx1B;

    union
    {
        UInt8 AGC2b_byte;                // address 0x1C
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 pulse_up_auto             :1;
            UInt8 pulse_up_width            :2;
            UInt8 AGC_On                    :1;
            UInt8 DETECT4_Cap_Reset_En      :1;
            UInt8 pdAGC2_DETECT4            :1;
            UInt8 pdAGC2_DETECT3            :1;
            UInt8 pdAGC2_DETECT2            :1;
#else
            UInt8 pdAGC2_DETECT2            :1;
            UInt8 pdAGC2_DETECT3            :1;
            UInt8 pdAGC2_DETECT4            :1;
            UInt8 DETECT4_Cap_Reset_En      :1;
            UInt8 AGC_On                    :1;
            UInt8 pulse_up_width            :2;
            UInt8 pulse_up_auto             :1;
#endif
        }bF;
    }uBx1C;

    union
    {
        UInt8 PSM_byte_2;                // address 0x1D
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 TM_Range                  :1;
            UInt8 TM_ON                     :1;
            UInt8 PSM_IFpoly                :2;
            UInt8 test_mode_agc2            :1;
            UInt8 LO_iqfib                  :1;
            UInt8 LO_iqmos                  :1;
            UInt8 H3H5_Dcboostn             :1;
#else
            UInt8 H3H5_Dcboostn             :1;
            UInt8 LO_iqmos                  :1;
            UInt8 LO_iqfib                  :1;
            UInt8 test_mode_agc2            :1;
            UInt8 PSM_IFpoly                :2;
            UInt8 TM_ON                     :1;
            UInt8 TM_Range                  :1;
#endif
        }bF;
    }uBx1D;

    union
    {
        UInt8 PSM_byte_3;                // address 0x1E
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 PSM_AGC1                  :2;
            UInt8 STOB_DC                   :2;
            UInt8 PSM_StoB                  :2;
            UInt8 PSM_RFpoly                :2;
#else
            UInt8 PSM_RFpoly                :2;
            UInt8 PSM_StoB                  :2;
            UInt8 STOB_DC                   :2;
            UInt8 PSM_AGC1                  :2;
#endif
        }bF;
    }uBx1E;

    union
    {
        UInt8 PSM_byte_4;                // address 0x1F
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 AGC1_Speed                :2;
            UInt8 digck_mode                :2;
            UInt8 UNUSED_0x1F               :1;
            UInt8 AGC1_aud_sel              :1;
            UInt8 AGC1_au_ptr               :2;
#else
            UInt8 AGC1_au_ptr               :2;
            UInt8 AGC1_aud_sel              :1;
            UInt8 UNUSED_0x1F               :1;
            UInt8 digck_mode                :2;
            UInt8 AGC1_Speed                :2;
#endif
        }bF;
    }uBx1F;

    union
    {
        UInt8 AGC1_byte_1;                // address 0x20
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 AGC2_RAM_sel              :2;
            UInt8 AGC2_Gup_sel              :1;
            UInt8 AGC1_Gup_sel              :1;
            UInt8 Manual_LT                 :1;
            UInt8 AGC1_aud                  :3;
#else
            UInt8 AGC1_aud                  :3;
            UInt8 Manual_LT                 :1;
            UInt8 AGC1_Gup_sel              :1;
            UInt8 AGC2_Gup_sel              :1;
            UInt8 AGC2_RAM_sel              :2;
#endif
        }bF;
    }uBx20;

    union
    {
        UInt8 AGC1_byte_2;                // address 0x21
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 AGC2_Speed                :2;
            UInt8 RFagc_fast                :1;
            UInt8 AGC1_Gud                  :5;
#else
            UInt8 AGC1_Gud                  :5;
            UInt8 RFagc_fast                :1;
            UInt8 AGC2_Speed                :2;
#endif
        }bF;
    }uBx21;

    union
    {
        UInt8 AGC1_byte_3;                // address 0x22
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 BUF1b_DCloopIH            :1;
            UInt8 BUF1a_DCCompIH            :1;
            UInt8 AGC1_loop_off             :1;
            UInt8 AGC1_bypass               :1;
            UInt8 AGC1_Speed_Up             :1;
            UInt8 AGC1_Speed_Do             :1;
            UInt8 AGC1_Do_step              :2;
#else
            UInt8 AGC1_Do_step              :2;
            UInt8 AGC1_Speed_Do             :1;
            UInt8 AGC1_Speed_Up             :1;
            UInt8 AGC1_bypass               :1;
            UInt8 AGC1_loop_off             :1;
            UInt8 BUF1a_DCCompIH            :1;
            UInt8 BUF1b_DCloopIH            :1;
#endif
        }bF;
    }uBx22;

    union
    {
        UInt8 AGC2_byte_1;                // address 0x23
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x23               :3;
            UInt8 AGC2_Gud                  :5;
#else
            UInt8 AGC2_Gud                  :5;
            UInt8 UNUSED_0x23               :3;
#endif
        }bF;
    }uBx23;

    union
    {
        UInt8 AGC2_byte_2;                // address 0x24
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 AGC1_gain_Force           :1;
            UInt8 AGC2_gain_Force           :1;
            UInt8 AGC2_loop_off             :1;
            UInt8 AGC2_bypass               :1;
            UInt8 AGC2_Speed_Up             :1;
            UInt8 AGC2_Speed_Do             :1;
            UInt8 AGC2_Do_step              :2;
#else
            UInt8 AGC2_Do_step              :2;
            UInt8 AGC2_Speed_Do             :1;
            UInt8 AGC2_Speed_Up             :1;
            UInt8 AGC2_bypass               :1;
            UInt8 AGC2_loop_off             :1;
            UInt8 AGC2_gain_Force           :1;
            UInt8 AGC1_gain_Force           :1;
#endif
        }bF;
    }uBx24;

    union
    {
        UInt8 Analog_AGC_byte;            // address 0x25
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 RC_Cal_Force              :1;
            UInt8 RFAGC_Top                 :3;
            UInt8 IFAGC_Top                 :4;
#else
            UInt8 IFAGC_Top                 :4;
            UInt8 RFAGC_Top                 :3;
            UInt8 RC_Cal_Force              :1;
#endif
        }bF;
    }uBx25;

    union
    {
        UInt8 RC_byte;                    // address 0x26
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 RC_Cal_3_to_0             :4;
            UInt8 RC_ReadCal_3_to_0         :4;
#else
            UInt8 RC_ReadCal_3_to_0         :4;
            UInt8 RC_Cal_3_to_0             :4;
#endif
        }bF;
    }uBx26;

    union
    {
        UInt8 RSSI_byte;                // address 0x27
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 RC_Cal_4                  :1;
            UInt8 RC_ReadCal_4              :1;
            UInt8 RSSI_AV                   :1;
            UInt8 RSSI_sinus_QAMnot         :1;
            UInt8 RSSI_Cap_Reset_En         :1;
            UInt8 RSSI_Cap_Val              :1;
            UInt8 RSSI_Ck_Speed             :1;
            UInt8 RSSI_Dicho_not            :1;
#else
            UInt8 RSSI_Dicho_not            :1;
            UInt8 RSSI_Ck_Speed             :1;
            UInt8 RSSI_Cap_Val              :1;
            UInt8 RSSI_Cap_Reset_En         :1;
            UInt8 RSSI_sinus_QAMnot         :1;
            UInt8 RSSI_AV                   :1;
            UInt8 RC_ReadCal_4              :1;
            UInt8 RC_Cal_4                  :1;
#endif
        }bF;
    }uBx27;

    union
    {
        UInt8 IR_CAL_byte_1;            // address 0x28
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x28               :1;
            UInt8 IR_Loop                   :3;
            UInt8 Force_Lock                :1;
            UInt8 IR_Target                 :3;
#else
            UInt8 IR_Target                 :3;
            UInt8 Force_Lock                :1;
            UInt8 IR_Loop                   :3;
            UInt8 UNUSED_0x28               :1;
#endif
        }bF;
    }uBx28;

    union
    {
        UInt8 IR_CAL_byte_2;            // address 0x29
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 extra_control2            :1;
            UInt8 IR_GStep                  :3;
            UInt8 STOBattON                 :1;
            UInt8 STOB_gain                 :1;
            UInt8 IR_Freq                   :2;
#else
            UInt8 IR_Freq                   :2;
            UInt8 STOB_gain                 :1;
            UInt8 STOBattON                 :1;
            UInt8 IR_GStep                  :3;
            UInt8 extra_control2            :1;
#endif
        }bF;
    }uBx29;

    union
    {
        UInt8 IR_CAL_byte_3;            // address 0x2A
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 shift                     :2;
            UInt8 IR_Cal_Boost              :2;
            UInt8 AGCK_minus3               :1;
            UInt8 Rx_Force                  :1;
            UInt8 Ptr_Rx_Read               :2;
#else
            UInt8 Ptr_Rx_Read               :2;
            UInt8 Rx_Force                  :1;
            UInt8 AGCK_minus3               :1;
            UInt8 IR_Cal_Boost              :2;
            UInt8 shift                     :2;
#endif
        }bF;
    }uBx2A;

    union
    {
        UInt8 IR_CAL_byte_4;            // address 0x2B
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 Rx_ptrW                   :2;
            UInt8 Rx_W                      :6;
#else
            UInt8 Rx_W                      :6;
            UInt8 Rx_ptrW                   :2;
#endif
        }bF;
    }uBx2B;

    union
    {
        UInt8 RF_Cal_byte_1;            // address 0x2C
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 HP_RF                     :1;
            UInt8 HP_LO                     :1;
            UInt8 CO_Amp                    :2;
            UInt8 Extra_control1            :1;
            UInt8 UNUSED_0x2C               :1;
            UInt8 AGC_DC                    :2;
#else
            UInt8 AGC_DC                    :2;
            UInt8 UNUSED_0x2C               :1;
            UInt8 Extra_control1            :1;
            UInt8 CO_Amp                    :2;
            UInt8 HP_LO                     :1;
            UInt8 HP_RF                     :1;
#endif
        }bF;
    }uBx2C;

    union
    {
        UInt8 RF_Cal_byte_2;            // address 0x2D
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 RFcal_RST_N               :1;
            UInt8 Indx_filter_sel           :1;
            UInt8 capw_filter_sel           :1;
            UInt8 Sel_3dB                   :1;
            UInt8 RefineAV                  :1;
            UInt8 HFbypassPOR               :1;
            UInt8 rfcal_clock_en            :1;
            UInt8 RFcal_modeOFF             :1;
#else
            UInt8 RFcal_modeOFF             :1;
            UInt8 rfcal_clock_en            :1;
            UInt8 HFbypassPOR               :1;
            UInt8 RefineAV                  :1;
            UInt8 Sel_3dB                   :1;
            UInt8 capw_filter_sel           :1;
            UInt8 Indx_filter_sel           :1;
            UInt8 RFcal_RST_N               :1;
#endif
        }bF;
    }uBx2D;

    union
    {
        UInt8 RF_Cal_byte_3;            // address 0x2E
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 LF_nHF                    :1;
            UInt8 FilterIndex               :7;
#else
            UInt8 FilterIndex               :7;
            UInt8 LF_nHF                    :1;
#endif
        }bF;
    }uBx2E;

    union
    {
        UInt8 RF_Cal_byte_4;            // address 0x2F
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x2F               :1;
            UInt8 Center                    :7;
#else
            UInt8 Center                    :7;
            UInt8 UNUSED_0x2F               :1;
#endif
        }bF;
    }uBx2F;

    union
    {
        UInt8 RF_Cal_byte_5;            // address 0x30
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 FreqCut_sel               :1;
            UInt8 FreqCut                   :7;
#else
            UInt8 FreqCut                   :7;
            UInt8 FreqCut_sel               :1;
#endif
        }bF;
    }uBx30;

    union
    {
        UInt8 RF_Cal_byte_6;            // address 0x31
        UInt8 GainMax_out;
    }uBx31;

    union
    {
        UInt8 RF_Cal_byte_7;            // address 0x32
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 GAIN_threshold            :3;
            UInt8 ShiftLF                   :2;
            UInt8 NmeasAV                   :3;
#else
            UInt8 NmeasAV                   :3;
            UInt8 ShiftLF                   :2;
            UInt8 GAIN_threshold            :3;
#endif
        }bF;
    }uBx32;

    union
    {
        UInt8 RF_Cal_byte_8;            // address 0x33
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x33               :1;
            UInt8 capw_gain                 :7;
#else
            UInt8 capw_gain                 :7;
            UInt8 UNUSED_0x33               :1;
#endif
        }bF;
    }uBx33;

    union
    {
        UInt8 RF_Cal_byte_9;            // address 0x34
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x34               :1;
            UInt8 capw_cad                  :7;
#else
            UInt8 capw_cad                  :7;
            UInt8 UNUSED_0x34               :1;
#endif
        }bF;
    }uBx34;

    union
    {
        UInt8 RF_Cal_byte_10;            // address 0x35
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x35               :1;
            UInt8 capw_ctank                :7;
#else
            UInt8 capw_ctank                :7;
            UInt8 UNUSED_0x35               :1;
#endif
        }bF;
    }uBx35;

    union
    {
        UInt8 RF_Cal_RAM_byte_1;        // address 0x36
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 UNUSED_0x36_2             :3;
            UInt8 SelRAM                    :1;
            UInt8 UNUSED_0x36_1             :1;
            UInt8 ModeI2CRAM                :1;
            UInt8 UNUSED_0x36_0             :1;
            UInt8 WRI2CRAM                  :1;
#else
            UInt8 WRI2CRAM                  :1;
            UInt8 UNUSED_0x36_0             :1;
            UInt8 ModeI2CRAM                :1;
            UInt8 UNUSED_0x36_1             :1;
            UInt8 SelRAM                    :1;
            UInt8 UNUSED_0x36_2             :3;
#endif
        }bF;
    }uBx36;

    union
    {
        UInt8 RF_Cal_RAM_byte_2;        // address 0x37
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 test_scan                 :4;
            UInt8 AddRAM                    :4;
#else
            UInt8 AddRAM                    :4;
            UInt8 test_scan                 :4;
#endif
        }bF;
    }uBx37;

    union
    {
        UInt8 Debug_byte;                // address 0x38
        struct
        {
#ifdef _BIG_ENDIAN
            UInt8 Sel_state                  :3;
            UInt8 state_out                  :5;
#else
            UInt8 state_out                  :5;
            UInt8 Sel_state                  :3;
#endif
        }bF;
    }uBx38;

    union
    {
        UInt8 Fmax_byte_1;                // address 0x39
        UInt8 Fmax_Lo;
    }uBx39;

    union
    {
        UInt8 Fmax_byte_2;                // address 0x3A
        UInt8 Fmax_Cal;
    }uBx3A;

} tmTDA18218I2CMap_t;

// Prototypes for Caen code

static int tuner_i2c_xfer(struct dvb_frontend * tuner_card, unsigned char * buf, int len, int is_read)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    int ret;
    int i;
    struct i2c_msg tuner_i2c_msg =
    {
        .addr  = priv->i2c_addr, // tuner_addr,
        .flags = is_read ? I2C_M_RD : 0,
        .buf   = buf,
        .len   = len,
    };

    ret = i2c_transfer(priv->i2c_adapt, &tuner_i2c_msg, 1); // returns number of successful transfers

    return (ret != 1) ? -EIO : 0;
}

static int tuner_i2c_read(struct dvb_frontend * tuner_card, unsigned char * buf, int len)
{
    int ret;

    ret = tuner_i2c_xfer(tuner_card, buf, len, 1);

    return ret;
}

static int tuner_i2c_write(struct dvb_frontend * tuner_card, unsigned char * buf, int len)
{

    return tuner_i2c_xfer(tuner_card, buf, len, 0);
}

/**
 * Write values from register map to chip, preceded by first register number
 * (Writes: <first_reg> map[first_reg] ... map[last_reg])
 *
 * @param tuner_card tuner instance reference
 * @param p_reg_map copy of state of 18211 registers
 * @param first_reg first register index to be written (> 0)
 * @param nb_data number or registers to be written
 * @return <0: error; 0: OK
 */
static int tda_write_chip(struct dvb_frontend * tuner_card, int reg_num, int reg_value)
{
    unsigned char buf[2] = { (unsigned char)reg_num, (unsigned char)reg_value };
    int ret;

    ret = tuner_i2c_write(tuner_card, buf, sizeof(buf));
    if (ret < 0) printk("error return %d\n", ret);

    return ret;
}

static int tda_write_map_to_chip(struct dvb_frontend * tuner_card, UInt8* p_reg_map, UInt8 first_reg, UInt8 nb_data)
{
    int ret;
    UInt8 regvalue;
    UInt8 last_reg = first_reg + nb_data -1;
    int i;

   /* Note - chip requires first register number followed by map data bytes.
    * To perform this in a single transfer, we temporarily store the
    * register number in the map byte _before_ the first register to be sent,
    * send register number + map bytes,
    * then restore the map byte value after the transfer.
    */

    if (first_reg <= 0) { dprintk("Warning - writing chip ID register\n"); first_reg = 1; }
    if (last_reg < first_reg) { dprintk("Warning - chip registers in wrong order\n"); regvalue = first_reg; first_reg = last_reg; last_reg = regvalue;}

    regvalue = p_reg_map[first_reg - 1]; // preserve map value
    p_reg_map[first_reg - 1] = first_reg; // insert reg addressstatic

    ret = tuner_i2c_write(tuner_card, &p_reg_map[first_reg - 1], (int)last_reg-first_reg+2);
    p_reg_map[first_reg - 1] = regvalue; // restore value


    if (ret < 0) dprintk("error return %d\n", ret);
    return ret;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218SetStandardMode:
//
// DESCRIPTION: Set the standard mode of this device.
//
// RETURN:      True or False
//
// NOTES:
//-------------------------------------------------------------------------------------
//
static Bool TDA18218SetStandardMode(struct dvb_frontend * tuner_card, enum TDA18218StandardMode StandardMode)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;

    // update channel type
    priv->Config_Instance.ChannelType = tmTDA18218DigitalChannel;

    // set uIF & Std
    switch (StandardMode)
    {
    case tmTDA18218DigitalChannel_6MHz:
        I2CMap->uBx1B.bF.pdAGC2a = 1;
        I2CMap->uBx18.bF.pdAGC2b = 0;
        I2CMap->uBx18.bF.PD_RFAGC_Det = 1;
        I2CMap->uBx1C.bF.pdAGC2_DETECT2 = 0;
        I2CMap->uBx1C.bF.pdAGC2_DETECT3 = 0;
        I2CMap->uBx1C.bF.pdAGC2_DETECT4 = 0;
        I2CMap->uBx17.bF.PD_RFAGC_Ifout = 0;
        I2CMap->uBx2D.bF.RFcal_modeOFF = 1;
        I2CMap->uBx1B.bF.LP_Fc = 0;
        priv->Config_Instance.uIF = 5000000;
        break;

    case tmTDA18218DigitalChannel_7MHz:
        I2CMap->uBx1B.bF.pdAGC2a = 1;
        I2CMap->uBx18.bF.pdAGC2b = 0;
        I2CMap->uBx18.bF.PD_RFAGC_Det = 1;
        I2CMap->uBx1C.bF.pdAGC2_DETECT2 = 0;
        I2CMap->uBx1C.bF.pdAGC2_DETECT3 = 0;
        I2CMap->uBx1C.bF.pdAGC2_DETECT4 = 0;
        I2CMap->uBx17.bF.PD_RFAGC_Ifout = 0;
        I2CMap->uBx2D.bF.RFcal_modeOFF = 1;
        I2CMap->uBx1B.bF.LP_Fc = 1;
        priv->Config_Instance.uIF = 5000000;
#ifdef DVBT
        priv->Config_Instance.uIF = 3500000;
#endif
        break;

    case tmTDA18218DigitalChannel_8MHz:
        I2CMap->uBx1B.bF.pdAGC2a = 1;
        I2CMap->uBx18.bF.pdAGC2b = 0;
        I2CMap->uBx18.bF.PD_RFAGC_Det = 1;
        I2CMap->uBx1C.bF.pdAGC2_DETECT2 = 0;
        I2CMap->uBx1C.bF.pdAGC2_DETECT3 = 0;
        I2CMap->uBx1C.bF.pdAGC2_DETECT4 = 0;
        I2CMap->uBx17.bF.PD_RFAGC_Ifout = 0;
        I2CMap->uBx2D.bF.RFcal_modeOFF = 1;
        I2CMap->uBx1B.bF.LP_Fc = 2;
        priv->Config_Instance.uIF = 5000000;
#ifdef DVBT
        priv->Config_Instance.uIF = 4000000;
#endif
        break;

    case tmTDA18218DigitalChannel_9MHz:
        I2CMap->uBx1B.bF.pdAGC2a = 1;
        I2CMap->uBx18.bF.pdAGC2b = 0;
        I2CMap->uBx18.bF.PD_RFAGC_Det = 1;
        I2CMap->uBx1C.bF.pdAGC2_DETECT2 = 0;
        I2CMap->uBx1C.bF.pdAGC2_DETECT3 = 0;
        I2CMap->uBx1C.bF.pdAGC2_DETECT4 = 0;
        I2CMap->uBx17.bF.PD_RFAGC_Ifout = 0;
        I2CMap->uBx2D.bF.RFcal_modeOFF = 1;
        I2CMap->uBx1B.bF.LP_Fc = 3;
        priv->Config_Instance.uIF = 5000000;
        break;

    default:
        // standard mode not supported
        return False;
    }

    // write standard
    if (TDA18218Write(tuner_card,0x1A,3) != True)
        return False;
    if (TDA18218Write(tuner_card,0x17,2) != True)
        return False;
    if (TDA18218Write(tuner_card,0x2D,1) != True)
        return False;

    // update standard mode
    priv->Config_Instance.StandardMode = StandardMode;

    return TM_OK;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218SetRf:
//
// DESCRIPTION: Calculate i2c I2CMap & write in TDA18218
//
// RETURN:      True or False
//
// NOTES:
//-------------------------------------------------------------------------------------
//
static Bool TDA18218SetRf (struct dvb_frontend * tuner_card, UInt32 uRF)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;
    UInt32 uLO;

    // Config.uRF update
    priv->Config_Instance.uRF = uRF;

    uLO = uRF + priv->Config_Instance.uIF;

    if ((uRF > 170000000) && (uRF <= 600000000))
    {
        I2CMap->uBx29.bF.IR_Freq = 2;
    }
    else if ((uRF > 600000000) && (uRF <= 1002000000))
    {
        I2CMap->uBx29.bF.IR_Freq = 3;
    }
    else
    {
        I2CMap->uBx29.bF.IR_Freq = 0;
    }
    if (TDA18218Write(tuner_card,0x29,1) != True)    return TM_FALSE;

    // Write MAIN PLL
    TDA18218WriteMAINPLL(tuner_card, uLO, True);

    // Band pass filters

    if ((uLO <=188000000))  {I2CMap->uBx1A.bF.BP_Filter = 3;}
    else if ((188000000< uLO) && (uLO <=253000000))  {I2CMap->uBx1A.bF.BP_Filter = 4;}
    else if ((253000000< uLO) && (uLO <=343000000))  {I2CMap->uBx1A.bF.BP_Filter = 5;}
    else if ((343000000< uLO))  {I2CMap->uBx1A.bF.BP_Filter = 6;}
    if (TDA18218Write(tuner_card,0x1A,1) != True)    return TM_FALSE;

    if (TDA18218WriteAGC2_TOP(tuner_card, I2CMap->uBx1A.bF.BP_Filter) != True)    return TM_FALSE;

    // AGC2 fast reset

    I2CMap->uBx24.bF.AGC2_bypass = 1;
    if (TDA18218Write(tuner_card,0x24,1) != True)    return TM_FALSE;
    msleep(7);
    I2CMap->uBx24.bF.AGC2_bypass = 0;
    if (TDA18218Write(tuner_card,0x24,1) != True)    return TM_FALSE;

    // return value
    return TM_OK;
}

//-----------------------------------------------------------------------------
// FUNCTION:    TDA18218Init:
//
// DESCRIPTION: initialization of the Tuner
//
// RETURN:      always True
//
// NOTES:
//-----------------------------------------------------------------------------
//
static int TDA18218Init (struct dvb_frontend * tuner_card)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;
    Bool ret;

    // tmTDA18218DigitalOnlyApplication
    // force channel type to digital
    priv->Config_Instance.ChannelType = tmTDA18218DigitalChannel;

    //----------------------
    // I2C map initialization
    //----------------------
    // write all initialization bytes
    I2CMap->uBx05.Read_byte_5 = 0x00;            // 0x05 byte
    I2CMap->uBx06.Read_byte_6 = 0x00;            // 0x06 byte
    I2CMap->uBx07.PSM_byte_1 = 0xD0;             // 0x07 byte
    I2CMap->uBx08.Main_Divider_byte_1 = 0x00;    // 0x08 byte
    I2CMap->uBx09.Main_Divider_byte_2 = 0x40;    // 0x09 byte
    I2CMap->uBx0A.Main_Divider_byte_3 = 0x00;    // 0x0A byte
    I2CMap->uBx0B.Main_Divider_byte_4 = 0x00;    // 0x0B byte
    I2CMap->uBx0C.Main_Divider_byte_5 = 0x07;    // 0x0C byte
    I2CMap->uBx0D.Main_Divider_byte_6 = 0xFF;    // 0x0D byte
    I2CMap->uBx0E.Main_Divider_byte_7 = 0x84;    // 0x0E byte
    I2CMap->uBx0F.Main_Divider_byte_8 = 0x09;    // 0x0F byte
    I2CMap->uBx10.Cal_Divider_byte_1 = 0x00;     // 0x10 byte
    I2CMap->uBx11.Cal_Divider_byte_2 = 0x13;     // 0x11 byte
    I2CMap->uBx12.Cal_Divider_byte_3 = 0x00;     // 0x12 byte
    I2CMap->uBx13.Cal_Divider_byte_4 = 0x00;     // 0x13 byte
    I2CMap->uBx14.Cal_Divider_byte_5 = 0x01;     // 0x14 byte
    I2CMap->uBx15.Cal_Divider_byte_6 = 0x84;     // 0x15 byte
    I2CMap->uBx16.Cal_Divider_byte_7 = 0x09;     // 0x16 byte
    I2CMap->uBx17.Power_Down_byte_1 = 0xF0;      // 0x17 byte
    I2CMap->uBx18.Power_Down_byte_2 = 0x19;      // 0x18 byte
    I2CMap->uBx19.Xtout_Byte = 0x0A;             // 0x19 byte

    switch(priv->Config_Instance.DeviceType)
    {
        default:
        case tmTDA18218MasterDeviceWithoutLT:
        break;

        case tmTDA18218MasterDeviceWithLT:
          I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 1;
          I2CMap->uBx17.bF.pdLT = 0x00;

        break;
    }

    I2CMap->uBx1A.IF_Byte_1 = 0x0E;              // 0x1A byte
    I2CMap->uBx1B.IF_Byte_2 = 0x69;              // 0x1B byte
    I2CMap->uBx1C.AGC2b_byte = 0x98;             // 0x1C byte
    I2CMap->uBx1D.PSM_byte_2 = 0x00;             // 0x1D byte
    I2CMap->uBx1E.PSM_byte_3 = 0x00;             // 0x1E byte
    I2CMap->uBx1F.PSM_byte_4 = 0x58;             // 0x1F byte Killer_on PRCR CFR_STB#40
    I2CMap->uBx20.AGC1_byte_1 = 0x10;            // 0x20 byte
    I2CMap->uBx21.AGC1_byte_2 = 0x40;            // 0x21 byte
    I2CMap->uBx22.AGC1_byte_3 = 0x8C;            // 0x22 byte
    I2CMap->uBx23.AGC2_byte_1 = 0x00;            // 0x23 byte
    I2CMap->uBx24.AGC2_byte_2 = 0x0C;            // 0x24 byte
    I2CMap->uBx25.Analog_AGC_byte = 0x48;        // 0x25 byte
    I2CMap->uBx26.RC_byte = 0x85;                // 0x26 byte
    I2CMap->uBx27.RSSI_byte = 0xC9;              // 0x27 byte
    I2CMap->uBx28.IR_CAL_byte_1 = 0xA7;          // 0x28 byte
    I2CMap->uBx29.IR_CAL_byte_2 = 0x00;          // 0x29 byte
    I2CMap->uBx2A.IR_CAL_byte_3 = 0x00;          // 0x2A byte
    I2CMap->uBx2B.IR_CAL_byte_4 = 0x00;          // 0x2B byte
    I2CMap->uBx2C.RF_Cal_byte_1 = 0x30;          // 0x2C byte
    I2CMap->uBx2D.RF_Cal_byte_2 = 0x81;          // 0x2D byte
    I2CMap->uBx2E.RF_Cal_byte_3 = 0x80;          // 0x2E byte
    I2CMap->uBx2F.RF_Cal_byte_4 = 0x00;          // 0x2F byte
    I2CMap->uBx30.RF_Cal_byte_5 = 0x39;          // 0x30 byte
    I2CMap->uBx31.RF_Cal_byte_6 = 0x00;          // 0x31 byte
    I2CMap->uBx32.RF_Cal_byte_7 = 0x8A;          // 0x32 byte
    I2CMap->uBx33.RF_Cal_byte_8 = 0x00;          // 0x33 byte
    I2CMap->uBx34.RF_Cal_byte_9 = 0x00;          // 0x34 byte
    I2CMap->uBx35.RF_Cal_byte_10 = 0x00;         // 0x35 byte
    I2CMap->uBx36.RF_Cal_RAM_byte_1 = 0x00;      // 0x36 byte
    I2CMap->uBx37.RF_Cal_RAM_byte_2 = 0x00;      // 0x37 byte
    I2CMap->uBx38.Debug_byte = 0x00;             // 0x38 byte
    I2CMap->uBx39.Fmax_byte_1 = 0xF6;            // 0x39 byte
    I2CMap->uBx3A.Fmax_byte_2 = 0xF6;            // 0x3A byte
    if (TDA18218Write(tuner_card, 0x05, 27) != True) return TMBSL_ERR_IIC_ERR;
    if (TDA18218Write(tuner_card, 0x22,  1) != True) return TMBSL_ERR_IIC_ERR;
    if (TDA18218Write(tuner_card, 0x24, 23) != True) return TMBSL_ERR_IIC_ERR;

    // launch msm
    I2CMap->uBx05.bF.msm_rst = 0x01;
    if (TDA18218Write(tuner_card, 0x05, 1) != True) return TMBSL_ERR_IIC_ERR;
    I2CMap->uBx05.bF.msm_rst = 0x00;
    if (TDA18218Write(tuner_card, 0x05, 1) != True) return TMBSL_ERR_IIC_ERR;
    I2CMap->uBx05.bF.launch_msm = 0x01;
    if (TDA18218Write(tuner_card, 0x05, 1) != True) return TMBSL_ERR_IIC_ERR;
    I2CMap->uBx05.bF.launch_msm = 0x00;
    if (TDA18218Write(tuner_card, 0x05, 1) != True) return TMBSL_ERR_IIC_ERR;

    // call IR calibration function
    ret = TDA18218IRCalibration(tuner_card);
    if (ret != True) {
        dprintk("%s(%d): error while IR Calibration\n", __FUNCTION__, __LINE__);
        return TMBSL_ERR_IIC_ERR;
    }
    // call reset agc function
    ret = TDA18218ResetAGC(tuner_card);
    if (ret != True) {
        dprintk("%s(%d): error while Reset AGC\n", __FUNCTION__, __LINE__);
        return TMBSL_ERR_IIC_ERR;
    }
    // return value
    return TM_OK;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218Write
//
// DESCRIPTION: This function writes I2C data in the Tuner
//
// RETURN:      True or False
//
// NOTES:
//-------------------------------------------------------------------------------------
//
static Bool TDA18218Write (struct dvb_frontend * tuner_card, UInt8 uSubAddress, UInt8 uNbData)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;
    Bool   I2CCommResult = True;
    int    ret;
    UInt8  uCounter;
    UInt8* pI2CMap;
    int i;
    UInt8  WriteBuffer[NUM_TDA18218_REG] = {0};
    UInt8* pWriteBuffer;

    // pI2CMap & pWriteBuffer initialization
    pI2CMap = &(I2CMap->uBx00.ID_byte);
    pWriteBuffer = WriteBuffer;

    // copy I2CMap data in WriteBuffer
    for (uCounter = 0; uCounter < NUM_TDA18218_REG; uCounter++)
    {
        switch(uCounter)
        {
        case 0x1B:
            *pWriteBuffer = (UInt8)((*pI2CMap & 0xBF) | (priv->Config_Instance.uRF_IF_Det << 6));
            break;
        default:
            *pWriteBuffer = (UInt8)(*pI2CMap);
            break;
        }
        pWriteBuffer ++;
        pI2CMap ++;
    }

    // write data in the Tuner
    ret = tda_write_map_to_chip(tuner_card, WriteBuffer, uSubAddress, uNbData);
    if (ret < 0) I2CCommResult = False;

    // return value
    return I2CCommResult;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218Read
//
// DESCRIPTION: This function reads I2C data from the Tuner
//
// RETURN:      True or False
//
// NOTES:
//-------------------------------------------------------------------------------------
//
static Bool TDA18218Read (struct dvb_frontend * tuner_card, UInt8 uSubAddress, UInt8 uNbData)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;
    Bool    I2CCommResult = True;
    int     ret;
    UInt8   uCounter;
    UInt8*  pI2CMap;
    UInt8   ReadBuffer[NUM_TDA18218_REG] = {0};

    // pI2CMap initialization
    pI2CMap = &(I2CMap->uBx00.ID_byte);

    // read data from the Tuner
    ret = tuner_i2c_read(tuner_card, ReadBuffer, (int)uNbData);
    if (ret < 0) I2CCommResult = False;

    if(I2CCommResult)
    {
        // copy read data in I2CMap
        for (uCounter = 0; uCounter < uNbData; uCounter++)
        {
            switch(uCounter)
            {
            case 0x00:
                I2CMap->uBx00.ID_byte = (UInt8)ReadBuffer[uCounter];
                break;
            case 0x1B:
                I2CMap->uBx1B.IF_Byte_2 = (UInt8)((ReadBuffer[uCounter] & 0xBF) | (priv->Config_Instance.uRF_IF_Det << 6));
                break;
            case 0x20:
                I2CMap->uBx20.AGC1_byte_1 = (UInt8)((ReadBuffer[uCounter] & 0x08) | (I2CMap->uBx20.AGC1_byte_1 & 0xF7));
                break;
            case 0x21:
                I2CMap->uBx21.AGC1_byte_2 = (UInt8)((ReadBuffer[uCounter] & 0xC0) | (I2CMap->uBx21.AGC1_byte_2 & 0x3F));
                break;
            case 0x23:
                break;
            default:
                pI2CMap[uCounter] = (UInt8)(ReadBuffer[uCounter]);
                break;
            }
        }
    }

    // return value
    return I2CCommResult;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218CalcMAINPLL:
//
// DESCRIPTION: Calculate the MAIN fractional PLL settings
//
// RETURN:      True or False
//
// NOTES:       This function doesn't write in the tuner
//-------------------------------------------------------------------------------------
//
static Bool TDA18218CalcMAINPLL (struct dvb_frontend * tuner_card, UInt32 uLO)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;
    UInt8    uCounter = 0;
    UInt32    uDiv;

    if (I2CMap->uBx07.bF.Freq_prog_En == 1) // auto
    {
        // convert LO in KHz
        uLO /= 1000;

        // update & write LO_Frac_Auto [31..0]
        I2CMap->uBx0A.LO_Frac_31_to_24 = (UInt8)(uLO >> 12);
        I2CMap->uBx0B.LO_Frac_23_to_16 = (UInt8)(uLO >> 4);
        I2CMap->uBx0C.bF.LO_Frac_15_to_12 = ((UInt8)(uLO));
    }
    else
    {
        //manual
        // search for MAIN_Post_Div corresponding to uLO
        uCounter = 0;
        do uCounter ++;
        while (uLO > MAIN_PLL_Map[uCounter - 1].uLO_Max && uCounter < TDA18218_MAIN_PLL_MAP_NB_ROWS);
        I2CMap->uBx08.Main_Divider_byte_1 = ((UInt8)MAIN_PLL_Map[uCounter - 1].uPost_Div);

        //// force LO_Sn05
        //I2CMap->uBx0F.bF..LO_Sn05 = 0;

        // calculate MAIN_Div
        uDiv = (((UInt32)(MAIN_PLL_Map[uCounter - 1].uDiv) * (uLO / 1000)) << 7) / 125;
        I2CMap->uBx09.bF.LO_Int = (UInt8)(uDiv >> 16) & 0x7F;
        I2CMap->uBx0A.LO_Frac_31_to_24 = (UInt8)(uDiv >> 13) & 0x07;
        I2CMap->uBx0B.LO_Frac_23_to_16 = (UInt8)(uDiv >> 5);
        I2CMap->uBx0C.LO_Frac_15_to_8 = ((UInt8)(uDiv) & 0xF8);
        I2CMap->uBx0D.LO_Frac_7_to_0 = 0x01;
    }

    return True;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218WriteMAINPLL:
//
// DESCRIPTION: Write the MAIN fractional PLL settings
//
// RETURN:      True or False
//
// NOTES:
//-------------------------------------------------------------------------------------
//
static Bool TDA18218WriteMAINPLL (struct dvb_frontend * tuner_card, UInt32 uLO, Bool bI2CEnabled)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;

    if (I2CMap->uBx07.bF.Freq_prog_En == 1) // auto
    {
        uLO /= 1000;

        // update & write LO_Frac_Auto [31..0]
        I2CMap->uBx0A.LO_Frac_31_to_24 = (UInt8)(uLO >> 12);
        I2CMap->uBx0B.LO_Frac_23_to_16 = (UInt8)(uLO >> 4);
        I2CMap->uBx0C.bF.LO_Frac_15_to_12 = ((UInt8)(uLO));
        if (bI2CEnabled)
        {
            if (TDA18218Write(tuner_card,0x0A,4) != True)
                return False;
        }

        // update & write Freq_prog_Start to 1
        I2CMap->uBx0F.bF.Freq_prog_Start = 0x01;
        if (bI2CEnabled)
        {
            if (TDA18218Write(tuner_card,0x0F,1) != True)
                return False;
        }

        // update & write Freq_prog_Start to 0
        I2CMap->uBx0F.bF.Freq_prog_Start = 0x00;
        if (bI2CEnabled)
        {
            if (TDA18218Write(tuner_card,0x0F,1) != True)
                return False;
        }
    }
    else // manual
    {
        // call TDA18218CalcMAINPLL function
        TDA18218CalcMAINPLL(tuner_card, uLO);

        // write main pll bytes
        if (bI2CEnabled)
        {
            if (TDA18218Write(tuner_card,0x08,6) != True)
                return False;
        }
    }

    //return value
    return True;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218WriteAGC1_TOP:
//
// DESCRIPTION: Send AGC1 TOP values from the table AGC1_TOP_Map in tmTDA18218
//
// RETURN:      True or False
//
// NOTES:   for multiFE
//-------------------------------------------------------------------------------------
//
static Bool TDA18218WriteAGC1_TOP (struct dvb_frontend * tuner_card)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;

    // write Gu
    I2CMap->uBx20.bF.AGC1_Gup_sel = 1;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;
    I2CMap->uBx21.bF.AGC1_Gud = (UInt8)AGC1_TOP_Map[0].uGu;
    if (TDA18218Write(tuner_card,0x21,1) != True) return False;

    // write Gd
    I2CMap->uBx20.bF.AGC1_Gup_sel = 0;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;
    I2CMap->uBx21.bF.AGC1_Gud = (UInt8)AGC1_TOP_Map[0].uGd;
    if (TDA18218Write(tuner_card,0x21,1) != True) return False;

    // write Au aud_sel au_ptr
    // write Au 0 3
    //for ES3 compatible ES2
    I2CMap->uBx1F.bF.AGC1_aud_sel = 0;
    I2CMap->uBx1F.bF.AGC1_au_ptr = 3;
    if (TDA18218Write(tuner_card,0x1F,1) != True) return False;
    I2CMap->uBx20.bF.AGC1_aud = (UInt8)AGC1_TOP_Map[0].uAu12;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;

    // write Au 0 1
    I2CMap->uBx1F.bF.AGC1_aud_sel = 0;
    I2CMap->uBx1F.bF.AGC1_au_ptr = 1;
    if (TDA18218Write(tuner_card,0x1F,1) != True) return False;
    //for ES2
    //I2CMap->AGC1_aud = AGC1_TOP_Map[0].uAu9;
    //for ES3 compatible ES2
    I2CMap->uBx20.bF.AGC1_aud = (UInt8)AGC1_TOP_Map[0].uAu6;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;

    // write Au 0 2
    I2CMap->uBx1F.bF.AGC1_aud_sel = 0;
    I2CMap->uBx1F.bF.AGC1_au_ptr = 2;
    if (TDA18218Write(tuner_card,0x1F,1) != True) return False;
    //for ES2
    //I2CMap->AGC1_aud = AGC1_TOP_Map[0].uAu12;
    //for ES3 compatible ES2
    I2CMap->uBx20.bF.AGC1_aud = (UInt8)AGC1_TOP_Map[0].uAu9;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;

    // write Ad 1 3
    //for ES3 compatible ES2
    I2CMap->uBx1F.bF.AGC1_aud_sel = 1;
    I2CMap->uBx1F.bF.AGC1_au_ptr = 3;
    if (TDA18218Write(tuner_card,0x1F,1) != True) return False;
    //for ES3 compatible ES2
    I2CMap->uBx20.bF.AGC1_aud = (UInt8)AGC1_TOP_Map[0].uAd12;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;

    // write Ad 1 1
    I2CMap->uBx1F.bF.AGC1_aud_sel = 1;
    I2CMap->uBx1F.bF.AGC1_au_ptr=1;
    if (TDA18218Write(tuner_card,0x1F,1) != True) return False;

    //for ES3 compatible ES2
    I2CMap->uBx20.bF.AGC1_aud = (UInt8)AGC1_TOP_Map[0].uAd9;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;

    // write Ad 1 2
    I2CMap->uBx1F.bF.AGC1_aud_sel = 1;
    I2CMap->uBx1F.bF.AGC1_au_ptr=2;
    if (TDA18218Write(tuner_card,0x1F,1) != True) return False;
    //for ES2
    //for ES3 compatible ES2
    I2CMap->uBx20.bF.AGC1_aud = (UInt8)AGC1_TOP_Map[0].uAd15;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;

    return True;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218WriteAGC2_TOP:
//
// DESCRIPTION: Send AGC2b TOP values from the table AGC2_TOP_Map in tmTDA18218
//
// RETURN:      True or False
//
// NOTES:    for MultiFE
//-------------------------------------------------------------------------------------
//
static Bool TDA18218WriteAGC2_TOP (struct dvb_frontend * tuner_card, UInt8 uBPIndex)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;

    // write Gu2
    I2CMap->uBx20.bF.AGC2_RAM_sel = 1;
    I2CMap->uBx20.bF.AGC2_Gup_sel = 1;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;
    I2CMap->uBx23.bF.AGC2_Gud = (UInt8)AGC2_TOP_Map[uBPIndex].uGu2;
    if (TDA18218Write(tuner_card,0x23,1) != True) return False;

    // write Gu3
    I2CMap->uBx20.bF.AGC2_RAM_sel = 2;
    I2CMap->uBx20.bF.AGC2_Gup_sel = 1;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;
    I2CMap->uBx23.bF.AGC2_Gud = (UInt8)AGC2_TOP_Map[uBPIndex].uGu3;
    if (TDA18218Write(tuner_card,0x23,1) != True) return False;

    // write Gu4
    I2CMap->uBx20.bF.AGC2_RAM_sel = 3;
    I2CMap->uBx20.bF.AGC2_Gup_sel = 1;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;
    I2CMap->uBx23.bF.AGC2_Gud = (UInt8)AGC2_TOP_Map[uBPIndex].uGu4;
    if (TDA18218Write(tuner_card,0x23,1) != True) return False;

    // write Gd2
    I2CMap->uBx20.bF.AGC2_RAM_sel = 1;
    I2CMap->uBx20.bF.AGC2_Gup_sel = 0;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;
    I2CMap->uBx23.bF.AGC2_Gud = (UInt8)AGC2_TOP_Map[uBPIndex].uGd2;
    if (TDA18218Write(tuner_card,0x23,1) != True) return False;

    // write Gd3
    I2CMap->uBx20.bF.AGC2_RAM_sel = 2;
    I2CMap->uBx20.bF.AGC2_Gup_sel = 0;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;
    I2CMap->uBx23.bF.AGC2_Gud = (UInt8)AGC2_TOP_Map[uBPIndex].uGd3;
    if (TDA18218Write(tuner_card,0x23,1) != True) return False;

    // write Gd4
    I2CMap->uBx20.bF.AGC2_RAM_sel = 3;
    I2CMap->uBx20.bF.AGC2_Gup_sel = 0;
    if (TDA18218Write(tuner_card,0x20,1) != True) return False;
    I2CMap->uBx23.bF.AGC2_Gud = (UInt8)AGC2_TOP_Map[uBPIndex].uGd4;
    if (TDA18218Write(tuner_card,0x23,1) != True) return False;

    return True;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218ResetAGC:
//
// DESCRIPTION: resets AGC1 & AGC2
//
// RETURN:   true or false
//
// NOTES:  for MultiFE
//-------------------------------------------------------------------------------------
static Bool TDA18218ResetAGC (struct dvb_frontend * tuner_card)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;
#pragma region TDA18218_DEBUG
#if 0
    UInt8 tmp_AGC_On = 0;
    UInt8 tmp_pdAGC2_DETECT2 = 0;
    UInt8 tmp_pdAGC2_DETECT3 = 0;
    UInt8 tmp_pdAGC2_DETECT4 = 0;


    // store values
    tmp_AGC_On = I2CMap->uBx1C.bF.AGC_On;
    tmp_pdAGC2_DETECT2 = I2CMap->uBx1C.bF.pdAGC2_DETECT2;
    tmp_pdAGC2_DETECT3 = I2CMap->uBx1C.bF.pdAGC2_DETECT3;
    tmp_pdAGC2_DETECT4 = I2CMap->uBx1C.bF.pdAGC2_DETECT4;

    // force values
    I2CMap->uBx1C.bF.pdAGC2_DETECT2 = (priv->Config_Instance.ChannelType == tmTDA18218AnalogChannel) ? 1 : 0;
    I2CMap->uBx1C.bF.pdAGC2_DETECT3 = (priv->Config_Instance.ChannelType == tmTDA18218AnalogChannel) ? 1 : 0;
    I2CMap->uBx1C.bF.pdAGC2_DETECT4 = (priv->Config_Instance.ChannelType == tmTDA18218AnalogChannel) ? 1 : 0;
#endif
#pragma endregion

    // start AGC clock
    I2CMap->uBx1C.bF.AGC_On = 1;
    if (TDA18218Write(tuner_card,0x1C,1) != True)    return False;

    // configure AGC1 (bypass on; speed = 62,5 KHz)
    I2CMap->uBx18.bF.pdDETECT1 = 0;
    if (TDA18218Write(tuner_card,0x18,1) != True)    return False;
    I2CMap->uBx22.bF.AGC1_bypass = 1;
    I2CMap->uBx22.bF.AGC1_Speed_Up = 1;
    I2CMap->uBx22.bF.AGC1_Speed_Do = 1;
    I2CMap->uBx22.bF.AGC1_loop_off = 0;
    if (TDA18218Write(tuner_card,0x22,1) != True)    return False;
    I2CMap->uBx1F.bF.AGC1_Speed = 1;   //@1F
    if (TDA18218Write(tuner_card,0x1F,1) != True)    return False;

    if (TDA18218Write(tuner_card,0x24,1) != True)    return False;

    // stop AGC clock
    I2CMap->uBx1C.bF.AGC_On = 0;
    if (TDA18218Write(tuner_card,0x1C,1) != True)    return False;

    // write AGC1 tops
    TDA18218WriteAGC1_TOP(tuner_card);

    // write AGC2 tops
    TDA18218WriteAGC2_TOP(tuner_card,6);

    // start AGC clock
    I2CMap->uBx1C.bF.AGC_On = 1;
    if (TDA18218Write(tuner_card,0x1C,1) != True)    return False;
    msleep(1);

    // configure AGC1 (bypass off; speed = 62,5 KHz)
    I2CMap->uBx22.bF.AGC1_bypass = 0;
    if (TDA18218Write(tuner_card,0x22,1) != True)    return False;

    msleep(300);

    return True;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218CalPOR:
//
// DESCRIPTION: RF tracking filter POR calibration
//
// RETURN:   true or false
//
// NOTES:
//-------------------------------------------------------------------------------------
static Bool TDA18218CalPOR (struct dvb_frontend * tuner_card)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;
    UInt8 updAGC1b;
    UInt8 uRFSW_AGC1b_out;

#if 0
#pragma region TDA18218_DEBUG
    UInt8 bTempRSSI = 0;
    UInt8 bTempCAL_Int = 0;

    // store values
    bTempRSSI = I2CMap->uBx27.RSSI_byte;
    bTempCAL_Int = I2CMap->uBx11.CAL_Int;

    // force values
    I2CMap->uBx27.RSSI_byte = 0xDE;            // @ 0x27
    if (TDA18218Write(tuner_card,0x27,1) != True)    return False;
    I2CMap->uBx11.CAL_Int = 0x13;            // @ 0x11
    if (TDA18218Write(tuner_card,0x11,1) != True)    return False;
#pragma endregion
#endif

    ///////////////////////////// switch off AGC1b
    // store pdAGC1b current value
    updAGC1b = I2CMap->uBx17.bF.pdAGC1b;
    // update & write pdAGC1b to 1
    I2CMap->uBx17.bF.pdAGC1b = 0x01;
    if (TDA18218Write(tuner_card, 0x17, 1) != True)    return False;

    ///////////////////////////// switch off RFSW_AGC1b_out
    // store RFSW_AGC1b_out current value
    uRFSW_AGC1b_out = I2CMap->uBx18.bF.RFSW_AGC1b_out;
    // update & write RFSW_AGC1b_out to 0
    I2CMap->uBx18.bF.RFSW_AGC1b_out = 0x00;
    if (TDA18218Write(tuner_card, 0x18, 1) != True)    return False;

    ///////////////////////////// clear flags
    // update & write FlagClear to 1
    I2CMap->uBx05.bF.FlagClear = 0x01;
    if (TDA18218Write(tuner_card, 0x05, 1) != True)    return False;
    // update & write FlagClear to 0
    I2CMap->uBx05.bF.FlagClear = 0x00;
    if (TDA18218Write(tuner_card, 0x05, 1) != True)    return False;
    // select RFCalPOR mode
    I2CMap->uBx19.bF.hc_mode = 0x03;
    if (TDA18218Write(tuner_card, 0x19, 1) != True)    return False;

    ///////////////////////////// launch msm
    // update & write launch_msm to 1
    I2CMap->uBx05.bF.launch_msm = 0x01;
    if (TDA18218Write(tuner_card, 0x05, 1) != True)    return False;
    // update & write launch_msm to 0
    I2CMap->uBx05.bF.launch_msm = 0x00;
    if (TDA18218Write(tuner_card, 0x05, 1) != True)    return False;

    ///////////////////////////// wait 200 ms
    msleep(150);

    ///////////////////////////// restore AGC1b
    // update & write pdAGC1b to previous value
    I2CMap->uBx17.bF.pdAGC1b = updAGC1b;
    if (TDA18218Write(tuner_card, 0x17, 1) != True)    return False;

    // update & write RFSW_AGC1b_out to previous value
    I2CMap->uBx18.bF.RFSW_AGC1b_out = uRFSW_AGC1b_out;
    if (TDA18218Write(tuner_card, 0x18, 1) != True)    return False;
#if 0
#pragma region TDA18218_DEBUG
    // Restore values
    I2CMap->uBx27.RSSI_byte = bTempRSSI;
    if (TDA18218Write(tuner_card,0x27,1) != True)    return False;
    I2CMap->uBx11.CAL_Int = bTempCAL_Int;
    if (TDA18218Write(tuner_card,0x11,1) != True)    return False;
#pragma endregion
#endif

    ///////////////////////////// select Normal mode
    I2CMap->uBx19.bF.hc_mode = 0x00;
    if (TDA18218Write(tuner_card, 0x19, 1) != True)    return False;

    ///////////////////////////// launch msm
    // update & write launch_msm to 1
    I2CMap->uBx05.bF.launch_msm = 0x01;
    if (TDA18218Write(tuner_card, 0x05, 1) != True)    return False;
    // update & write launch_msm to 0
    I2CMap->uBx05.bF.launch_msm = 0x00;
    if (TDA18218Write(tuner_card, 0x05, 1) != True)    return False;

    return True;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218CalAV:
//
// DESCRIPTION: RF tracking filter AV calibration
//
// RETURN:   true or false
//
// NOTES:
//-------------------------------------------------------------------------------------
static Bool TDA18218CalAV (struct dvb_frontend * tuner_card)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;
    UInt8 bTempo = 0;

#pragma region TDA18218_DEBUG
    UInt8 bTempRSSI = 0;
    UInt8 bTempCAL_Int = 0;
    UInt8 bTempAGC2b_byte = 0;

    // store values
    bTempRSSI = I2CMap->uBx27.RSSI_byte;
    bTempCAL_Int = I2CMap->uBx11.CAL_Int;
    bTempAGC2b_byte = I2CMap->uBx1C.AGC2b_byte;

    // force values
    I2CMap->uBx27.RSSI_byte = 0xDE;            // @ 0x27
    if (TDA18218Write(tuner_card,0x27,1) != True) return False;
    I2CMap->uBx11.CAL_Int = 0x13;            // @ 0x11
    if (TDA18218Write(tuner_card,0x11,1) != True)    return False;
#pragma endregion

    ///////////////////////////// clear flags
    // update & write FlagClear to 1
    I2CMap->uBx05.bF.FlagClear = 0x01;
    if (TDA18218Write(tuner_card, 0x05, 1)!= True)    return False;
    // update & write FlagClear to 0
    I2CMap->uBx05.bF.FlagClear = 0x00;
    if (TDA18218Write(tuner_card, 0x05, 1)!= True)    return False;

    ///////////////////////////// Work around for ES2
    I2CMap->uBx28.bF.Force_Lock = 0x01;
    if (TDA18218Write(tuner_card, 0x28, 1)!= True)    return False;

    ///////////////////////////// select RFCalAV mode
    I2CMap->uBx19.bF.hc_mode = 0x04;
    if (TDA18218Write(tuner_card, 0x19, 1)!= True)    return False;

    ///////////////////////////// launch msm
    // update & write launch_msm to 1
    I2CMap->uBx05.bF.launch_msm = 0x01;
    if (TDA18218Write(tuner_card, 0x05, 1)!= True)    return False;
    // update & write launch_msm to 0
    I2CMap->uBx05.bF.launch_msm = 0x00;
    if (TDA18218Write(tuner_card, 0x05, 1)!= True)    return False;

    ///////////////////////////// wait
    bTempo = 3 + (2 * I2CMap->uBx32.bF.NmeasAV);
    msleep(bTempo);

    ///////////////////////////// select Normal mode
    I2CMap->uBx19.bF.hc_mode = 0x00;
    if (TDA18218Write(tuner_card, 0x19, 1)!= True)    return False;

    // Speed up the RFAGC setting
    I2CMap->uBx1C.bF.pulse_up_auto = 0;
    I2CMap->uBx1C.bF.pulse_up_width = 0;
    if (TDA18218Write(tuner_card,0x1C,1) != True)    return False;

    ///////////////////////////// launch msm
    // update & write launch_msm to 1
    I2CMap->uBx05.bF.launch_msm = 0x01;
    if (TDA18218Write(tuner_card, 0x05, 1)!= True)    return False;
    // update & write launch_msm to 0
    I2CMap->uBx05.bF.launch_msm = 0x00;
    if (TDA18218Write(tuner_card, 0x05, 1)!= True)    return False;
    // a waiting time of 11ms to pre-position RFAGC (first call to CALAV), done in Setrf
    // no waiting time if the RFAGC is already pre-positioned (second call to CALAV)

    // Work around for ES2
    I2CMap->uBx28.bF.Force_Lock = 0x00;
    if (TDA18218Write(tuner_card, 0x28, 1)!= True)    return False;

#pragma region TDA18218_DEBUG
    // Restore values
    I2CMap->uBx1C.AGC2b_byte = bTempAGC2b_byte;
    if (TDA18218Write(tuner_card,0x1C,1) != True)    return False;
    I2CMap->uBx27.RSSI_byte = bTempRSSI;
    if (TDA18218Write(tuner_card,0x27,1) != True)    return False;
    I2CMap->uBx11.CAL_Int = bTempCAL_Int;
    if (TDA18218Write(tuner_card,0x11,1) != True)    return False;
#pragma endregion

    return True;
}

//-------------------------------------------------------------------------------------
// FUNCTION:    TDA18218SetRFIO:
//
// DESCRIPTION: Set the input and output configuration of first tuner amplifier
//
// RETURN:   true or false
//
// NOTES:  for internal
//-------------------------------------------------------------------------------------
static Bool TDA18218SetRFIO(struct dvb_frontend * tuner_card, enum TDA18218RFIOConfig Index)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;

    switch(Index)
    {
    case tmTDA18218Single_HZin_noLTO:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 0;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Single_HZin_LTOonMTO:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 0;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Single_HZin_LTOonLT_test:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 0;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 0;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Single_RFin_noLTO:
        I2CMap->uBx17.bF.pdHZlna = 1;
        I2CMap->uBx17.bF.pdAGC1a = 1;
        I2CMap->uBx17.bF.pdAGC1b = 0;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 1;
        break;

    case tmTDA18218Single_RFin_LTOonLT:
        I2CMap->uBx17.bF.pdHZlna = 1;
        I2CMap->uBx17.bF.pdAGC1a = 1;
        I2CMap->uBx17.bF.pdAGC1b = 0;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 1;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 1;
        break;

    case tmTDA18218Single_Rfin_LTOonMTO_test:
        I2CMap->uBx17.bF.pdHZlna = 1;
        I2CMap->uBx17.bF.pdAGC1a = 1;
        I2CMap->uBx17.bF.pdAGC1b = 0;
        I2CMap->uBx17.bF.pdLT = 0;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 1;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 1;
        break;

    case tmTDA18218Master_HZin_noLTO:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 0;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Master_HZin_LTOonMTO:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 0;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Master_HZin_LTOonLT_test:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 0;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 0;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Master_RFin_noLTO:
        I2CMap->uBx17.bF.pdHZlna = 1;
        I2CMap->uBx17.bF.pdAGC1a = 1;
        I2CMap->uBx17.bF.pdAGC1b = 0;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 1;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 1;
        break;

    case tmTDA18218Master_RFin_LTOonLT:
        I2CMap->uBx17.bF.pdHZlna = 1;
        I2CMap->uBx17.bF.pdAGC1a = 1;
        I2CMap->uBx17.bF.pdAGC1b = 0;
        I2CMap->uBx17.bF.pdLT = 0;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 1;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 1;
        break;

    case tmTDA18218Master_Rfin_LTOonMTO_test:
        I2CMap->uBx17.bF.pdHZlna = 1;
        I2CMap->uBx17.bF.pdAGC1a = 1;
        I2CMap->uBx17.bF.pdAGC1b = 0;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 1;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 1;
        break;

    case tmTDA18218Slave_M_HZin_noLTO:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 0;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Slave_M_HZin_LTOonMTO:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 0;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Slave_M_HZin_LTOonLT_test:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 0;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 0;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 0;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Slave_M_RFin_noLTO:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 1;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 1;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Slave_M_RFin_LTOonLT:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 1;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 0;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 1;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    case tmTDA18218Slave_M_Rfin_LTOonMTO_test:
        I2CMap->uBx17.bF.pdHZlna = 0;
        I2CMap->uBx17.bF.pdAGC1a = 1;
        I2CMap->uBx17.bF.pdAGC1b = 1;
        I2CMap->uBx17.bF.pdLT = 1;
        I2CMap->uBx18.bF.pdDETECT1 = 0;
        I2CMap->uBx18.bF.RFSW_MTO_LT_Hzin = 1;
        I2CMap->uBx18.bF.RFSW_MTO_LT_RFin = 0;
        I2CMap->uBx18.bF.RFSW_Buf1_out = 1;
        I2CMap->uBx18.bF.RFSW_AGC1b_out = 0;
        break;

    default:
        break;
    }

    // write bytes 0x17 to 0x18
    if (TDA18218Write(tuner_card,0x17,2) != True)
        return False;

    // store RFIO config
    priv->Config_Instance.RFIOConfig = Index;

    return True;
}

//-------------------------------------------------------------------------------------
// FUNCTION:   TDA18218IRCalibration:
//
// DESCRIPTION: Launch the procedure of IR calibration. It should be done once at the power up of the tuner
//
// RETURN:      True or False
//
// NOTES:
//-------------------------------------------------------------------------------------
//
static Bool TDA18218IRCalibration (struct dvb_frontend * tuner_card)
{
    UInt32 uRF;
    UInt8 Index = 0;
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;

    // force values
    //Init before calibration
    I2CMap->uBx27.RSSI_byte = 0xDE;            // @ 0x27
    if (TDA18218Write(tuner_card,0x27,1) != True)    return False;
    I2CMap->uBx17.Power_Down_byte_1 = 0xF8;    // @ 0x17
    if (TDA18218Write(tuner_card,0x17,1) != True)    return False;
    I2CMap->uBx18.Power_Down_byte_2 = 0x0F;    // @ 0x18
    if (TDA18218Write(tuner_card,0x18,1) != True)    return False;
    I2CMap->uBx1C.AGC2b_byte = 0x8B;            // @ 0x1C
    if (TDA18218Write(tuner_card,0x1C,1) != True)    return False;

    // 1st step IRCAL wanted
    I2CMap->uBx29.bF.IR_Freq = 2;            // @ 0x29
    if (TDA18218Write(tuner_card,0x29,1) != True)    return False;
    I2CMap->uBx19.bF.hc_mode = 1;            // @ 0x19
    if (TDA18218Write(tuner_card,0x19,1) != True)    return False;
    I2CMap->uBx11.CAL_Int = 0x13;        // @ 0x11, 19x64kHz = 1,216 MHz
    if (TDA18218Write(tuner_card,0x11,1) != True)    return False;
    uRF = IR_Map[1].uRF_Max;
    I2CMap->uBx0A.LO_Frac_31_to_24 = (UInt8)(uRF >> 12);
    I2CMap->uBx0B.LO_Frac_23_to_16 = (UInt8)(uRF >> 4);
    I2CMap->uBx0C.bF.LO_Frac_15_to_12 = (UInt8)(uRF);
    if (TDA18218Write(tuner_card,0x0A,3) != True)    return False;
    I2CMap->uBx0F.bF.Freq_prog_Start = 1; // @ 0x0F
    if (TDA18218Write(tuner_card,0x0F,1) != True)    return False;
    msleep(5);

    I2CMap->uBx05.bF.FlagClear = 1;            // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.FlagClear = 0;        // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.launch_msm = 1;        // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.launch_msm = 0;
    msleep(1);
    if (TDA18218Read(tuner_card,0x00,7) != True)    return False;
    if (I2CMap->uBx05.bF.FlagMSM_OK != 1)   return False;

    // Image
    I2CMap->uBx11.CAL_Int = (UInt8)0xED;        // @ 0x11, -19x64kHz = -1,216 MHz
    if (TDA18218Write(tuner_card,0x11,1) != True)    return False;
    I2CMap->uBx0F.bF.Freq_prog_Start = 1; // @ 0x0F
    if (TDA18218Write(tuner_card,0x0F,1) != True)    return False;
    msleep(5);
    I2CMap->uBx19.bF.hc_mode = 2;            // @ 0x19
    if (TDA18218Write(tuner_card,0x19,1) != True)    return False;

    I2CMap->uBx05.bF.FlagClear = 1;            // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.FlagClear = 0;        // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.launch_msm = 1;        // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.launch_msm = 0;
    msleep(40);
    if (TDA18218Read(tuner_card,0x00,7) != True)    return False;
    if (I2CMap->uBx05.bF.FlagMSM_OK != 1) return False;

    // 2nd step IRCAL wanted
    I2CMap->uBx29.bF.IR_Freq = 3;            // @ 0x29
    if (TDA18218Write(tuner_card,0x29,1) != True)    return False;
    I2CMap->uBx19.bF.hc_mode = 1;            // @ 0x19
    if (TDA18218Write(tuner_card,0x19,1) != True)    return False;
    I2CMap->uBx11.CAL_Int = 0x13;        // @ 0x11, 19x64kHz = 1,216 MHz
    if (TDA18218Write(tuner_card,0x11,1) != True)    return False;
    uRF = IR_Map[2].uRF_Max;
    I2CMap->uBx0A.LO_Frac_31_to_24 = (UInt8)(uRF >> 12);
    I2CMap->uBx0B.LO_Frac_23_to_16 = (UInt8)(uRF >> 4);
    I2CMap->uBx0C.bF.LO_Frac_15_to_12 = (UInt8)(uRF);
    if (TDA18218Write(tuner_card,0x0A,3) != True)    return False;
    I2CMap->uBx0F.bF.Freq_prog_Start = 1; // @ 0x0F
    if (TDA18218Write(tuner_card,0x0F,1) != True)    return False;
    msleep(5);

    I2CMap->uBx05.bF.FlagClear = 1;            // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.FlagClear = 0;        // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.launch_msm = 1;        // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.launch_msm = 0;
    msleep(1);
    if (TDA18218Read(tuner_card,0x00,7) != True)    return False;
    if (I2CMap->uBx05.bF.FlagMSM_OK != 1) return False;

    // Image
    I2CMap->uBx11.CAL_Int = (UInt8)0xED;        // @ 0x11, -19x64kHz = -1,216 MHz
    if (TDA18218Write(tuner_card,0x11,1) != True)    return False;
    I2CMap->uBx0F.bF.Freq_prog_Start = 1; // @ 0x0F
    if (TDA18218Write(tuner_card,0x0F,1) != True)    return False;
    msleep(5);
    I2CMap->uBx19.bF.hc_mode = 2;            // @ 0x19
    if (TDA18218Write(tuner_card,0x19,1) != True)    return False;

    I2CMap->uBx05.bF.FlagClear = 1;            // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.FlagClear = 0;        // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.launch_msm = 1;        // @ 0x05
    if (TDA18218Write(tuner_card,0x05,1) != True)    return False;
    I2CMap->uBx05.bF.launch_msm = 0;
    msleep(40);
    if (TDA18218Read(tuner_card,0x00,7) != True)    return False;
    if (I2CMap->uBx05.bF.FlagMSM_OK != 1)            return False;

    I2CMap->uBx19.bF.hc_mode = 0;            // @ 0x19
    if (TDA18218Write(tuner_card,0x19,1) != True)    return False;

    // restore values
    I2CMap->uBx27.RSSI_byte = 0xC9;            // @ 0x27
    if (TDA18218Write(tuner_card,0x27,1) != True)    return False;
    I2CMap->uBx11.CAL_Int = 0x13;
    I2CMap->uBx17.Power_Down_byte_1 = 0xF0;
    I2CMap->uBx18.Power_Down_byte_2 = 0x19;
    I2CMap->uBx1C.AGC2b_byte = 0x98;
    if (TDA18218Write(tuner_card,0x11,1) != True)    return False;
    if (TDA18218Write(tuner_card,0x17,2) != True)    return False;
    if (TDA18218Write(tuner_card,0x1C,1) != True)    return False;


    // Save initial calibration coefficient
    I2CMap->uBx29.bF.IR_Freq = 3;
    if (TDA18218Write(tuner_card,0x29,1) != True)    return False;
    for (Index=0 ;Index<4; Index++) {
        I2CMap->uBx2A.bF.Ptr_Rx_Read = Index;
        if (TDA18218Write(tuner_card, 0x2A, 1) != True)    return False;
        if (TDA18218Read(tuner_card, 0x00, 59) != True)    return False;
        priv->Config_Instance.IRCoefHighF[Index] = I2CMap->uBx2B.bF.Rx_W;
    }

    return True;
}

//-------------------------------------------------------------------------------------
// FUNCTION:   TDA18218WriteTrimIRCal:
//
// DESCRIPTION: Write the trim values of IR cal
//
// RETURN:      true or false
//
// NOTES:
//-------------------------------------------------------------------------------------
//
static Bool TDA18218WriteTrimIRCal (struct dvb_frontend * tuner_card)
{
    struct tda18218_priv * priv = tuner_card->tuner_priv;
    tmTDA18218I2CMap_t * I2CMap = (tmTDA18218I2CMap_t *)priv->tda18218_regs;

    I2CMap->uBx2B.bF.Rx_ptrW = 0;
    if (TDA18218Write(tuner_card,0x2A,1) != True)    return False;
    I2CMap->uBx2B.bF.Rx_W = (UInt8)IR_Rx_Map[0].uR2I;
    if (TDA18218Write(tuner_card,0x2B,1) != True)    return False;
    I2CMap->uBx2B.bF.Rx_ptrW = 1;
    if (TDA18218Write(tuner_card,0x2A,1) != True)    return False;
    I2CMap->uBx2B.bF.Rx_W = (UInt8)IR_Rx_Map[0].uR2Q;
    if (TDA18218Write(tuner_card,0x2B,1) != True)    return False;
    I2CMap->uBx2B.bF.Rx_ptrW = 2;
    if (TDA18218Write(tuner_card,0x2A,1) != True)    return False;
    I2CMap->uBx2B.bF.Rx_W = (UInt8)IR_Rx_Map[0].uR3IQ;
    if (TDA18218Write(tuner_card,0x2B,1) != True)    return False;
    I2CMap->uBx2B.bF.Rx_ptrW = 3;
    if (TDA18218Write(tuner_card,0x2A,1) != True)    return False;
    I2CMap->uBx2B.bF.Rx_W = (UInt8)IR_Rx_Map[0].uR3InQ;
    if (TDA18218Write(tuner_card,0x2B,1) != True)    return False;

    return True;
}

/**
 * Set frequency, operating mode, bandwidth
 *
 * @param fe frontend
 * @param params ptr to structure with settings
 * @return 0:success >0:invalid value or operation
 */
static int tda18218_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
    struct tda18218_priv *priv = fe->tuner_priv;
    int bw = 0;

    dprintk("%s(%d)\n", __FUNCTION__, __LINE__);

    // First-time initialisation
    if (!priv->init) {
        TDA18218Init(fe);
        priv->init = 1;
    }

    // Check parameters
    if (priv == NULL || params == NULL)
    {
        dprintk("%s: %s NULL\n", __FUNCTION__, (priv == NULL) ? "fe->priv" : "params");
        return -EINVAL;
    }

    // Set operating mode & bandwidth from fe info
    // @todo determine how to deal with other modes
    switch (fe->ops.info.type)
    {
        case FE_OFDM:
            switch (params->u.ofdm.bandwidth) {
                    case BANDWIDTH_6_MHZ:
                        TDA18218SetStandardMode(fe,tmTDA18218DigitalChannel_6MHz);
                        bw = 6000000;
                        break;
                    case BANDWIDTH_7_MHZ:
                        TDA18218SetStandardMode(fe,tmTDA18218DigitalChannel_7MHz);
                        bw = 7000000;
                        break;
                    case BANDWIDTH_8_MHZ:
                        TDA18218SetStandardMode(fe,tmTDA18218DigitalChannel_8MHz);
                        bw = 8000000;
                        break;
                    default:
                        dprintk("%s: invalid OFDM setting\n", __FUNCTION__);
                        return -EINVAL;
                    }
            break;
        case FE_ATSC:
        case FE_QPSK:
        case FE_QAM:
        default:
            dprintk("%s: invalid fe type\n", __FUNCTION__);
            return -EINVAL;
    }

    dprintk("\n%s: freq: '%d', bw: '%d', if: '%d'\n", __FUNCTION__, params->frequency, bw, priv->Config_Instance.uIF);

    // tune to frequency
    TDA18218SetRf(fe, params->frequency); // freq supplied is in Hz
    // save settings
    priv->frequency = params->frequency;
    priv->bandwidth = bw;

    dprintk("%s(%d): Pll lock:%c RF cal:%c IR cal:%c\n", __FUNCTION__, __LINE__, (priv->tda18218_regs[1] & 0x40) ? 'y' : 'n', (priv->tda18218_regs[3] & 0x10) ? 'y' : 'n', (priv->tda18218_regs[3] & 0x08) ? 'y' : 'n');

    return 0;
}

/**
 * Driver release
 * @param fe frontend
 * @return 0:success
 */
static int tda18218_release(struct dvb_frontend *fe)
{

    dprintk("%s(%d)\n", __FUNCTION__, __LINE__);

    if (fe != NULL)
    {
        kfree(fe->tuner_priv);
        fe->tuner_priv = NULL;
    }

    return 0;
}

/**
 * Report tuned frequency
 * @param fe frontend
 * @param frequency location in which tuned frequency is returned (non-NULL)
 * @return 0:success
 */
int tda18218_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
    struct tda18218_priv *priv = fe->tuner_priv;

    dprintk("%s(%d): frequency %d\n", __FUNCTION__, __LINE__, priv->frequency);

    *frequency = priv->frequency;
    return 0;
}

/**
 * Report set bandwidth
 * @param fe frontend
 * @param bandwidth location in which configured bandwidth is returned (non-NULL)
 * @return 0:success
 */
static int tda18218_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
{
    struct tda18218_priv *priv = fe->tuner_priv;

    dprintk("%s(%d)\n", __FUNCTION__, __LINE__);

    *bandwidth = priv->bandwidth;
    return 0;
}

/**
 * Standard tuner operations
 */
static struct dvb_tuner_ops tda18218_tuner_ops = {
    .info =
    {
        .name = "NXP TDA18218",
        .frequency_min  = 174000000,
        .frequency_max  = 864000000,
        .frequency_step = 8000000
    },
    .set_params        = tda18218_set_params,
    .get_frequency     = tda18218_get_frequency,
    .get_bandwidth     = tda18218_get_bandwidth,
    .release           = tda18218_release,
};

/**
 * Allocate memory for tuner private data and ops, attach to frontend
 *
 * @param fe frontend to attach to
 * @param addr I2C address
 * @param i2c I2C bus
 */
struct dvb_frontend * tda18218_attach(struct dvb_frontend * fe, u8 i2c_addr, struct i2c_adapter * i2c_adap)
{
    struct tda18218_priv * priv;
    int i = 0;

    priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
    if (priv == NULL)
    {
        return NULL;
    }

    priv->i2c_addr = i2c_addr;
    priv->i2c_adapt = i2c_adap;
    /* Static Configuration */
    priv->Config_Instance.RFIOConfig = tmTDA18218Single_RFin_noLTO;
    priv->Config_Instance.StandardMode = tmTDA18218DigitalChannel_8MHz;
    priv->Config_Instance.ChannelType = tmTDA18218DigitalChannel;
    priv->Config_Instance.DeviceType  = tmTDA18218MasterDeviceWithoutLT;
    priv->Config_Instance.uRF = 511250000;
    priv->Config_Instance.uIF = 4000000;
    priv->Config_Instance.uBW = 6000000;

    memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops, sizeof(tda18218_tuner_ops));

    fe->tuner_priv = priv;

    return fe;
}

module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, " Turn on (=1) debugging. Default off (=0).");

EXPORT_SYMBOL(tda18218_attach);

MODULE_DESCRIPTION("NXP TDA182182");
MODULE_AUTHOR("NXP");
MODULE_LICENSE("GPL");
