linux/drivers/media/dvb/frontends/stv6110x.c
<<
>>
Prefs
   1/*
   2        STV6110(A) Silicon tuner driver
   3
   4        Copyright (C) Manu Abraham <abraham.manu@gmail.com>
   5
   6        Copyright (C) ST Microelectronics
   7
   8        This program is free software; you can redistribute it and/or modify
   9        it under the terms of the GNU General Public License as published by
  10        the Free Software Foundation; either version 2 of the License, or
  11        (at your option) any later version.
  12
  13        This program is distributed in the hope that it will be useful,
  14        but WITHOUT ANY WARRANTY; without even the implied warranty of
  15        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16        GNU General Public License for more details.
  17
  18        You should have received a copy of the GNU General Public License
  19        along with this program; if not, write to the Free Software
  20        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21*/
  22
  23#include <linux/init.h>
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26#include <linux/slab.h>
  27#include <linux/string.h>
  28
  29#include "dvb_frontend.h"
  30
  31#include "stv6110x_reg.h"
  32#include "stv6110x.h"
  33#include "stv6110x_priv.h"
  34
  35static unsigned int verbose;
  36module_param(verbose, int, 0644);
  37MODULE_PARM_DESC(verbose, "Set Verbosity level");
  38
  39static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
  40{
  41        int ret;
  42        const struct stv6110x_config *config = stv6110x->config;
  43        u8 b0[] = { reg };
  44        u8 b1[] = { 0 };
  45        struct i2c_msg msg[] = {
  46                { .addr = config->addr, .flags = 0,        .buf = b0, .len = 1 },
  47                { .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }
  48        };
  49
  50        ret = i2c_transfer(stv6110x->i2c, msg, 2);
  51        if (ret != 2) {
  52                dprintk(FE_ERROR, 1, "I/O Error");
  53                return -EREMOTEIO;
  54        }
  55        *data = b1[0];
  56
  57        return 0;
  58}
  59
  60static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 data[], int len)
  61{
  62        int ret;
  63        const struct stv6110x_config *config = stv6110x->config;
  64        u8 buf[len + 1];
  65        struct i2c_msg msg = {
  66                .addr = config->addr,
  67                .flags = 0,
  68                .buf = buf,
  69                .len = len + 1
  70        };
  71
  72        if (start + len > 8)
  73                return -EINVAL;
  74
  75        buf[0] = start;
  76        memcpy(&buf[1], data, len);
  77
  78        ret = i2c_transfer(stv6110x->i2c, &msg, 1);
  79        if (ret != 1) {
  80                dprintk(FE_ERROR, 1, "I/O Error");
  81                return -EREMOTEIO;
  82        }
  83
  84        return 0;
  85}
  86
  87static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
  88{
  89        return stv6110x_write_regs(stv6110x, reg, &data, 1);
  90}
  91
  92static int stv6110x_init(struct dvb_frontend *fe)
  93{
  94        struct stv6110x_state *stv6110x = fe->tuner_priv;
  95        int ret;
  96
  97        ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs,
  98                                  ARRAY_SIZE(stv6110x->regs));
  99        if (ret < 0) {
 100                dprintk(FE_ERROR, 1, "Initialization failed");
 101                return -1;
 102        }
 103
 104        return 0;
 105}
 106
 107static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
 108{
 109        struct stv6110x_state *stv6110x = fe->tuner_priv;
 110        u32 rDiv, divider;
 111        s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000;
 112        u8 i;
 113
 114        STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
 115
 116        if (frequency <= 1023000) {
 117                STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
 118                STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
 119                pVal = 40;
 120        } else if (frequency <= 1300000) {
 121                STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
 122                STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
 123                pVal = 40;
 124        } else if (frequency <= 2046000) {
 125                STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
 126                STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
 127                pVal = 20;
 128        } else {
 129                STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
 130                STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
 131                pVal = 20;
 132        }
 133
 134        for (rDiv = 0; rDiv <= 3; rDiv++) {
 135                pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv);
 136
 137                if ((abs((s32)(pCalc - pVal))) < (abs((s32)(pCalcOpt - pVal))))
 138                        rDivOpt = rDiv;
 139
 140                pCalcOpt = (REFCLOCK_kHz / 100) / R_DIV(rDivOpt);
 141        }
 142
 143        divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
 144        divider = (divider + 5) / 10;
 145
 146        STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
 147        STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
 148        STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
 149
 150        /* VCO Auto calibration */
 151        STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
 152
 153        stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
 154        stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x->regs[STV6110x_TNG1]);
 155        stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x->regs[STV6110x_TNG0]);
 156        stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
 157
 158        for (i = 0; i < TRIALS; i++) {
 159                stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
 160                if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x->regs[STV6110x_STAT1]))
 161                                break;
 162                msleep(1);
 163        }
 164
 165        return 0;
 166}
 167
 168static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 169{
 170        struct stv6110x_state *stv6110x = fe->tuner_priv;
 171
 172        stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x->regs[STV6110x_TNG1]);
 173        stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x->regs[STV6110x_TNG0]);
 174
 175        *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x->regs[STV6110x_TNG1]),
 176                                 STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x->regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
 177
 178        *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x->regs[STV6110x_TNG1]) +
 179                             STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x->regs[STV6110x_TNG1])));
 180
 181        *frequency >>= 2;
 182
 183        return 0;
 184}
 185
 186static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
 187{
 188        struct stv6110x_state *stv6110x = fe->tuner_priv;
 189        u32 halfbw;
 190        u8 i;
 191
 192        halfbw = bandwidth >> 1;
 193
 194        if (halfbw > 36000000)
 195                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
 196        else if (halfbw < 5000000)
 197                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
 198        else
 199                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
 200
 201
 202        STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
 203        STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
 204
 205        stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
 206        stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
 207
 208        for (i = 0; i < TRIALS; i++) {
 209                stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
 210                if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x->regs[STV6110x_STAT1]))
 211                        break;
 212                msleep(1);
 213        }
 214        STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
 215        stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
 216
 217        return 0;
 218}
 219
 220static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 221{
 222        struct stv6110x_state *stv6110x = fe->tuner_priv;
 223
 224        stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x->regs[STV6110x_CTRL3]);
 225        *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x->regs[STV6110x_CTRL3]) + 5) * 2000000;
 226
 227        return 0;
 228}
 229
 230static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
 231{
 232        struct stv6110x_state *stv6110x = fe->tuner_priv;
 233
 234        /* setup divider */
 235        switch (refclock) {
 236        default:
 237        case 1:
 238                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
 239                break;
 240        case 2:
 241                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
 242                break;
 243        case 4:
 244                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
 245                break;
 246        case 8:
 247        case 0:
 248                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
 249                break;
 250        }
 251        stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
 252
 253        return 0;
 254}
 255
 256static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
 257{
 258        struct stv6110x_state *stv6110x = fe->tuner_priv;
 259
 260        stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x->regs[STV6110x_CTRL2]);
 261        *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x->regs[STV6110x_CTRL2]);
 262
 263        return 0;
 264}
 265
 266static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
 267{
 268        struct stv6110x_state *stv6110x = fe->tuner_priv;
 269
 270        STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
 271        stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
 272
 273        return 0;
 274}
 275
 276static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
 277{
 278        struct stv6110x_state *stv6110x = fe->tuner_priv;
 279        int ret;
 280
 281        switch (mode) {
 282        case TUNER_SLEEP:
 283                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 0);
 284                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 0);
 285                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 0);
 286                break;
 287
 288        case TUNER_WAKE:
 289                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 1);
 290                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 1);
 291                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 1);
 292                break;
 293        }
 294
 295        ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
 296        if (ret < 0) {
 297                dprintk(FE_ERROR, 1, "I/O Error");
 298                return -EIO;
 299        }
 300
 301        return 0;
 302}
 303
 304static int stv6110x_sleep(struct dvb_frontend *fe)
 305{
 306        if (fe->tuner_priv)
 307                return stv6110x_set_mode(fe, TUNER_SLEEP);
 308
 309        return 0;
 310}
 311
 312static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
 313{
 314        struct stv6110x_state *stv6110x = fe->tuner_priv;
 315
 316        stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
 317
 318        if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x->regs[STV6110x_STAT1]))
 319                *status = TUNER_PHASELOCKED;
 320        else
 321                *status = 0;
 322
 323        return 0;
 324}
 325
 326
 327static int stv6110x_release(struct dvb_frontend *fe)
 328{
 329        struct stv6110x_state *stv6110x = fe->tuner_priv;
 330
 331        fe->tuner_priv = NULL;
 332        kfree(stv6110x);
 333
 334        return 0;
 335}
 336
 337static struct dvb_tuner_ops stv6110x_ops = {
 338        .info = {
 339                .name           = "STV6110(A) Silicon Tuner",
 340                .frequency_min  =  950000,
 341                .frequency_max  = 2150000,
 342                .frequency_step = 0,
 343        },
 344        .release                = stv6110x_release
 345};
 346
 347static struct stv6110x_devctl stv6110x_ctl = {
 348        .tuner_init             = stv6110x_init,
 349        .tuner_sleep            = stv6110x_sleep,
 350        .tuner_set_mode         = stv6110x_set_mode,
 351        .tuner_set_frequency    = stv6110x_set_frequency,
 352        .tuner_get_frequency    = stv6110x_get_frequency,
 353        .tuner_set_bandwidth    = stv6110x_set_bandwidth,
 354        .tuner_get_bandwidth    = stv6110x_get_bandwidth,
 355        .tuner_set_bbgain       = stv6110x_set_bbgain,
 356        .tuner_get_bbgain       = stv6110x_get_bbgain,
 357        .tuner_set_refclk       = stv6110x_set_refclock,
 358        .tuner_get_status       = stv6110x_get_status,
 359};
 360
 361struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
 362                                        const struct stv6110x_config *config,
 363                                        struct i2c_adapter *i2c)
 364{
 365        struct stv6110x_state *stv6110x;
 366        u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
 367
 368        stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
 369        if (!stv6110x)
 370                return NULL;
 371
 372        stv6110x->i2c           = i2c;
 373        stv6110x->config        = config;
 374        stv6110x->devctl        = &stv6110x_ctl;
 375        memcpy(stv6110x->regs, default_regs, 8);
 376
 377        /* setup divider */
 378        switch (stv6110x->config->clk_div) {
 379        default:
 380        case 1:
 381                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
 382                break;
 383        case 2:
 384                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
 385                break;
 386        case 4:
 387                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
 388                break;
 389        case 8:
 390        case 0:
 391                STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
 392                break;
 393        }
 394
 395        fe->tuner_priv          = stv6110x;
 396        fe->ops.tuner_ops       = stv6110x_ops;
 397
 398        printk(KERN_INFO "%s: Attaching STV6110x\n", __func__);
 399        return stv6110x->devctl;
 400}
 401EXPORT_SYMBOL(stv6110x_attach);
 402
 403MODULE_AUTHOR("Manu Abraham");
 404MODULE_DESCRIPTION("STV6110x Silicon tuner");
 405MODULE_LICENSE("GPL");
 406