linux/drivers/media/dvb/pt1/va1j5jf8007s.c
<<
>>
Prefs
   1/*
   2 * ISDB-S driver for VA1J5JF8007
   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 "va1j5jf8007s.h"
  30
  31enum va1j5jf8007s_tune_state {
  32        VA1J5JF8007S_IDLE,
  33        VA1J5JF8007S_SET_FREQUENCY_1,
  34        VA1J5JF8007S_SET_FREQUENCY_2,
  35        VA1J5JF8007S_SET_FREQUENCY_3,
  36        VA1J5JF8007S_CHECK_FREQUENCY,
  37        VA1J5JF8007S_SET_MODULATION,
  38        VA1J5JF8007S_CHECK_MODULATION,
  39        VA1J5JF8007S_SET_TS_ID,
  40        VA1J5JF8007S_CHECK_TS_ID,
  41        VA1J5JF8007S_TRACK,
  42};
  43
  44struct va1j5jf8007s_state {
  45        const struct va1j5jf8007s_config *config;
  46        struct i2c_adapter *adap;
  47        struct dvb_frontend fe;
  48        enum va1j5jf8007s_tune_state tune_state;
  49};
  50
  51static int va1j5jf8007s_get_frontend_algo(struct dvb_frontend *fe)
  52{
  53        return DVBFE_ALGO_HW;
  54}
  55
  56static int
  57va1j5jf8007s_read_status(struct dvb_frontend *fe, fe_status_t *status)
  58{
  59        struct va1j5jf8007s_state *state;
  60
  61        state = fe->demodulator_priv;
  62
  63        switch (state->tune_state) {
  64        case VA1J5JF8007S_IDLE:
  65        case VA1J5JF8007S_SET_FREQUENCY_1:
  66        case VA1J5JF8007S_SET_FREQUENCY_2:
  67        case VA1J5JF8007S_SET_FREQUENCY_3:
  68        case VA1J5JF8007S_CHECK_FREQUENCY:
  69                *status = 0;
  70                return 0;
  71
  72
  73        case VA1J5JF8007S_SET_MODULATION:
  74        case VA1J5JF8007S_CHECK_MODULATION:
  75                *status |= FE_HAS_SIGNAL;
  76                return 0;
  77
  78        case VA1J5JF8007S_SET_TS_ID:
  79        case VA1J5JF8007S_CHECK_TS_ID:
  80                *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
  81                return 0;
  82
  83        case VA1J5JF8007S_TRACK:
  84                *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
  85                return 0;
  86        }
  87
  88        BUG();
  89}
  90
  91struct va1j5jf8007s_cb_map {
  92        u32 frequency;
  93        u8 cb;
  94};
  95
  96static const struct va1j5jf8007s_cb_map va1j5jf8007s_cb_maps[] = {
  97        {  986000, 0xb2 },
  98        { 1072000, 0xd2 },
  99        { 1154000, 0xe2 },
 100        { 1291000, 0x20 },
 101        { 1447000, 0x40 },
 102        { 1615000, 0x60 },
 103        { 1791000, 0x80 },
 104        { 1972000, 0xa0 },
 105};
 106
 107static u8 va1j5jf8007s_lookup_cb(u32 frequency)
 108{
 109        int i;
 110        const struct va1j5jf8007s_cb_map *map;
 111
 112        for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_cb_maps); i++) {
 113                map = &va1j5jf8007s_cb_maps[i];
 114                if (frequency < map->frequency)
 115                        return map->cb;
 116        }
 117        return 0xc0;
 118}
 119
 120static int va1j5jf8007s_set_frequency_1(struct va1j5jf8007s_state *state)
 121{
 122        u32 frequency;
 123        u16 word;
 124        u8 buf[6];
 125        struct i2c_msg msg;
 126
 127        frequency = state->fe.dtv_property_cache.frequency;
 128
 129        word = (frequency + 500) / 1000;
 130        if (frequency < 1072000)
 131                word = (word << 1 & ~0x1f) | (word & 0x0f);
 132
 133        buf[0] = 0xfe;
 134        buf[1] = 0xc0;
 135        buf[2] = 0x40 | word >> 8;
 136        buf[3] = word;
 137        buf[4] = 0xe0;
 138        buf[5] = va1j5jf8007s_lookup_cb(frequency);
 139
 140        msg.addr = state->config->demod_address;
 141        msg.flags = 0;
 142        msg.len = sizeof(buf);
 143        msg.buf = buf;
 144
 145        if (i2c_transfer(state->adap, &msg, 1) != 1)
 146                return -EREMOTEIO;
 147
 148        return 0;
 149}
 150
 151static int va1j5jf8007s_set_frequency_2(struct va1j5jf8007s_state *state)
 152{
 153        u8 buf[3];
 154        struct i2c_msg msg;
 155
 156        buf[0] = 0xfe;
 157        buf[1] = 0xc0;
 158        buf[2] = 0xe4;
 159
 160        msg.addr = state->config->demod_address;
 161        msg.flags = 0;
 162        msg.len = sizeof(buf);
 163        msg.buf = buf;
 164
 165        if (i2c_transfer(state->adap, &msg, 1) != 1)
 166                return -EREMOTEIO;
 167
 168        return 0;
 169}
 170
 171static int va1j5jf8007s_set_frequency_3(struct va1j5jf8007s_state *state)
 172{
 173        u32 frequency;
 174        u8 buf[4];
 175        struct i2c_msg msg;
 176
 177        frequency = state->fe.dtv_property_cache.frequency;
 178
 179        buf[0] = 0xfe;
 180        buf[1] = 0xc0;
 181        buf[2] = 0xf4;
 182        buf[3] = va1j5jf8007s_lookup_cb(frequency) | 0x4;
 183
 184        msg.addr = state->config->demod_address;
 185        msg.flags = 0;
 186        msg.len = sizeof(buf);
 187        msg.buf = buf;
 188
 189        if (i2c_transfer(state->adap, &msg, 1) != 1)
 190                return -EREMOTEIO;
 191
 192        return 0;
 193}
 194
 195static int
 196va1j5jf8007s_check_frequency(struct va1j5jf8007s_state *state, int *lock)
 197{
 198        u8 addr;
 199        u8 write_buf[2], read_buf[1];
 200        struct i2c_msg msgs[2];
 201
 202        addr = state->config->demod_address;
 203
 204        write_buf[0] = 0xfe;
 205        write_buf[1] = 0xc1;
 206
 207        msgs[0].addr = addr;
 208        msgs[0].flags = 0;
 209        msgs[0].len = sizeof(write_buf);
 210        msgs[0].buf = write_buf;
 211
 212        msgs[1].addr = addr;
 213        msgs[1].flags = I2C_M_RD;
 214        msgs[1].len = sizeof(read_buf);
 215        msgs[1].buf = read_buf;
 216
 217        if (i2c_transfer(state->adap, msgs, 2) != 2)
 218                return -EREMOTEIO;
 219
 220        *lock = read_buf[0] & 0x40;
 221        return 0;
 222}
 223
 224static int va1j5jf8007s_set_modulation(struct va1j5jf8007s_state *state)
 225{
 226        u8 buf[2];
 227        struct i2c_msg msg;
 228
 229        buf[0] = 0x03;
 230        buf[1] = 0x01;
 231
 232        msg.addr = state->config->demod_address;
 233        msg.flags = 0;
 234        msg.len = sizeof(buf);
 235        msg.buf = buf;
 236
 237        if (i2c_transfer(state->adap, &msg, 1) != 1)
 238                return -EREMOTEIO;
 239
 240        return 0;
 241}
 242
 243static int
 244va1j5jf8007s_check_modulation(struct va1j5jf8007s_state *state, int *lock)
 245{
 246        u8 addr;
 247        u8 write_buf[1], read_buf[1];
 248        struct i2c_msg msgs[2];
 249
 250        addr = state->config->demod_address;
 251
 252        write_buf[0] = 0xc3;
 253
 254        msgs[0].addr = addr;
 255        msgs[0].flags = 0;
 256        msgs[0].len = sizeof(write_buf);
 257        msgs[0].buf = write_buf;
 258
 259        msgs[1].addr = addr;
 260        msgs[1].flags = I2C_M_RD;
 261        msgs[1].len = sizeof(read_buf);
 262        msgs[1].buf = read_buf;
 263
 264        if (i2c_transfer(state->adap, msgs, 2) != 2)
 265                return -EREMOTEIO;
 266
 267        *lock = !(read_buf[0] & 0x10);
 268        return 0;
 269}
 270
 271static int
 272va1j5jf8007s_set_ts_id(struct va1j5jf8007s_state *state)
 273{
 274        u32 ts_id;
 275        u8 buf[3];
 276        struct i2c_msg msg;
 277
 278        ts_id = state->fe.dtv_property_cache.isdbs_ts_id;
 279        if (!ts_id)
 280                return 0;
 281
 282        buf[0] = 0x8f;
 283        buf[1] = ts_id >> 8;
 284        buf[2] = ts_id;
 285
 286        msg.addr = state->config->demod_address;
 287        msg.flags = 0;
 288        msg.len = sizeof(buf);
 289        msg.buf = buf;
 290
 291        if (i2c_transfer(state->adap, &msg, 1) != 1)
 292                return -EREMOTEIO;
 293
 294        return 0;
 295}
 296
 297static int
 298va1j5jf8007s_check_ts_id(struct va1j5jf8007s_state *state, int *lock)
 299{
 300        u8 addr;
 301        u8 write_buf[1], read_buf[2];
 302        struct i2c_msg msgs[2];
 303        u32 ts_id;
 304
 305        ts_id = state->fe.dtv_property_cache.isdbs_ts_id;
 306        if (!ts_id) {
 307                *lock = 1;
 308                return 0;
 309        }
 310
 311        addr = state->config->demod_address;
 312
 313        write_buf[0] = 0xe6;
 314
 315        msgs[0].addr = addr;
 316        msgs[0].flags = 0;
 317        msgs[0].len = sizeof(write_buf);
 318        msgs[0].buf = write_buf;
 319
 320        msgs[1].addr = addr;
 321        msgs[1].flags = I2C_M_RD;
 322        msgs[1].len = sizeof(read_buf);
 323        msgs[1].buf = read_buf;
 324
 325        if (i2c_transfer(state->adap, msgs, 2) != 2)
 326                return -EREMOTEIO;
 327
 328        *lock = (read_buf[0] << 8 | read_buf[1]) == ts_id;
 329        return 0;
 330}
 331
 332static int
 333va1j5jf8007s_tune(struct dvb_frontend *fe,
 334                  struct dvb_frontend_parameters *params,
 335                  unsigned int mode_flags,  unsigned int *delay,
 336                  fe_status_t *status)
 337{
 338        struct va1j5jf8007s_state *state;
 339        int ret;
 340        int lock;
 341
 342        state = fe->demodulator_priv;
 343
 344        if (params != NULL)
 345                state->tune_state = VA1J5JF8007S_SET_FREQUENCY_1;
 346
 347        switch (state->tune_state) {
 348        case VA1J5JF8007S_IDLE:
 349                *delay = 3 * HZ;
 350                *status = 0;
 351                return 0;
 352
 353        case VA1J5JF8007S_SET_FREQUENCY_1:
 354                ret = va1j5jf8007s_set_frequency_1(state);
 355                if (ret < 0)
 356                        return ret;
 357
 358                state->tune_state = VA1J5JF8007S_SET_FREQUENCY_2;
 359                *delay = 0;
 360                *status = 0;
 361                return 0;
 362
 363        case VA1J5JF8007S_SET_FREQUENCY_2:
 364                ret = va1j5jf8007s_set_frequency_2(state);
 365                if (ret < 0)
 366                        return ret;
 367
 368                state->tune_state = VA1J5JF8007S_SET_FREQUENCY_3;
 369                *delay = (HZ + 99) / 100;
 370                *status = 0;
 371                return 0;
 372
 373        case VA1J5JF8007S_SET_FREQUENCY_3:
 374                ret = va1j5jf8007s_set_frequency_3(state);
 375                if (ret < 0)
 376                        return ret;
 377
 378                state->tune_state = VA1J5JF8007S_CHECK_FREQUENCY;
 379                *delay = 0;
 380                *status = 0;
 381                return 0;
 382
 383        case VA1J5JF8007S_CHECK_FREQUENCY:
 384                ret = va1j5jf8007s_check_frequency(state, &lock);
 385                if (ret < 0)
 386                        return ret;
 387
 388                if (!lock)  {
 389                        *delay = (HZ + 999) / 1000;
 390                        *status = 0;
 391                        return 0;
 392                }
 393
 394                state->tune_state = VA1J5JF8007S_SET_MODULATION;
 395                *delay = 0;
 396                *status = FE_HAS_SIGNAL;
 397                return 0;
 398
 399        case VA1J5JF8007S_SET_MODULATION:
 400                ret = va1j5jf8007s_set_modulation(state);
 401                if (ret < 0)
 402                        return ret;
 403
 404                state->tune_state = VA1J5JF8007S_CHECK_MODULATION;
 405                *delay = 0;
 406                *status = FE_HAS_SIGNAL;
 407                return 0;
 408
 409        case VA1J5JF8007S_CHECK_MODULATION:
 410                ret = va1j5jf8007s_check_modulation(state, &lock);
 411                if (ret < 0)
 412                        return ret;
 413
 414                if (!lock)  {
 415                        *delay = (HZ + 49) / 50;
 416                        *status = FE_HAS_SIGNAL;
 417                        return 0;
 418                }
 419
 420                state->tune_state = VA1J5JF8007S_SET_TS_ID;
 421                *delay = 0;
 422                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
 423                return 0;
 424
 425        case VA1J5JF8007S_SET_TS_ID:
 426                ret = va1j5jf8007s_set_ts_id(state);
 427                if (ret < 0)
 428                        return ret;
 429
 430                state->tune_state = VA1J5JF8007S_CHECK_TS_ID;
 431                return 0;
 432
 433        case VA1J5JF8007S_CHECK_TS_ID:
 434                ret = va1j5jf8007s_check_ts_id(state, &lock);
 435                if (ret < 0)
 436                        return ret;
 437
 438                if (!lock)  {
 439                        *delay = (HZ + 99) / 100;
 440                        *status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
 441                        return 0;
 442                }
 443
 444                state->tune_state = VA1J5JF8007S_TRACK;
 445                /* fall through */
 446
 447        case VA1J5JF8007S_TRACK:
 448                *delay = 3 * HZ;
 449                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
 450                return 0;
 451        }
 452
 453        BUG();
 454}
 455
 456static int va1j5jf8007s_init_frequency(struct va1j5jf8007s_state *state)
 457{
 458        u8 buf[4];
 459        struct i2c_msg msg;
 460
 461        buf[0] = 0xfe;
 462        buf[1] = 0xc0;
 463        buf[2] = 0xf0;
 464        buf[3] = 0x04;
 465
 466        msg.addr = state->config->demod_address;
 467        msg.flags = 0;
 468        msg.len = sizeof(buf);
 469        msg.buf = buf;
 470
 471        if (i2c_transfer(state->adap, &msg, 1) != 1)
 472                return -EREMOTEIO;
 473
 474        return 0;
 475}
 476
 477static int va1j5jf8007s_set_sleep(struct va1j5jf8007s_state *state, int sleep)
 478{
 479        u8 buf[2];
 480        struct i2c_msg msg;
 481
 482        buf[0] = 0x17;
 483        buf[1] = sleep ? 0x01 : 0x00;
 484
 485        msg.addr = state->config->demod_address;
 486        msg.flags = 0;
 487        msg.len = sizeof(buf);
 488        msg.buf = buf;
 489
 490        if (i2c_transfer(state->adap, &msg, 1) != 1)
 491                return -EREMOTEIO;
 492
 493        return 0;
 494}
 495
 496static int va1j5jf8007s_sleep(struct dvb_frontend *fe)
 497{
 498        struct va1j5jf8007s_state *state;
 499        int ret;
 500
 501        state = fe->demodulator_priv;
 502
 503        ret = va1j5jf8007s_init_frequency(state);
 504        if (ret < 0)
 505                return ret;
 506
 507        return va1j5jf8007s_set_sleep(state, 1);
 508}
 509
 510static int va1j5jf8007s_init(struct dvb_frontend *fe)
 511{
 512        struct va1j5jf8007s_state *state;
 513
 514        state = fe->demodulator_priv;
 515        state->tune_state = VA1J5JF8007S_IDLE;
 516
 517        return va1j5jf8007s_set_sleep(state, 0);
 518}
 519
 520static void va1j5jf8007s_release(struct dvb_frontend *fe)
 521{
 522        struct va1j5jf8007s_state *state;
 523        state = fe->demodulator_priv;
 524        kfree(state);
 525}
 526
 527static struct dvb_frontend_ops va1j5jf8007s_ops = {
 528        .info = {
 529                .name = "VA1J5JF8007 ISDB-S",
 530                .type = FE_QPSK,
 531                .frequency_min = 950000,
 532                .frequency_max = 2150000,
 533                .frequency_stepsize = 1000,
 534                .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
 535                        FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
 536                        FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
 537        },
 538
 539        .get_frontend_algo = va1j5jf8007s_get_frontend_algo,
 540        .read_status = va1j5jf8007s_read_status,
 541        .tune = va1j5jf8007s_tune,
 542        .sleep = va1j5jf8007s_sleep,
 543        .init = va1j5jf8007s_init,
 544        .release = va1j5jf8007s_release,
 545};
 546
 547static int va1j5jf8007s_prepare_1(struct va1j5jf8007s_state *state)
 548{
 549        u8 addr;
 550        u8 write_buf[1], read_buf[1];
 551        struct i2c_msg msgs[2];
 552
 553        addr = state->config->demod_address;
 554
 555        write_buf[0] = 0x07;
 556
 557        msgs[0].addr = addr;
 558        msgs[0].flags = 0;
 559        msgs[0].len = sizeof(write_buf);
 560        msgs[0].buf = write_buf;
 561
 562        msgs[1].addr = addr;
 563        msgs[1].flags = I2C_M_RD;
 564        msgs[1].len = sizeof(read_buf);
 565        msgs[1].buf = read_buf;
 566
 567        if (i2c_transfer(state->adap, msgs, 2) != 2)
 568                return -EREMOTEIO;
 569
 570        if (read_buf[0] != 0x41)
 571                return -EIO;
 572
 573        return 0;
 574}
 575
 576static const u8 va1j5jf8007s_prepare_bufs[][2] = {
 577        {0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01},
 578        {0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0},
 579        {0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69},
 580        {0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0},
 581};
 582
 583static int va1j5jf8007s_prepare_2(struct va1j5jf8007s_state *state)
 584{
 585        u8 addr;
 586        u8 buf[2];
 587        struct i2c_msg msg;
 588        int i;
 589
 590        addr = state->config->demod_address;
 591
 592        msg.addr = addr;
 593        msg.flags = 0;
 594        msg.len = 2;
 595        msg.buf = buf;
 596        for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_prepare_bufs); i++) {
 597                memcpy(buf, va1j5jf8007s_prepare_bufs[i], sizeof(buf));
 598                if (i2c_transfer(state->adap, &msg, 1) != 1)
 599                        return -EREMOTEIO;
 600        }
 601
 602        return 0;
 603}
 604
 605/* must be called after va1j5jf8007t_attach */
 606int va1j5jf8007s_prepare(struct dvb_frontend *fe)
 607{
 608        struct va1j5jf8007s_state *state;
 609        int ret;
 610
 611        state = fe->demodulator_priv;
 612
 613        ret = va1j5jf8007s_prepare_1(state);
 614        if (ret < 0)
 615                return ret;
 616
 617        ret = va1j5jf8007s_prepare_2(state);
 618        if (ret < 0)
 619                return ret;
 620
 621        return va1j5jf8007s_init_frequency(state);
 622}
 623
 624struct dvb_frontend *
 625va1j5jf8007s_attach(const struct va1j5jf8007s_config *config,
 626                    struct i2c_adapter *adap)
 627{
 628        struct va1j5jf8007s_state *state;
 629        struct dvb_frontend *fe;
 630        u8 buf[2];
 631        struct i2c_msg msg;
 632
 633        state = kzalloc(sizeof(struct va1j5jf8007s_state), GFP_KERNEL);
 634        if (!state)
 635                return NULL;
 636
 637        state->config = config;
 638        state->adap = adap;
 639
 640        fe = &state->fe;
 641        memcpy(&fe->ops, &va1j5jf8007s_ops, sizeof(struct dvb_frontend_ops));
 642        fe->demodulator_priv = state;
 643
 644        buf[0] = 0x01;
 645        buf[1] = 0x80;
 646
 647        msg.addr = state->config->demod_address;
 648        msg.flags = 0;
 649        msg.len = sizeof(buf);
 650        msg.buf = buf;
 651
 652        if (i2c_transfer(state->adap, &msg, 1) != 1) {
 653                kfree(state);
 654                return NULL;
 655        }
 656
 657        return fe;
 658}
 659