linux/drivers/media/pci/pt1/va1j5jf8007t.c
<<
>>
Prefs
   1/*
   2 * ISDB-T driver for VA1J5JF8007/VA1J5JF8011
   3 *
   4 * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
   5 *
   6 * based on pt1dvr - http://pt1dvr.sourceforge.jp/
   7 *      by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22 */
  23
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26#include <linux/slab.h>
  27#include <linux/i2c.h>
  28#include "dvb_frontend.h"
  29#include "dvb_math.h"
  30#include "va1j5jf8007t.h"
  31
  32enum va1j5jf8007t_tune_state {
  33        VA1J5JF8007T_IDLE,
  34        VA1J5JF8007T_SET_FREQUENCY,
  35        VA1J5JF8007T_CHECK_FREQUENCY,
  36        VA1J5JF8007T_SET_MODULATION,
  37        VA1J5JF8007T_CHECK_MODULATION,
  38        VA1J5JF8007T_TRACK,
  39        VA1J5JF8007T_ABORT,
  40};
  41
  42struct va1j5jf8007t_state {
  43        const struct va1j5jf8007t_config *config;
  44        struct i2c_adapter *adap;
  45        struct dvb_frontend fe;
  46        enum va1j5jf8007t_tune_state tune_state;
  47};
  48
  49static int va1j5jf8007t_read_snr(struct dvb_frontend *fe, u16 *snr)
  50{
  51        struct va1j5jf8007t_state *state;
  52        u8 addr;
  53        int i;
  54        u8 write_buf[1], read_buf[1];
  55        struct i2c_msg msgs[2];
  56        s32 word, x, y;
  57
  58        state = fe->demodulator_priv;
  59        addr = state->config->demod_address;
  60
  61        word = 0;
  62        for (i = 0; i < 3; i++) {
  63                write_buf[0] = 0x8b + i;
  64
  65                msgs[0].addr = addr;
  66                msgs[0].flags = 0;
  67                msgs[0].len = sizeof(write_buf);
  68                msgs[0].buf = write_buf;
  69
  70                msgs[1].addr = addr;
  71                msgs[1].flags = I2C_M_RD;
  72                msgs[1].len = sizeof(read_buf);
  73                msgs[1].buf = read_buf;
  74
  75                if (i2c_transfer(state->adap, msgs, 2) != 2)
  76                        return -EREMOTEIO;
  77
  78                word <<= 8;
  79                word |= read_buf[0];
  80        }
  81
  82        if (!word)
  83                return -EIO;
  84
  85        x = 10 * (intlog10(0x540000 * 100 / word) - (2 << 24));
  86        y = (24ll << 46) / 1000000;
  87        y = ((s64)y * x >> 30) - (16ll << 40) / 10000;
  88        y = ((s64)y * x >> 29) + (398ll << 35) / 10000;
  89        y = ((s64)y * x >> 30) + (5491ll << 29) / 10000;
  90        y = ((s64)y * x >> 30) + (30965ll << 23) / 10000;
  91        *snr = y >> 15;
  92        return 0;
  93}
  94
  95static int va1j5jf8007t_get_frontend_algo(struct dvb_frontend *fe)
  96{
  97        return DVBFE_ALGO_HW;
  98}
  99
 100static int
 101va1j5jf8007t_read_status(struct dvb_frontend *fe, enum fe_status *status)
 102{
 103        struct va1j5jf8007t_state *state;
 104
 105        state = fe->demodulator_priv;
 106
 107        switch (state->tune_state) {
 108        case VA1J5JF8007T_IDLE:
 109        case VA1J5JF8007T_SET_FREQUENCY:
 110        case VA1J5JF8007T_CHECK_FREQUENCY:
 111                *status = 0;
 112                return 0;
 113
 114
 115        case VA1J5JF8007T_SET_MODULATION:
 116        case VA1J5JF8007T_CHECK_MODULATION:
 117        case VA1J5JF8007T_ABORT:
 118                *status |= FE_HAS_SIGNAL;
 119                return 0;
 120
 121        case VA1J5JF8007T_TRACK:
 122                *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
 123                return 0;
 124        }
 125
 126        BUG();
 127}
 128
 129struct va1j5jf8007t_cb_map {
 130        u32 frequency;
 131        u8 cb;
 132};
 133
 134static const struct va1j5jf8007t_cb_map va1j5jf8007t_cb_maps[] = {
 135        {  90000000, 0x80 },
 136        { 140000000, 0x81 },
 137        { 170000000, 0xa1 },
 138        { 220000000, 0x62 },
 139        { 330000000, 0xa2 },
 140        { 402000000, 0xe2 },
 141        { 450000000, 0x64 },
 142        { 550000000, 0x84 },
 143        { 600000000, 0xa4 },
 144        { 700000000, 0xc4 },
 145};
 146
 147static u8 va1j5jf8007t_lookup_cb(u32 frequency)
 148{
 149        int i;
 150        const struct va1j5jf8007t_cb_map *map;
 151
 152        for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_cb_maps); i++) {
 153                map = &va1j5jf8007t_cb_maps[i];
 154                if (frequency < map->frequency)
 155                        return map->cb;
 156        }
 157        return 0xe4;
 158}
 159
 160static int va1j5jf8007t_set_frequency(struct va1j5jf8007t_state *state)
 161{
 162        u32 frequency;
 163        u16 word;
 164        u8 buf[6];
 165        struct i2c_msg msg;
 166
 167        frequency = state->fe.dtv_property_cache.frequency;
 168
 169        word = (frequency + 71428) / 142857 + 399;
 170        buf[0] = 0xfe;
 171        buf[1] = 0xc2;
 172        buf[2] = word >> 8;
 173        buf[3] = word;
 174        buf[4] = 0x80;
 175        buf[5] = va1j5jf8007t_lookup_cb(frequency);
 176
 177        msg.addr = state->config->demod_address;
 178        msg.flags = 0;
 179        msg.len = sizeof(buf);
 180        msg.buf = buf;
 181
 182        if (i2c_transfer(state->adap, &msg, 1) != 1)
 183                return -EREMOTEIO;
 184
 185        return 0;
 186}
 187
 188static int
 189va1j5jf8007t_check_frequency(struct va1j5jf8007t_state *state, int *lock)
 190{
 191        u8 addr;
 192        u8 write_buf[2], read_buf[1];
 193        struct i2c_msg msgs[2];
 194
 195        addr = state->config->demod_address;
 196
 197        write_buf[0] = 0xfe;
 198        write_buf[1] = 0xc3;
 199
 200        msgs[0].addr = addr;
 201        msgs[0].flags = 0;
 202        msgs[0].len = sizeof(write_buf);
 203        msgs[0].buf = write_buf;
 204
 205        msgs[1].addr = addr;
 206        msgs[1].flags = I2C_M_RD;
 207        msgs[1].len = sizeof(read_buf);
 208        msgs[1].buf = read_buf;
 209
 210        if (i2c_transfer(state->adap, msgs, 2) != 2)
 211                return -EREMOTEIO;
 212
 213        *lock = read_buf[0] & 0x40;
 214        return 0;
 215}
 216
 217static int va1j5jf8007t_set_modulation(struct va1j5jf8007t_state *state)
 218{
 219        u8 buf[2];
 220        struct i2c_msg msg;
 221
 222        buf[0] = 0x01;
 223        buf[1] = 0x40;
 224
 225        msg.addr = state->config->demod_address;
 226        msg.flags = 0;
 227        msg.len = sizeof(buf);
 228        msg.buf = buf;
 229
 230        if (i2c_transfer(state->adap, &msg, 1) != 1)
 231                return -EREMOTEIO;
 232
 233        return 0;
 234}
 235
 236static int va1j5jf8007t_check_modulation(struct va1j5jf8007t_state *state,
 237                                         int *lock, int *retry)
 238{
 239        u8 addr;
 240        u8 write_buf[1], read_buf[1];
 241        struct i2c_msg msgs[2];
 242
 243        addr = state->config->demod_address;
 244
 245        write_buf[0] = 0x80;
 246
 247        msgs[0].addr = addr;
 248        msgs[0].flags = 0;
 249        msgs[0].len = sizeof(write_buf);
 250        msgs[0].buf = write_buf;
 251
 252        msgs[1].addr = addr;
 253        msgs[1].flags = I2C_M_RD;
 254        msgs[1].len = sizeof(read_buf);
 255        msgs[1].buf = read_buf;
 256
 257        if (i2c_transfer(state->adap, msgs, 2) != 2)
 258                return -EREMOTEIO;
 259
 260        *lock = !(read_buf[0] & 0x10);
 261        *retry = read_buf[0] & 0x80;
 262        return 0;
 263}
 264
 265static int
 266va1j5jf8007t_tune(struct dvb_frontend *fe,
 267                  bool re_tune,
 268                  unsigned int mode_flags,  unsigned int *delay,
 269                  enum fe_status *status)
 270{
 271        struct va1j5jf8007t_state *state;
 272        int ret;
 273        int lock = 0, retry = 0;
 274
 275        state = fe->demodulator_priv;
 276
 277        if (re_tune)
 278                state->tune_state = VA1J5JF8007T_SET_FREQUENCY;
 279
 280        switch (state->tune_state) {
 281        case VA1J5JF8007T_IDLE:
 282                *delay = 3 * HZ;
 283                *status = 0;
 284                return 0;
 285
 286        case VA1J5JF8007T_SET_FREQUENCY:
 287                ret = va1j5jf8007t_set_frequency(state);
 288                if (ret < 0)
 289                        return ret;
 290
 291                state->tune_state = VA1J5JF8007T_CHECK_FREQUENCY;
 292                *delay = 0;
 293                *status = 0;
 294                return 0;
 295
 296        case VA1J5JF8007T_CHECK_FREQUENCY:
 297                ret = va1j5jf8007t_check_frequency(state, &lock);
 298                if (ret < 0)
 299                        return ret;
 300
 301                if (!lock)  {
 302                        *delay = (HZ + 999) / 1000;
 303                        *status = 0;
 304                        return 0;
 305                }
 306
 307                state->tune_state = VA1J5JF8007T_SET_MODULATION;
 308                *delay = 0;
 309                *status = FE_HAS_SIGNAL;
 310                return 0;
 311
 312        case VA1J5JF8007T_SET_MODULATION:
 313                ret = va1j5jf8007t_set_modulation(state);
 314                if (ret < 0)
 315                        return ret;
 316
 317                state->tune_state = VA1J5JF8007T_CHECK_MODULATION;
 318                *delay = 0;
 319                *status = FE_HAS_SIGNAL;
 320                return 0;
 321
 322        case VA1J5JF8007T_CHECK_MODULATION:
 323                ret = va1j5jf8007t_check_modulation(state, &lock, &retry);
 324                if (ret < 0)
 325                        return ret;
 326
 327                if (!lock)  {
 328                        if (!retry)  {
 329                                state->tune_state = VA1J5JF8007T_ABORT;
 330                                *delay = 3 * HZ;
 331                                *status = FE_HAS_SIGNAL;
 332                                return 0;
 333                        }
 334                        *delay = (HZ + 999) / 1000;
 335                        *status = FE_HAS_SIGNAL;
 336                        return 0;
 337                }
 338
 339                state->tune_state = VA1J5JF8007T_TRACK;
 340                /* fall through */
 341
 342        case VA1J5JF8007T_TRACK:
 343                *delay = 3 * HZ;
 344                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
 345                return 0;
 346
 347        case VA1J5JF8007T_ABORT:
 348                *delay = 3 * HZ;
 349                *status = FE_HAS_SIGNAL;
 350                return 0;
 351        }
 352
 353        BUG();
 354}
 355
 356static int va1j5jf8007t_init_frequency(struct va1j5jf8007t_state *state)
 357{
 358        u8 buf[7];
 359        struct i2c_msg msg;
 360
 361        buf[0] = 0xfe;
 362        buf[1] = 0xc2;
 363        buf[2] = 0x01;
 364        buf[3] = 0x8f;
 365        buf[4] = 0xc1;
 366        buf[5] = 0x80;
 367        buf[6] = 0x80;
 368
 369        msg.addr = state->config->demod_address;
 370        msg.flags = 0;
 371        msg.len = sizeof(buf);
 372        msg.buf = buf;
 373
 374        if (i2c_transfer(state->adap, &msg, 1) != 1)
 375                return -EREMOTEIO;
 376
 377        return 0;
 378}
 379
 380static int va1j5jf8007t_set_sleep(struct va1j5jf8007t_state *state, int sleep)
 381{
 382        u8 buf[2];
 383        struct i2c_msg msg;
 384
 385        buf[0] = 0x03;
 386        buf[1] = sleep ? 0x90 : 0x80;
 387
 388        msg.addr = state->config->demod_address;
 389        msg.flags = 0;
 390        msg.len = sizeof(buf);
 391        msg.buf = buf;
 392
 393        if (i2c_transfer(state->adap, &msg, 1) != 1)
 394                return -EREMOTEIO;
 395
 396        return 0;
 397}
 398
 399static int va1j5jf8007t_sleep(struct dvb_frontend *fe)
 400{
 401        struct va1j5jf8007t_state *state;
 402        int ret;
 403
 404        state = fe->demodulator_priv;
 405
 406        ret = va1j5jf8007t_init_frequency(state);
 407        if (ret < 0)
 408                return ret;
 409
 410        return va1j5jf8007t_set_sleep(state, 1);
 411}
 412
 413static int va1j5jf8007t_init(struct dvb_frontend *fe)
 414{
 415        struct va1j5jf8007t_state *state;
 416
 417        state = fe->demodulator_priv;
 418        state->tune_state = VA1J5JF8007T_IDLE;
 419
 420        return va1j5jf8007t_set_sleep(state, 0);
 421}
 422
 423static void va1j5jf8007t_release(struct dvb_frontend *fe)
 424{
 425        struct va1j5jf8007t_state *state;
 426        state = fe->demodulator_priv;
 427        kfree(state);
 428}
 429
 430static struct dvb_frontend_ops va1j5jf8007t_ops = {
 431        .delsys = { SYS_ISDBT },
 432        .info = {
 433                .name = "VA1J5JF8007/VA1J5JF8011 ISDB-T",
 434                .frequency_min = 90000000,
 435                .frequency_max = 770000000,
 436                .frequency_stepsize = 142857,
 437                .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
 438                        FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
 439                        FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
 440        },
 441
 442        .read_snr = va1j5jf8007t_read_snr,
 443        .get_frontend_algo = va1j5jf8007t_get_frontend_algo,
 444        .read_status = va1j5jf8007t_read_status,
 445        .tune = va1j5jf8007t_tune,
 446        .sleep = va1j5jf8007t_sleep,
 447        .init = va1j5jf8007t_init,
 448        .release = va1j5jf8007t_release,
 449};
 450
 451static const u8 va1j5jf8007t_20mhz_prepare_bufs[][2] = {
 452        {0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2},
 453        {0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00},
 454        {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03},
 455        {0xef, 0x01}
 456};
 457
 458static const u8 va1j5jf8007t_25mhz_prepare_bufs[][2] = {
 459        {0x03, 0x90}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, {0x22, 0x83},
 460        {0x3a, 0x00}, {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x0a}, {0x76, 0x4c},
 461        {0x77, 0x03}, {0xef, 0x01}
 462};
 463
 464int va1j5jf8007t_prepare(struct dvb_frontend *fe)
 465{
 466        struct va1j5jf8007t_state *state;
 467        const u8 (*bufs)[2];
 468        int size;
 469        u8 buf[2];
 470        struct i2c_msg msg;
 471        int i;
 472
 473        state = fe->demodulator_priv;
 474
 475        switch (state->config->frequency) {
 476        case VA1J5JF8007T_20MHZ:
 477                bufs = va1j5jf8007t_20mhz_prepare_bufs;
 478                size = ARRAY_SIZE(va1j5jf8007t_20mhz_prepare_bufs);
 479                break;
 480        case VA1J5JF8007T_25MHZ:
 481                bufs = va1j5jf8007t_25mhz_prepare_bufs;
 482                size = ARRAY_SIZE(va1j5jf8007t_25mhz_prepare_bufs);
 483                break;
 484        default:
 485                return -EINVAL;
 486        }
 487
 488        msg.addr = state->config->demod_address;
 489        msg.flags = 0;
 490        msg.len = sizeof(buf);
 491        msg.buf = buf;
 492
 493        for (i = 0; i < size; i++) {
 494                memcpy(buf, bufs[i], sizeof(buf));
 495                if (i2c_transfer(state->adap, &msg, 1) != 1)
 496                        return -EREMOTEIO;
 497        }
 498
 499        return va1j5jf8007t_init_frequency(state);
 500}
 501
 502struct dvb_frontend *
 503va1j5jf8007t_attach(const struct va1j5jf8007t_config *config,
 504                    struct i2c_adapter *adap)
 505{
 506        struct va1j5jf8007t_state *state;
 507        struct dvb_frontend *fe;
 508        u8 buf[2];
 509        struct i2c_msg msg;
 510
 511        state = kzalloc(sizeof(struct va1j5jf8007t_state), GFP_KERNEL);
 512        if (!state)
 513                return NULL;
 514
 515        state->config = config;
 516        state->adap = adap;
 517
 518        fe = &state->fe;
 519        memcpy(&fe->ops, &va1j5jf8007t_ops, sizeof(struct dvb_frontend_ops));
 520        fe->demodulator_priv = state;
 521
 522        buf[0] = 0x01;
 523        buf[1] = 0x80;
 524
 525        msg.addr = state->config->demod_address;
 526        msg.flags = 0;
 527        msg.len = sizeof(buf);
 528        msg.buf = buf;
 529
 530        if (i2c_transfer(state->adap, &msg, 1) != 1) {
 531                kfree(state);
 532                return NULL;
 533        }
 534
 535        return fe;
 536}
 537