Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Driver for mt2063 Micronas tuner
0004  *
0005  * Copyright (c) 2011 Mauro Carvalho Chehab
0006  *
0007  * This driver came from a driver originally written by:
0008  *      Henry Wang <Henry.wang@AzureWave.com>
0009  * Made publicly available by Terratec, at:
0010  *  http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
0011  */
0012 
0013 #include <linux/init.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/string.h>
0017 #include <linux/videodev2.h>
0018 #include <linux/gcd.h>
0019 
0020 #include "mt2063.h"
0021 
0022 static unsigned int debug;
0023 module_param(debug, int, 0644);
0024 MODULE_PARM_DESC(debug, "Set Verbosity level");
0025 
0026 #define dprintk(level, fmt, arg...) do {                \
0027 if (debug >= level)                         \
0028     printk(KERN_DEBUG "mt2063 %s: " fmt, __func__, ## arg); \
0029 } while (0)
0030 
0031 
0032 /* positive error codes used internally */
0033 
0034 /*  Info: Unavoidable LO-related spur may be present in the output  */
0035 #define MT2063_SPUR_PRESENT_ERR             (0x00800000)
0036 
0037 /*  Info: Mask of bits used for # of LO-related spurs that were avoided during tuning  */
0038 #define MT2063_SPUR_CNT_MASK                (0x001f0000)
0039 #define MT2063_SPUR_SHIFT                   (16)
0040 
0041 /*  Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
0042 #define MT2063_UPC_RANGE                    (0x04000000)
0043 
0044 /*  Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
0045 #define MT2063_DNC_RANGE                    (0x08000000)
0046 
0047 /*
0048  *  Constant defining the version of the following structure
0049  *  and therefore the API for this code.
0050  *
0051  *  When compiling the tuner driver, the preprocessor will
0052  *  check against this version number to make sure that
0053  *  it matches the version that the tuner driver knows about.
0054  */
0055 
0056 /* DECT Frequency Avoidance */
0057 #define MT2063_DECT_AVOID_US_FREQS      0x00000001
0058 
0059 #define MT2063_DECT_AVOID_EURO_FREQS    0x00000002
0060 
0061 #define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
0062 
0063 #define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
0064 
0065 enum MT2063_DECT_Avoid_Type {
0066     MT2063_NO_DECT_AVOIDANCE = 0,               /* Do not create DECT exclusion zones.     */
0067     MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS,  /* Avoid US DECT frequencies.              */
0068     MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS,  /* Avoid European DECT frequencies.        */
0069     MT2063_AVOID_BOTH                   /* Avoid both regions. Not typically used. */
0070 };
0071 
0072 #define MT2063_MAX_ZONES 48
0073 
0074 struct MT2063_ExclZone_t {
0075     u32 min_;
0076     u32 max_;
0077     struct MT2063_ExclZone_t *next_;
0078 };
0079 
0080 /*
0081  *  Structure of data needed for Spur Avoidance
0082  */
0083 struct MT2063_AvoidSpursData_t {
0084     u32 f_ref;
0085     u32 f_in;
0086     u32 f_LO1;
0087     u32 f_if1_Center;
0088     u32 f_if1_Request;
0089     u32 f_if1_bw;
0090     u32 f_LO2;
0091     u32 f_out;
0092     u32 f_out_bw;
0093     u32 f_LO1_Step;
0094     u32 f_LO2_Step;
0095     u32 f_LO1_FracN_Avoid;
0096     u32 f_LO2_FracN_Avoid;
0097     u32 f_zif_bw;
0098     u32 f_min_LO_Separation;
0099     u32 maxH1;
0100     u32 maxH2;
0101     enum MT2063_DECT_Avoid_Type avoidDECT;
0102     u32 bSpurPresent;
0103     u32 bSpurAvoided;
0104     u32 nSpursFound;
0105     u32 nZones;
0106     struct MT2063_ExclZone_t *freeZones;
0107     struct MT2063_ExclZone_t *usedZones;
0108     struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
0109 };
0110 
0111 /*
0112  * Parameter for function MT2063_SetPowerMask that specifies the power down
0113  * of various sections of the MT2063.
0114  */
0115 enum MT2063_Mask_Bits {
0116     MT2063_REG_SD = 0x0040,     /* Shutdown regulator                 */
0117     MT2063_SRO_SD = 0x0020,     /* Shutdown SRO                       */
0118     MT2063_AFC_SD = 0x0010,     /* Shutdown AFC A/D                   */
0119     MT2063_PD_SD = 0x0002,      /* Enable power detector shutdown     */
0120     MT2063_PDADC_SD = 0x0001,   /* Enable power detector A/D shutdown */
0121     MT2063_VCO_SD = 0x8000,     /* Enable VCO shutdown                */
0122     MT2063_LTX_SD = 0x4000,     /* Enable LTX shutdown                */
0123     MT2063_LT1_SD = 0x2000,     /* Enable LT1 shutdown                */
0124     MT2063_LNA_SD = 0x1000,     /* Enable LNA shutdown                */
0125     MT2063_UPC_SD = 0x0800,     /* Enable upconverter shutdown        */
0126     MT2063_DNC_SD = 0x0400,     /* Enable downconverter shutdown      */
0127     MT2063_VGA_SD = 0x0200,     /* Enable VGA shutdown                */
0128     MT2063_AMP_SD = 0x0100,     /* Enable AMP shutdown                */
0129     MT2063_ALL_SD = 0xFF73,     /* All shutdown bits for this tuner   */
0130     MT2063_NONE_SD = 0x0000     /* No shutdown bits                   */
0131 };
0132 
0133 /*
0134  *  Possible values for MT2063_DNC_OUTPUT
0135  */
0136 enum MT2063_DNC_Output_Enable {
0137     MT2063_DNC_NONE = 0,
0138     MT2063_DNC_1,
0139     MT2063_DNC_2,
0140     MT2063_DNC_BOTH
0141 };
0142 
0143 /*
0144  *  Two-wire serial bus subaddresses of the tuner registers.
0145  *  Also known as the tuner's register addresses.
0146  */
0147 enum MT2063_Register_Offsets {
0148     MT2063_REG_PART_REV = 0,    /*  0x00: Part/Rev Code         */
0149     MT2063_REG_LO1CQ_1,     /*  0x01: LO1C Queued Byte 1    */
0150     MT2063_REG_LO1CQ_2,     /*  0x02: LO1C Queued Byte 2    */
0151     MT2063_REG_LO2CQ_1,     /*  0x03: LO2C Queued Byte 1    */
0152     MT2063_REG_LO2CQ_2,     /*  0x04: LO2C Queued Byte 2    */
0153     MT2063_REG_LO2CQ_3,     /*  0x05: LO2C Queued Byte 3    */
0154     MT2063_REG_RSVD_06,     /*  0x06: Reserved              */
0155     MT2063_REG_LO_STATUS,       /*  0x07: LO Status             */
0156     MT2063_REG_FIFFC,       /*  0x08: FIFF Center           */
0157     MT2063_REG_CLEARTUNE,       /*  0x09: ClearTune Filter      */
0158     MT2063_REG_ADC_OUT,     /*  0x0A: ADC_OUT               */
0159     MT2063_REG_LO1C_1,      /*  0x0B: LO1C Byte 1           */
0160     MT2063_REG_LO1C_2,      /*  0x0C: LO1C Byte 2           */
0161     MT2063_REG_LO2C_1,      /*  0x0D: LO2C Byte 1           */
0162     MT2063_REG_LO2C_2,      /*  0x0E: LO2C Byte 2           */
0163     MT2063_REG_LO2C_3,      /*  0x0F: LO2C Byte 3           */
0164     MT2063_REG_RSVD_10,     /*  0x10: Reserved              */
0165     MT2063_REG_PWR_1,       /*  0x11: PWR Byte 1            */
0166     MT2063_REG_PWR_2,       /*  0x12: PWR Byte 2            */
0167     MT2063_REG_TEMP_STATUS,     /*  0x13: Temp Status           */
0168     MT2063_REG_XO_STATUS,       /*  0x14: Crystal Status        */
0169     MT2063_REG_RF_STATUS,       /*  0x15: RF Attn Status        */
0170     MT2063_REG_FIF_STATUS,      /*  0x16: FIF Attn Status       */
0171     MT2063_REG_LNA_OV,      /*  0x17: LNA Attn Override     */
0172     MT2063_REG_RF_OV,       /*  0x18: RF Attn Override      */
0173     MT2063_REG_FIF_OV,      /*  0x19: FIF Attn Override     */
0174     MT2063_REG_LNA_TGT,     /*  0x1A: Reserved              */
0175     MT2063_REG_PD1_TGT,     /*  0x1B: Pwr Det 1 Target      */
0176     MT2063_REG_PD2_TGT,     /*  0x1C: Pwr Det 2 Target      */
0177     MT2063_REG_RSVD_1D,     /*  0x1D: Reserved              */
0178     MT2063_REG_RSVD_1E,     /*  0x1E: Reserved              */
0179     MT2063_REG_RSVD_1F,     /*  0x1F: Reserved              */
0180     MT2063_REG_RSVD_20,     /*  0x20: Reserved              */
0181     MT2063_REG_BYP_CTRL,        /*  0x21: Bypass Control        */
0182     MT2063_REG_RSVD_22,     /*  0x22: Reserved              */
0183     MT2063_REG_RSVD_23,     /*  0x23: Reserved              */
0184     MT2063_REG_RSVD_24,     /*  0x24: Reserved              */
0185     MT2063_REG_RSVD_25,     /*  0x25: Reserved              */
0186     MT2063_REG_RSVD_26,     /*  0x26: Reserved              */
0187     MT2063_REG_RSVD_27,     /*  0x27: Reserved              */
0188     MT2063_REG_FIFF_CTRL,       /*  0x28: FIFF Control          */
0189     MT2063_REG_FIFF_OFFSET,     /*  0x29: FIFF Offset           */
0190     MT2063_REG_CTUNE_CTRL,      /*  0x2A: Reserved              */
0191     MT2063_REG_CTUNE_OV,        /*  0x2B: Reserved              */
0192     MT2063_REG_CTRL_2C,     /*  0x2C: Reserved              */
0193     MT2063_REG_FIFF_CTRL2,      /*  0x2D: Fiff Control          */
0194     MT2063_REG_RSVD_2E,     /*  0x2E: Reserved              */
0195     MT2063_REG_DNC_GAIN,        /*  0x2F: DNC Control           */
0196     MT2063_REG_VGA_GAIN,        /*  0x30: VGA Gain Ctrl         */
0197     MT2063_REG_RSVD_31,     /*  0x31: Reserved              */
0198     MT2063_REG_TEMP_SEL,        /*  0x32: Temperature Selection */
0199     MT2063_REG_RSVD_33,     /*  0x33: Reserved              */
0200     MT2063_REG_RSVD_34,     /*  0x34: Reserved              */
0201     MT2063_REG_RSVD_35,     /*  0x35: Reserved              */
0202     MT2063_REG_RSVD_36,     /*  0x36: Reserved              */
0203     MT2063_REG_RSVD_37,     /*  0x37: Reserved              */
0204     MT2063_REG_RSVD_38,     /*  0x38: Reserved              */
0205     MT2063_REG_RSVD_39,     /*  0x39: Reserved              */
0206     MT2063_REG_RSVD_3A,     /*  0x3A: Reserved              */
0207     MT2063_REG_RSVD_3B,     /*  0x3B: Reserved              */
0208     MT2063_REG_RSVD_3C,     /*  0x3C: Reserved              */
0209     MT2063_REG_END_REGS
0210 };
0211 
0212 struct mt2063_state {
0213     struct i2c_adapter *i2c;
0214 
0215     bool init;
0216 
0217     const struct mt2063_config *config;
0218     struct dvb_tuner_ops ops;
0219     struct dvb_frontend *frontend;
0220 
0221     u32 frequency;
0222     u32 srate;
0223     u32 bandwidth;
0224     u32 reference;
0225 
0226     u32 tuner_id;
0227     struct MT2063_AvoidSpursData_t AS_Data;
0228     u32 f_IF1_actual;
0229     u32 rcvr_mode;
0230     u32 ctfilt_sw;
0231     u32 CTFiltMax[31];
0232     u32 num_regs;
0233     u8 reg[MT2063_REG_END_REGS];
0234 };
0235 
0236 /*
0237  * mt2063_write - Write data into the I2C bus
0238  */
0239 static int mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
0240 {
0241     struct dvb_frontend *fe = state->frontend;
0242     int ret;
0243     u8 buf[60];
0244     struct i2c_msg msg = {
0245         .addr = state->config->tuner_address,
0246         .flags = 0,
0247         .buf = buf,
0248         .len = len + 1
0249     };
0250 
0251     dprintk(2, "\n");
0252 
0253     msg.buf[0] = reg;
0254     memcpy(msg.buf + 1, data, len);
0255 
0256     if (fe->ops.i2c_gate_ctrl)
0257         fe->ops.i2c_gate_ctrl(fe, 1);
0258     ret = i2c_transfer(state->i2c, &msg, 1);
0259     if (fe->ops.i2c_gate_ctrl)
0260         fe->ops.i2c_gate_ctrl(fe, 0);
0261 
0262     if (ret < 0)
0263         printk(KERN_ERR "%s error ret=%d\n", __func__, ret);
0264 
0265     return ret;
0266 }
0267 
0268 /*
0269  * mt2063_write - Write register data into the I2C bus, caching the value
0270  */
0271 static int mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
0272 {
0273     int status;
0274 
0275     dprintk(2, "\n");
0276 
0277     if (reg >= MT2063_REG_END_REGS)
0278         return -ERANGE;
0279 
0280     status = mt2063_write(state, reg, &val, 1);
0281     if (status < 0)
0282         return status;
0283 
0284     state->reg[reg] = val;
0285 
0286     return 0;
0287 }
0288 
0289 /*
0290  * mt2063_read - Read data from the I2C bus
0291  */
0292 static int mt2063_read(struct mt2063_state *state,
0293                u8 subAddress, u8 *pData, u32 cnt)
0294 {
0295     int status = 0; /* Status to be returned        */
0296     struct dvb_frontend *fe = state->frontend;
0297     u32 i = 0;
0298 
0299     dprintk(2, "addr 0x%02x, cnt %d\n", subAddress, cnt);
0300 
0301     if (fe->ops.i2c_gate_ctrl)
0302         fe->ops.i2c_gate_ctrl(fe, 1);
0303 
0304     for (i = 0; i < cnt; i++) {
0305         u8 b0[] = { subAddress + i };
0306         struct i2c_msg msg[] = {
0307             {
0308                 .addr = state->config->tuner_address,
0309                 .flags = 0,
0310                 .buf = b0,
0311                 .len = 1
0312             }, {
0313                 .addr = state->config->tuner_address,
0314                 .flags = I2C_M_RD,
0315                 .buf = pData + i,
0316                 .len = 1
0317             }
0318         };
0319 
0320         status = i2c_transfer(state->i2c, msg, 2);
0321         dprintk(2, "addr 0x%02x, ret = %d, val = 0x%02x\n",
0322                subAddress + i, status, *(pData + i));
0323         if (status < 0)
0324             break;
0325     }
0326     if (fe->ops.i2c_gate_ctrl)
0327         fe->ops.i2c_gate_ctrl(fe, 0);
0328 
0329     if (status < 0)
0330         printk(KERN_ERR "Can't read from address 0x%02x,\n",
0331                subAddress + i);
0332 
0333     return status;
0334 }
0335 
0336 /*
0337  * FIXME: Is this really needed?
0338  */
0339 static int MT2063_Sleep(struct dvb_frontend *fe)
0340 {
0341     /*
0342      *  ToDo:  Add code here to implement a OS blocking
0343      */
0344     msleep(100);
0345 
0346     return 0;
0347 }
0348 
0349 /*
0350  * Microtune spur avoidance
0351  */
0352 
0353 /*  Implement ceiling, floor functions.  */
0354 #define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
0355 #define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
0356 
0357 struct MT2063_FIFZone_t {
0358     s32 min_;
0359     s32 max_;
0360 };
0361 
0362 static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
0363                         *pAS_Info,
0364                         struct MT2063_ExclZone_t *pPrevNode)
0365 {
0366     struct MT2063_ExclZone_t *pNode;
0367 
0368     dprintk(2, "\n");
0369 
0370     /*  Check for a node in the free list  */
0371     if (pAS_Info->freeZones != NULL) {
0372         /*  Use one from the free list  */
0373         pNode = pAS_Info->freeZones;
0374         pAS_Info->freeZones = pNode->next_;
0375     } else {
0376         /*  Grab a node from the array  */
0377         pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
0378     }
0379 
0380     if (pPrevNode != NULL) {
0381         pNode->next_ = pPrevNode->next_;
0382         pPrevNode->next_ = pNode;
0383     } else {        /*  insert at the beginning of the list  */
0384 
0385         pNode->next_ = pAS_Info->usedZones;
0386         pAS_Info->usedZones = pNode;
0387     }
0388 
0389     pAS_Info->nZones++;
0390     return pNode;
0391 }
0392 
0393 static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
0394                         *pAS_Info,
0395                         struct MT2063_ExclZone_t *pPrevNode,
0396                         struct MT2063_ExclZone_t
0397                         *pNodeToRemove)
0398 {
0399     struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
0400 
0401     dprintk(2, "\n");
0402 
0403     /*  Make previous node point to the subsequent node  */
0404     if (pPrevNode != NULL)
0405         pPrevNode->next_ = pNext;
0406 
0407     /*  Add pNodeToRemove to the beginning of the freeZones  */
0408     pNodeToRemove->next_ = pAS_Info->freeZones;
0409     pAS_Info->freeZones = pNodeToRemove;
0410 
0411     /*  Decrement node count  */
0412     pAS_Info->nZones--;
0413 
0414     return pNext;
0415 }
0416 
0417 /*
0418  * MT_AddExclZone()
0419  *
0420  * Add (and merge) an exclusion zone into the list.
0421  * If the range (f_min, f_max) is totally outside the
0422  * 1st IF BW, ignore the entry.
0423  * If the range (f_min, f_max) is negative, ignore the entry.
0424  */
0425 static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
0426                    u32 f_min, u32 f_max)
0427 {
0428     struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
0429     struct MT2063_ExclZone_t *pPrev = NULL;
0430     struct MT2063_ExclZone_t *pNext = NULL;
0431 
0432     dprintk(2, "\n");
0433 
0434     /*  Check to see if this overlaps the 1st IF filter  */
0435     if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
0436         && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
0437         && (f_min < f_max)) {
0438         /*
0439          *                1        2         3      4       5        6
0440          *
0441          *   New entry:  |---|    |--|      |--|    |-|    |---|    |--|
0442          *                or       or        or     or      or
0443          *   Existing:  |--|      |--|      |--|    |---|  |-|      |--|
0444          */
0445 
0446         /*  Check for our place in the list  */
0447         while ((pNode != NULL) && (pNode->max_ < f_min)) {
0448             pPrev = pNode;
0449             pNode = pNode->next_;
0450         }
0451 
0452         if ((pNode != NULL) && (pNode->min_ < f_max)) {
0453             /*  Combine me with pNode  */
0454             if (f_min < pNode->min_)
0455                 pNode->min_ = f_min;
0456             if (f_max > pNode->max_)
0457                 pNode->max_ = f_max;
0458         } else {
0459             pNode = InsertNode(pAS_Info, pPrev);
0460             pNode->min_ = f_min;
0461             pNode->max_ = f_max;
0462         }
0463 
0464         /*  Look for merging possibilities  */
0465         pNext = pNode->next_;
0466         while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
0467             if (pNext->max_ > pNode->max_)
0468                 pNode->max_ = pNext->max_;
0469             /*  Remove pNext, return ptr to pNext->next  */
0470             pNext = RemoveNode(pAS_Info, pNode, pNext);
0471         }
0472     }
0473 }
0474 
0475 /*
0476  *  Reset all exclusion zones.
0477  *  Add zones to protect the PLL FracN regions near zero
0478  */
0479 static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
0480 {
0481     u32 center;
0482 
0483     dprintk(2, "\n");
0484 
0485     pAS_Info->nZones = 0;   /*  this clears the used list  */
0486     pAS_Info->usedZones = NULL; /*  reset ptr                  */
0487     pAS_Info->freeZones = NULL; /*  reset ptr                  */
0488 
0489     center =
0490         pAS_Info->f_ref *
0491         ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
0492           pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
0493     while (center <
0494            pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
0495            pAS_Info->f_LO1_FracN_Avoid) {
0496         /*  Exclude LO1 FracN  */
0497         MT2063_AddExclZone(pAS_Info,
0498                    center - pAS_Info->f_LO1_FracN_Avoid,
0499                    center - 1);
0500         MT2063_AddExclZone(pAS_Info, center + 1,
0501                    center + pAS_Info->f_LO1_FracN_Avoid);
0502         center += pAS_Info->f_ref;
0503     }
0504 
0505     center =
0506         pAS_Info->f_ref *
0507         ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
0508           pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
0509     while (center <
0510            pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
0511            pAS_Info->f_LO2_FracN_Avoid) {
0512         /*  Exclude LO2 FracN  */
0513         MT2063_AddExclZone(pAS_Info,
0514                    center - pAS_Info->f_LO2_FracN_Avoid,
0515                    center - 1);
0516         MT2063_AddExclZone(pAS_Info, center + 1,
0517                    center + pAS_Info->f_LO2_FracN_Avoid);
0518         center += pAS_Info->f_ref;
0519     }
0520 
0521     if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
0522         /*  Exclude LO1 values that conflict with DECT channels */
0523         MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
0524         MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
0525         MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
0526         MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
0527         MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
0528     }
0529 
0530     if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
0531         MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
0532         MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
0533         MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
0534         MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16  */
0535         MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
0536         MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
0537         MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
0538         MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
0539         MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52  */
0540         MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
0541     }
0542 }
0543 
0544 /*
0545  * MT_ChooseFirstIF - Choose the best available 1st IF
0546  *                    If f_Desired is not excluded, choose that first.
0547  *                    Otherwise, return the value closest to f_Center that is
0548  *                    not excluded
0549  */
0550 static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
0551 {
0552     /*
0553      * Update "f_Desired" to be the nearest "combinational-multiple" of
0554      * "f_LO1_Step".
0555      * The resulting number, F_LO1 must be a multiple of f_LO1_Step.
0556      * And F_LO1 is the arithmetic sum of f_in + f_Center.
0557      * Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
0558      * However, the sum must be.
0559      */
0560     const u32 f_Desired =
0561         pAS_Info->f_LO1_Step *
0562         ((pAS_Info->f_if1_Request + pAS_Info->f_in +
0563           pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
0564         pAS_Info->f_in;
0565     const u32 f_Step =
0566         (pAS_Info->f_LO1_Step >
0567          pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
0568         f_LO2_Step;
0569     u32 f_Center;
0570     s32 i;
0571     s32 j = 0;
0572     u32 bDesiredExcluded = 0;
0573     u32 bZeroExcluded = 0;
0574     s32 tmpMin, tmpMax;
0575     s32 bestDiff;
0576     struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
0577     struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
0578 
0579     dprintk(2, "\n");
0580 
0581     if (pAS_Info->nZones == 0)
0582         return f_Desired;
0583 
0584     /*
0585      *  f_Center needs to be an integer multiple of f_Step away
0586      *  from f_Desired
0587      */
0588     if (pAS_Info->f_if1_Center > f_Desired)
0589         f_Center =
0590             f_Desired +
0591             f_Step *
0592             ((pAS_Info->f_if1_Center - f_Desired +
0593               f_Step / 2) / f_Step);
0594     else
0595         f_Center =
0596             f_Desired -
0597             f_Step *
0598             ((f_Desired - pAS_Info->f_if1_Center +
0599               f_Step / 2) / f_Step);
0600 
0601     /*
0602      * Take MT_ExclZones, center around f_Center and change the
0603      * resolution to f_Step
0604      */
0605     while (pNode != NULL) {
0606         /*  floor function  */
0607         tmpMin =
0608             floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
0609 
0610         /*  ceil function  */
0611         tmpMax =
0612             ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
0613 
0614         if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
0615             bDesiredExcluded = 1;
0616 
0617         if ((tmpMin < 0) && (tmpMax > 0))
0618             bZeroExcluded = 1;
0619 
0620         /*  See if this zone overlaps the previous  */
0621         if ((j > 0) && (tmpMin < zones[j - 1].max_))
0622             zones[j - 1].max_ = tmpMax;
0623         else {
0624             /*  Add new zone  */
0625             zones[j].min_ = tmpMin;
0626             zones[j].max_ = tmpMax;
0627             j++;
0628         }
0629         pNode = pNode->next_;
0630     }
0631 
0632     /*
0633      *  If the desired is okay, return with it
0634      */
0635     if (bDesiredExcluded == 0)
0636         return f_Desired;
0637 
0638     /*
0639      *  If the desired is excluded and the center is okay, return with it
0640      */
0641     if (bZeroExcluded == 0)
0642         return f_Center;
0643 
0644     /*  Find the value closest to 0 (f_Center)  */
0645     bestDiff = zones[0].min_;
0646     for (i = 0; i < j; i++) {
0647         if (abs(zones[i].min_) < abs(bestDiff))
0648             bestDiff = zones[i].min_;
0649         if (abs(zones[i].max_) < abs(bestDiff))
0650             bestDiff = zones[i].max_;
0651     }
0652 
0653     if (bestDiff < 0)
0654         return f_Center - ((u32) (-bestDiff) * f_Step);
0655 
0656     return f_Center + (bestDiff * f_Step);
0657 }
0658 
0659 /**
0660  * IsSpurInBand() - Checks to see if a spur will be present within the IF's
0661  *                  bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
0662  *
0663  *                    ma   mb                                     mc   md
0664  *                  <--+-+-+-------------------+-------------------+-+-+-->
0665  *                     |   ^                   0                   ^   |
0666  *                     ^   b=-fIFOut+fIFBW/2      -b=+fIFOut-fIFBW/2   ^
0667  *                     a=-fIFOut-fIFBW/2              -a=+fIFOut+fIFBW/2
0668  *
0669  *                  Note that some equations are doubled to prevent round-off
0670  *                  problems when calculating fIFBW/2
0671  *
0672  * @pAS_Info:   Avoid Spurs information block
0673  * @fm:     If spur, amount f_IF1 has to move negative
0674  * @fp:     If spur, amount f_IF1 has to move positive
0675  *
0676  *  Returns 1 if an LO spur would be present, otherwise 0.
0677  */
0678 static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
0679             u32 *fm, u32 * fp)
0680 {
0681     /*
0682      **  Calculate LO frequency settings.
0683      */
0684     u32 n, n0;
0685     const u32 f_LO1 = pAS_Info->f_LO1;
0686     const u32 f_LO2 = pAS_Info->f_LO2;
0687     const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
0688     const u32 c = d - pAS_Info->f_out_bw;
0689     const u32 f = pAS_Info->f_zif_bw / 2;
0690     const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
0691     s32 f_nsLO1, f_nsLO2;
0692     s32 f_Spur;
0693     u32 ma, mb, mc, md, me, mf;
0694     u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
0695 
0696     dprintk(2, "\n");
0697 
0698     *fm = 0;
0699 
0700     /*
0701      ** For each edge (d, c & f), calculate a scale, based on the gcd
0702      ** of f_LO1, f_LO2 and the edge value.  Use the larger of this
0703      ** gcd-based scale factor or f_Scale.
0704      */
0705     lo_gcd = gcd(f_LO1, f_LO2);
0706     gd_Scale = max((u32) gcd(lo_gcd, d), f_Scale);
0707     hgds = gd_Scale / 2;
0708     gc_Scale = max((u32) gcd(lo_gcd, c), f_Scale);
0709     hgcs = gc_Scale / 2;
0710     gf_Scale = max((u32) gcd(lo_gcd, f), f_Scale);
0711     hgfs = gf_Scale / 2;
0712 
0713     n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
0714 
0715     /*  Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic  */
0716     for (n = n0; n <= pAS_Info->maxH1; ++n) {
0717         md = (n * ((f_LO1 + hgds) / gd_Scale) -
0718               ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
0719 
0720         /*  If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present  */
0721         if (md >= pAS_Info->maxH1)
0722             break;
0723 
0724         ma = (n * ((f_LO1 + hgds) / gd_Scale) +
0725               ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
0726 
0727         /*  If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic  */
0728         if (md == ma)
0729             continue;
0730 
0731         mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
0732               ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
0733         if (mc != md) {
0734             f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
0735             f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
0736             f_Spur =
0737                 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
0738                 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
0739 
0740             *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
0741             *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
0742             return 1;
0743         }
0744 
0745         /*  Location of Zero-IF-spur to be checked  */
0746         me = (n * ((f_LO1 + hgfs) / gf_Scale) +
0747               ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
0748         mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
0749               ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
0750         if (me != mf) {
0751             f_nsLO1 = n * (f_LO1 / gf_Scale);
0752             f_nsLO2 = me * (f_LO2 / gf_Scale);
0753             f_Spur =
0754                 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
0755                 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
0756 
0757             *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
0758             *fm = (((s32) f - f_Spur) / (me - n)) + 1;
0759             return 1;
0760         }
0761 
0762         mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
0763               ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
0764         if (ma != mb) {
0765             f_nsLO1 = n * (f_LO1 / gc_Scale);
0766             f_nsLO2 = ma * (f_LO2 / gc_Scale);
0767             f_Spur =
0768                 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
0769                 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
0770 
0771             *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
0772             *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
0773             return 1;
0774         }
0775     }
0776 
0777     /*  No spurs found  */
0778     return 0;
0779 }
0780 
0781 /*
0782  * MT_AvoidSpurs() - Main entry point to avoid spurs.
0783  *                   Checks for existing spurs in present LO1, LO2 freqs
0784  *                   and if present, chooses spur-free LO1, LO2 combination
0785  *                   that tunes the same input/output frequencies.
0786  */
0787 static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
0788 {
0789     int status = 0;
0790     u32 fm, fp;     /*  restricted range on LO's        */
0791     pAS_Info->bSpurAvoided = 0;
0792     pAS_Info->nSpursFound = 0;
0793 
0794     dprintk(2, "\n");
0795 
0796     if (pAS_Info->maxH1 == 0)
0797         return 0;
0798 
0799     /*
0800      * Avoid LO Generated Spurs
0801      *
0802      * Make sure that have no LO-related spurs within the IF output
0803      * bandwidth.
0804      *
0805      * If there is an LO spur in this band, start at the current IF1 frequency
0806      * and work out until we find a spur-free frequency or run up against the
0807      * 1st IF SAW band edge.  Use temporary copies of fLO1 and fLO2 so that they
0808      * will be unchanged if a spur-free setting is not found.
0809      */
0810     pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
0811     if (pAS_Info->bSpurPresent) {
0812         u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in;   /*  current attempt at a 1st IF  */
0813         u32 zfLO1 = pAS_Info->f_LO1;    /*  current attempt at an LO1 freq  */
0814         u32 zfLO2 = pAS_Info->f_LO2;    /*  current attempt at an LO2 freq  */
0815         u32 delta_IF1;
0816         u32 new_IF1;
0817 
0818         /*
0819          **  Spur was found, attempt to find a spur-free 1st IF
0820          */
0821         do {
0822             pAS_Info->nSpursFound++;
0823 
0824             /*  Raise f_IF1_upper, if needed  */
0825             MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
0826 
0827             /*  Choose next IF1 that is closest to f_IF1_CENTER              */
0828             new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
0829 
0830             if (new_IF1 > zfIF1) {
0831                 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
0832                 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
0833             } else {
0834                 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
0835                 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
0836             }
0837             zfIF1 = new_IF1;
0838 
0839             if (zfIF1 > pAS_Info->f_if1_Center)
0840                 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
0841             else
0842                 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
0843 
0844             pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
0845         /*
0846          *  Continue while the new 1st IF is still within the 1st IF bandwidth
0847          *  and there is a spur in the band (again)
0848          */
0849         } while ((2 * delta_IF1 + pAS_Info->f_out_bw <= pAS_Info->f_if1_bw) && pAS_Info->bSpurPresent);
0850 
0851         /*
0852          * Use the LO-spur free values found.  If the search went all
0853          * the way to the 1st IF band edge and always found spurs, just
0854          * leave the original choice.  It's as "good" as any other.
0855          */
0856         if (pAS_Info->bSpurPresent == 1) {
0857             status |= MT2063_SPUR_PRESENT_ERR;
0858             pAS_Info->f_LO1 = zfLO1;
0859             pAS_Info->f_LO2 = zfLO2;
0860         } else
0861             pAS_Info->bSpurAvoided = 1;
0862     }
0863 
0864     status |=
0865         ((pAS_Info->
0866           nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
0867 
0868     return status;
0869 }
0870 
0871 /*
0872  * Constants used by the tuning algorithm
0873  */
0874 #define MT2063_REF_FREQ          (16000000UL)   /* Reference oscillator Frequency (in Hz) */
0875 #define MT2063_IF1_BW            (22000000UL)   /* The IF1 filter bandwidth (in Hz) */
0876 #define MT2063_TUNE_STEP_SIZE       (50000UL)   /* Tune in steps of 50 kHz */
0877 #define MT2063_SPUR_STEP_HZ        (250000UL)   /* Step size (in Hz) to move IF1 when avoiding spurs */
0878 #define MT2063_ZIF_BW             (2000000UL)   /* Zero-IF spur-free bandwidth (in Hz) */
0879 #define MT2063_MAX_HARMONICS_1         (15UL)   /* Highest intra-tuner LO Spur Harmonic to be avoided */
0880 #define MT2063_MAX_HARMONICS_2          (5UL)   /* Highest inter-tuner LO Spur Harmonic to be avoided */
0881 #define MT2063_MIN_LO_SEP         (1000000UL)   /* Minimum inter-tuner LO frequency separation */
0882 #define MT2063_LO1_FRACN_AVOID          (0UL)   /* LO1 FracN numerator avoid region (in Hz) */
0883 #define MT2063_LO2_FRACN_AVOID     (199999UL)   /* LO2 FracN numerator avoid region (in Hz) */
0884 #define MT2063_MIN_FIN_FREQ      (44000000UL)   /* Minimum input frequency (in Hz) */
0885 #define MT2063_MAX_FIN_FREQ    (1100000000UL)   /* Maximum input frequency (in Hz) */
0886 #define MT2063_MIN_FOUT_FREQ     (36000000UL)   /* Minimum output frequency (in Hz) */
0887 #define MT2063_MAX_FOUT_FREQ     (57000000UL)   /* Maximum output frequency (in Hz) */
0888 #define MT2063_MIN_DNC_FREQ    (1293000000UL)   /* Minimum LO2 frequency (in Hz) */
0889 #define MT2063_MAX_DNC_FREQ    (1614000000UL)   /* Maximum LO2 frequency (in Hz) */
0890 #define MT2063_MIN_UPC_FREQ    (1396000000UL)   /* Minimum LO1 frequency (in Hz) */
0891 #define MT2063_MAX_UPC_FREQ    (2750000000UL)   /* Maximum LO1 frequency (in Hz) */
0892 
0893 /*
0894  *  Define the supported Part/Rev codes for the MT2063
0895  */
0896 #define MT2063_B0       (0x9B)
0897 #define MT2063_B1       (0x9C)
0898 #define MT2063_B2       (0x9D)
0899 #define MT2063_B3       (0x9E)
0900 
0901 /**
0902  * mt2063_lockStatus - Checks to see if LO1 and LO2 are locked
0903  *
0904  * @state:  struct mt2063_state pointer
0905  *
0906  * This function returns 0, if no lock, 1 if locked and a value < 1 if error
0907  */
0908 static int mt2063_lockStatus(struct mt2063_state *state)
0909 {
0910     const u32 nMaxWait = 100;   /*  wait a maximum of 100 msec   */
0911     const u32 nPollRate = 2;    /*  poll status bits every 2 ms */
0912     const u32 nMaxLoops = nMaxWait / nPollRate;
0913     const u8 LO1LK = 0x80;
0914     u8 LO2LK = 0x08;
0915     int status;
0916     u32 nDelays = 0;
0917 
0918     dprintk(2, "\n");
0919 
0920     /*  LO2 Lock bit was in a different place for B0 version  */
0921     if (state->tuner_id == MT2063_B0)
0922         LO2LK = 0x40;
0923 
0924     do {
0925         status = mt2063_read(state, MT2063_REG_LO_STATUS,
0926                      &state->reg[MT2063_REG_LO_STATUS], 1);
0927 
0928         if (status < 0)
0929             return status;
0930 
0931         if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
0932             (LO1LK | LO2LK)) {
0933             return TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO;
0934         }
0935         msleep(nPollRate);  /*  Wait between retries  */
0936     } while (++nDelays < nMaxLoops);
0937 
0938     /*
0939      * Got no lock or partial lock
0940      */
0941     return 0;
0942 }
0943 
0944 /*
0945  *  Constants for setting receiver modes.
0946  *  (6 modes defined at this time, enumerated by mt2063_delivery_sys)
0947  *  (DNC1GC & DNC2GC are the values, which are used, when the specific
0948  *   DNC Output is selected, the other is always off)
0949  *
0950  *                enum mt2063_delivery_sys
0951  * -------------+----------------------------------------------
0952  * Mode 0 :     | MT2063_CABLE_QAM
0953  * Mode 1 :     | MT2063_CABLE_ANALOG
0954  * Mode 2 :     | MT2063_OFFAIR_COFDM
0955  * Mode 3 :     | MT2063_OFFAIR_COFDM_SAWLESS
0956  * Mode 4 :     | MT2063_OFFAIR_ANALOG
0957  * Mode 5 :     | MT2063_OFFAIR_8VSB
0958  * --------------+----------------------------------------------
0959  *
0960  *                |<----------   Mode  -------------->|
0961  *    Reg Field   |  0  |  1  |  2  |  3  |  4  |  5  |
0962  *    ------------+-----+-----+-----+-----+-----+-----+
0963  *    RFAGCen     | OFF | OFF | OFF | OFF | OFF | OFF
0964  *    LNARin      |   0 |   0 |   3 |   3 |  3  |  3
0965  *    FIFFQen     |   1 |   1 |   1 |   1 |  1  |  1
0966  *    FIFFq       |   0 |   0 |   0 |   0 |  0  |  0
0967  *    DNC1gc      |   0 |   0 |   0 |   0 |  0  |  0
0968  *    DNC2gc      |   0 |   0 |   0 |   0 |  0  |  0
0969  *    GCU Auto    |   1 |   1 |   1 |   1 |  1  |  1
0970  *    LNA max Atn |  31 |  31 |  31 |  31 | 31  | 31
0971  *    LNA Target  |  44 |  43 |  43 |  43 | 43  | 43
0972  *    ign  RF Ovl |   0 |   0 |   0 |   0 |  0  |  0
0973  *    RF  max Atn |  31 |  31 |  31 |  31 | 31  | 31
0974  *    PD1 Target  |  36 |  36 |  38 |  38 | 36  | 38
0975  *    ign FIF Ovl |   0 |   0 |   0 |   0 |  0  |  0
0976  *    FIF max Atn |   5 |   5 |   5 |   5 |  5  |  5
0977  *    PD2 Target  |  40 |  33 |  42 |  42 | 33  | 42
0978  */
0979 
0980 enum mt2063_delivery_sys {
0981     MT2063_CABLE_QAM = 0,
0982     MT2063_CABLE_ANALOG,
0983     MT2063_OFFAIR_COFDM,
0984     MT2063_OFFAIR_COFDM_SAWLESS,
0985     MT2063_OFFAIR_ANALOG,
0986     MT2063_OFFAIR_8VSB,
0987     MT2063_NUM_RCVR_MODES
0988 };
0989 
0990 static const char *mt2063_mode_name[] = {
0991     [MT2063_CABLE_QAM]      = "digital cable",
0992     [MT2063_CABLE_ANALOG]       = "analog cable",
0993     [MT2063_OFFAIR_COFDM]       = "digital offair",
0994     [MT2063_OFFAIR_COFDM_SAWLESS]   = "digital offair without SAW",
0995     [MT2063_OFFAIR_ANALOG]      = "analog offair",
0996     [MT2063_OFFAIR_8VSB]        = "analog offair 8vsb",
0997 };
0998 
0999 static const u8 RFAGCEN[]   = {  0,  0,  0,  0,  0,  0 };
1000 static const u8 LNARIN[]    = {  0,  0,  3,  3,  3,  3 };
1001 static const u8 FIFFQEN[]   = {  1,  1,  1,  1,  1,  1 };
1002 static const u8 FIFFQ[]     = {  0,  0,  0,  0,  0,  0 };
1003 static const u8 DNC1GC[]    = {  0,  0,  0,  0,  0,  0 };
1004 static const u8 DNC2GC[]    = {  0,  0,  0,  0,  0,  0 };
1005 static const u8 ACLNAMAX[]  = { 31, 31, 31, 31, 31, 31 };
1006 static const u8 LNATGT[]    = { 44, 43, 43, 43, 43, 43 };
1007 static const u8 RFOVDIS[]   = {  0,  0,  0,  0,  0,  0 };
1008 static const u8 ACRFMAX[]   = { 31, 31, 31, 31, 31, 31 };
1009 static const u8 PD1TGT[]    = { 36, 36, 38, 38, 36, 38 };
1010 static const u8 FIFOVDIS[]  = {  0,  0,  0,  0,  0,  0 };
1011 static const u8 ACFIFMAX[]  = { 29, 29, 29, 29, 29, 29 };
1012 static const u8 PD2TGT[]    = { 40, 33, 38, 42, 30, 38 };
1013 
1014 /*
1015  * mt2063_set_dnc_output_enable()
1016  */
1017 static u32 mt2063_get_dnc_output_enable(struct mt2063_state *state,
1018                     enum MT2063_DNC_Output_Enable *pValue)
1019 {
1020     dprintk(2, "\n");
1021 
1022     if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1023         if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)   /* if DNC2 is off */
1024             *pValue = MT2063_DNC_NONE;
1025         else
1026             *pValue = MT2063_DNC_2;
1027     } else {    /* DNC1 is on */
1028         if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)   /* if DNC2 is off */
1029             *pValue = MT2063_DNC_1;
1030         else
1031             *pValue = MT2063_DNC_BOTH;
1032     }
1033     return 0;
1034 }
1035 
1036 /*
1037  * mt2063_set_dnc_output_enable()
1038  */
1039 static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
1040                     enum MT2063_DNC_Output_Enable nValue)
1041 {
1042     int status = 0; /* Status to be returned        */
1043     u8 val = 0;
1044 
1045     dprintk(2, "\n");
1046 
1047     /* selects, which DNC output is used */
1048     switch (nValue) {
1049     case MT2063_DNC_NONE:
1050         val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;  /* Set DNC1GC=3 */
1051         if (state->reg[MT2063_REG_DNC_GAIN] !=
1052             val)
1053             status |=
1054                 mt2063_setreg(state,
1055                       MT2063_REG_DNC_GAIN,
1056                       val);
1057 
1058         val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;  /* Set DNC2GC=3 */
1059         if (state->reg[MT2063_REG_VGA_GAIN] !=
1060             val)
1061             status |=
1062                 mt2063_setreg(state,
1063                       MT2063_REG_VGA_GAIN,
1064                       val);
1065 
1066         val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
1067         if (state->reg[MT2063_REG_RSVD_20] !=
1068             val)
1069             status |=
1070                 mt2063_setreg(state,
1071                       MT2063_REG_RSVD_20,
1072                       val);
1073 
1074         break;
1075     case MT2063_DNC_1:
1076         val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
1077         if (state->reg[MT2063_REG_DNC_GAIN] !=
1078             val)
1079             status |=
1080                 mt2063_setreg(state,
1081                       MT2063_REG_DNC_GAIN,
1082                       val);
1083 
1084         val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;  /* Set DNC2GC=3 */
1085         if (state->reg[MT2063_REG_VGA_GAIN] !=
1086             val)
1087             status |=
1088                 mt2063_setreg(state,
1089                       MT2063_REG_VGA_GAIN,
1090                       val);
1091 
1092         val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
1093         if (state->reg[MT2063_REG_RSVD_20] !=
1094             val)
1095             status |=
1096                 mt2063_setreg(state,
1097                       MT2063_REG_RSVD_20,
1098                       val);
1099 
1100         break;
1101     case MT2063_DNC_2:
1102         val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;  /* Set DNC1GC=3 */
1103         if (state->reg[MT2063_REG_DNC_GAIN] !=
1104             val)
1105             status |=
1106                 mt2063_setreg(state,
1107                       MT2063_REG_DNC_GAIN,
1108                       val);
1109 
1110         val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
1111         if (state->reg[MT2063_REG_VGA_GAIN] !=
1112             val)
1113             status |=
1114                 mt2063_setreg(state,
1115                       MT2063_REG_VGA_GAIN,
1116                       val);
1117 
1118         val = (state->reg[MT2063_REG_RSVD_20] | 0x40);  /* Set PD2MUX=1 */
1119         if (state->reg[MT2063_REG_RSVD_20] !=
1120             val)
1121             status |=
1122                 mt2063_setreg(state,
1123                       MT2063_REG_RSVD_20,
1124                       val);
1125 
1126         break;
1127     case MT2063_DNC_BOTH:
1128         val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
1129         if (state->reg[MT2063_REG_DNC_GAIN] !=
1130             val)
1131             status |=
1132                 mt2063_setreg(state,
1133                       MT2063_REG_DNC_GAIN,
1134                       val);
1135 
1136         val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
1137         if (state->reg[MT2063_REG_VGA_GAIN] !=
1138             val)
1139             status |=
1140                 mt2063_setreg(state,
1141                       MT2063_REG_VGA_GAIN,
1142                       val);
1143 
1144         val = (state->reg[MT2063_REG_RSVD_20] | 0x40);  /* Set PD2MUX=1 */
1145         if (state->reg[MT2063_REG_RSVD_20] !=
1146             val)
1147             status |=
1148                 mt2063_setreg(state,
1149                       MT2063_REG_RSVD_20,
1150                       val);
1151 
1152         break;
1153     default:
1154         break;
1155     }
1156 
1157     return status;
1158 }
1159 
1160 /*
1161  * MT2063_SetReceiverMode() - Set the MT2063 receiver mode, according with
1162  *                the selected enum mt2063_delivery_sys type.
1163  *
1164  *  (DNC1GC & DNC2GC are the values, which are used, when the specific
1165  *   DNC Output is selected, the other is always off)
1166  *
1167  * @state:  ptr to mt2063_state structure
1168  * @Mode:   desired receiver delivery system
1169  *
1170  * Note: Register cache must be valid for it to work
1171  */
1172 
1173 static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
1174                   enum mt2063_delivery_sys Mode)
1175 {
1176     int status = 0; /* Status to be returned        */
1177     u8 val;
1178     u32 longval;
1179 
1180     dprintk(2, "\n");
1181 
1182     if (Mode >= MT2063_NUM_RCVR_MODES)
1183         status = -ERANGE;
1184 
1185     /* RFAGCen */
1186     if (status >= 0) {
1187         val =
1188             (state->
1189              reg[MT2063_REG_PD1_TGT] & ~0x40) | (RFAGCEN[Mode]
1190                                    ? 0x40 :
1191                                    0x00);
1192         if (state->reg[MT2063_REG_PD1_TGT] != val)
1193             status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
1194     }
1195 
1196     /* LNARin */
1197     if (status >= 0) {
1198         u8 val = (state->reg[MT2063_REG_CTRL_2C] & ~0x03) |
1199              (LNARIN[Mode] & 0x03);
1200         if (state->reg[MT2063_REG_CTRL_2C] != val)
1201             status |= mt2063_setreg(state, MT2063_REG_CTRL_2C, val);
1202     }
1203 
1204     /* FIFFQEN and FIFFQ */
1205     if (status >= 0) {
1206         val =
1207             (state->
1208              reg[MT2063_REG_FIFF_CTRL2] & ~0xF0) |
1209             (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
1210         if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
1211             status |=
1212                 mt2063_setreg(state, MT2063_REG_FIFF_CTRL2, val);
1213             /* trigger FIFF calibration, needed after changing FIFFQ */
1214             val =
1215                 (state->reg[MT2063_REG_FIFF_CTRL] | 0x01);
1216             status |=
1217                 mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
1218             val =
1219                 (state->
1220                  reg[MT2063_REG_FIFF_CTRL] & ~0x01);
1221             status |=
1222                 mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
1223         }
1224     }
1225 
1226     /* DNC1GC & DNC2GC */
1227     status |= mt2063_get_dnc_output_enable(state, &longval);
1228     status |= mt2063_set_dnc_output_enable(state, longval);
1229 
1230     /* acLNAmax */
1231     if (status >= 0) {
1232         u8 val = (state->reg[MT2063_REG_LNA_OV] & ~0x1F) |
1233              (ACLNAMAX[Mode] & 0x1F);
1234         if (state->reg[MT2063_REG_LNA_OV] != val)
1235             status |= mt2063_setreg(state, MT2063_REG_LNA_OV, val);
1236     }
1237 
1238     /* LNATGT */
1239     if (status >= 0) {
1240         u8 val = (state->reg[MT2063_REG_LNA_TGT] & ~0x3F) |
1241              (LNATGT[Mode] & 0x3F);
1242         if (state->reg[MT2063_REG_LNA_TGT] != val)
1243             status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
1244     }
1245 
1246     /* ACRF */
1247     if (status >= 0) {
1248         u8 val = (state->reg[MT2063_REG_RF_OV] & ~0x1F) |
1249              (ACRFMAX[Mode] & 0x1F);
1250         if (state->reg[MT2063_REG_RF_OV] != val)
1251             status |= mt2063_setreg(state, MT2063_REG_RF_OV, val);
1252     }
1253 
1254     /* PD1TGT */
1255     if (status >= 0) {
1256         u8 val = (state->reg[MT2063_REG_PD1_TGT] & ~0x3F) |
1257              (PD1TGT[Mode] & 0x3F);
1258         if (state->reg[MT2063_REG_PD1_TGT] != val)
1259             status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
1260     }
1261 
1262     /* FIFATN */
1263     if (status >= 0) {
1264         u8 val = ACFIFMAX[Mode];
1265         if (state->reg[MT2063_REG_PART_REV] != MT2063_B3 && val > 5)
1266             val = 5;
1267         val = (state->reg[MT2063_REG_FIF_OV] & ~0x1F) |
1268               (val & 0x1F);
1269         if (state->reg[MT2063_REG_FIF_OV] != val)
1270             status |= mt2063_setreg(state, MT2063_REG_FIF_OV, val);
1271     }
1272 
1273     /* PD2TGT */
1274     if (status >= 0) {
1275         u8 val = (state->reg[MT2063_REG_PD2_TGT] & ~0x3F) |
1276             (PD2TGT[Mode] & 0x3F);
1277         if (state->reg[MT2063_REG_PD2_TGT] != val)
1278             status |= mt2063_setreg(state, MT2063_REG_PD2_TGT, val);
1279     }
1280 
1281     /* Ignore ATN Overload */
1282     if (status >= 0) {
1283         val = (state->reg[MT2063_REG_LNA_TGT] & ~0x80) |
1284               (RFOVDIS[Mode] ? 0x80 : 0x00);
1285         if (state->reg[MT2063_REG_LNA_TGT] != val)
1286             status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
1287     }
1288 
1289     /* Ignore FIF Overload */
1290     if (status >= 0) {
1291         val = (state->reg[MT2063_REG_PD1_TGT] & ~0x80) |
1292               (FIFOVDIS[Mode] ? 0x80 : 0x00);
1293         if (state->reg[MT2063_REG_PD1_TGT] != val)
1294             status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
1295     }
1296 
1297     if (status >= 0) {
1298         state->rcvr_mode = Mode;
1299         dprintk(1, "mt2063 mode changed to %s\n",
1300             mt2063_mode_name[state->rcvr_mode]);
1301     }
1302 
1303     return status;
1304 }
1305 
1306 /*
1307  * MT2063_ClearPowerMaskBits () - Clears the power-down mask bits for various
1308  *                sections of the MT2063
1309  *
1310  * @Bits:       Mask bits to be cleared.
1311  *
1312  * See definition of MT2063_Mask_Bits type for description
1313  * of each of the power bits.
1314  */
1315 static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
1316                      enum MT2063_Mask_Bits Bits)
1317 {
1318     int status = 0;
1319 
1320     dprintk(2, "\n");
1321     Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD);   /* Only valid bits for this tuner */
1322     if ((Bits & 0xFF00) != 0) {
1323         state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
1324         status |=
1325             mt2063_write(state,
1326                     MT2063_REG_PWR_2,
1327                     &state->reg[MT2063_REG_PWR_2], 1);
1328     }
1329     if ((Bits & 0xFF) != 0) {
1330         state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
1331         status |=
1332             mt2063_write(state,
1333                     MT2063_REG_PWR_1,
1334                     &state->reg[MT2063_REG_PWR_1], 1);
1335     }
1336 
1337     return status;
1338 }
1339 
1340 /*
1341  * MT2063_SoftwareShutdown() - Enables or disables software shutdown function.
1342  *                 When Shutdown is 1, any section whose power
1343  *                 mask is set will be shutdown.
1344  */
1345 static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
1346 {
1347     int status;
1348 
1349     dprintk(2, "\n");
1350     if (Shutdown == 1)
1351         state->reg[MT2063_REG_PWR_1] |= 0x04;
1352     else
1353         state->reg[MT2063_REG_PWR_1] &= ~0x04;
1354 
1355     status = mt2063_write(state,
1356                 MT2063_REG_PWR_1,
1357                 &state->reg[MT2063_REG_PWR_1], 1);
1358 
1359     if (Shutdown != 1) {
1360         state->reg[MT2063_REG_BYP_CTRL] =
1361             (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
1362         status |=
1363             mt2063_write(state,
1364                     MT2063_REG_BYP_CTRL,
1365                     &state->reg[MT2063_REG_BYP_CTRL],
1366                     1);
1367         state->reg[MT2063_REG_BYP_CTRL] =
1368             (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
1369         status |=
1370             mt2063_write(state,
1371                     MT2063_REG_BYP_CTRL,
1372                     &state->reg[MT2063_REG_BYP_CTRL],
1373                     1);
1374     }
1375 
1376     return status;
1377 }
1378 
1379 static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
1380 {
1381     return f_ref * (f_LO / f_ref)
1382         + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
1383 }
1384 
1385 /**
1386  * MT2063_fLO_FractionalTerm - Calculates the portion contributed by FracN / denom.
1387  *                        This function preserves maximum precision without
1388  *                        risk of overflow.  It accurately calculates
1389  *                        f_ref * num / denom to within 1 HZ with fixed math.
1390  *
1391  * @f_ref:  SRO frequency.
1392  * @num:    Fractional portion of the multiplier
1393  * @denom:  denominator portion of the ratio
1394  *
1395  * This calculation handles f_ref as two separate 14-bit fields.
1396  * Therefore, a maximum value of 2^28-1 may safely be used for f_ref.
1397  * This is the genesis of the magic number "14" and the magic mask value of
1398  * 0x03FFF.
1399  *
1400  * This routine successfully handles denom values up to and including 2^18.
1401  *  Returns:        f_ref * num / denom
1402  */
1403 static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num, u32 denom)
1404 {
1405     u32 t1 = (f_ref >> 14) * num;
1406     u32 term1 = t1 / denom;
1407     u32 loss = t1 % denom;
1408     u32 term2 =
1409         (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
1410     return (term1 << 14) + term2;
1411 }
1412 
1413 /*
1414  * MT2063_CalcLO1Mult - Calculates Integer divider value and the numerator
1415  *                value for a FracN PLL.
1416  *
1417  *                This function assumes that the f_LO and f_Ref are
1418  *                evenly divisible by f_LO_Step.
1419  *
1420  * @Div:    OUTPUT: Whole number portion of the multiplier
1421  * @FracN:  OUTPUT: Fractional portion of the multiplier
1422  * @f_LO:   desired LO frequency.
1423  * @f_LO_Step:  Minimum step size for the LO (in Hz).
1424  * @f_Ref:  SRO frequency.
1425  * @f_Avoid:    Range of PLL frequencies to avoid near integer multiples
1426  *      of f_Ref (in Hz).
1427  *
1428  * Returns:        Recalculated LO frequency.
1429  */
1430 static u32 MT2063_CalcLO1Mult(u32 *Div,
1431                   u32 *FracN,
1432                   u32 f_LO,
1433                   u32 f_LO_Step, u32 f_Ref)
1434 {
1435     /*  Calculate the whole number portion of the divider */
1436     *Div = f_LO / f_Ref;
1437 
1438     /*  Calculate the numerator value (round to nearest f_LO_Step) */
1439     *FracN =
1440         (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
1441          (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
1442 
1443     return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
1444 }
1445 
1446 /**
1447  * MT2063_CalcLO2Mult - Calculates Integer divider value and the numerator
1448  *                 value for a FracN PLL.
1449  *
1450  *                  This function assumes that the f_LO and f_Ref are
1451  *                  evenly divisible by f_LO_Step.
1452  *
1453  * @Div:    OUTPUT: Whole number portion of the multiplier
1454  * @FracN:  OUTPUT: Fractional portion of the multiplier
1455  * @f_LO:   desired LO frequency.
1456  * @f_LO_Step:  Minimum step size for the LO (in Hz).
1457  * @f_Ref:  SRO frequency.
1458  *
1459  * Returns: Recalculated LO frequency.
1460  */
1461 static u32 MT2063_CalcLO2Mult(u32 *Div,
1462                   u32 *FracN,
1463                   u32 f_LO,
1464                   u32 f_LO_Step, u32 f_Ref)
1465 {
1466     /*  Calculate the whole number portion of the divider */
1467     *Div = f_LO / f_Ref;
1468 
1469     /*  Calculate the numerator value (round to nearest f_LO_Step) */
1470     *FracN =
1471         (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
1472          (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
1473 
1474     return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
1475                                 8191);
1476 }
1477 
1478 /*
1479  * FindClearTuneFilter() - Calculate the corrrect ClearTune filter to be
1480  *             used for a given input frequency.
1481  *
1482  * @state:  ptr to tuner data structure
1483  * @f_in:   RF input center frequency (in Hz).
1484  *
1485  * Returns: ClearTune filter number (0-31)
1486  */
1487 static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
1488 {
1489     u32 RFBand;
1490     u32 idx;        /*  index loop                      */
1491 
1492     /*
1493      **  Find RF Band setting
1494      */
1495     RFBand = 31;        /*  def when f_in > all    */
1496     for (idx = 0; idx < 31; ++idx) {
1497         if (state->CTFiltMax[idx] >= f_in) {
1498             RFBand = idx;
1499             break;
1500         }
1501     }
1502     return RFBand;
1503 }
1504 
1505 /*
1506  * MT2063_Tune() - Change the tuner's tuned frequency to RFin.
1507  */
1508 static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
1509 {               /* RF input center frequency   */
1510 
1511     int status = 0;
1512     u32 LO1;        /*  1st LO register value           */
1513     u32 Num1;       /*  Numerator for LO1 reg. value    */
1514     u32 f_IF1;      /*  1st IF requested                */
1515     u32 LO2;        /*  2nd LO register value           */
1516     u32 Num2;       /*  Numerator for LO2 reg. value    */
1517     u32 ofLO1, ofLO2;   /*  last time's LO frequencies      */
1518     u8 fiffc = 0x80;    /*  FIFF center freq from tuner     */
1519     u32 fiffof;     /*  Offset from FIFF center freq    */
1520     const u8 LO1LK = 0x80;  /*  Mask for LO1 Lock bit           */
1521     u8 LO2LK = 0x08;    /*  Mask for LO2 Lock bit           */
1522     u8 val;
1523     u32 RFBand;
1524 
1525     dprintk(2, "\n");
1526     /*  Check the input and output frequency ranges                   */
1527     if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
1528         return -EINVAL;
1529 
1530     if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
1531         || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
1532         return -EINVAL;
1533 
1534     /*
1535      * Save original LO1 and LO2 register values
1536      */
1537     ofLO1 = state->AS_Data.f_LO1;
1538     ofLO2 = state->AS_Data.f_LO2;
1539 
1540     /*
1541      * Find and set RF Band setting
1542      */
1543     if (state->ctfilt_sw == 1) {
1544         val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
1545         if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
1546             status |=
1547                 mt2063_setreg(state, MT2063_REG_CTUNE_CTRL, val);
1548         }
1549         val = state->reg[MT2063_REG_CTUNE_OV];
1550         RFBand = FindClearTuneFilter(state, f_in);
1551         state->reg[MT2063_REG_CTUNE_OV] =
1552             (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
1553                   | RFBand);
1554         if (state->reg[MT2063_REG_CTUNE_OV] != val) {
1555             status |=
1556                 mt2063_setreg(state, MT2063_REG_CTUNE_OV, val);
1557         }
1558     }
1559 
1560     /*
1561      * Read the FIFF Center Frequency from the tuner
1562      */
1563     if (status >= 0) {
1564         status |=
1565             mt2063_read(state,
1566                    MT2063_REG_FIFFC,
1567                    &state->reg[MT2063_REG_FIFFC], 1);
1568         fiffc = state->reg[MT2063_REG_FIFFC];
1569     }
1570     /*
1571      * Assign in the requested values
1572      */
1573     state->AS_Data.f_in = f_in;
1574     /*  Request a 1st IF such that LO1 is on a step size */
1575     state->AS_Data.f_if1_Request =
1576         MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
1577                  state->AS_Data.f_LO1_Step,
1578                  state->AS_Data.f_ref) - f_in;
1579 
1580     /*
1581      * Calculate frequency settings.  f_IF1_FREQ + f_in is the
1582      * desired LO1 frequency
1583      */
1584     MT2063_ResetExclZones(&state->AS_Data);
1585 
1586     f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
1587 
1588     state->AS_Data.f_LO1 =
1589         MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
1590                  state->AS_Data.f_ref);
1591 
1592     state->AS_Data.f_LO2 =
1593         MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
1594                  state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
1595 
1596     /*
1597      * Check for any LO spurs in the output bandwidth and adjust
1598      * the LO settings to avoid them if needed
1599      */
1600     status |= MT2063_AvoidSpurs(&state->AS_Data);
1601     /*
1602      * MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
1603      * Recalculate the LO frequencies and the values to be placed
1604      * in the tuning registers.
1605      */
1606     state->AS_Data.f_LO1 =
1607         MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
1608                    state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
1609     state->AS_Data.f_LO2 =
1610         MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
1611                  state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
1612     state->AS_Data.f_LO2 =
1613         MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
1614                    state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
1615 
1616     /*
1617      *  Check the upconverter and downconverter frequency ranges
1618      */
1619     if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
1620         || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
1621         status |= MT2063_UPC_RANGE;
1622     if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
1623         || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
1624         status |= MT2063_DNC_RANGE;
1625     /*  LO2 Lock bit was in a different place for B0 version  */
1626     if (state->tuner_id == MT2063_B0)
1627         LO2LK = 0x40;
1628 
1629     /*
1630      *  If we have the same LO frequencies and we're already locked,
1631      *  then skip re-programming the LO registers.
1632      */
1633     if ((ofLO1 != state->AS_Data.f_LO1)
1634         || (ofLO2 != state->AS_Data.f_LO2)
1635         || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
1636         (LO1LK | LO2LK))) {
1637         /*
1638          * Calculate the FIFFOF register value
1639          *
1640          *           IF1_Actual
1641          * FIFFOF = ------------ - 8 * FIFFC - 4992
1642          *            f_ref/64
1643          */
1644         fiffof =
1645             (state->AS_Data.f_LO1 -
1646              f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
1647             4992;
1648         if (fiffof > 0xFF)
1649             fiffof = 0xFF;
1650 
1651         /*
1652          * Place all of the calculated values into the local tuner
1653          * register fields.
1654          */
1655         if (status >= 0) {
1656             state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
1657             state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F);    /* NUM1q */
1658             state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1)  /* DIV2q */
1659                                    |(Num2 >> 12));  /* NUM2q (hi) */
1660             state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4);   /* NUM2q (mid) */
1661             state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
1662 
1663             /*
1664              * Now write out the computed register values
1665              * IMPORTANT: There is a required order for writing
1666              *            (0x05 must follow all the others).
1667              */
1668             status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5);  /* 0x01 - 0x05 */
1669             if (state->tuner_id == MT2063_B0) {
1670                 /* Re-write the one-shot bits to trigger the tune operation */
1671                 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1);  /* 0x05 */
1672             }
1673             /* Write out the FIFF offset only if it's changing */
1674             if (state->reg[MT2063_REG_FIFF_OFFSET] !=
1675                 (u8) fiffof) {
1676                 state->reg[MT2063_REG_FIFF_OFFSET] =
1677                     (u8) fiffof;
1678                 status |=
1679                     mt2063_write(state,
1680                             MT2063_REG_FIFF_OFFSET,
1681                             &state->
1682                             reg[MT2063_REG_FIFF_OFFSET],
1683                             1);
1684             }
1685         }
1686 
1687         /*
1688          * Check for LO's locking
1689          */
1690 
1691         if (status < 0)
1692             return status;
1693 
1694         status = mt2063_lockStatus(state);
1695         if (status < 0)
1696             return status;
1697         if (!status)
1698             return -EINVAL;     /* Couldn't lock */
1699 
1700         /*
1701          * If we locked OK, assign calculated data to mt2063_state structure
1702          */
1703         state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
1704     }
1705 
1706     return status;
1707 }
1708 
1709 static const u8 MT2063B0_defaults[] = {
1710     /* Reg,  Value */
1711     0x19, 0x05,
1712     0x1B, 0x1D,
1713     0x1C, 0x1F,
1714     0x1D, 0x0F,
1715     0x1E, 0x3F,
1716     0x1F, 0x0F,
1717     0x20, 0x3F,
1718     0x22, 0x21,
1719     0x23, 0x3F,
1720     0x24, 0x20,
1721     0x25, 0x3F,
1722     0x27, 0xEE,
1723     0x2C, 0x27, /*  bit at 0x20 is cleared below  */
1724     0x30, 0x03,
1725     0x2C, 0x07, /*  bit at 0x20 is cleared here   */
1726     0x2D, 0x87,
1727     0x2E, 0xAA,
1728     0x28, 0xE1, /*  Set the FIFCrst bit here      */
1729     0x28, 0xE0, /*  Clear the FIFCrst bit here    */
1730     0x00
1731 };
1732 
1733 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
1734 static const u8 MT2063B1_defaults[] = {
1735     /* Reg,  Value */
1736     0x05, 0xF0,
1737     0x11, 0x10, /* New Enable AFCsd */
1738     0x19, 0x05,
1739     0x1A, 0x6C,
1740     0x1B, 0x24,
1741     0x1C, 0x28,
1742     0x1D, 0x8F,
1743     0x1E, 0x14,
1744     0x1F, 0x8F,
1745     0x20, 0x57,
1746     0x22, 0x21, /* New - ver 1.03 */
1747     0x23, 0x3C, /* New - ver 1.10 */
1748     0x24, 0x20, /* New - ver 1.03 */
1749     0x2C, 0x24, /*  bit at 0x20 is cleared below  */
1750     0x2D, 0x87, /*  FIFFQ=0  */
1751     0x2F, 0xF3,
1752     0x30, 0x0C, /* New - ver 1.11 */
1753     0x31, 0x1B, /* New - ver 1.11 */
1754     0x2C, 0x04, /*  bit at 0x20 is cleared here  */
1755     0x28, 0xE1, /*  Set the FIFCrst bit here      */
1756     0x28, 0xE0, /*  Clear the FIFCrst bit here    */
1757     0x00
1758 };
1759 
1760 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
1761 static const u8 MT2063B3_defaults[] = {
1762     /* Reg,  Value */
1763     0x05, 0xF0,
1764     0x19, 0x3D,
1765     0x2C, 0x24, /*  bit at 0x20 is cleared below  */
1766     0x2C, 0x04, /*  bit at 0x20 is cleared here  */
1767     0x28, 0xE1, /*  Set the FIFCrst bit here      */
1768     0x28, 0xE0, /*  Clear the FIFCrst bit here    */
1769     0x00
1770 };
1771 
1772 static int mt2063_init(struct dvb_frontend *fe)
1773 {
1774     int status;
1775     struct mt2063_state *state = fe->tuner_priv;
1776     u8 all_resets = 0xF0;   /* reset/load bits */
1777     const u8 *def = NULL;
1778     char *step;
1779     u32 FCRUN;
1780     s32 maxReads;
1781     u32 fcu_osc;
1782     u32 i;
1783 
1784     dprintk(2, "\n");
1785 
1786     state->rcvr_mode = MT2063_CABLE_QAM;
1787 
1788     /*  Read the Part/Rev code from the tuner */
1789     status = mt2063_read(state, MT2063_REG_PART_REV,
1790                  &state->reg[MT2063_REG_PART_REV], 1);
1791     if (status < 0) {
1792         printk(KERN_ERR "Can't read mt2063 part ID\n");
1793         return status;
1794     }
1795 
1796     /* Check the part/rev code */
1797     switch (state->reg[MT2063_REG_PART_REV]) {
1798     case MT2063_B0:
1799         step = "B0";
1800         break;
1801     case MT2063_B1:
1802         step = "B1";
1803         break;
1804     case MT2063_B2:
1805         step = "B2";
1806         break;
1807     case MT2063_B3:
1808         step = "B3";
1809         break;
1810     default:
1811         printk(KERN_ERR "mt2063: Unknown mt2063 device ID (0x%02x)\n",
1812                state->reg[MT2063_REG_PART_REV]);
1813         return -ENODEV; /*  Wrong tuner Part/Rev code */
1814     }
1815 
1816     /*  Check the 2nd byte of the Part/Rev code from the tuner */
1817     status = mt2063_read(state, MT2063_REG_RSVD_3B,
1818                  &state->reg[MT2063_REG_RSVD_3B], 1);
1819 
1820     /* b7 != 0 ==> NOT MT2063 */
1821     if (status < 0 || ((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) {
1822         printk(KERN_ERR "mt2063: Unknown part ID (0x%02x%02x)\n",
1823                state->reg[MT2063_REG_PART_REV],
1824                state->reg[MT2063_REG_RSVD_3B]);
1825         return -ENODEV; /*  Wrong tuner Part/Rev code */
1826     }
1827 
1828     printk(KERN_INFO "mt2063: detected a mt2063 %s\n", step);
1829 
1830     /*  Reset the tuner  */
1831     status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
1832     if (status < 0)
1833         return status;
1834 
1835     /* change all of the default values that vary from the HW reset values */
1836     /*  def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
1837     switch (state->reg[MT2063_REG_PART_REV]) {
1838     case MT2063_B3:
1839         def = MT2063B3_defaults;
1840         break;
1841 
1842     case MT2063_B1:
1843         def = MT2063B1_defaults;
1844         break;
1845 
1846     case MT2063_B0:
1847         def = MT2063B0_defaults;
1848         break;
1849 
1850     default:
1851         return -ENODEV;
1852     }
1853 
1854     while (status >= 0 && *def) {
1855         u8 reg = *def++;
1856         u8 val = *def++;
1857         status = mt2063_write(state, reg, &val, 1);
1858     }
1859     if (status < 0)
1860         return status;
1861 
1862     /*  Wait for FIFF location to complete.  */
1863     FCRUN = 1;
1864     maxReads = 10;
1865     while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
1866         msleep(2);
1867         status = mt2063_read(state,
1868                      MT2063_REG_XO_STATUS,
1869                      &state->
1870                      reg[MT2063_REG_XO_STATUS], 1);
1871         FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
1872     }
1873 
1874     if (FCRUN != 0 || status < 0)
1875         return -ENODEV;
1876 
1877     status = mt2063_read(state,
1878                MT2063_REG_FIFFC,
1879                &state->reg[MT2063_REG_FIFFC], 1);
1880     if (status < 0)
1881         return status;
1882 
1883     /* Read back all the registers from the tuner */
1884     status = mt2063_read(state,
1885                 MT2063_REG_PART_REV,
1886                 state->reg, MT2063_REG_END_REGS);
1887     if (status < 0)
1888         return status;
1889 
1890     /*  Initialize the tuner state.  */
1891     state->tuner_id = state->reg[MT2063_REG_PART_REV];
1892     state->AS_Data.f_ref = MT2063_REF_FREQ;
1893     state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
1894                       ((u32) state->reg[MT2063_REG_FIFFC] + 640);
1895     state->AS_Data.f_if1_bw = MT2063_IF1_BW;
1896     state->AS_Data.f_out = 43750000UL;
1897     state->AS_Data.f_out_bw = 6750000UL;
1898     state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
1899     state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
1900     state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
1901     state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
1902     state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
1903     state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
1904     state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
1905     state->AS_Data.f_LO1 = 2181000000UL;
1906     state->AS_Data.f_LO2 = 1486249786UL;
1907     state->f_IF1_actual = state->AS_Data.f_if1_Center;
1908     state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
1909     state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
1910     state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
1911     state->num_regs = MT2063_REG_END_REGS;
1912     state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
1913     state->ctfilt_sw = 0;
1914 
1915     state->CTFiltMax[0] = 69230000;
1916     state->CTFiltMax[1] = 105770000;
1917     state->CTFiltMax[2] = 140350000;
1918     state->CTFiltMax[3] = 177110000;
1919     state->CTFiltMax[4] = 212860000;
1920     state->CTFiltMax[5] = 241130000;
1921     state->CTFiltMax[6] = 274370000;
1922     state->CTFiltMax[7] = 309820000;
1923     state->CTFiltMax[8] = 342450000;
1924     state->CTFiltMax[9] = 378870000;
1925     state->CTFiltMax[10] = 416210000;
1926     state->CTFiltMax[11] = 456500000;
1927     state->CTFiltMax[12] = 495790000;
1928     state->CTFiltMax[13] = 534530000;
1929     state->CTFiltMax[14] = 572610000;
1930     state->CTFiltMax[15] = 598970000;
1931     state->CTFiltMax[16] = 635910000;
1932     state->CTFiltMax[17] = 672130000;
1933     state->CTFiltMax[18] = 714840000;
1934     state->CTFiltMax[19] = 739660000;
1935     state->CTFiltMax[20] = 770410000;
1936     state->CTFiltMax[21] = 814660000;
1937     state->CTFiltMax[22] = 846950000;
1938     state->CTFiltMax[23] = 867820000;
1939     state->CTFiltMax[24] = 915980000;
1940     state->CTFiltMax[25] = 947450000;
1941     state->CTFiltMax[26] = 983110000;
1942     state->CTFiltMax[27] = 1021630000;
1943     state->CTFiltMax[28] = 1061870000;
1944     state->CTFiltMax[29] = 1098330000;
1945     state->CTFiltMax[30] = 1138990000;
1946 
1947     /*
1948      **   Fetch the FCU osc value and use it and the fRef value to
1949      **   scale all of the Band Max values
1950      */
1951 
1952     state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
1953     status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
1954                   &state->reg[MT2063_REG_CTUNE_CTRL], 1);
1955     if (status < 0)
1956         return status;
1957 
1958     /*  Read the ClearTune filter calibration value  */
1959     status = mt2063_read(state, MT2063_REG_FIFFC,
1960                  &state->reg[MT2063_REG_FIFFC], 1);
1961     if (status < 0)
1962         return status;
1963 
1964     fcu_osc = state->reg[MT2063_REG_FIFFC];
1965 
1966     state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
1967     status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
1968                   &state->reg[MT2063_REG_CTUNE_CTRL], 1);
1969     if (status < 0)
1970         return status;
1971 
1972     /*  Adjust each of the values in the ClearTune filter cross-over table  */
1973     for (i = 0; i < 31; i++)
1974         state->CTFiltMax[i] = (state->CTFiltMax[i] / 768) * (fcu_osc + 640);
1975 
1976     status = MT2063_SoftwareShutdown(state, 1);
1977     if (status < 0)
1978         return status;
1979     status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
1980     if (status < 0)
1981         return status;
1982 
1983     state->init = true;
1984 
1985     return 0;
1986 }
1987 
1988 static int mt2063_get_status(struct dvb_frontend *fe, u32 *tuner_status)
1989 {
1990     struct mt2063_state *state = fe->tuner_priv;
1991     int status;
1992 
1993     dprintk(2, "\n");
1994 
1995     if (!state->init)
1996         return -ENODEV;
1997 
1998     *tuner_status = 0;
1999     status = mt2063_lockStatus(state);
2000     if (status < 0)
2001         return status;
2002     if (status)
2003         *tuner_status = TUNER_STATUS_LOCKED;
2004 
2005     dprintk(1, "Tuner status: %d", *tuner_status);
2006 
2007     return 0;
2008 }
2009 
2010 static void mt2063_release(struct dvb_frontend *fe)
2011 {
2012     struct mt2063_state *state = fe->tuner_priv;
2013 
2014     dprintk(2, "\n");
2015 
2016     fe->tuner_priv = NULL;
2017     kfree(state);
2018 }
2019 
2020 static int mt2063_set_analog_params(struct dvb_frontend *fe,
2021                     struct analog_parameters *params)
2022 {
2023     struct mt2063_state *state = fe->tuner_priv;
2024     s32 pict_car;
2025     s32 pict2chanb_vsb;
2026     s32 ch_bw;
2027     s32 if_mid;
2028     s32 rcvr_mode;
2029     int status;
2030 
2031     dprintk(2, "\n");
2032 
2033     if (!state->init) {
2034         status = mt2063_init(fe);
2035         if (status < 0)
2036             return status;
2037     }
2038 
2039     switch (params->mode) {
2040     case V4L2_TUNER_RADIO:
2041         pict_car = 38900000;
2042         ch_bw = 8000000;
2043         pict2chanb_vsb = -(ch_bw / 2);
2044         rcvr_mode = MT2063_OFFAIR_ANALOG;
2045         break;
2046     case V4L2_TUNER_ANALOG_TV:
2047         rcvr_mode = MT2063_CABLE_ANALOG;
2048         if (params->std & ~V4L2_STD_MN) {
2049             pict_car = 38900000;
2050             ch_bw = 6000000;
2051             pict2chanb_vsb = -1250000;
2052         } else if (params->std & V4L2_STD_PAL_G) {
2053             pict_car = 38900000;
2054             ch_bw = 7000000;
2055             pict2chanb_vsb = -1250000;
2056         } else {        /* PAL/SECAM standards */
2057             pict_car = 38900000;
2058             ch_bw = 8000000;
2059             pict2chanb_vsb = -1250000;
2060         }
2061         break;
2062     default:
2063         return -EINVAL;
2064     }
2065     if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
2066 
2067     state->AS_Data.f_LO2_Step = 125000; /* FIXME: probably 5000 for FM */
2068     state->AS_Data.f_out = if_mid;
2069     state->AS_Data.f_out_bw = ch_bw + 750000;
2070     status = MT2063_SetReceiverMode(state, rcvr_mode);
2071     if (status < 0)
2072         return status;
2073 
2074     dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
2075         params->frequency, ch_bw, pict2chanb_vsb);
2076 
2077     status = MT2063_Tune(state, (params->frequency + (pict2chanb_vsb + (ch_bw / 2))));
2078     if (status < 0)
2079         return status;
2080 
2081     state->frequency = params->frequency;
2082     return 0;
2083 }
2084 
2085 /*
2086  * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
2087  * So, the amount of the needed bandwidth is given by:
2088  *  Bw = Symbol_rate * (1 + 0.15)
2089  * As such, the maximum symbol rate supported by 6 MHz is given by:
2090  *  max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
2091  */
2092 #define MAX_SYMBOL_RATE_6MHz    5217391
2093 
2094 static int mt2063_set_params(struct dvb_frontend *fe)
2095 {
2096     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
2097     struct mt2063_state *state = fe->tuner_priv;
2098     int status;
2099     s32 pict_car;
2100     s32 pict2chanb_vsb;
2101     s32 ch_bw;
2102     s32 if_mid;
2103     s32 rcvr_mode;
2104 
2105     if (!state->init) {
2106         status = mt2063_init(fe);
2107         if (status < 0)
2108             return status;
2109     }
2110 
2111     dprintk(2, "\n");
2112 
2113     if (c->bandwidth_hz == 0)
2114         return -EINVAL;
2115     if (c->bandwidth_hz <= 6000000)
2116         ch_bw = 6000000;
2117     else if (c->bandwidth_hz <= 7000000)
2118         ch_bw = 7000000;
2119     else
2120         ch_bw = 8000000;
2121 
2122     switch (c->delivery_system) {
2123     case SYS_DVBT:
2124         rcvr_mode = MT2063_OFFAIR_COFDM;
2125         pict_car = 36125000;
2126         pict2chanb_vsb = -(ch_bw / 2);
2127         break;
2128     case SYS_DVBC_ANNEX_A:
2129     case SYS_DVBC_ANNEX_C:
2130         rcvr_mode = MT2063_CABLE_QAM;
2131         pict_car = 36125000;
2132         pict2chanb_vsb = -(ch_bw / 2);
2133         break;
2134     default:
2135         return -EINVAL;
2136     }
2137     if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
2138 
2139     state->AS_Data.f_LO2_Step = 125000; /* FIXME: probably 5000 for FM */
2140     state->AS_Data.f_out = if_mid;
2141     state->AS_Data.f_out_bw = ch_bw + 750000;
2142     status = MT2063_SetReceiverMode(state, rcvr_mode);
2143     if (status < 0)
2144         return status;
2145 
2146     dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
2147         c->frequency, ch_bw, pict2chanb_vsb);
2148 
2149     status = MT2063_Tune(state, (c->frequency + (pict2chanb_vsb + (ch_bw / 2))));
2150 
2151     if (status < 0)
2152         return status;
2153 
2154     state->frequency = c->frequency;
2155     return 0;
2156 }
2157 
2158 static int mt2063_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
2159 {
2160     struct mt2063_state *state = fe->tuner_priv;
2161 
2162     dprintk(2, "\n");
2163 
2164     if (!state->init)
2165         return -ENODEV;
2166 
2167     *freq = state->AS_Data.f_out;
2168 
2169     dprintk(1, "IF frequency: %d\n", *freq);
2170 
2171     return 0;
2172 }
2173 
2174 static int mt2063_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
2175 {
2176     struct mt2063_state *state = fe->tuner_priv;
2177 
2178     dprintk(2, "\n");
2179 
2180     if (!state->init)
2181         return -ENODEV;
2182 
2183     *bw = state->AS_Data.f_out_bw - 750000;
2184 
2185     dprintk(1, "bandwidth: %d\n", *bw);
2186 
2187     return 0;
2188 }
2189 
2190 static const struct dvb_tuner_ops mt2063_ops = {
2191     .info = {
2192          .name = "MT2063 Silicon Tuner",
2193          .frequency_min_hz  =  45 * MHz,
2194          .frequency_max_hz  = 865 * MHz,
2195      },
2196 
2197     .init = mt2063_init,
2198     .sleep = MT2063_Sleep,
2199     .get_status = mt2063_get_status,
2200     .set_analog_params = mt2063_set_analog_params,
2201     .set_params    = mt2063_set_params,
2202     .get_if_frequency = mt2063_get_if_frequency,
2203     .get_bandwidth = mt2063_get_bandwidth,
2204     .release = mt2063_release,
2205 };
2206 
2207 struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
2208                    struct mt2063_config *config,
2209                    struct i2c_adapter *i2c)
2210 {
2211     struct mt2063_state *state = NULL;
2212 
2213     dprintk(2, "\n");
2214 
2215     state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
2216     if (!state)
2217         return NULL;
2218 
2219     state->config = config;
2220     state->i2c = i2c;
2221     state->frontend = fe;
2222     state->reference = config->refclock / 1000; /* kHz */
2223     fe->tuner_priv = state;
2224     fe->ops.tuner_ops = mt2063_ops;
2225 
2226     printk(KERN_INFO "%s: Attaching MT2063\n", __func__);
2227     return fe;
2228 }
2229 EXPORT_SYMBOL_GPL(mt2063_attach);
2230 
2231 #if 0
2232 /*
2233  * Ancillary routines visible outside mt2063
2234  * FIXME: Remove them in favor of using standard tuner callbacks
2235  */
2236 static int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
2237 {
2238     struct mt2063_state *state = fe->tuner_priv;
2239     int err = 0;
2240 
2241     dprintk(2, "\n");
2242 
2243     err = MT2063_SoftwareShutdown(state, 1);
2244     if (err < 0)
2245         printk(KERN_ERR "%s: Couldn't shutdown\n", __func__);
2246 
2247     return err;
2248 }
2249 
2250 static int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
2251 {
2252     struct mt2063_state *state = fe->tuner_priv;
2253     int err = 0;
2254 
2255     dprintk(2, "\n");
2256 
2257     err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
2258     if (err < 0)
2259         printk(KERN_ERR "%s: Invalid parameter\n", __func__);
2260 
2261     return err;
2262 }
2263 #endif
2264 
2265 MODULE_AUTHOR("Mauro Carvalho Chehab");
2266 MODULE_DESCRIPTION("MT2063 Silicon tuner");
2267 MODULE_LICENSE("GPL");