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/string.h>
  27
  28#include "dvb_frontend.h"
  29
  30#include "stv6110x_reg.h"
  31#include "stv6110x.h"
  32#include "stv6110x_priv.h"
  33
  34static unsigned int verbose;
  35module_param(verbose, int, 0644);
  36MODULE_PARM_DESC(verbose, "Set Verbosity level");
  37
  38static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
  39
  40static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
  41{
  42        int ret;
  43        const struct stv6110x_config *config = stv6110x->config;
  44        u8 b0[] = { reg };
  45        u8 b1[] = { 0 };
  46        struct i2c_msg msg[] = {
  47                { .addr = config->addr, .flags = 0,        .buf = b0, .len = 1 },
  48                { .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }
  49        };
  50
  51        ret = i2c_transfer(stv6110x->i2c, msg, 2);
  52        if (ret != 2) {
  53                dprintk(FE_ERROR, 1, "I/O Error");
  54                return -EREMOTEIO;
  55        }
  56        *data = b1[0];
  57
  58        return 0;
  59}
  60
  61static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
  62{
  63        int ret;
  64        const struct stv6110x_config *config = stv6110x->config;
  65        u8 buf[] = { reg, data };
  66        struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 };
  67
  68        ret = i2c_transfer(stv6110x->i2c, &msg, 1);
  69        if (ret != 1) {
  70                dprintk(FE_ERROR, 1, "I/O Error");
  71                return -EREMOTEIO;
  72        }
  73
  74        return 0;
  75}
  76
  77static int stv6110x_init(struct dvb_frontend *fe)
  78{
  79        struct stv6110x_state *stv6110x = fe->tuner_priv;
  80        int ret;
  81        u8 i;
  82
  83        for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) {
  84                ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]);
  85                if (ret < 0) {
  86                        dprintk(FE_ERROR, 1, "Initialization failed");
  87                        return -1;
  88                }
  89        }
  90
  91        return 0;
  92}
  93
  94static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
  95{
  96        struct stv6110x_state *stv6110x = fe->tuner_priv;
  97        u32 rDiv, divider;
  98        s32 pVal, pCalc, rDivOpt = 0;
  99        u8 i;
 100
 101        STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
 102
 103        if (frequency <= 1023000) {
 104                STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
 105                STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
 106                pVal = 40;
 107        } else if (frequency <= 1300000) {
 108                STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
 109                STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
 110                pVal = 40;
 111        } else if (frequency <= 2046000) {
 112                STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
 113                STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
 114                pVal = 20;
 115        } else {
 116                STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
 117                STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
 118                pVal = 20;
 119        }
 120
 121        for (rDiv = 0; rDiv <= 3; rDiv++) {
 122                pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv);
 123
 124                if ((abs((s32)(pCalc - pVal))) < (abs((s32)(1000 - pVal))))
 125                        rDivOpt = rDiv;
 126        }
 127
 128        divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
 129        divider = (divider + 5) / 10;
 130
 131        STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
 132        STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
 133        STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
 134
 135        /* VCO Auto calibration */
 136        STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
 137
 138        stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
 139        stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]);
 140        stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]);
 141        stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
 142
 143        for (i = 0; i < TRIALS; i++) {
 144                stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
 145                if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1]))
 146                                break;
 147                msleep(1);
 148        }
 149
 150        return 0;
 151}
 152
 153static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 154{
 155        struct stv6110x_state *stv6110x = fe->tuner_priv;
 156
 157        stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]);
 158        stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]);
 159
 160        *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]),
 161                                 STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
 162
 163        *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) +
 164                             STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1])));
 165
 166        *frequency >>= 2;
 167
 168        return 0;
 169}
 170
 171static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
 172{
 173        struct stv6110x_state *stv6110x = fe->tuner_priv;
 174        u32 halfbw;
 175        u8 i;
 176
 177        halfbw = bandwidth >> 1;
 178
 179        if (halfbw > 36000000)
 180                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
 181        else if (halfbw < 5000000)
 182                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
 183        else
 184                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
 185
 186
 187        STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
 188        STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
 189
 190        stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
 191        stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
 192
 193        for (i = 0; i < TRIALS; i++) {
 194                stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
 195                if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1]))
 196                        break;
 197                msleep(1);
 198        }
 199        STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
 200        stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
 201
 202        return 0;
 203}
 204
 205static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 206{
 207        struct stv6110x_state *stv6110x = fe->tuner_priv;
 208
 209        stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]);
 210        *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000;
 211
 212        return 0;
 213}
 214
 215static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
 216{
 217        struct stv6110x_state *stv6110x = fe->tuner_priv;
 218
 219        /* setup divider */
 220        switch (refclock) {
 221        default:
 222        case 1:
 223                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
 224                break;
 225        case 2:
 226                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
 227                break;
 228        case 4:
 229                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
 230                break;
 231        case 8:
 232        case 0:
 233                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
 234                break;
 235        }
 236        stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
 237
 238        return 0;
 239}
 240
 241static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
 242{
 243        struct stv6110x_state *stv6110x = fe->tuner_priv;
 244
 245        stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]);
 246        *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]);
 247
 248        return 0;
 249}
 250
 251static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
 252{
 253        struct stv6110x_state *stv6110x = fe->tuner_priv;
 254
 255        STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
 256        stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
 257
 258        return 0;
 259}
 260
 261static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
 262{
 263        struct stv6110x_state *stv6110x = fe->tuner_priv;
 264        int ret;
 265
 266        switch (mode) {
 267        case TUNER_SLEEP:
 268                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0);
 269                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0);
 270                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0);
 271                break;
 272
 273        case TUNER_WAKE:
 274                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1);
 275                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1);
 276                STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1);
 277                break;
 278        }
 279
 280        ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
 281        if (ret < 0) {
 282                dprintk(FE_ERROR, 1, "I/O Error");
 283                return -EIO;
 284        }
 285
 286        return 0;
 287}
 288
 289static int stv6110x_sleep(struct dvb_frontend *fe)
 290{
 291        return stv6110x_set_mode(fe, TUNER_SLEEP);
 292}
 293
 294static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
 295{
 296        struct stv6110x_state *stv6110x = fe->tuner_priv;
 297
 298        stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
 299
 300        if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1]))
 301                *status = TUNER_PHASELOCKED;
 302        else
 303                *status = 0;
 304
 305        return 0;
 306}
 307
 308
 309static int stv6110x_release(struct dvb_frontend *fe)
 310{
 311        struct stv6110x_state *stv6110x = fe->tuner_priv;
 312
 313        fe->tuner_priv = NULL;
 314        kfree(stv6110x);
 315
 316        return 0;
 317}
 318
 319static struct dvb_tuner_ops stv6110x_ops = {
 320        .info = {
 321                .name           = "STV6110(A) Silicon Tuner",
 322                .frequency_min  =  950000,
 323                .frequency_max  = 2150000,
 324                .frequency_step = 0,
 325        },
 326
 327        .init                   = stv6110x_init,
 328        .sleep                  = stv6110x_sleep,
 329        .release                = stv6110x_release
 330};
 331
 332static struct stv6110x_devctl stv6110x_ctl = {
 333        .tuner_init             = stv6110x_init,
 334        .tuner_set_mode         = stv6110x_set_mode,
 335        .tuner_set_frequency    = stv6110x_set_frequency,
 336        .tuner_get_frequency    = stv6110x_get_frequency,
 337        .tuner_set_bandwidth    = stv6110x_set_bandwidth,
 338        .tuner_get_bandwidth    = stv6110x_get_bandwidth,
 339        .tuner_set_bbgain       = stv6110x_set_bbgain,
 340        .tuner_get_bbgain       = stv6110x_get_bbgain,
 341        .tuner_set_refclk       = stv6110x_set_refclock,
 342        .tuner_get_status       = stv6110x_get_status,
 343};
 344
 345struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
 346                                        const struct stv6110x_config *config,
 347                                        struct i2c_adapter *i2c)
 348{
 349        struct stv6110x_state *stv6110x;
 350
 351        stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
 352        if (stv6110x == NULL)
 353                goto error;
 354
 355        stv6110x->i2c           = i2c;
 356        stv6110x->config        = config;
 357        stv6110x->devctl        = &stv6110x_ctl;
 358
 359        fe->tuner_priv          = stv6110x;
 360        fe->ops.tuner_ops       = stv6110x_ops;
 361
 362        printk("%s: Attaching STV6110x \n", __func__);
 363        return stv6110x->devctl;
 364
 365error:
 366        kfree(stv6110x);
 367        return NULL;
 368}
 369EXPORT_SYMBOL(stv6110x_attach);
 370
 371MODULE_AUTHOR("Manu Abraham");
 372MODULE_DESCRIPTION("STV6110x Silicon tuner");
 373MODULE_LICENSE("GPL");
 374