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