linux/drivers/media/tuners/qt1010.c
<<
>>
Prefs
   1/*
   2 *  Driver for Quantek QT1010 silicon tuner
   3 *
   4 *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
   5 *                     Aapo Tahkola <aet@rasterburn.org>
   6 *
   7 *  This program is free software; you can redistribute it and/or modify
   8 *  it under the terms of the GNU General Public License as published by
   9 *  the Free Software Foundation; either version 2 of the License, or
  10 *  (at your option) any later version.
  11 *
  12 *  This program is distributed in the hope that it will be useful,
  13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 *  GNU General Public License for more details.
  16 *
  17 *  You should have received a copy of the GNU General Public License
  18 *  along with this program; if not, write to the Free Software
  19 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20 */
  21#include "qt1010.h"
  22#include "qt1010_priv.h"
  23
  24/* read single register */
  25static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val)
  26{
  27        struct i2c_msg msg[2] = {
  28                { .addr = priv->cfg->i2c_address,
  29                  .flags = 0, .buf = &reg, .len = 1 },
  30                { .addr = priv->cfg->i2c_address,
  31                  .flags = I2C_M_RD, .buf = val, .len = 1 },
  32        };
  33
  34        if (i2c_transfer(priv->i2c, msg, 2) != 2) {
  35                dev_warn(&priv->i2c->dev, "%s: i2c rd failed reg=%02x\n",
  36                                KBUILD_MODNAME, reg);
  37                return -EREMOTEIO;
  38        }
  39        return 0;
  40}
  41
  42/* write single register */
  43static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val)
  44{
  45        u8 buf[2] = { reg, val };
  46        struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
  47                               .flags = 0, .buf = buf, .len = 2 };
  48
  49        if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
  50                dev_warn(&priv->i2c->dev, "%s: i2c wr failed reg=%02x\n",
  51                                KBUILD_MODNAME, reg);
  52                return -EREMOTEIO;
  53        }
  54        return 0;
  55}
  56
  57static int qt1010_set_params(struct dvb_frontend *fe)
  58{
  59        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  60        struct qt1010_priv *priv;
  61        int err;
  62        u32 freq, div, mod1, mod2;
  63        u8 i, tmpval, reg05;
  64        qt1010_i2c_oper_t rd[48] = {
  65                { QT1010_WR, 0x01, 0x80 },
  66                { QT1010_WR, 0x02, 0x3f },
  67                { QT1010_WR, 0x05, 0xff }, /* 02 c write */
  68                { QT1010_WR, 0x06, 0x44 },
  69                { QT1010_WR, 0x07, 0xff }, /* 04 c write */
  70                { QT1010_WR, 0x08, 0x08 },
  71                { QT1010_WR, 0x09, 0xff }, /* 06 c write */
  72                { QT1010_WR, 0x0a, 0xff }, /* 07 c write */
  73                { QT1010_WR, 0x0b, 0xff }, /* 08 c write */
  74                { QT1010_WR, 0x0c, 0xe1 },
  75                { QT1010_WR, 0x1a, 0xff }, /* 10 c write */
  76                { QT1010_WR, 0x1b, 0x00 },
  77                { QT1010_WR, 0x1c, 0x89 },
  78                { QT1010_WR, 0x11, 0xff }, /* 13 c write */
  79                { QT1010_WR, 0x12, 0xff }, /* 14 c write */
  80                { QT1010_WR, 0x22, 0xff }, /* 15 c write */
  81                { QT1010_WR, 0x1e, 0x00 },
  82                { QT1010_WR, 0x1e, 0xd0 },
  83                { QT1010_RD, 0x22, 0xff }, /* 16 c read */
  84                { QT1010_WR, 0x1e, 0x00 },
  85                { QT1010_RD, 0x05, 0xff }, /* 20 c read */
  86                { QT1010_RD, 0x22, 0xff }, /* 21 c read */
  87                { QT1010_WR, 0x23, 0xd0 },
  88                { QT1010_WR, 0x1e, 0x00 },
  89                { QT1010_WR, 0x1e, 0xe0 },
  90                { QT1010_RD, 0x23, 0xff }, /* 25 c read */
  91                { QT1010_RD, 0x23, 0xff }, /* 26 c read */
  92                { QT1010_WR, 0x1e, 0x00 },
  93                { QT1010_WR, 0x24, 0xd0 },
  94                { QT1010_WR, 0x1e, 0x00 },
  95                { QT1010_WR, 0x1e, 0xf0 },
  96                { QT1010_RD, 0x24, 0xff }, /* 31 c read */
  97                { QT1010_WR, 0x1e, 0x00 },
  98                { QT1010_WR, 0x14, 0x7f },
  99                { QT1010_WR, 0x15, 0x7f },
 100                { QT1010_WR, 0x05, 0xff }, /* 35 c write */
 101                { QT1010_WR, 0x06, 0x00 },
 102                { QT1010_WR, 0x15, 0x1f },
 103                { QT1010_WR, 0x16, 0xff },
 104                { QT1010_WR, 0x18, 0xff },
 105                { QT1010_WR, 0x1f, 0xff }, /* 40 c write */
 106                { QT1010_WR, 0x20, 0xff }, /* 41 c write */
 107                { QT1010_WR, 0x21, 0x53 },
 108                { QT1010_WR, 0x25, 0xff }, /* 43 c write */
 109                { QT1010_WR, 0x26, 0x15 },
 110                { QT1010_WR, 0x00, 0xff }, /* 45 c write */
 111                { QT1010_WR, 0x02, 0x00 },
 112                { QT1010_WR, 0x01, 0x00 }
 113        };
 114
 115#define FREQ1 32000000 /* 32 MHz */
 116#define FREQ2  4000000 /* 4 MHz Quartz oscillator in the stick? */
 117
 118        priv = fe->tuner_priv;
 119        freq = c->frequency;
 120        div = (freq + QT1010_OFFSET) / QT1010_STEP;
 121        freq = (div * QT1010_STEP) - QT1010_OFFSET;
 122        mod1 = (freq + QT1010_OFFSET) % FREQ1;
 123        mod2 = (freq + QT1010_OFFSET) % FREQ2;
 124        priv->frequency = freq;
 125
 126        if (fe->ops.i2c_gate_ctrl)
 127                fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
 128
 129        /* reg 05 base value */
 130        if      (freq < 290000000) reg05 = 0x14; /* 290 MHz */
 131        else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */
 132        else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */
 133        else                       reg05 = 0x74;
 134
 135        /* 0x5 */
 136        rd[2].val = reg05;
 137
 138        /* 07 - set frequency: 32 MHz scale */
 139        rd[4].val = (freq + QT1010_OFFSET) / FREQ1;
 140
 141        /* 09 - changes every 8/24 MHz */
 142        if (mod1 < 8000000) rd[6].val = 0x1d;
 143        else                rd[6].val = 0x1c;
 144
 145        /* 0a - set frequency: 4 MHz scale (max 28 MHz) */
 146        if      (mod1 < 1*FREQ2) rd[7].val = 0x09; /*  +0 MHz */
 147        else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /*  +4 MHz */
 148        else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /*  +8 MHz */
 149        else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */
 150        else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */
 151        else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */
 152        else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */
 153        else                     rd[7].val = 0x0a; /* +28 MHz */
 154
 155        /* 0b - changes every 2/2 MHz */
 156        if (mod2 < 2000000) rd[8].val = 0x45;
 157        else                rd[8].val = 0x44;
 158
 159        /* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/
 160        tmpval = 0x78; /* byte, overflows intentionally */
 161        rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08);
 162
 163        /* 11 */
 164        rd[13].val = 0xfd; /* TODO: correct value calculation */
 165
 166        /* 12 */
 167        rd[14].val = 0x91; /* TODO: correct value calculation */
 168
 169        /* 22 */
 170        if      (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */
 171        else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */
 172        else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */
 173        else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */
 174        else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */
 175        else                       rd[15].val = 0xd0;
 176
 177        /* 05 */
 178        rd[35].val = (reg05 & 0xf0);
 179
 180        /* 1f */
 181        if      (mod1 <  8000000) tmpval = 0x00;
 182        else if (mod1 < 12000000) tmpval = 0x01;
 183        else if (mod1 < 16000000) tmpval = 0x02;
 184        else if (mod1 < 24000000) tmpval = 0x03;
 185        else if (mod1 < 28000000) tmpval = 0x04;
 186        else                      tmpval = 0x05;
 187        rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval);
 188
 189        /* 20 */
 190        if      (mod1 <  8000000) tmpval = 0x00;
 191        else if (mod1 < 12000000) tmpval = 0x01;
 192        else if (mod1 < 20000000) tmpval = 0x02;
 193        else if (mod1 < 24000000) tmpval = 0x03;
 194        else if (mod1 < 28000000) tmpval = 0x04;
 195        else                      tmpval = 0x05;
 196        rd[41].val = (priv->reg20_init_val + 0x0d + tmpval);
 197
 198        /* 25 */
 199        rd[43].val = priv->reg25_init_val;
 200
 201        /* 00 */
 202        rd[45].val = 0x92; /* TODO: correct value calculation */
 203
 204        dev_dbg(&priv->i2c->dev,
 205                        "%s: freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
 206                        "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
 207                        "20:%02x 25:%02x 00:%02x\n", __func__, \
 208                        freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, \
 209                        rd[8].val, rd[10].val, rd[13].val, rd[14].val, \
 210                        rd[15].val, rd[35].val, rd[40].val, rd[41].val, \
 211                        rd[43].val, rd[45].val);
 212
 213        for (i = 0; i < ARRAY_SIZE(rd); i++) {
 214                if (rd[i].oper == QT1010_WR) {
 215                        err = qt1010_writereg(priv, rd[i].reg, rd[i].val);
 216                } else { /* read is required to proper locking */
 217                        err = qt1010_readreg(priv, rd[i].reg, &tmpval);
 218                }
 219                if (err) return err;
 220        }
 221
 222        if (fe->ops.i2c_gate_ctrl)
 223                fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
 224
 225        return 0;
 226}
 227
 228static int qt1010_init_meas1(struct qt1010_priv *priv,
 229                             u8 oper, u8 reg, u8 reg_init_val, u8 *retval)
 230{
 231        u8 i, val1, val2;
 232        int err;
 233
 234        qt1010_i2c_oper_t i2c_data[] = {
 235                { QT1010_WR, reg, reg_init_val },
 236                { QT1010_WR, 0x1e, 0x00 },
 237                { QT1010_WR, 0x1e, oper },
 238                { QT1010_RD, reg, 0xff }
 239        };
 240
 241        for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
 242                if (i2c_data[i].oper == QT1010_WR) {
 243                        err = qt1010_writereg(priv, i2c_data[i].reg,
 244                                              i2c_data[i].val);
 245                } else {
 246                        err = qt1010_readreg(priv, i2c_data[i].reg, &val2);
 247                }
 248                if (err) return err;
 249        }
 250
 251        do {
 252                val1 = val2;
 253                err = qt1010_readreg(priv, reg, &val2);
 254                if (err) return err;
 255                dev_dbg(&priv->i2c->dev, "%s: compare reg:%02x %02x %02x\n",
 256                                __func__, reg, val1, val2);
 257        } while (val1 != val2);
 258        *retval = val1;
 259
 260        return qt1010_writereg(priv, 0x1e, 0x00);
 261}
 262
 263static int qt1010_init_meas2(struct qt1010_priv *priv,
 264                            u8 reg_init_val, u8 *retval)
 265{
 266        u8 i, val;
 267        int err;
 268        qt1010_i2c_oper_t i2c_data[] = {
 269                { QT1010_WR, 0x07, reg_init_val },
 270                { QT1010_WR, 0x22, 0xd0 },
 271                { QT1010_WR, 0x1e, 0x00 },
 272                { QT1010_WR, 0x1e, 0xd0 },
 273                { QT1010_RD, 0x22, 0xff },
 274                { QT1010_WR, 0x1e, 0x00 },
 275                { QT1010_WR, 0x22, 0xff }
 276        };
 277        for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
 278                if (i2c_data[i].oper == QT1010_WR) {
 279                        err = qt1010_writereg(priv, i2c_data[i].reg,
 280                                              i2c_data[i].val);
 281                } else {
 282                        err = qt1010_readreg(priv, i2c_data[i].reg, &val);
 283                }
 284                if (err) return err;
 285        }
 286        *retval = val;
 287        return 0;
 288}
 289
 290static int qt1010_init(struct dvb_frontend *fe)
 291{
 292        struct qt1010_priv *priv = fe->tuner_priv;
 293        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 294        int err = 0;
 295        u8 i, tmpval, *valptr = NULL;
 296
 297        qt1010_i2c_oper_t i2c_data[] = {
 298                { QT1010_WR, 0x01, 0x80 },
 299                { QT1010_WR, 0x0d, 0x84 },
 300                { QT1010_WR, 0x0e, 0xb7 },
 301                { QT1010_WR, 0x2a, 0x23 },
 302                { QT1010_WR, 0x2c, 0xdc },
 303                { QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */
 304                { QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */
 305                { QT1010_WR, 0x2b, 0x70 },
 306                { QT1010_WR, 0x2a, 0x23 },
 307                { QT1010_M1, 0x26, 0x08 },
 308                { QT1010_M1, 0x82, 0xff },
 309                { QT1010_WR, 0x05, 0x14 },
 310                { QT1010_WR, 0x06, 0x44 },
 311                { QT1010_WR, 0x07, 0x28 },
 312                { QT1010_WR, 0x08, 0x0b },
 313                { QT1010_WR, 0x11, 0xfd },
 314                { QT1010_M1, 0x22, 0x0d },
 315                { QT1010_M1, 0xd0, 0xff },
 316                { QT1010_WR, 0x06, 0x40 },
 317                { QT1010_WR, 0x16, 0xf0 },
 318                { QT1010_WR, 0x02, 0x38 },
 319                { QT1010_WR, 0x03, 0x18 },
 320                { QT1010_WR, 0x20, 0xe0 },
 321                { QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */
 322                { QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */
 323                { QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */
 324                { QT1010_WR, 0x03, 0x19 },
 325                { QT1010_WR, 0x02, 0x3f },
 326                { QT1010_WR, 0x21, 0x53 },
 327                { QT1010_RD, 0x21, 0xff },
 328                { QT1010_WR, 0x11, 0xfd },
 329                { QT1010_WR, 0x05, 0x34 },
 330                { QT1010_WR, 0x06, 0x44 },
 331                { QT1010_WR, 0x08, 0x08 }
 332        };
 333
 334        if (fe->ops.i2c_gate_ctrl)
 335                fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
 336
 337        for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
 338                switch (i2c_data[i].oper) {
 339                case QT1010_WR:
 340                        err = qt1010_writereg(priv, i2c_data[i].reg,
 341                                              i2c_data[i].val);
 342                        break;
 343                case QT1010_RD:
 344                        if (i2c_data[i].val == 0x20)
 345                                valptr = &priv->reg20_init_val;
 346                        else
 347                                valptr = &tmpval;
 348                        err = qt1010_readreg(priv, i2c_data[i].reg, valptr);
 349                        break;
 350                case QT1010_M1:
 351                        if (i2c_data[i].val == 0x25)
 352                                valptr = &priv->reg25_init_val;
 353                        else if (i2c_data[i].val == 0x1f)
 354                                valptr = &priv->reg1f_init_val;
 355                        else
 356                                valptr = &tmpval;
 357                        err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
 358                                                i2c_data[i].reg,
 359                                                i2c_data[i].val, valptr);
 360                        i++;
 361                        break;
 362                }
 363                if (err) return err;
 364        }
 365
 366        for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */
 367                if ((err = qt1010_init_meas2(priv, i, &tmpval)))
 368                        return err;
 369
 370        if (!c->frequency)
 371                c->frequency = 545000000; /* Sigmatek DVB-110 545000000 */
 372                                      /* MSI Megasky 580 GL861 533000000 */
 373        return qt1010_set_params(fe);
 374}
 375
 376static int qt1010_release(struct dvb_frontend *fe)
 377{
 378        kfree(fe->tuner_priv);
 379        fe->tuner_priv = NULL;
 380        return 0;
 381}
 382
 383static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 384{
 385        struct qt1010_priv *priv = fe->tuner_priv;
 386        *frequency = priv->frequency;
 387        return 0;
 388}
 389
 390static int qt1010_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 391{
 392        *frequency = 36125000;
 393        return 0;
 394}
 395
 396static const struct dvb_tuner_ops qt1010_tuner_ops = {
 397        .info = {
 398                .name           = "Quantek QT1010",
 399                .frequency_min  = QT1010_MIN_FREQ,
 400                .frequency_max  = QT1010_MAX_FREQ,
 401                .frequency_step = QT1010_STEP,
 402        },
 403
 404        .release       = qt1010_release,
 405        .init          = qt1010_init,
 406        /* TODO: implement sleep */
 407
 408        .set_params    = qt1010_set_params,
 409        .get_frequency = qt1010_get_frequency,
 410        .get_if_frequency = qt1010_get_if_frequency,
 411};
 412
 413struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
 414                                    struct i2c_adapter *i2c,
 415                                    struct qt1010_config *cfg)
 416{
 417        struct qt1010_priv *priv = NULL;
 418        u8 id;
 419
 420        priv = kzalloc(sizeof(struct qt1010_priv), GFP_KERNEL);
 421        if (priv == NULL)
 422                return NULL;
 423
 424        priv->cfg = cfg;
 425        priv->i2c = i2c;
 426
 427        if (fe->ops.i2c_gate_ctrl)
 428                fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
 429
 430
 431        /* Try to detect tuner chip. Probably this is not correct register. */
 432        if (qt1010_readreg(priv, 0x29, &id) != 0 || (id != 0x39)) {
 433                kfree(priv);
 434                return NULL;
 435        }
 436
 437        if (fe->ops.i2c_gate_ctrl)
 438                fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
 439
 440        dev_info(&priv->i2c->dev,
 441                        "%s: Quantek QT1010 successfully identified\n",
 442                        KBUILD_MODNAME);
 443
 444        memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops,
 445               sizeof(struct dvb_tuner_ops));
 446
 447        fe->tuner_priv = priv;
 448        return fe;
 449}
 450EXPORT_SYMBOL(qt1010_attach);
 451
 452MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver");
 453MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 454MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
 455MODULE_VERSION("0.1");
 456MODULE_LICENSE("GPL");
 457