linux/drivers/media/tuners/mt2063.c
<<
>>
Prefs
   1/*
   2 * Driver for mt2063 Micronas tuner
   3 *
   4 * Copyright (c) 2011 Mauro Carvalho Chehab <mchehab@redhat.com>
   5 *
   6 * This driver came from a driver originally written by:
   7 *              Henry Wang <Henry.wang@AzureWave.com>
   8 * Made publicly available by Terratec, at:
   9 *      http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
  10 * The original driver's license is GPL, as declared with MODULE_LICENSE()
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation under version 2 of the License.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 */
  21
  22#include <linux/init.h>
  23#include <linux/kernel.h>
  24#include <linux/module.h>
  25#include <linux/string.h>
  26#include <linux/videodev2.h>
  27
  28#include "mt2063.h"
  29
  30static unsigned int debug;
  31module_param(debug, int, 0644);
  32MODULE_PARM_DESC(debug, "Set Verbosity level");
  33
  34#define dprintk(level, fmt, arg...) do {                                \
  35if (debug >= level)                                                     \
  36        printk(KERN_DEBUG "mt2063 %s: " fmt, __func__, ## arg); \
  37} while (0)
  38
  39
  40/* positive error codes used internally */
  41
  42/*  Info: Unavoidable LO-related spur may be present in the output  */
  43#define MT2063_SPUR_PRESENT_ERR             (0x00800000)
  44
  45/*  Info: Mask of bits used for # of LO-related spurs that were avoided during tuning  */
  46#define MT2063_SPUR_CNT_MASK                (0x001f0000)
  47#define MT2063_SPUR_SHIFT                   (16)
  48
  49/*  Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
  50#define MT2063_UPC_RANGE                    (0x04000000)
  51
  52/*  Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
  53#define MT2063_DNC_RANGE                    (0x08000000)
  54
  55/*
  56 *  Constant defining the version of the following structure
  57 *  and therefore the API for this code.
  58 *
  59 *  When compiling the tuner driver, the preprocessor will
  60 *  check against this version number to make sure that
  61 *  it matches the version that the tuner driver knows about.
  62 */
  63
  64/* DECT Frequency Avoidance */
  65#define MT2063_DECT_AVOID_US_FREQS      0x00000001
  66
  67#define MT2063_DECT_AVOID_EURO_FREQS    0x00000002
  68
  69#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
  70
  71#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
  72
  73enum MT2063_DECT_Avoid_Type {
  74        MT2063_NO_DECT_AVOIDANCE = 0,                           /* Do not create DECT exclusion zones.     */
  75        MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS,      /* Avoid US DECT frequencies.              */
  76        MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS,  /* Avoid European DECT frequencies.        */
  77        MT2063_AVOID_BOTH                                       /* Avoid both regions. Not typically used. */
  78};
  79
  80#define MT2063_MAX_ZONES 48
  81
  82struct MT2063_ExclZone_t {
  83        u32 min_;
  84        u32 max_;
  85        struct MT2063_ExclZone_t *next_;
  86};
  87
  88/*
  89 *  Structure of data needed for Spur Avoidance
  90 */
  91struct MT2063_AvoidSpursData_t {
  92        u32 f_ref;
  93        u32 f_in;
  94        u32 f_LO1;
  95        u32 f_if1_Center;
  96        u32 f_if1_Request;
  97        u32 f_if1_bw;
  98        u32 f_LO2;
  99        u32 f_out;
 100        u32 f_out_bw;
 101        u32 f_LO1_Step;
 102        u32 f_LO2_Step;
 103        u32 f_LO1_FracN_Avoid;
 104        u32 f_LO2_FracN_Avoid;
 105        u32 f_zif_bw;
 106        u32 f_min_LO_Separation;
 107        u32 maxH1;
 108        u32 maxH2;
 109        enum MT2063_DECT_Avoid_Type avoidDECT;
 110        u32 bSpurPresent;
 111        u32 bSpurAvoided;
 112        u32 nSpursFound;
 113        u32 nZones;
 114        struct MT2063_ExclZone_t *freeZones;
 115        struct MT2063_ExclZone_t *usedZones;
 116        struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
 117};
 118
 119/*
 120 * Parameter for function MT2063_SetPowerMask that specifies the power down
 121 * of various sections of the MT2063.
 122 */
 123enum MT2063_Mask_Bits {
 124        MT2063_REG_SD = 0x0040,         /* Shutdown regulator                 */
 125        MT2063_SRO_SD = 0x0020,         /* Shutdown SRO                       */
 126        MT2063_AFC_SD = 0x0010,         /* Shutdown AFC A/D                   */
 127        MT2063_PD_SD = 0x0002,          /* Enable power detector shutdown     */
 128        MT2063_PDADC_SD = 0x0001,       /* Enable power detector A/D shutdown */
 129        MT2063_VCO_SD = 0x8000,         /* Enable VCO shutdown                */
 130        MT2063_LTX_SD = 0x4000,         /* Enable LTX shutdown                */
 131        MT2063_LT1_SD = 0x2000,         /* Enable LT1 shutdown                */
 132        MT2063_LNA_SD = 0x1000,         /* Enable LNA shutdown                */
 133        MT2063_UPC_SD = 0x0800,         /* Enable upconverter shutdown        */
 134        MT2063_DNC_SD = 0x0400,         /* Enable downconverter shutdown      */
 135        MT2063_VGA_SD = 0x0200,         /* Enable VGA shutdown                */
 136        MT2063_AMP_SD = 0x0100,         /* Enable AMP shutdown                */
 137        MT2063_ALL_SD = 0xFF73,         /* All shutdown bits for this tuner   */
 138        MT2063_NONE_SD = 0x0000         /* No shutdown bits                   */
 139};
 140
 141/*
 142 *  Possible values for MT2063_DNC_OUTPUT
 143 */
 144enum MT2063_DNC_Output_Enable {
 145        MT2063_DNC_NONE = 0,
 146        MT2063_DNC_1,
 147        MT2063_DNC_2,
 148        MT2063_DNC_BOTH
 149};
 150
 151/*
 152 *  Two-wire serial bus subaddresses of the tuner registers.
 153 *  Also known as the tuner's register addresses.
 154 */
 155enum MT2063_Register_Offsets {
 156        MT2063_REG_PART_REV = 0,        /*  0x00: Part/Rev Code         */
 157        MT2063_REG_LO1CQ_1,             /*  0x01: LO1C Queued Byte 1    */
 158        MT2063_REG_LO1CQ_2,             /*  0x02: LO1C Queued Byte 2    */
 159        MT2063_REG_LO2CQ_1,             /*  0x03: LO2C Queued Byte 1    */
 160        MT2063_REG_LO2CQ_2,             /*  0x04: LO2C Queued Byte 2    */
 161        MT2063_REG_LO2CQ_3,             /*  0x05: LO2C Queued Byte 3    */
 162        MT2063_REG_RSVD_06,             /*  0x06: Reserved              */
 163        MT2063_REG_LO_STATUS,           /*  0x07: LO Status             */
 164        MT2063_REG_FIFFC,               /*  0x08: FIFF Center           */
 165        MT2063_REG_CLEARTUNE,           /*  0x09: ClearTune Filter      */
 166        MT2063_REG_ADC_OUT,             /*  0x0A: ADC_OUT               */
 167        MT2063_REG_LO1C_1,              /*  0x0B: LO1C Byte 1           */
 168        MT2063_REG_LO1C_2,              /*  0x0C: LO1C Byte 2           */
 169        MT2063_REG_LO2C_1,              /*  0x0D: LO2C Byte 1           */
 170        MT2063_REG_LO2C_2,              /*  0x0E: LO2C Byte 2           */
 171        MT2063_REG_LO2C_3,              /*  0x0F: LO2C Byte 3           */
 172        MT2063_REG_RSVD_10,             /*  0x10: Reserved              */
 173        MT2063_REG_PWR_1,               /*  0x11: PWR Byte 1            */
 174        MT2063_REG_PWR_2,               /*  0x12: PWR Byte 2            */
 175        MT2063_REG_TEMP_STATUS,         /*  0x13: Temp Status           */
 176        MT2063_REG_XO_STATUS,           /*  0x14: Crystal Status        */
 177        MT2063_REG_RF_STATUS,           /*  0x15: RF Attn Status        */
 178        MT2063_REG_FIF_STATUS,          /*  0x16: FIF Attn Status       */
 179        MT2063_REG_LNA_OV,              /*  0x17: LNA Attn Override     */
 180        MT2063_REG_RF_OV,               /*  0x18: RF Attn Override      */
 181        MT2063_REG_FIF_OV,              /*  0x19: FIF Attn Override     */
 182        MT2063_REG_LNA_TGT,             /*  0x1A: Reserved              */
 183        MT2063_REG_PD1_TGT,             /*  0x1B: Pwr Det 1 Target      */
 184        MT2063_REG_PD2_TGT,             /*  0x1C: Pwr Det 2 Target      */
 185        MT2063_REG_RSVD_1D,             /*  0x1D: Reserved              */
 186        MT2063_REG_RSVD_1E,             /*  0x1E: Reserved              */
 187        MT2063_REG_RSVD_1F,             /*  0x1F: Reserved              */
 188        MT2063_REG_RSVD_20,             /*  0x20: Reserved              */
 189        MT2063_REG_BYP_CTRL,            /*  0x21: Bypass Control        */
 190        MT2063_REG_RSVD_22,             /*  0x22: Reserved              */
 191        MT2063_REG_RSVD_23,             /*  0x23: Reserved              */
 192        MT2063_REG_RSVD_24,             /*  0x24: Reserved              */
 193        MT2063_REG_RSVD_25,             /*  0x25: Reserved              */
 194        MT2063_REG_RSVD_26,             /*  0x26: Reserved              */
 195        MT2063_REG_RSVD_27,             /*  0x27: Reserved              */
 196        MT2063_REG_FIFF_CTRL,           /*  0x28: FIFF Control          */
 197        MT2063_REG_FIFF_OFFSET,         /*  0x29: FIFF Offset           */
 198        MT2063_REG_CTUNE_CTRL,          /*  0x2A: Reserved              */
 199        MT2063_REG_CTUNE_OV,            /*  0x2B: Reserved              */
 200        MT2063_REG_CTRL_2C,             /*  0x2C: Reserved              */
 201        MT2063_REG_FIFF_CTRL2,          /*  0x2D: Fiff Control          */
 202        MT2063_REG_RSVD_2E,             /*  0x2E: Reserved              */
 203        MT2063_REG_DNC_GAIN,            /*  0x2F: DNC Control           */
 204        MT2063_REG_VGA_GAIN,            /*  0x30: VGA Gain Ctrl         */
 205        MT2063_REG_RSVD_31,             /*  0x31: Reserved              */
 206        MT2063_REG_TEMP_SEL,            /*  0x32: Temperature Selection */
 207        MT2063_REG_RSVD_33,             /*  0x33: Reserved              */
 208        MT2063_REG_RSVD_34,             /*  0x34: Reserved              */
 209        MT2063_REG_RSVD_35,             /*  0x35: Reserved              */
 210        MT2063_REG_RSVD_36,             /*  0x36: Reserved              */
 211        MT2063_REG_RSVD_37,             /*  0x37: Reserved              */
 212        MT2063_REG_RSVD_38,             /*  0x38: Reserved              */
 213        MT2063_REG_RSVD_39,             /*  0x39: Reserved              */
 214        MT2063_REG_RSVD_3A,             /*  0x3A: Reserved              */
 215        MT2063_REG_RSVD_3B,             /*  0x3B: Reserved              */
 216        MT2063_REG_RSVD_3C,             /*  0x3C: Reserved              */
 217        MT2063_REG_END_REGS
 218};
 219
 220struct mt2063_state {
 221        struct i2c_adapter *i2c;
 222
 223        bool init;
 224
 225        const struct mt2063_config *config;
 226        struct dvb_tuner_ops ops;
 227        struct dvb_frontend *frontend;
 228        struct tuner_state status;
 229
 230        u32 frequency;
 231        u32 srate;
 232        u32 bandwidth;
 233        u32 reference;
 234
 235        u32 tuner_id;
 236        struct MT2063_AvoidSpursData_t AS_Data;
 237        u32 f_IF1_actual;
 238        u32 rcvr_mode;
 239        u32 ctfilt_sw;
 240        u32 CTFiltMax[31];
 241        u32 num_regs;
 242        u8 reg[MT2063_REG_END_REGS];
 243};
 244
 245/*
 246 * mt2063_write - Write data into the I2C bus
 247 */
 248static int mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
 249{
 250        struct dvb_frontend *fe = state->frontend;
 251        int ret;
 252        u8 buf[60];
 253        struct i2c_msg msg = {
 254                .addr = state->config->tuner_address,
 255                .flags = 0,
 256                .buf = buf,
 257                .len = len + 1
 258        };
 259
 260        dprintk(2, "\n");
 261
 262        msg.buf[0] = reg;
 263        memcpy(msg.buf + 1, data, len);
 264
 265        if (fe->ops.i2c_gate_ctrl)
 266                fe->ops.i2c_gate_ctrl(fe, 1);
 267        ret = i2c_transfer(state->i2c, &msg, 1);
 268        if (fe->ops.i2c_gate_ctrl)
 269                fe->ops.i2c_gate_ctrl(fe, 0);
 270
 271        if (ret < 0)
 272                printk(KERN_ERR "%s error ret=%d\n", __func__, ret);
 273
 274        return ret;
 275}
 276
 277/*
 278 * mt2063_write - Write register data into the I2C bus, caching the value
 279 */
 280static int mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
 281{
 282        int status;
 283
 284        dprintk(2, "\n");
 285
 286        if (reg >= MT2063_REG_END_REGS)
 287                return -ERANGE;
 288
 289        status = mt2063_write(state, reg, &val, 1);
 290        if (status < 0)
 291                return status;
 292
 293        state->reg[reg] = val;
 294
 295        return 0;
 296}
 297
 298/*
 299 * mt2063_read - Read data from the I2C bus
 300 */
 301static int mt2063_read(struct mt2063_state *state,
 302                           u8 subAddress, u8 *pData, u32 cnt)
 303{
 304        int status = 0; /* Status to be returned        */
 305        struct dvb_frontend *fe = state->frontend;
 306        u32 i = 0;
 307
 308        dprintk(2, "addr 0x%02x, cnt %d\n", subAddress, cnt);
 309
 310        if (fe->ops.i2c_gate_ctrl)
 311                fe->ops.i2c_gate_ctrl(fe, 1);
 312
 313        for (i = 0; i < cnt; i++) {
 314                u8 b0[] = { subAddress + i };
 315                struct i2c_msg msg[] = {
 316                        {
 317                                .addr = state->config->tuner_address,
 318                                .flags = 0,
 319                                .buf = b0,
 320                                .len = 1
 321                        }, {
 322                                .addr = state->config->tuner_address,
 323                                .flags = I2C_M_RD,
 324                                .buf = pData + i,
 325                                .len = 1
 326                        }
 327                };
 328
 329                status = i2c_transfer(state->i2c, msg, 2);
 330                dprintk(2, "addr 0x%02x, ret = %d, val = 0x%02x\n",
 331                           subAddress + i, status, *(pData + i));
 332                if (status < 0)
 333                        break;
 334        }
 335        if (fe->ops.i2c_gate_ctrl)
 336                fe->ops.i2c_gate_ctrl(fe, 0);
 337
 338        if (status < 0)
 339                printk(KERN_ERR "Can't read from address 0x%02x,\n",
 340                       subAddress + i);
 341
 342        return status;
 343}
 344
 345/*
 346 * FIXME: Is this really needed?
 347 */
 348static int MT2063_Sleep(struct dvb_frontend *fe)
 349{
 350        /*
 351         *  ToDo:  Add code here to implement a OS blocking
 352         */
 353        msleep(100);
 354
 355        return 0;
 356}
 357
 358/*
 359 * Microtune spur avoidance
 360 */
 361
 362/*  Implement ceiling, floor functions.  */
 363#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
 364#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
 365
 366struct MT2063_FIFZone_t {
 367        s32 min_;
 368        s32 max_;
 369};
 370
 371static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
 372                                            *pAS_Info,
 373                                            struct MT2063_ExclZone_t *pPrevNode)
 374{
 375        struct MT2063_ExclZone_t *pNode;
 376
 377        dprintk(2, "\n");
 378
 379        /*  Check for a node in the free list  */
 380        if (pAS_Info->freeZones != NULL) {
 381                /*  Use one from the free list  */
 382                pNode = pAS_Info->freeZones;
 383                pAS_Info->freeZones = pNode->next_;
 384        } else {
 385                /*  Grab a node from the array  */
 386                pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
 387        }
 388
 389        if (pPrevNode != NULL) {
 390                pNode->next_ = pPrevNode->next_;
 391                pPrevNode->next_ = pNode;
 392        } else {                /*  insert at the beginning of the list  */
 393
 394                pNode->next_ = pAS_Info->usedZones;
 395                pAS_Info->usedZones = pNode;
 396        }
 397
 398        pAS_Info->nZones++;
 399        return pNode;
 400}
 401
 402static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
 403                                            *pAS_Info,
 404                                            struct MT2063_ExclZone_t *pPrevNode,
 405                                            struct MT2063_ExclZone_t
 406                                            *pNodeToRemove)
 407{
 408        struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
 409
 410        dprintk(2, "\n");
 411
 412        /*  Make previous node point to the subsequent node  */
 413        if (pPrevNode != NULL)
 414                pPrevNode->next_ = pNext;
 415
 416        /*  Add pNodeToRemove to the beginning of the freeZones  */
 417        pNodeToRemove->next_ = pAS_Info->freeZones;
 418        pAS_Info->freeZones = pNodeToRemove;
 419
 420        /*  Decrement node count  */
 421        pAS_Info->nZones--;
 422
 423        return pNext;
 424}
 425
 426/*
 427 * MT_AddExclZone()
 428 *
 429 * Add (and merge) an exclusion zone into the list.
 430 * If the range (f_min, f_max) is totally outside the
 431 * 1st IF BW, ignore the entry.
 432 * If the range (f_min, f_max) is negative, ignore the entry.
 433 */
 434static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
 435                               u32 f_min, u32 f_max)
 436{
 437        struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
 438        struct MT2063_ExclZone_t *pPrev = NULL;
 439        struct MT2063_ExclZone_t *pNext = NULL;
 440
 441        dprintk(2, "\n");
 442
 443        /*  Check to see if this overlaps the 1st IF filter  */
 444        if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
 445            && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
 446            && (f_min < f_max)) {
 447                /*
 448                 *                1        2         3      4       5        6
 449                 *
 450                 *   New entry:  |---|    |--|      |--|    |-|    |---|    |--|
 451                 *                or       or        or     or      or
 452                 *   Existing:  |--|      |--|      |--|    |---|  |-|      |--|
 453                 */
 454
 455                /*  Check for our place in the list  */
 456                while ((pNode != NULL) && (pNode->max_ < f_min)) {
 457                        pPrev = pNode;
 458                        pNode = pNode->next_;
 459                }
 460
 461                if ((pNode != NULL) && (pNode->min_ < f_max)) {
 462                        /*  Combine me with pNode  */
 463                        if (f_min < pNode->min_)
 464                                pNode->min_ = f_min;
 465                        if (f_max > pNode->max_)
 466                                pNode->max_ = f_max;
 467                } else {
 468                        pNode = InsertNode(pAS_Info, pPrev);
 469                        pNode->min_ = f_min;
 470                        pNode->max_ = f_max;
 471                }
 472
 473                /*  Look for merging possibilities  */
 474                pNext = pNode->next_;
 475                while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
 476                        if (pNext->max_ > pNode->max_)
 477                                pNode->max_ = pNext->max_;
 478                        /*  Remove pNext, return ptr to pNext->next  */
 479                        pNext = RemoveNode(pAS_Info, pNode, pNext);
 480                }
 481        }
 482}
 483
 484/*
 485 *  Reset all exclusion zones.
 486 *  Add zones to protect the PLL FracN regions near zero
 487 */
 488static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
 489{
 490        u32 center;
 491
 492        dprintk(2, "\n");
 493
 494        pAS_Info->nZones = 0;   /*  this clears the used list  */
 495        pAS_Info->usedZones = NULL;     /*  reset ptr                  */
 496        pAS_Info->freeZones = NULL;     /*  reset ptr                  */
 497
 498        center =
 499            pAS_Info->f_ref *
 500            ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
 501              pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
 502        while (center <
 503               pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
 504               pAS_Info->f_LO1_FracN_Avoid) {
 505                /*  Exclude LO1 FracN  */
 506                MT2063_AddExclZone(pAS_Info,
 507                                   center - pAS_Info->f_LO1_FracN_Avoid,
 508                                   center - 1);
 509                MT2063_AddExclZone(pAS_Info, center + 1,
 510                                   center + pAS_Info->f_LO1_FracN_Avoid);
 511                center += pAS_Info->f_ref;
 512        }
 513
 514        center =
 515            pAS_Info->f_ref *
 516            ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
 517              pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
 518        while (center <
 519               pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
 520               pAS_Info->f_LO2_FracN_Avoid) {
 521                /*  Exclude LO2 FracN  */
 522                MT2063_AddExclZone(pAS_Info,
 523                                   center - pAS_Info->f_LO2_FracN_Avoid,
 524                                   center - 1);
 525                MT2063_AddExclZone(pAS_Info, center + 1,
 526                                   center + pAS_Info->f_LO2_FracN_Avoid);
 527                center += pAS_Info->f_ref;
 528        }
 529
 530        if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
 531                /*  Exclude LO1 values that conflict with DECT channels */
 532                MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
 533                MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
 534                MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
 535                MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
 536                MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
 537        }
 538
 539        if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
 540                MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
 541                MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
 542                MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
 543                MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16  */
 544                MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
 545                MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
 546                MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
 547                MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
 548                MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52  */
 549                MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
 550        }
 551}
 552
 553/*
 554 * MT_ChooseFirstIF - Choose the best available 1st IF
 555 *                    If f_Desired is not excluded, choose that first.
 556 *                    Otherwise, return the value closest to f_Center that is
 557 *                    not excluded
 558 */
 559static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
 560{
 561        /*
 562         * Update "f_Desired" to be the nearest "combinational-multiple" of
 563         * "f_LO1_Step".
 564         * The resulting number, F_LO1 must be a multiple of f_LO1_Step.
 565         * And F_LO1 is the arithmetic sum of f_in + f_Center.
 566         * Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
 567         * However, the sum must be.
 568         */
 569        const u32 f_Desired =
 570            pAS_Info->f_LO1_Step *
 571            ((pAS_Info->f_if1_Request + pAS_Info->f_in +
 572              pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
 573            pAS_Info->f_in;
 574        const u32 f_Step =
 575            (pAS_Info->f_LO1_Step >
 576             pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
 577            f_LO2_Step;
 578        u32 f_Center;
 579        s32 i;
 580        s32 j = 0;
 581        u32 bDesiredExcluded = 0;
 582        u32 bZeroExcluded = 0;
 583        s32 tmpMin, tmpMax;
 584        s32 bestDiff;
 585        struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
 586        struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
 587
 588        dprintk(2, "\n");
 589
 590        if (pAS_Info->nZones == 0)
 591                return f_Desired;
 592
 593        /*
 594         *  f_Center needs to be an integer multiple of f_Step away
 595         *  from f_Desired
 596         */
 597        if (pAS_Info->f_if1_Center > f_Desired)
 598                f_Center =
 599                    f_Desired +
 600                    f_Step *
 601                    ((pAS_Info->f_if1_Center - f_Desired +
 602                      f_Step / 2) / f_Step);
 603        else
 604                f_Center =
 605                    f_Desired -
 606                    f_Step *
 607                    ((f_Desired - pAS_Info->f_if1_Center +
 608                      f_Step / 2) / f_Step);
 609
 610        /*
 611         * Take MT_ExclZones, center around f_Center and change the
 612         * resolution to f_Step
 613         */
 614        while (pNode != NULL) {
 615                /*  floor function  */
 616                tmpMin =
 617                    floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
 618
 619                /*  ceil function  */
 620                tmpMax =
 621                    ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
 622
 623                if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
 624                        bDesiredExcluded = 1;
 625
 626                if ((tmpMin < 0) && (tmpMax > 0))
 627                        bZeroExcluded = 1;
 628
 629                /*  See if this zone overlaps the previous  */
 630                if ((j > 0) && (tmpMin < zones[j - 1].max_))
 631                        zones[j - 1].max_ = tmpMax;
 632                else {
 633                        /*  Add new zone  */
 634                        zones[j].min_ = tmpMin;
 635                        zones[j].max_ = tmpMax;
 636                        j++;
 637                }
 638                pNode = pNode->next_;
 639        }
 640
 641        /*
 642         *  If the desired is okay, return with it
 643         */
 644        if (bDesiredExcluded == 0)
 645                return f_Desired;
 646
 647        /*
 648         *  If the desired is excluded and the center is okay, return with it
 649         */
 650        if (bZeroExcluded == 0)
 651                return f_Center;
 652
 653        /*  Find the value closest to 0 (f_Center)  */
 654        bestDiff = zones[0].min_;
 655        for (i = 0; i < j; i++) {
 656                if (abs(zones[i].min_) < abs(bestDiff))
 657                        bestDiff = zones[i].min_;
 658                if (abs(zones[i].max_) < abs(bestDiff))
 659                        bestDiff = zones[i].max_;
 660        }
 661
 662        if (bestDiff < 0)
 663                return f_Center - ((u32) (-bestDiff) * f_Step);
 664
 665        return f_Center + (bestDiff * f_Step);
 666}
 667
 668/**
 669 * gcd() - Uses Euclid's algorithm
 670 *
 671 * @u, @v:      Unsigned values whose GCD is desired.
 672 *
 673 * Returns THE greatest common divisor of u and v, if either value is 0,
 674 * the other value is returned as the result.
 675 */
 676static u32 MT2063_gcd(u32 u, u32 v)
 677{
 678        u32 r;
 679
 680        while (v != 0) {
 681                r = u % v;
 682                u = v;
 683                v = r;
 684        }
 685
 686        return u;
 687}
 688
 689/**
 690 * IsSpurInBand() - Checks to see if a spur will be present within the IF's
 691 *                  bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
 692 *
 693 *                    ma   mb                                     mc   md
 694 *                  <--+-+-+-------------------+-------------------+-+-+-->
 695 *                     |   ^                   0                   ^   |
 696 *                     ^   b=-fIFOut+fIFBW/2      -b=+fIFOut-fIFBW/2   ^
 697 *                     a=-fIFOut-fIFBW/2              -a=+fIFOut+fIFBW/2
 698 *
 699 *                  Note that some equations are doubled to prevent round-off
 700 *                  problems when calculating fIFBW/2
 701 *
 702 * @pAS_Info:   Avoid Spurs information block
 703 * @fm:         If spur, amount f_IF1 has to move negative
 704 * @fp:         If spur, amount f_IF1 has to move positive
 705 *
 706 *  Returns 1 if an LO spur would be present, otherwise 0.
 707 */
 708static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
 709                        u32 *fm, u32 * fp)
 710{
 711        /*
 712         **  Calculate LO frequency settings.
 713         */
 714        u32 n, n0;
 715        const u32 f_LO1 = pAS_Info->f_LO1;
 716        const u32 f_LO2 = pAS_Info->f_LO2;
 717        const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
 718        const u32 c = d - pAS_Info->f_out_bw;
 719        const u32 f = pAS_Info->f_zif_bw / 2;
 720        const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
 721        s32 f_nsLO1, f_nsLO2;
 722        s32 f_Spur;
 723        u32 ma, mb, mc, md, me, mf;
 724        u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
 725
 726        dprintk(2, "\n");
 727
 728        *fm = 0;
 729
 730        /*
 731         ** For each edge (d, c & f), calculate a scale, based on the gcd
 732         ** of f_LO1, f_LO2 and the edge value.  Use the larger of this
 733         ** gcd-based scale factor or f_Scale.
 734         */
 735        lo_gcd = MT2063_gcd(f_LO1, f_LO2);
 736        gd_Scale = max((u32) MT2063_gcd(lo_gcd, d), f_Scale);
 737        hgds = gd_Scale / 2;
 738        gc_Scale = max((u32) MT2063_gcd(lo_gcd, c), f_Scale);
 739        hgcs = gc_Scale / 2;
 740        gf_Scale = max((u32) MT2063_gcd(lo_gcd, f), f_Scale);
 741        hgfs = gf_Scale / 2;
 742
 743        n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
 744
 745        /*  Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic  */
 746        for (n = n0; n <= pAS_Info->maxH1; ++n) {
 747                md = (n * ((f_LO1 + hgds) / gd_Scale) -
 748                      ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
 749
 750                /*  If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present  */
 751                if (md >= pAS_Info->maxH1)
 752                        break;
 753
 754                ma = (n * ((f_LO1 + hgds) / gd_Scale) +
 755                      ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
 756
 757                /*  If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic  */
 758                if (md == ma)
 759                        continue;
 760
 761                mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
 762                      ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
 763                if (mc != md) {
 764                        f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
 765                        f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
 766                        f_Spur =
 767                            (gc_Scale * (f_nsLO1 - f_nsLO2)) +
 768                            n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
 769
 770                        *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
 771                        *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
 772                        return 1;
 773                }
 774
 775                /*  Location of Zero-IF-spur to be checked  */
 776                me = (n * ((f_LO1 + hgfs) / gf_Scale) +
 777                      ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
 778                mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
 779                      ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
 780                if (me != mf) {
 781                        f_nsLO1 = n * (f_LO1 / gf_Scale);
 782                        f_nsLO2 = me * (f_LO2 / gf_Scale);
 783                        f_Spur =
 784                            (gf_Scale * (f_nsLO1 - f_nsLO2)) +
 785                            n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
 786
 787                        *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
 788                        *fm = (((s32) f - f_Spur) / (me - n)) + 1;
 789                        return 1;
 790                }
 791
 792                mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
 793                      ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
 794                if (ma != mb) {
 795                        f_nsLO1 = n * (f_LO1 / gc_Scale);
 796                        f_nsLO2 = ma * (f_LO2 / gc_Scale);
 797                        f_Spur =
 798                            (gc_Scale * (f_nsLO1 - f_nsLO2)) +
 799                            n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
 800
 801                        *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
 802                        *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
 803                        return 1;
 804                }
 805        }
 806
 807        /*  No spurs found  */
 808        return 0;
 809}
 810
 811/*
 812 * MT_AvoidSpurs() - Main entry point to avoid spurs.
 813 *                   Checks for existing spurs in present LO1, LO2 freqs
 814 *                   and if present, chooses spur-free LO1, LO2 combination
 815 *                   that tunes the same input/output frequencies.
 816 */
 817static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
 818{
 819        int status = 0;
 820        u32 fm, fp;             /*  restricted range on LO's        */
 821        pAS_Info->bSpurAvoided = 0;
 822        pAS_Info->nSpursFound = 0;
 823
 824        dprintk(2, "\n");
 825
 826        if (pAS_Info->maxH1 == 0)
 827                return 0;
 828
 829        /*
 830         * Avoid LO Generated Spurs
 831         *
 832         * Make sure that have no LO-related spurs within the IF output
 833         * bandwidth.
 834         *
 835         * If there is an LO spur in this band, start at the current IF1 frequency
 836         * and work out until we find a spur-free frequency or run up against the
 837         * 1st IF SAW band edge.  Use temporary copies of fLO1 and fLO2 so that they
 838         * will be unchanged if a spur-free setting is not found.
 839         */
 840        pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
 841        if (pAS_Info->bSpurPresent) {
 842                u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in;   /*  current attempt at a 1st IF  */
 843                u32 zfLO1 = pAS_Info->f_LO1;    /*  current attempt at an LO1 freq  */
 844                u32 zfLO2 = pAS_Info->f_LO2;    /*  current attempt at an LO2 freq  */
 845                u32 delta_IF1;
 846                u32 new_IF1;
 847
 848                /*
 849                 **  Spur was found, attempt to find a spur-free 1st IF
 850                 */
 851                do {
 852                        pAS_Info->nSpursFound++;
 853
 854                        /*  Raise f_IF1_upper, if needed  */
 855                        MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
 856
 857                        /*  Choose next IF1 that is closest to f_IF1_CENTER              */
 858                        new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
 859
 860                        if (new_IF1 > zfIF1) {
 861                                pAS_Info->f_LO1 += (new_IF1 - zfIF1);
 862                                pAS_Info->f_LO2 += (new_IF1 - zfIF1);
 863                        } else {
 864                                pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
 865                                pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
 866                        }
 867                        zfIF1 = new_IF1;
 868
 869                        if (zfIF1 > pAS_Info->f_if1_Center)
 870                                delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
 871                        else
 872                                delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
 873
 874                        pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
 875                /*
 876                 *  Continue while the new 1st IF is still within the 1st IF bandwidth
 877                 *  and there is a spur in the band (again)
 878                 */
 879                } while ((2 * delta_IF1 + pAS_Info->f_out_bw <= pAS_Info->f_if1_bw) && pAS_Info->bSpurPresent);
 880
 881                /*
 882                 * Use the LO-spur free values found.  If the search went all
 883                 * the way to the 1st IF band edge and always found spurs, just
 884                 * leave the original choice.  It's as "good" as any other.
 885                 */
 886                if (pAS_Info->bSpurPresent == 1) {
 887                        status |= MT2063_SPUR_PRESENT_ERR;
 888                        pAS_Info->f_LO1 = zfLO1;
 889                        pAS_Info->f_LO2 = zfLO2;
 890                } else
 891                        pAS_Info->bSpurAvoided = 1;
 892        }
 893
 894        status |=
 895            ((pAS_Info->
 896              nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
 897
 898        return status;
 899}
 900
 901/*
 902 * Constants used by the tuning algorithm
 903 */
 904#define MT2063_REF_FREQ          (16000000UL)   /* Reference oscillator Frequency (in Hz) */
 905#define MT2063_IF1_BW            (22000000UL)   /* The IF1 filter bandwidth (in Hz) */
 906#define MT2063_TUNE_STEP_SIZE       (50000UL)   /* Tune in steps of 50 kHz */
 907#define MT2063_SPUR_STEP_HZ        (250000UL)   /* Step size (in Hz) to move IF1 when avoiding spurs */
 908#define MT2063_ZIF_BW             (2000000UL)   /* Zero-IF spur-free bandwidth (in Hz) */
 909#define MT2063_MAX_HARMONICS_1         (15UL)   /* Highest intra-tuner LO Spur Harmonic to be avoided */
 910#define MT2063_MAX_HARMONICS_2          (5UL)   /* Highest inter-tuner LO Spur Harmonic to be avoided */
 911#define MT2063_MIN_LO_SEP         (1000000UL)   /* Minimum inter-tuner LO frequency separation */
 912#define MT2063_LO1_FRACN_AVOID          (0UL)   /* LO1 FracN numerator avoid region (in Hz) */
 913#define MT2063_LO2_FRACN_AVOID     (199999UL)   /* LO2 FracN numerator avoid region (in Hz) */
 914#define MT2063_MIN_FIN_FREQ      (44000000UL)   /* Minimum input frequency (in Hz) */
 915#define MT2063_MAX_FIN_FREQ    (1100000000UL)   /* Maximum input frequency (in Hz) */
 916#define MT2063_MIN_FOUT_FREQ     (36000000UL)   /* Minimum output frequency (in Hz) */
 917#define MT2063_MAX_FOUT_FREQ     (57000000UL)   /* Maximum output frequency (in Hz) */
 918#define MT2063_MIN_DNC_FREQ    (1293000000UL)   /* Minimum LO2 frequency (in Hz) */
 919#define MT2063_MAX_DNC_FREQ    (1614000000UL)   /* Maximum LO2 frequency (in Hz) */
 920#define MT2063_MIN_UPC_FREQ    (1396000000UL)   /* Minimum LO1 frequency (in Hz) */
 921#define MT2063_MAX_UPC_FREQ    (2750000000UL)   /* Maximum LO1 frequency (in Hz) */
 922
 923/*
 924 *  Define the supported Part/Rev codes for the MT2063
 925 */
 926#define MT2063_B0       (0x9B)
 927#define MT2063_B1       (0x9C)
 928#define MT2063_B2       (0x9D)
 929#define MT2063_B3       (0x9E)
 930
 931/**
 932 * mt2063_lockStatus - Checks to see if LO1 and LO2 are locked
 933 *
 934 * @state:      struct mt2063_state pointer
 935 *
 936 * This function returns 0, if no lock, 1 if locked and a value < 1 if error
 937 */
 938static int mt2063_lockStatus(struct mt2063_state *state)
 939{
 940        const u32 nMaxWait = 100;       /*  wait a maximum of 100 msec   */
 941        const u32 nPollRate = 2;        /*  poll status bits every 2 ms */
 942        const u32 nMaxLoops = nMaxWait / nPollRate;
 943        const u8 LO1LK = 0x80;
 944        u8 LO2LK = 0x08;
 945        int status;
 946        u32 nDelays = 0;
 947
 948        dprintk(2, "\n");
 949
 950        /*  LO2 Lock bit was in a different place for B0 version  */
 951        if (state->tuner_id == MT2063_B0)
 952                LO2LK = 0x40;
 953
 954        do {
 955                status = mt2063_read(state, MT2063_REG_LO_STATUS,
 956                                     &state->reg[MT2063_REG_LO_STATUS], 1);
 957
 958                if (status < 0)
 959                        return status;
 960
 961                if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
 962                    (LO1LK | LO2LK)) {
 963                        return TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO;
 964                }
 965                msleep(nPollRate);      /*  Wait between retries  */
 966        } while (++nDelays < nMaxLoops);
 967
 968        /*
 969         * Got no lock or partial lock
 970         */
 971        return 0;
 972}
 973
 974/*
 975 *  Constants for setting receiver modes.
 976 *  (6 modes defined at this time, enumerated by mt2063_delivery_sys)
 977 *  (DNC1GC & DNC2GC are the values, which are used, when the specific
 978 *   DNC Output is selected, the other is always off)
 979 *
 980 *                enum mt2063_delivery_sys
 981 * -------------+----------------------------------------------
 982 * Mode 0 :     | MT2063_CABLE_QAM
 983 * Mode 1 :     | MT2063_CABLE_ANALOG
 984 * Mode 2 :     | MT2063_OFFAIR_COFDM
 985 * Mode 3 :     | MT2063_OFFAIR_COFDM_SAWLESS
 986 * Mode 4 :     | MT2063_OFFAIR_ANALOG
 987 * Mode 5 :     | MT2063_OFFAIR_8VSB
 988 * --------------+----------------------------------------------
 989 *
 990 *                |<----------   Mode  -------------->|
 991 *    Reg Field   |  0  |  1  |  2  |  3  |  4  |  5  |
 992 *    ------------+-----+-----+-----+-----+-----+-----+
 993 *    RFAGCen     | OFF | OFF | OFF | OFF | OFF | OFF
 994 *    LNARin      |   0 |   0 |   3 |   3 |  3  |  3
 995 *    FIFFQen     |   1 |   1 |   1 |   1 |  1  |  1
 996 *    FIFFq       |   0 |   0 |   0 |   0 |  0  |  0
 997 *    DNC1gc      |   0 |   0 |   0 |   0 |  0  |  0
 998 *    DNC2gc      |   0 |   0 |   0 |   0 |  0  |  0
 999 *    GCU Auto    |   1 |   1 |   1 |   1 |  1  |  1
1000 *    LNA max Atn |  31 |  31 |  31 |  31 | 31  | 31
1001 *    LNA Target  |  44 |  43 |  43 |  43 | 43  | 43
1002 *    ign  RF Ovl |   0 |   0 |   0 |   0 |  0  |  0
1003 *    RF  max Atn |  31 |  31 |  31 |  31 | 31  | 31
1004 *    PD1 Target  |  36 |  36 |  38 |  38 | 36  | 38
1005 *    ign FIF Ovl |   0 |   0 |   0 |   0 |  0  |  0
1006 *    FIF max Atn |   5 |   5 |   5 |   5 |  5  |  5
1007 *    PD2 Target  |  40 |  33 |  42 |  42 | 33  | 42
1008 */
1009
1010enum mt2063_delivery_sys {
1011        MT2063_CABLE_QAM = 0,
1012        MT2063_CABLE_ANALOG,
1013        MT2063_OFFAIR_COFDM,
1014        MT2063_OFFAIR_COFDM_SAWLESS,
1015        MT2063_OFFAIR_ANALOG,
1016        MT2063_OFFAIR_8VSB,
1017        MT2063_NUM_RCVR_MODES
1018};
1019
1020static const char *mt2063_mode_name[] = {
1021        [MT2063_CABLE_QAM]              = "digital cable",
1022        [MT2063_CABLE_ANALOG]           = "analog cable",
1023        [MT2063_OFFAIR_COFDM]           = "digital offair",
1024        [MT2063_OFFAIR_COFDM_SAWLESS]   = "digital offair without SAW",
1025        [MT2063_OFFAIR_ANALOG]          = "analog offair",
1026        [MT2063_OFFAIR_8VSB]            = "analog offair 8vsb",
1027};
1028
1029static const u8 RFAGCEN[]       = {  0,  0,  0,  0,  0,  0 };
1030static const u8 LNARIN[]        = {  0,  0,  3,  3,  3,  3 };
1031static const u8 FIFFQEN[]       = {  1,  1,  1,  1,  1,  1 };
1032static const u8 FIFFQ[]         = {  0,  0,  0,  0,  0,  0 };
1033static const u8 DNC1GC[]        = {  0,  0,  0,  0,  0,  0 };
1034static const u8 DNC2GC[]        = {  0,  0,  0,  0,  0,  0 };
1035static const u8 ACLNAMAX[]      = { 31, 31, 31, 31, 31, 31 };
1036static const u8 LNATGT[]        = { 44, 43, 43, 43, 43, 43 };
1037static const u8 RFOVDIS[]       = {  0,  0,  0,  0,  0,  0 };
1038static const u8 ACRFMAX[]       = { 31, 31, 31, 31, 31, 31 };
1039static const u8 PD1TGT[]        = { 36, 36, 38, 38, 36, 38 };
1040static const u8 FIFOVDIS[]      = {  0,  0,  0,  0,  0,  0 };
1041static const u8 ACFIFMAX[]      = { 29, 29, 29, 29, 29, 29 };
1042static const u8 PD2TGT[]        = { 40, 33, 38, 42, 30, 38 };
1043
1044/*
1045 * mt2063_set_dnc_output_enable()
1046 */
1047static u32 mt2063_get_dnc_output_enable(struct mt2063_state *state,
1048                                        enum MT2063_DNC_Output_Enable *pValue)
1049{
1050        dprintk(2, "\n");
1051
1052        if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1053                if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)   /* if DNC2 is off */
1054                        *pValue = MT2063_DNC_NONE;
1055                else
1056                        *pValue = MT2063_DNC_2;
1057        } else {        /* DNC1 is on */
1058                if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)   /* if DNC2 is off */
1059                        *pValue = MT2063_DNC_1;
1060                else
1061                        *pValue = MT2063_DNC_BOTH;
1062        }
1063        return 0;
1064}
1065
1066/*
1067 * mt2063_set_dnc_output_enable()
1068 */
1069static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
1070                                        enum MT2063_DNC_Output_Enable nValue)
1071{
1072        int status = 0; /* Status to be returned        */
1073        u8 val = 0;
1074
1075        dprintk(2, "\n");
1076
1077        /* selects, which DNC output is used */
1078        switch (nValue) {
1079        case MT2063_DNC_NONE:
1080                val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;  /* Set DNC1GC=3 */
1081                if (state->reg[MT2063_REG_DNC_GAIN] !=
1082                    val)
1083                        status |=
1084                            mt2063_setreg(state,
1085                                          MT2063_REG_DNC_GAIN,
1086                                          val);
1087
1088                val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;  /* Set DNC2GC=3 */
1089                if (state->reg[MT2063_REG_VGA_GAIN] !=
1090                    val)
1091                        status |=
1092                            mt2063_setreg(state,
1093                                          MT2063_REG_VGA_GAIN,
1094                                          val);
1095
1096                val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
1097                if (state->reg[MT2063_REG_RSVD_20] !=
1098                    val)
1099                        status |=
1100                            mt2063_setreg(state,
1101                                          MT2063_REG_RSVD_20,
1102                                          val);
1103
1104                break;
1105        case MT2063_DNC_1:
1106                val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03);     /* Set DNC1GC=x */
1107                if (state->reg[MT2063_REG_DNC_GAIN] !=
1108                    val)
1109                        status |=
1110                            mt2063_setreg(state,
1111                                          MT2063_REG_DNC_GAIN,
1112                                          val);
1113
1114                val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;  /* Set DNC2GC=3 */
1115                if (state->reg[MT2063_REG_VGA_GAIN] !=
1116                    val)
1117                        status |=
1118                            mt2063_setreg(state,
1119                                          MT2063_REG_VGA_GAIN,
1120                                          val);
1121
1122                val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
1123                if (state->reg[MT2063_REG_RSVD_20] !=
1124                    val)
1125                        status |=
1126                            mt2063_setreg(state,
1127                                          MT2063_REG_RSVD_20,
1128                                          val);
1129
1130                break;
1131        case MT2063_DNC_2:
1132                val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;  /* Set DNC1GC=3 */
1133                if (state->reg[MT2063_REG_DNC_GAIN] !=
1134                    val)
1135                        status |=
1136                            mt2063_setreg(state,
1137                                          MT2063_REG_DNC_GAIN,
1138                                          val);
1139
1140                val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03);     /* Set DNC2GC=x */
1141                if (state->reg[MT2063_REG_VGA_GAIN] !=
1142                    val)
1143                        status |=
1144                            mt2063_setreg(state,
1145                                          MT2063_REG_VGA_GAIN,
1146                                          val);
1147
1148                val = (state->reg[MT2063_REG_RSVD_20] | 0x40);  /* Set PD2MUX=1 */
1149                if (state->reg[MT2063_REG_RSVD_20] !=
1150                    val)
1151                        status |=
1152                            mt2063_setreg(state,
1153                                          MT2063_REG_RSVD_20,
1154                                          val);
1155
1156                break;
1157        case MT2063_DNC_BOTH:
1158                val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03);     /* Set DNC1GC=x */
1159                if (state->reg[MT2063_REG_DNC_GAIN] !=
1160                    val)
1161                        status |=
1162                            mt2063_setreg(state,
1163                                          MT2063_REG_DNC_GAIN,
1164                                          val);
1165
1166                val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03);     /* Set DNC2GC=x */
1167                if (state->reg[MT2063_REG_VGA_GAIN] !=
1168                    val)
1169                        status |=
1170                            mt2063_setreg(state,
1171                                          MT2063_REG_VGA_GAIN,
1172                                          val);
1173
1174                val = (state->reg[MT2063_REG_RSVD_20] | 0x40);  /* Set PD2MUX=1 */
1175                if (state->reg[MT2063_REG_RSVD_20] !=
1176                    val)
1177                        status |=
1178                            mt2063_setreg(state,
1179                                          MT2063_REG_RSVD_20,
1180                                          val);
1181
1182                break;
1183        default:
1184                break;
1185        }
1186
1187        return status;
1188}
1189
1190/*
1191 * MT2063_SetReceiverMode() - Set the MT2063 receiver mode, according with
1192 *                            the selected enum mt2063_delivery_sys type.
1193 *
1194 *  (DNC1GC & DNC2GC are the values, which are used, when the specific
1195 *   DNC Output is selected, the other is always off)
1196 *
1197 * @state:      ptr to mt2063_state structure
1198 * @Mode:       desired reciever delivery system
1199 *
1200 * Note: Register cache must be valid for it to work
1201 */
1202
1203static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
1204                                  enum mt2063_delivery_sys Mode)
1205{
1206        int status = 0; /* Status to be returned        */
1207        u8 val;
1208        u32 longval;
1209
1210        dprintk(2, "\n");
1211
1212        if (Mode >= MT2063_NUM_RCVR_MODES)
1213                status = -ERANGE;
1214
1215        /* RFAGCen */
1216        if (status >= 0) {
1217                val =
1218                    (state->
1219                     reg[MT2063_REG_PD1_TGT] & (u8) ~0x40) | (RFAGCEN[Mode]
1220                                                                   ? 0x40 :
1221                                                                   0x00);
1222                if (state->reg[MT2063_REG_PD1_TGT] != val)
1223                        status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
1224        }
1225
1226        /* LNARin */
1227        if (status >= 0) {
1228                u8 val = (state->reg[MT2063_REG_CTRL_2C] & (u8) ~0x03) |
1229                         (LNARIN[Mode] & 0x03);
1230                if (state->reg[MT2063_REG_CTRL_2C] != val)
1231                        status |= mt2063_setreg(state, MT2063_REG_CTRL_2C, val);
1232        }
1233
1234        /* FIFFQEN and FIFFQ */
1235        if (status >= 0) {
1236                val =
1237                    (state->
1238                     reg[MT2063_REG_FIFF_CTRL2] & (u8) ~0xF0) |
1239                    (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
1240                if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
1241                        status |=
1242                            mt2063_setreg(state, MT2063_REG_FIFF_CTRL2, val);
1243                        /* trigger FIFF calibration, needed after changing FIFFQ */
1244                        val =
1245                            (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
1246                        status |=
1247                            mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
1248                        val =
1249                            (state->
1250                             reg[MT2063_REG_FIFF_CTRL] & (u8) ~0x01);
1251                        status |=
1252                            mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
1253                }
1254        }
1255
1256        /* DNC1GC & DNC2GC */
1257        status |= mt2063_get_dnc_output_enable(state, &longval);
1258        status |= mt2063_set_dnc_output_enable(state, longval);
1259
1260        /* acLNAmax */
1261        if (status >= 0) {
1262                u8 val = (state->reg[MT2063_REG_LNA_OV] & (u8) ~0x1F) |
1263                         (ACLNAMAX[Mode] & 0x1F);
1264                if (state->reg[MT2063_REG_LNA_OV] != val)
1265                        status |= mt2063_setreg(state, MT2063_REG_LNA_OV, val);
1266        }
1267
1268        /* LNATGT */
1269        if (status >= 0) {
1270                u8 val = (state->reg[MT2063_REG_LNA_TGT] & (u8) ~0x3F) |
1271                         (LNATGT[Mode] & 0x3F);
1272                if (state->reg[MT2063_REG_LNA_TGT] != val)
1273                        status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
1274        }
1275
1276        /* ACRF */
1277        if (status >= 0) {
1278                u8 val = (state->reg[MT2063_REG_RF_OV] & (u8) ~0x1F) |
1279                         (ACRFMAX[Mode] & 0x1F);
1280                if (state->reg[MT2063_REG_RF_OV] != val)
1281                        status |= mt2063_setreg(state, MT2063_REG_RF_OV, val);
1282        }
1283
1284        /* PD1TGT */
1285        if (status >= 0) {
1286                u8 val = (state->reg[MT2063_REG_PD1_TGT] & (u8) ~0x3F) |
1287                         (PD1TGT[Mode] & 0x3F);
1288                if (state->reg[MT2063_REG_PD1_TGT] != val)
1289                        status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
1290        }
1291
1292        /* FIFATN */
1293        if (status >= 0) {
1294                u8 val = ACFIFMAX[Mode];
1295                if (state->reg[MT2063_REG_PART_REV] != MT2063_B3 && val > 5)
1296                        val = 5;
1297                val = (state->reg[MT2063_REG_FIF_OV] & (u8) ~0x1F) |
1298                      (val & 0x1F);
1299                if (state->reg[MT2063_REG_FIF_OV] != val)
1300                        status |= mt2063_setreg(state, MT2063_REG_FIF_OV, val);
1301        }
1302
1303        /* PD2TGT */
1304        if (status >= 0) {
1305                u8 val = (state->reg[MT2063_REG_PD2_TGT] & (u8) ~0x3F) |
1306                    (PD2TGT[Mode] & 0x3F);
1307                if (state->reg[MT2063_REG_PD2_TGT] != val)
1308                        status |= mt2063_setreg(state, MT2063_REG_PD2_TGT, val);
1309        }
1310
1311        /* Ignore ATN Overload */
1312        if (status >= 0) {
1313                val = (state->reg[MT2063_REG_LNA_TGT] & (u8) ~0x80) |
1314                      (RFOVDIS[Mode] ? 0x80 : 0x00);
1315                if (state->reg[MT2063_REG_LNA_TGT] != val)
1316                        status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
1317        }
1318
1319        /* Ignore FIF Overload */
1320        if (status >= 0) {
1321                val = (state->reg[MT2063_REG_PD1_TGT] & (u8) ~0x80) |
1322                      (FIFOVDIS[Mode] ? 0x80 : 0x00);
1323                if (state->reg[MT2063_REG_PD1_TGT] != val)
1324                        status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
1325        }
1326
1327        if (status >= 0) {
1328                state->rcvr_mode = Mode;
1329                dprintk(1, "mt2063 mode changed to %s\n",
1330                        mt2063_mode_name[state->rcvr_mode]);
1331        }
1332
1333        return status;
1334}
1335
1336/*
1337 * MT2063_ClearPowerMaskBits () - Clears the power-down mask bits for various
1338 *                                sections of the MT2063
1339 *
1340 * @Bits:               Mask bits to be cleared.
1341 *
1342 * See definition of MT2063_Mask_Bits type for description
1343 * of each of the power bits.
1344 */
1345static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
1346                                     enum MT2063_Mask_Bits Bits)
1347{
1348        int status = 0;
1349
1350        dprintk(2, "\n");
1351        Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD);   /* Only valid bits for this tuner */
1352        if ((Bits & 0xFF00) != 0) {
1353                state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
1354                status |=
1355                    mt2063_write(state,
1356                                    MT2063_REG_PWR_2,
1357                                    &state->reg[MT2063_REG_PWR_2], 1);
1358        }
1359        if ((Bits & 0xFF) != 0) {
1360                state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
1361                status |=
1362                    mt2063_write(state,
1363                                    MT2063_REG_PWR_1,
1364                                    &state->reg[MT2063_REG_PWR_1], 1);
1365        }
1366
1367        return status;
1368}
1369
1370/*
1371 * MT2063_SoftwareShutdown() - Enables or disables software shutdown function.
1372 *                             When Shutdown is 1, any section whose power
1373 *                             mask is set will be shutdown.
1374 */
1375static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
1376{
1377        int status;
1378
1379        dprintk(2, "\n");
1380        if (Shutdown == 1)
1381                state->reg[MT2063_REG_PWR_1] |= 0x04;
1382        else
1383                state->reg[MT2063_REG_PWR_1] &= ~0x04;
1384
1385        status = mt2063_write(state,
1386                            MT2063_REG_PWR_1,
1387                            &state->reg[MT2063_REG_PWR_1], 1);
1388
1389        if (Shutdown != 1) {
1390                state->reg[MT2063_REG_BYP_CTRL] =
1391                    (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
1392                status |=
1393                    mt2063_write(state,
1394                                    MT2063_REG_BYP_CTRL,
1395                                    &state->reg[MT2063_REG_BYP_CTRL],
1396                                    1);
1397                state->reg[MT2063_REG_BYP_CTRL] =
1398                    (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
1399                status |=
1400                    mt2063_write(state,
1401                                    MT2063_REG_BYP_CTRL,
1402                                    &state->reg[MT2063_REG_BYP_CTRL],
1403                                    1);
1404        }
1405
1406        return status;
1407}
1408
1409static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
1410{
1411        return f_ref * (f_LO / f_ref)
1412            + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
1413}
1414
1415/**
1416 * fLO_FractionalTerm() - Calculates the portion contributed by FracN / denom.
1417 *                        This function preserves maximum precision without
1418 *                        risk of overflow.  It accurately calculates
1419 *                        f_ref * num / denom to within 1 HZ with fixed math.
1420 *
1421 * @num :       Fractional portion of the multiplier
1422 * @denom:      denominator portion of the ratio
1423 * @f_Ref:      SRO frequency.
1424 *
1425 * This calculation handles f_ref as two separate 14-bit fields.
1426 * Therefore, a maximum value of 2^28-1 may safely be used for f_ref.
1427 * This is the genesis of the magic number "14" and the magic mask value of
1428 * 0x03FFF.
1429 *
1430 * This routine successfully handles denom values up to and including 2^18.
1431 *  Returns:        f_ref * num / denom
1432 */
1433static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num, u32 denom)
1434{
1435        u32 t1 = (f_ref >> 14) * num;
1436        u32 term1 = t1 / denom;
1437        u32 loss = t1 % denom;
1438        u32 term2 =
1439            (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
1440        return (term1 << 14) + term2;
1441}
1442
1443/*
1444 * CalcLO1Mult()- Calculates Integer divider value and the numerator
1445 *                value for a FracN PLL.
1446 *
1447 *                This function assumes that the f_LO and f_Ref are
1448 *                evenly divisible by f_LO_Step.
1449 *
1450 * @Div:        OUTPUT: Whole number portion of the multiplier
1451 * @FracN:      OUTPUT: Fractional portion of the multiplier
1452 * @f_LO:       desired LO frequency.
1453 * @f_LO_Step:  Minimum step size for the LO (in Hz).
1454 * @f_Ref:      SRO frequency.
1455 * @f_Avoid:    Range of PLL frequencies to avoid near integer multiples
1456 *              of f_Ref (in Hz).
1457 *
1458 * Returns:        Recalculated LO frequency.
1459 */
1460static u32 MT2063_CalcLO1Mult(u32 *Div,
1461                              u32 *FracN,
1462                              u32 f_LO,
1463                              u32 f_LO_Step, u32 f_Ref)
1464{
1465        /*  Calculate the whole number portion of the divider */
1466        *Div = f_LO / f_Ref;
1467
1468        /*  Calculate the numerator value (round to nearest f_LO_Step) */
1469        *FracN =
1470            (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
1471             (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
1472
1473        return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
1474}
1475
1476/**
1477 * CalcLO2Mult() - Calculates Integer divider value and the numerator
1478 *                 value for a FracN PLL.
1479 *
1480 *                  This function assumes that the f_LO and f_Ref are
1481 *                  evenly divisible by f_LO_Step.
1482 *
1483 * @Div:        OUTPUT: Whole number portion of the multiplier
1484 * @FracN:      OUTPUT: Fractional portion of the multiplier
1485 * @f_LO:       desired LO frequency.
1486 * @f_LO_Step:  Minimum step size for the LO (in Hz).
1487 * @f_Ref:      SRO frequency.
1488 * @f_Avoid:    Range of PLL frequencies to avoid near
1489 *              integer multiples of f_Ref (in Hz).
1490 *
1491 * Returns: Recalculated LO frequency.
1492 */
1493static u32 MT2063_CalcLO2Mult(u32 *Div,
1494                              u32 *FracN,
1495                              u32 f_LO,
1496                              u32 f_LO_Step, u32 f_Ref)
1497{
1498        /*  Calculate the whole number portion of the divider */
1499        *Div = f_LO / f_Ref;
1500
1501        /*  Calculate the numerator value (round to nearest f_LO_Step) */
1502        *FracN =
1503            (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
1504             (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
1505
1506        return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
1507                                                            8191);
1508}
1509
1510/*
1511 * FindClearTuneFilter() - Calculate the corrrect ClearTune filter to be
1512 *                         used for a given input frequency.
1513 *
1514 * @state:      ptr to tuner data structure
1515 * @f_in:       RF input center frequency (in Hz).
1516 *
1517 * Returns: ClearTune filter number (0-31)
1518 */
1519static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
1520{
1521        u32 RFBand;
1522        u32 idx;                /*  index loop                      */
1523
1524        /*
1525         **  Find RF Band setting
1526         */
1527        RFBand = 31;            /*  def when f_in > all    */
1528        for (idx = 0; idx < 31; ++idx) {
1529                if (state->CTFiltMax[idx] >= f_in) {
1530                        RFBand = idx;
1531                        break;
1532                }
1533        }
1534        return RFBand;
1535}
1536
1537/*
1538 * MT2063_Tune() - Change the tuner's tuned frequency to RFin.
1539 */
1540static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
1541{                               /* RF input center frequency   */
1542
1543        int status = 0;
1544        u32 LO1;                /*  1st LO register value           */
1545        u32 Num1;               /*  Numerator for LO1 reg. value    */
1546        u32 f_IF1;              /*  1st IF requested                */
1547        u32 LO2;                /*  2nd LO register value           */
1548        u32 Num2;               /*  Numerator for LO2 reg. value    */
1549        u32 ofLO1, ofLO2;       /*  last time's LO frequencies      */
1550        u8 fiffc = 0x80;        /*  FIFF center freq from tuner     */
1551        u32 fiffof;             /*  Offset from FIFF center freq    */
1552        const u8 LO1LK = 0x80;  /*  Mask for LO1 Lock bit           */
1553        u8 LO2LK = 0x08;        /*  Mask for LO2 Lock bit           */
1554        u8 val;
1555        u32 RFBand;
1556
1557        dprintk(2, "\n");
1558        /*  Check the input and output frequency ranges                   */
1559        if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
1560                return -EINVAL;
1561
1562        if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
1563            || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
1564                return -EINVAL;
1565
1566        /*
1567         * Save original LO1 and LO2 register values
1568         */
1569        ofLO1 = state->AS_Data.f_LO1;
1570        ofLO2 = state->AS_Data.f_LO2; 
1571
1572        /*
1573         * Find and set RF Band setting
1574         */
1575        if (state->ctfilt_sw == 1) {
1576                val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
1577                if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
1578                        status |=
1579                            mt2063_setreg(state, MT2063_REG_CTUNE_CTRL, val);
1580                }
1581                val = state->reg[MT2063_REG_CTUNE_OV];
1582                RFBand = FindClearTuneFilter(state, f_in);
1583                state->reg[MT2063_REG_CTUNE_OV] =
1584                    (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
1585                              | RFBand);
1586                if (state->reg[MT2063_REG_CTUNE_OV] != val) {
1587                        status |=
1588                            mt2063_setreg(state, MT2063_REG_CTUNE_OV, val);
1589                }
1590        }
1591
1592        /*
1593         * Read the FIFF Center Frequency from the tuner
1594         */
1595        if (status >= 0) {
1596                status |=
1597                    mt2063_read(state,
1598                                   MT2063_REG_FIFFC,
1599                                   &state->reg[MT2063_REG_FIFFC], 1);
1600                fiffc = state->reg[MT2063_REG_FIFFC];
1601        }
1602        /*
1603         * Assign in the requested values
1604         */
1605        state->AS_Data.f_in = f_in;
1606        /*  Request a 1st IF such that LO1 is on a step size */
1607        state->AS_Data.f_if1_Request =
1608            MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
1609                             state->AS_Data.f_LO1_Step,
1610                             state->AS_Data.f_ref) - f_in;
1611
1612        /*
1613         * Calculate frequency settings.  f_IF1_FREQ + f_in is the
1614         * desired LO1 frequency
1615         */
1616        MT2063_ResetExclZones(&state->AS_Data);
1617
1618        f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
1619
1620        state->AS_Data.f_LO1 =
1621            MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
1622                             state->AS_Data.f_ref);
1623
1624        state->AS_Data.f_LO2 =
1625            MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
1626                             state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
1627
1628        /*
1629         * Check for any LO spurs in the output bandwidth and adjust
1630         * the LO settings to avoid them if needed
1631         */
1632        status |= MT2063_AvoidSpurs(&state->AS_Data);
1633        /*
1634         * MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
1635         * Recalculate the LO frequencies and the values to be placed
1636         * in the tuning registers.
1637         */
1638        state->AS_Data.f_LO1 =
1639            MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
1640                               state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
1641        state->AS_Data.f_LO2 =
1642            MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
1643                             state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
1644        state->AS_Data.f_LO2 =
1645            MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
1646                               state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
1647
1648        /*
1649         *  Check the upconverter and downconverter frequency ranges
1650         */
1651        if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
1652            || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
1653                status |= MT2063_UPC_RANGE;
1654        if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
1655            || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
1656                status |= MT2063_DNC_RANGE;
1657        /*  LO2 Lock bit was in a different place for B0 version  */
1658        if (state->tuner_id == MT2063_B0)
1659                LO2LK = 0x40;
1660
1661        /*
1662         *  If we have the same LO frequencies and we're already locked,
1663         *  then skip re-programming the LO registers.
1664         */
1665        if ((ofLO1 != state->AS_Data.f_LO1)
1666            || (ofLO2 != state->AS_Data.f_LO2)
1667            || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
1668                (LO1LK | LO2LK))) {
1669                /*
1670                 * Calculate the FIFFOF register value
1671                 *
1672                 *           IF1_Actual
1673                 * FIFFOF = ------------ - 8 * FIFFC - 4992
1674                 *            f_ref/64
1675                 */
1676                fiffof =
1677                    (state->AS_Data.f_LO1 -
1678                     f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
1679                    4992;
1680                if (fiffof > 0xFF)
1681                        fiffof = 0xFF;
1682
1683                /*
1684                 * Place all of the calculated values into the local tuner
1685                 * register fields.
1686                 */
1687                if (status >= 0) {
1688                        state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF);     /* DIV1q */
1689                        state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F);    /* NUM1q */
1690                        state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1)      /* DIV2q */
1691                                                                   |(Num2 >> 12));      /* NUM2q (hi) */
1692                        state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4);   /* NUM2q (mid) */
1693                        state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
1694
1695                        /*
1696                         * Now write out the computed register values
1697                         * IMPORTANT: There is a required order for writing
1698                         *            (0x05 must follow all the others).
1699                         */
1700                        status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5);  /* 0x01 - 0x05 */
1701                        if (state->tuner_id == MT2063_B0) {
1702                                /* Re-write the one-shot bits to trigger the tune operation */
1703                                status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1);  /* 0x05 */
1704                        }
1705                        /* Write out the FIFF offset only if it's changing */
1706                        if (state->reg[MT2063_REG_FIFF_OFFSET] !=
1707                            (u8) fiffof) {
1708                                state->reg[MT2063_REG_FIFF_OFFSET] =
1709                                    (u8) fiffof;
1710                                status |=
1711                                    mt2063_write(state,
1712                                                    MT2063_REG_FIFF_OFFSET,
1713                                                    &state->
1714                                                    reg[MT2063_REG_FIFF_OFFSET],
1715                                                    1);
1716                        }
1717                }
1718
1719                /*
1720                 * Check for LO's locking
1721                 */
1722
1723                if (status < 0)
1724                        return status;
1725
1726                status = mt2063_lockStatus(state);
1727                if (status < 0)
1728                        return status;
1729                if (!status)
1730                        return -EINVAL;         /* Couldn't lock */
1731
1732                /*
1733                 * If we locked OK, assign calculated data to mt2063_state structure
1734                 */
1735                state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
1736        }
1737
1738        return status;
1739}
1740
1741static const u8 MT2063B0_defaults[] = {
1742        /* Reg,  Value */
1743        0x19, 0x05,
1744        0x1B, 0x1D,
1745        0x1C, 0x1F,
1746        0x1D, 0x0F,
1747        0x1E, 0x3F,
1748        0x1F, 0x0F,
1749        0x20, 0x3F,
1750        0x22, 0x21,
1751        0x23, 0x3F,
1752        0x24, 0x20,
1753        0x25, 0x3F,
1754        0x27, 0xEE,
1755        0x2C, 0x27,     /*  bit at 0x20 is cleared below  */
1756        0x30, 0x03,
1757        0x2C, 0x07,     /*  bit at 0x20 is cleared here   */
1758        0x2D, 0x87,
1759        0x2E, 0xAA,
1760        0x28, 0xE1,     /*  Set the FIFCrst bit here      */
1761        0x28, 0xE0,     /*  Clear the FIFCrst bit here    */
1762        0x00
1763};
1764
1765/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
1766static const u8 MT2063B1_defaults[] = {
1767        /* Reg,  Value */
1768        0x05, 0xF0,
1769        0x11, 0x10,     /* New Enable AFCsd */
1770        0x19, 0x05,
1771        0x1A, 0x6C,
1772        0x1B, 0x24,
1773        0x1C, 0x28,
1774        0x1D, 0x8F,
1775        0x1E, 0x14,
1776        0x1F, 0x8F,
1777        0x20, 0x57,
1778        0x22, 0x21,     /* New - ver 1.03 */
1779        0x23, 0x3C,     /* New - ver 1.10 */
1780        0x24, 0x20,     /* New - ver 1.03 */
1781        0x2C, 0x24,     /*  bit at 0x20 is cleared below  */
1782        0x2D, 0x87,     /*  FIFFQ=0  */
1783        0x2F, 0xF3,
1784        0x30, 0x0C,     /* New - ver 1.11 */
1785        0x31, 0x1B,     /* New - ver 1.11 */
1786        0x2C, 0x04,     /*  bit at 0x20 is cleared here  */
1787        0x28, 0xE1,     /*  Set the FIFCrst bit here      */
1788        0x28, 0xE0,     /*  Clear the FIFCrst bit here    */
1789        0x00
1790};
1791
1792/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
1793static const u8 MT2063B3_defaults[] = {
1794        /* Reg,  Value */
1795        0x05, 0xF0,
1796        0x19, 0x3D,
1797        0x2C, 0x24,     /*  bit at 0x20 is cleared below  */
1798        0x2C, 0x04,     /*  bit at 0x20 is cleared here  */
1799        0x28, 0xE1,     /*  Set the FIFCrst bit here      */
1800        0x28, 0xE0,     /*  Clear the FIFCrst bit here    */
1801        0x00
1802};
1803
1804static int mt2063_init(struct dvb_frontend *fe)
1805{
1806        int status;
1807        struct mt2063_state *state = fe->tuner_priv;
1808        u8 all_resets = 0xF0;   /* reset/load bits */
1809        const u8 *def = NULL;
1810        char *step;
1811        u32 FCRUN;
1812        s32 maxReads;
1813        u32 fcu_osc;
1814        u32 i;
1815
1816        dprintk(2, "\n");
1817
1818        state->rcvr_mode = MT2063_CABLE_QAM;
1819
1820        /*  Read the Part/Rev code from the tuner */
1821        status = mt2063_read(state, MT2063_REG_PART_REV,
1822                             &state->reg[MT2063_REG_PART_REV], 1);
1823        if (status < 0) {
1824                printk(KERN_ERR "Can't read mt2063 part ID\n");
1825                return status;
1826        }
1827
1828        /* Check the part/rev code */
1829        switch (state->reg[MT2063_REG_PART_REV]) {
1830        case MT2063_B0:
1831                step = "B0";
1832                break;
1833        case MT2063_B1:
1834                step = "B1";
1835                break;
1836        case MT2063_B2:
1837                step = "B2";
1838                break;
1839        case MT2063_B3:
1840                step = "B3";
1841                break;
1842        default:
1843                printk(KERN_ERR "mt2063: Unknown mt2063 device ID (0x%02x)\n",
1844                       state->reg[MT2063_REG_PART_REV]);
1845                return -ENODEV; /*  Wrong tuner Part/Rev code */
1846        }
1847
1848        /*  Check the 2nd byte of the Part/Rev code from the tuner */
1849        status = mt2063_read(state, MT2063_REG_RSVD_3B,
1850                             &state->reg[MT2063_REG_RSVD_3B], 1);
1851
1852        /* b7 != 0 ==> NOT MT2063 */
1853        if (status < 0 || ((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) {
1854                printk(KERN_ERR "mt2063: Unknown part ID (0x%02x%02x)\n",
1855                       state->reg[MT2063_REG_PART_REV],
1856                       state->reg[MT2063_REG_RSVD_3B]);
1857                return -ENODEV; /*  Wrong tuner Part/Rev code */
1858        }
1859
1860        printk(KERN_INFO "mt2063: detected a mt2063 %s\n", step);
1861
1862        /*  Reset the tuner  */
1863        status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
1864        if (status < 0)
1865                return status;
1866
1867        /* change all of the default values that vary from the HW reset values */
1868        /*  def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
1869        switch (state->reg[MT2063_REG_PART_REV]) {
1870        case MT2063_B3:
1871                def = MT2063B3_defaults;
1872                break;
1873
1874        case MT2063_B1:
1875                def = MT2063B1_defaults;
1876                break;
1877
1878        case MT2063_B0:
1879                def = MT2063B0_defaults;
1880                break;
1881
1882        default:
1883                return -ENODEV;
1884                break;
1885        }
1886
1887        while (status >= 0 && *def) {
1888                u8 reg = *def++;
1889                u8 val = *def++;
1890                status = mt2063_write(state, reg, &val, 1);
1891        }
1892        if (status < 0)
1893                return status;
1894
1895        /*  Wait for FIFF location to complete.  */
1896        FCRUN = 1;
1897        maxReads = 10;
1898        while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
1899                msleep(2);
1900                status = mt2063_read(state,
1901                                         MT2063_REG_XO_STATUS,
1902                                         &state->
1903                                         reg[MT2063_REG_XO_STATUS], 1);
1904                FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
1905        }
1906
1907        if (FCRUN != 0 || status < 0)
1908                return -ENODEV;
1909
1910        status = mt2063_read(state,
1911                           MT2063_REG_FIFFC,
1912                           &state->reg[MT2063_REG_FIFFC], 1);
1913        if (status < 0)
1914                return status;
1915
1916        /* Read back all the registers from the tuner */
1917        status = mt2063_read(state,
1918                                MT2063_REG_PART_REV,
1919                                state->reg, MT2063_REG_END_REGS);
1920        if (status < 0)
1921                return status;
1922
1923        /*  Initialize the tuner state.  */
1924        state->tuner_id = state->reg[MT2063_REG_PART_REV];
1925        state->AS_Data.f_ref = MT2063_REF_FREQ;
1926        state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
1927                                      ((u32) state->reg[MT2063_REG_FIFFC] + 640);
1928        state->AS_Data.f_if1_bw = MT2063_IF1_BW;
1929        state->AS_Data.f_out = 43750000UL;
1930        state->AS_Data.f_out_bw = 6750000UL;
1931        state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
1932        state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
1933        state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
1934        state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
1935        state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
1936        state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
1937        state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
1938        state->AS_Data.f_LO1 = 2181000000UL;
1939        state->AS_Data.f_LO2 = 1486249786UL;
1940        state->f_IF1_actual = state->AS_Data.f_if1_Center;
1941        state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
1942        state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
1943        state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
1944        state->num_regs = MT2063_REG_END_REGS;
1945        state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
1946        state->ctfilt_sw = 0;
1947
1948        state->CTFiltMax[0] = 69230000;
1949        state->CTFiltMax[1] = 105770000;
1950        state->CTFiltMax[2] = 140350000;
1951        state->CTFiltMax[3] = 177110000;
1952        state->CTFiltMax[4] = 212860000;
1953        state->CTFiltMax[5] = 241130000;
1954        state->CTFiltMax[6] = 274370000;
1955        state->CTFiltMax[7] = 309820000;
1956        state->CTFiltMax[8] = 342450000;
1957        state->CTFiltMax[9] = 378870000;
1958        state->CTFiltMax[10] = 416210000;
1959        state->CTFiltMax[11] = 456500000;
1960        state->CTFiltMax[12] = 495790000;
1961        state->CTFiltMax[13] = 534530000;
1962        state->CTFiltMax[14] = 572610000;
1963        state->CTFiltMax[15] = 598970000;
1964        state->CTFiltMax[16] = 635910000;
1965        state->CTFiltMax[17] = 672130000;
1966        state->CTFiltMax[18] = 714840000;
1967        state->CTFiltMax[19] = 739660000;
1968        state->CTFiltMax[20] = 770410000;
1969        state->CTFiltMax[21] = 814660000;
1970        state->CTFiltMax[22] = 846950000;
1971        state->CTFiltMax[23] = 867820000;
1972        state->CTFiltMax[24] = 915980000;
1973        state->CTFiltMax[25] = 947450000;
1974        state->CTFiltMax[26] = 983110000;
1975        state->CTFiltMax[27] = 1021630000;
1976        state->CTFiltMax[28] = 1061870000;
1977        state->CTFiltMax[29] = 1098330000;
1978        state->CTFiltMax[30] = 1138990000;
1979
1980        /*
1981         **   Fetch the FCU osc value and use it and the fRef value to
1982         **   scale all of the Band Max values
1983         */
1984
1985        state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
1986        status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
1987                              &state->reg[MT2063_REG_CTUNE_CTRL], 1);
1988        if (status < 0)
1989                return status;
1990
1991        /*  Read the ClearTune filter calibration value  */
1992        status = mt2063_read(state, MT2063_REG_FIFFC,
1993                             &state->reg[MT2063_REG_FIFFC], 1);
1994        if (status < 0)
1995                return status;
1996
1997        fcu_osc = state->reg[MT2063_REG_FIFFC];
1998
1999        state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
2000        status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
2001                              &state->reg[MT2063_REG_CTUNE_CTRL], 1);
2002        if (status < 0)
2003                return status;
2004
2005        /*  Adjust each of the values in the ClearTune filter cross-over table  */
2006        for (i = 0; i < 31; i++)
2007                state->CTFiltMax[i] = (state->CTFiltMax[i] / 768) * (fcu_osc + 640);
2008
2009        status = MT2063_SoftwareShutdown(state, 1);
2010        if (status < 0)
2011                return status;
2012        status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
2013        if (status < 0)
2014                return status;
2015
2016        state->init = true;
2017
2018        return 0;
2019}
2020
2021static int mt2063_get_status(struct dvb_frontend *fe, u32 *tuner_status)
2022{
2023        struct mt2063_state *state = fe->tuner_priv;
2024        int status;
2025
2026        dprintk(2, "\n");
2027
2028        if (!state->init)
2029                return -ENODEV;
2030
2031        *tuner_status = 0;
2032        status = mt2063_lockStatus(state);
2033        if (status < 0)
2034                return status;
2035        if (status)
2036                *tuner_status = TUNER_STATUS_LOCKED;
2037
2038        dprintk(1, "Tuner status: %d", *tuner_status);
2039
2040        return 0;
2041}
2042
2043static int mt2063_release(struct dvb_frontend *fe)
2044{
2045        struct mt2063_state *state = fe->tuner_priv;
2046
2047        dprintk(2, "\n");
2048
2049        fe->tuner_priv = NULL;
2050        kfree(state);
2051
2052        return 0;
2053}
2054
2055static int mt2063_set_analog_params(struct dvb_frontend *fe,
2056                                    struct analog_parameters *params)
2057{
2058        struct mt2063_state *state = fe->tuner_priv;
2059        s32 pict_car;
2060        s32 pict2chanb_vsb;
2061        s32 ch_bw;
2062        s32 if_mid;
2063        s32 rcvr_mode;
2064        int status;
2065
2066        dprintk(2, "\n");
2067
2068        if (!state->init) {
2069                status = mt2063_init(fe);
2070                if (status < 0)
2071                        return status;
2072        }
2073
2074        switch (params->mode) {
2075        case V4L2_TUNER_RADIO:
2076                pict_car = 38900000;
2077                ch_bw = 8000000;
2078                pict2chanb_vsb = -(ch_bw / 2);
2079                rcvr_mode = MT2063_OFFAIR_ANALOG;
2080                break;
2081        case V4L2_TUNER_ANALOG_TV:
2082                rcvr_mode = MT2063_CABLE_ANALOG;
2083                if (params->std & ~V4L2_STD_MN) {
2084                        pict_car = 38900000;
2085                        ch_bw = 6000000;
2086                        pict2chanb_vsb = -1250000;
2087                } else if (params->std & V4L2_STD_PAL_G) {
2088                        pict_car = 38900000;
2089                        ch_bw = 7000000;
2090                        pict2chanb_vsb = -1250000;
2091                } else {                /* PAL/SECAM standards */
2092                        pict_car = 38900000;
2093                        ch_bw = 8000000;
2094                        pict2chanb_vsb = -1250000;
2095                }
2096                break;
2097        default:
2098                return -EINVAL;
2099        }
2100        if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
2101
2102        state->AS_Data.f_LO2_Step = 125000;     /* FIXME: probably 5000 for FM */
2103        state->AS_Data.f_out = if_mid;
2104        state->AS_Data.f_out_bw = ch_bw + 750000;
2105        status = MT2063_SetReceiverMode(state, rcvr_mode);
2106        if (status < 0)
2107                return status;
2108
2109        dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
2110                params->frequency, ch_bw, pict2chanb_vsb);
2111
2112        status = MT2063_Tune(state, (params->frequency + (pict2chanb_vsb + (ch_bw / 2))));
2113        if (status < 0)
2114                return status;
2115
2116        state->frequency = params->frequency;
2117        return 0;
2118}
2119
2120/*
2121 * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
2122 * So, the amount of the needed bandwith is given by:
2123 *      Bw = Symbol_rate * (1 + 0.15)
2124 * As such, the maximum symbol rate supported by 6 MHz is given by:
2125 *      max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
2126 */
2127#define MAX_SYMBOL_RATE_6MHz    5217391
2128
2129static int mt2063_set_params(struct dvb_frontend *fe)
2130{
2131        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
2132        struct mt2063_state *state = fe->tuner_priv;
2133        int status;
2134        s32 pict_car;
2135        s32 pict2chanb_vsb;
2136        s32 ch_bw;
2137        s32 if_mid;
2138        s32 rcvr_mode;
2139
2140        if (!state->init) {
2141                status = mt2063_init(fe);
2142                if (status < 0)
2143                        return status;
2144        }
2145
2146        dprintk(2, "\n");
2147
2148        if (c->bandwidth_hz == 0)
2149                return -EINVAL;
2150        if (c->bandwidth_hz <= 6000000)
2151                ch_bw = 6000000;
2152        else if (c->bandwidth_hz <= 7000000)
2153                ch_bw = 7000000;
2154        else
2155                ch_bw = 8000000;
2156
2157        switch (c->delivery_system) {
2158        case SYS_DVBT:
2159                rcvr_mode = MT2063_OFFAIR_COFDM;
2160                pict_car = 36125000;
2161                pict2chanb_vsb = -(ch_bw / 2);
2162                break;
2163        case SYS_DVBC_ANNEX_A:
2164        case SYS_DVBC_ANNEX_C:
2165                rcvr_mode = MT2063_CABLE_QAM;
2166                pict_car = 36125000;
2167                pict2chanb_vsb = -(ch_bw / 2);
2168                break;
2169        default:
2170                return -EINVAL;
2171        }
2172        if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
2173
2174        state->AS_Data.f_LO2_Step = 125000;     /* FIXME: probably 5000 for FM */
2175        state->AS_Data.f_out = if_mid;
2176        state->AS_Data.f_out_bw = ch_bw + 750000;
2177        status = MT2063_SetReceiverMode(state, rcvr_mode);
2178        if (status < 0)
2179                return status;
2180
2181        dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
2182                c->frequency, ch_bw, pict2chanb_vsb);
2183
2184        status = MT2063_Tune(state, (c->frequency + (pict2chanb_vsb + (ch_bw / 2))));
2185
2186        if (status < 0)
2187                return status;
2188
2189        state->frequency = c->frequency;
2190        return 0;
2191}
2192
2193static int mt2063_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
2194{
2195        struct mt2063_state *state = fe->tuner_priv;
2196
2197        dprintk(2, "\n");
2198
2199        if (!state->init)
2200                return -ENODEV;
2201
2202        *freq = state->AS_Data.f_out;
2203
2204        dprintk(1, "IF frequency: %d\n", *freq);
2205
2206        return 0;
2207}
2208
2209static int mt2063_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
2210{
2211        struct mt2063_state *state = fe->tuner_priv;
2212
2213        dprintk(2, "\n");
2214
2215        if (!state->init)
2216                return -ENODEV;
2217
2218        *bw = state->AS_Data.f_out_bw - 750000;
2219
2220        dprintk(1, "bandwidth: %d\n", *bw);
2221
2222        return 0;
2223}
2224
2225static struct dvb_tuner_ops mt2063_ops = {
2226        .info = {
2227                 .name = "MT2063 Silicon Tuner",
2228                 .frequency_min = 45000000,
2229                 .frequency_max = 865000000,
2230                 .frequency_step = 0,
2231                 },
2232
2233        .init = mt2063_init,
2234        .sleep = MT2063_Sleep,
2235        .get_status = mt2063_get_status,
2236        .set_analog_params = mt2063_set_analog_params,
2237        .set_params    = mt2063_set_params,
2238        .get_if_frequency = mt2063_get_if_frequency,
2239        .get_bandwidth = mt2063_get_bandwidth,
2240        .release = mt2063_release,
2241};
2242
2243struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
2244                                   struct mt2063_config *config,
2245                                   struct i2c_adapter *i2c)
2246{
2247        struct mt2063_state *state = NULL;
2248
2249        dprintk(2, "\n");
2250
2251        state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
2252        if (!state)
2253                return NULL;
2254
2255        state->config = config;
2256        state->i2c = i2c;
2257        state->frontend = fe;
2258        state->reference = config->refclock / 1000;     /* kHz */
2259        fe->tuner_priv = state;
2260        fe->ops.tuner_ops = mt2063_ops;
2261
2262        printk(KERN_INFO "%s: Attaching MT2063\n", __func__);
2263        return fe;
2264}
2265EXPORT_SYMBOL_GPL(mt2063_attach);
2266
2267#if 0
2268/*
2269 * Ancillary routines visible outside mt2063
2270 * FIXME: Remove them in favor of using standard tuner callbacks
2271 */
2272static int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
2273{
2274        struct mt2063_state *state = fe->tuner_priv;
2275        int err = 0;
2276
2277        dprintk(2, "\n");
2278
2279        err = MT2063_SoftwareShutdown(state, 1);
2280        if (err < 0)
2281                printk(KERN_ERR "%s: Couldn't shutdown\n", __func__);
2282
2283        return err;
2284}
2285
2286static int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
2287{
2288        struct mt2063_state *state = fe->tuner_priv;
2289        int err = 0;
2290
2291        dprintk(2, "\n");
2292
2293        err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
2294        if (err < 0)
2295                printk(KERN_ERR "%s: Invalid parameter\n", __func__);
2296
2297        return err;
2298}
2299#endif
2300
2301MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
2302MODULE_DESCRIPTION("MT2063 Silicon tuner");
2303MODULE_LICENSE("GPL");
2304