linux/drivers/media/dvb-frontends/lg2160.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *    Support for LG2160 - ATSC/MH
   4 *
   5 *    Copyright (C) 2010 Michael Krufky <mkrufky@linuxtv.org>
   6 */
   7
   8#include <linux/jiffies.h>
   9#include <linux/dvb/frontend.h>
  10#include "lg2160.h"
  11
  12static int debug;
  13module_param(debug, int, 0644);
  14MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
  15
  16#define DBG_INFO 1
  17#define DBG_REG  2
  18
  19#define lg_printk(kern, fmt, arg...)                                    \
  20        printk(kern "%s: " fmt, __func__, ##arg)
  21
  22#define lg_info(fmt, arg...)    printk(KERN_INFO "lg2160: " fmt, ##arg)
  23#define lg_warn(fmt, arg...)    lg_printk(KERN_WARNING,       fmt, ##arg)
  24#define lg_err(fmt, arg...)     lg_printk(KERN_ERR,           fmt, ##arg)
  25#define lg_dbg(fmt, arg...) if (debug & DBG_INFO)                       \
  26                                lg_printk(KERN_DEBUG,         fmt, ##arg)
  27#define lg_reg(fmt, arg...) if (debug & DBG_REG)                        \
  28                                lg_printk(KERN_DEBUG,         fmt, ##arg)
  29
  30#define lg_fail(ret)                                                    \
  31({                                                                      \
  32        int __ret;                                                      \
  33        __ret = (ret < 0);                                              \
  34        if (__ret)                                                      \
  35                lg_err("error %d on line %d\n", ret, __LINE__);         \
  36        __ret;                                                          \
  37})
  38
  39struct lg216x_state {
  40        struct i2c_adapter *i2c_adap;
  41        const struct lg2160_config *cfg;
  42
  43        struct dvb_frontend frontend;
  44
  45        u32 current_frequency;
  46        u8 parade_id;
  47        u8 fic_ver;
  48        unsigned int last_reset;
  49};
  50
  51/* ------------------------------------------------------------------------ */
  52
  53static int lg216x_write_reg(struct lg216x_state *state, u16 reg, u8 val)
  54{
  55        int ret;
  56        u8 buf[] = { reg >> 8, reg & 0xff, val };
  57        struct i2c_msg msg = {
  58                .addr = state->cfg->i2c_addr, .flags = 0,
  59                .buf = buf, .len = 3,
  60        };
  61
  62        lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
  63
  64        ret = i2c_transfer(state->i2c_adap, &msg, 1);
  65
  66        if (ret != 1) {
  67                lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
  68                       msg.buf[0], msg.buf[1], msg.buf[2], ret);
  69                if (ret < 0)
  70                        return ret;
  71                else
  72                        return -EREMOTEIO;
  73        }
  74        return 0;
  75}
  76
  77static int lg216x_read_reg(struct lg216x_state *state, u16 reg, u8 *val)
  78{
  79        int ret;
  80        u8 reg_buf[] = { reg >> 8, reg & 0xff };
  81        struct i2c_msg msg[] = {
  82                { .addr = state->cfg->i2c_addr,
  83                  .flags = 0, .buf = reg_buf, .len = 2 },
  84                { .addr = state->cfg->i2c_addr,
  85                  .flags = I2C_M_RD, .buf = val, .len = 1 },
  86        };
  87
  88        lg_reg("reg: 0x%04x\n", reg);
  89
  90        ret = i2c_transfer(state->i2c_adap, msg, 2);
  91
  92        if (ret != 2) {
  93                lg_err("error (addr %02x reg %04x error (ret == %i)\n",
  94                       state->cfg->i2c_addr, reg, ret);
  95                if (ret < 0)
  96                        return ret;
  97                else
  98                        return -EREMOTEIO;
  99        }
 100        return 0;
 101}
 102
 103struct lg216x_reg {
 104        u16 reg;
 105        u8 val;
 106};
 107
 108static int lg216x_write_regs(struct lg216x_state *state,
 109                             struct lg216x_reg *regs, int len)
 110{
 111        int i, ret;
 112
 113        lg_reg("writing %d registers...\n", len);
 114
 115        for (i = 0; i < len; i++) {
 116                ret = lg216x_write_reg(state, regs[i].reg, regs[i].val);
 117                if (lg_fail(ret))
 118                        return ret;
 119        }
 120        return 0;
 121}
 122
 123static int lg216x_set_reg_bit(struct lg216x_state *state,
 124                              u16 reg, int bit, int onoff)
 125{
 126        u8 val;
 127        int ret;
 128
 129        lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
 130
 131        ret = lg216x_read_reg(state, reg, &val);
 132        if (lg_fail(ret))
 133                goto fail;
 134
 135        val &= ~(1 << bit);
 136        val |= (onoff & 1) << bit;
 137
 138        ret = lg216x_write_reg(state, reg, val);
 139        lg_fail(ret);
 140fail:
 141        return ret;
 142}
 143
 144/* ------------------------------------------------------------------------ */
 145
 146static int lg216x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 147{
 148        struct lg216x_state *state = fe->demodulator_priv;
 149        int ret;
 150
 151        if (state->cfg->deny_i2c_rptr)
 152                return 0;
 153
 154        lg_dbg("(%d)\n", enable);
 155
 156        ret = lg216x_set_reg_bit(state, 0x0000, 0, enable ? 0 : 1);
 157
 158        msleep(1);
 159
 160        return ret;
 161}
 162
 163static int lg216x_soft_reset(struct lg216x_state *state)
 164{
 165        int ret;
 166
 167        lg_dbg("\n");
 168
 169        ret = lg216x_write_reg(state, 0x0002, 0x00);
 170        if (lg_fail(ret))
 171                goto fail;
 172
 173        msleep(20);
 174        ret = lg216x_write_reg(state, 0x0002, 0x01);
 175        if (lg_fail(ret))
 176                goto fail;
 177
 178        state->last_reset = jiffies_to_msecs(jiffies);
 179fail:
 180        return ret;
 181}
 182
 183static int lg216x_initialize(struct lg216x_state *state)
 184{
 185        int ret;
 186
 187        static struct lg216x_reg lg2160_init[] = {
 188#if 0
 189                { .reg = 0x0015, .val = 0xe6 },
 190#else
 191                { .reg = 0x0015, .val = 0xf7 },
 192                { .reg = 0x001b, .val = 0x52 },
 193                { .reg = 0x0208, .val = 0x00 },
 194                { .reg = 0x0209, .val = 0x82 },
 195                { .reg = 0x0210, .val = 0xf9 },
 196                { .reg = 0x020a, .val = 0x00 },
 197                { .reg = 0x020b, .val = 0x82 },
 198                { .reg = 0x020d, .val = 0x28 },
 199                { .reg = 0x020f, .val = 0x14 },
 200#endif
 201        };
 202
 203        static struct lg216x_reg lg2161_init[] = {
 204                { .reg = 0x0000, .val = 0x41 },
 205                { .reg = 0x0001, .val = 0xfb },
 206                { .reg = 0x0216, .val = 0x00 },
 207                { .reg = 0x0219, .val = 0x00 },
 208                { .reg = 0x021b, .val = 0x55 },
 209                { .reg = 0x0606, .val = 0x0a },
 210        };
 211
 212        switch (state->cfg->lg_chip) {
 213        case LG2160:
 214                ret = lg216x_write_regs(state,
 215                                        lg2160_init, ARRAY_SIZE(lg2160_init));
 216                break;
 217        case LG2161:
 218                ret = lg216x_write_regs(state,
 219                                        lg2161_init, ARRAY_SIZE(lg2161_init));
 220                break;
 221        default:
 222                ret = -EINVAL;
 223                break;
 224        }
 225        if (lg_fail(ret))
 226                goto fail;
 227
 228        ret = lg216x_soft_reset(state);
 229        lg_fail(ret);
 230fail:
 231        return ret;
 232}
 233
 234/* ------------------------------------------------------------------------ */
 235
 236static int lg216x_set_if(struct lg216x_state *state)
 237{
 238        u8 val;
 239        int ret;
 240
 241        lg_dbg("%d KHz\n", state->cfg->if_khz);
 242
 243        ret = lg216x_read_reg(state, 0x0132, &val);
 244        if (lg_fail(ret))
 245                goto fail;
 246
 247        val &= 0xfb;
 248        val |= (0 == state->cfg->if_khz) ? 0x04 : 0x00;
 249
 250        ret = lg216x_write_reg(state, 0x0132, val);
 251        lg_fail(ret);
 252
 253        /* if NOT zero IF, 6 MHz is the default */
 254fail:
 255        return ret;
 256}
 257
 258/* ------------------------------------------------------------------------ */
 259
 260static int lg2160_agc_fix(struct lg216x_state *state,
 261                          int if_agc_fix, int rf_agc_fix)
 262{
 263        u8 val;
 264        int ret;
 265
 266        ret = lg216x_read_reg(state, 0x0100, &val);
 267        if (lg_fail(ret))
 268                goto fail;
 269
 270        val &= 0xf3;
 271        val |= (if_agc_fix) ? 0x08 : 0x00;
 272        val |= (rf_agc_fix) ? 0x04 : 0x00;
 273
 274        ret = lg216x_write_reg(state, 0x0100, val);
 275        lg_fail(ret);
 276fail:
 277        return ret;
 278}
 279
 280#if 0
 281static int lg2160_agc_freeze(struct lg216x_state *state,
 282                             int if_agc_freeze, int rf_agc_freeze)
 283{
 284        u8 val;
 285        int ret;
 286
 287        ret = lg216x_read_reg(state, 0x0100, &val);
 288        if (lg_fail(ret))
 289                goto fail;
 290
 291        val &= 0xcf;
 292        val |= (if_agc_freeze) ? 0x20 : 0x00;
 293        val |= (rf_agc_freeze) ? 0x10 : 0x00;
 294
 295        ret = lg216x_write_reg(state, 0x0100, val);
 296        lg_fail(ret);
 297fail:
 298        return ret;
 299}
 300#endif
 301
 302static int lg2160_agc_polarity(struct lg216x_state *state,
 303                               int if_agc_polarity, int rf_agc_polarity)
 304{
 305        u8 val;
 306        int ret;
 307
 308        ret = lg216x_read_reg(state, 0x0100, &val);
 309        if (lg_fail(ret))
 310                goto fail;
 311
 312        val &= 0xfc;
 313        val |= (if_agc_polarity) ? 0x02 : 0x00;
 314        val |= (rf_agc_polarity) ? 0x01 : 0x00;
 315
 316        ret = lg216x_write_reg(state, 0x0100, val);
 317        lg_fail(ret);
 318fail:
 319        return ret;
 320}
 321
 322static int lg2160_tuner_pwr_save_polarity(struct lg216x_state *state,
 323                                          int polarity)
 324{
 325        u8 val;
 326        int ret;
 327
 328        ret = lg216x_read_reg(state, 0x0008, &val);
 329        if (lg_fail(ret))
 330                goto fail;
 331
 332        val &= 0xfe;
 333        val |= (polarity) ? 0x01 : 0x00;
 334
 335        ret = lg216x_write_reg(state, 0x0008, val);
 336        lg_fail(ret);
 337fail:
 338        return ret;
 339}
 340
 341static int lg2160_spectrum_polarity(struct lg216x_state *state,
 342                                    int inverted)
 343{
 344        u8 val;
 345        int ret;
 346
 347        ret = lg216x_read_reg(state, 0x0132, &val);
 348        if (lg_fail(ret))
 349                goto fail;
 350
 351        val &= 0xfd;
 352        val |= (inverted) ? 0x02 : 0x00;
 353
 354        ret = lg216x_write_reg(state, 0x0132, val);
 355        lg_fail(ret);
 356fail:
 357        return lg216x_soft_reset(state);
 358}
 359
 360static int lg2160_tuner_pwr_save(struct lg216x_state *state, int onoff)
 361{
 362        u8 val;
 363        int ret;
 364
 365        ret = lg216x_read_reg(state, 0x0007, &val);
 366        if (lg_fail(ret))
 367                goto fail;
 368
 369        val &= 0xbf;
 370        val |= (onoff) ? 0x40 : 0x00;
 371
 372        ret = lg216x_write_reg(state, 0x0007, val);
 373        lg_fail(ret);
 374fail:
 375        return ret;
 376}
 377
 378static int lg216x_set_parade(struct lg216x_state *state, int id)
 379{
 380        int ret;
 381
 382        ret = lg216x_write_reg(state, 0x013e, id & 0x7f);
 383        if (lg_fail(ret))
 384                goto fail;
 385
 386        state->parade_id = id & 0x7f;
 387fail:
 388        return ret;
 389}
 390
 391static int lg216x_set_ensemble(struct lg216x_state *state, int id)
 392{
 393        int ret;
 394        u16 reg;
 395        u8 val;
 396
 397        switch (state->cfg->lg_chip) {
 398        case LG2160:
 399                reg = 0x0400;
 400                break;
 401        case LG2161:
 402        default:
 403                reg = 0x0500;
 404                break;
 405        }
 406
 407        ret = lg216x_read_reg(state, reg, &val);
 408        if (lg_fail(ret))
 409                goto fail;
 410
 411        val &= 0xfe;
 412        val |= (id) ? 0x01 : 0x00;
 413
 414        ret = lg216x_write_reg(state, reg, val);
 415        lg_fail(ret);
 416fail:
 417        return ret;
 418}
 419
 420static int lg2160_set_spi_clock(struct lg216x_state *state)
 421{
 422        u8 val;
 423        int ret;
 424
 425        ret = lg216x_read_reg(state, 0x0014, &val);
 426        if (lg_fail(ret))
 427                goto fail;
 428
 429        val &= 0xf3;
 430        val |= (state->cfg->spi_clock << 2);
 431
 432        ret = lg216x_write_reg(state, 0x0014, val);
 433        lg_fail(ret);
 434fail:
 435        return ret;
 436}
 437
 438static int lg2161_set_output_interface(struct lg216x_state *state)
 439{
 440        u8 val;
 441        int ret;
 442
 443        ret = lg216x_read_reg(state, 0x0014, &val);
 444        if (lg_fail(ret))
 445                goto fail;
 446
 447        val &= ~0x07;
 448        val |= state->cfg->output_if; /* FIXME: needs sanity check */
 449
 450        ret = lg216x_write_reg(state, 0x0014, val);
 451        lg_fail(ret);
 452fail:
 453        return ret;
 454}
 455
 456static int lg216x_enable_fic(struct lg216x_state *state, int onoff)
 457{
 458        int ret;
 459
 460        ret = lg216x_write_reg(state, 0x0017, 0x23);
 461        if (lg_fail(ret))
 462                goto fail;
 463
 464        ret = lg216x_write_reg(state, 0x0016, 0xfc);
 465        if (lg_fail(ret))
 466                goto fail;
 467
 468        switch (state->cfg->lg_chip) {
 469        case LG2160:
 470                ret = lg216x_write_reg(state, 0x0016,
 471                                       0xfc | ((onoff) ? 0x02 : 0x00));
 472                break;
 473        case LG2161:
 474                ret = lg216x_write_reg(state, 0x0016, (onoff) ? 0x10 : 0x00);
 475                break;
 476        }
 477        if (lg_fail(ret))
 478                goto fail;
 479
 480        ret = lg216x_initialize(state);
 481        if (lg_fail(ret))
 482                goto fail;
 483
 484        if (onoff) {
 485                ret = lg216x_write_reg(state, 0x0017, 0x03);
 486                lg_fail(ret);
 487        }
 488fail:
 489        return ret;
 490}
 491
 492/* ------------------------------------------------------------------------ */
 493
 494static int lg216x_get_fic_version(struct lg216x_state *state, u8 *ficver)
 495{
 496        u8 val;
 497        int ret;
 498
 499        *ficver = 0xff; /* invalid value */
 500
 501        ret = lg216x_read_reg(state, 0x0128, &val);
 502        if (lg_fail(ret))
 503                goto fail;
 504
 505        *ficver = (val >> 3) & 0x1f;
 506fail:
 507        return ret;
 508}
 509
 510#if 0
 511static int lg2160_get_parade_id(struct lg216x_state *state, u8 *id)
 512{
 513        u8 val;
 514        int ret;
 515
 516        *id = 0xff; /* invalid value */
 517
 518        ret = lg216x_read_reg(state, 0x0123, &val);
 519        if (lg_fail(ret))
 520                goto fail;
 521
 522        *id = val & 0x7f;
 523fail:
 524        return ret;
 525}
 526#endif
 527
 528static int lg216x_get_nog(struct lg216x_state *state, u8 *nog)
 529{
 530        u8 val;
 531        int ret;
 532
 533        *nog = 0xff; /* invalid value */
 534
 535        ret = lg216x_read_reg(state, 0x0124, &val);
 536        if (lg_fail(ret))
 537                goto fail;
 538
 539        *nog = ((val >> 4) & 0x07) + 1;
 540fail:
 541        return ret;
 542}
 543
 544static int lg216x_get_tnog(struct lg216x_state *state, u8 *tnog)
 545{
 546        u8 val;
 547        int ret;
 548
 549        *tnog = 0xff; /* invalid value */
 550
 551        ret = lg216x_read_reg(state, 0x0125, &val);
 552        if (lg_fail(ret))
 553                goto fail;
 554
 555        *tnog = val & 0x1f;
 556fail:
 557        return ret;
 558}
 559
 560static int lg216x_get_sgn(struct lg216x_state *state, u8 *sgn)
 561{
 562        u8 val;
 563        int ret;
 564
 565        *sgn = 0xff; /* invalid value */
 566
 567        ret = lg216x_read_reg(state, 0x0124, &val);
 568        if (lg_fail(ret))
 569                goto fail;
 570
 571        *sgn = val & 0x0f;
 572fail:
 573        return ret;
 574}
 575
 576static int lg216x_get_prc(struct lg216x_state *state, u8 *prc)
 577{
 578        u8 val;
 579        int ret;
 580
 581        *prc = 0xff; /* invalid value */
 582
 583        ret = lg216x_read_reg(state, 0x0125, &val);
 584        if (lg_fail(ret))
 585                goto fail;
 586
 587        *prc = ((val >> 5) & 0x07) + 1;
 588fail:
 589        return ret;
 590}
 591
 592/* ------------------------------------------------------------------------ */
 593
 594static int lg216x_get_rs_frame_mode(struct lg216x_state *state,
 595                                    enum atscmh_rs_frame_mode *rs_framemode)
 596{
 597        u8 val;
 598        int ret;
 599
 600        switch (state->cfg->lg_chip) {
 601        case LG2160:
 602                ret = lg216x_read_reg(state, 0x0410, &val);
 603                break;
 604        case LG2161:
 605                ret = lg216x_read_reg(state, 0x0513, &val);
 606                break;
 607        default:
 608                ret = -EINVAL;
 609        }
 610        if (lg_fail(ret))
 611                goto fail;
 612
 613        switch ((val >> 4) & 0x03) {
 614#if 1
 615        default:
 616#endif
 617        case 0x00:
 618                *rs_framemode = ATSCMH_RSFRAME_PRI_ONLY;
 619                break;
 620        case 0x01:
 621                *rs_framemode = ATSCMH_RSFRAME_PRI_SEC;
 622                break;
 623#if 0
 624        default:
 625                *rs_framemode = ATSCMH_RSFRAME_RES;
 626                break;
 627#endif
 628        }
 629fail:
 630        return ret;
 631}
 632
 633static
 634int lg216x_get_rs_frame_ensemble(struct lg216x_state *state,
 635                                 enum atscmh_rs_frame_ensemble *rs_frame_ens)
 636{
 637        u8 val;
 638        int ret;
 639
 640        switch (state->cfg->lg_chip) {
 641        case LG2160:
 642                ret = lg216x_read_reg(state, 0x0400, &val);
 643                break;
 644        case LG2161:
 645                ret = lg216x_read_reg(state, 0x0500, &val);
 646                break;
 647        default:
 648                ret = -EINVAL;
 649        }
 650        if (lg_fail(ret))
 651                goto fail;
 652
 653        val &= 0x01;
 654        *rs_frame_ens = (enum atscmh_rs_frame_ensemble) val;
 655fail:
 656        return ret;
 657}
 658
 659static int lg216x_get_rs_code_mode(struct lg216x_state *state,
 660                                   enum atscmh_rs_code_mode *rs_code_pri,
 661                                   enum atscmh_rs_code_mode *rs_code_sec)
 662{
 663        u8 val;
 664        int ret;
 665
 666        switch (state->cfg->lg_chip) {
 667        case LG2160:
 668                ret = lg216x_read_reg(state, 0x0410, &val);
 669                break;
 670        case LG2161:
 671                ret = lg216x_read_reg(state, 0x0513, &val);
 672                break;
 673        default:
 674                ret = -EINVAL;
 675        }
 676        if (lg_fail(ret))
 677                goto fail;
 678
 679        *rs_code_pri = (enum atscmh_rs_code_mode) ((val >> 2) & 0x03);
 680        *rs_code_sec = (enum atscmh_rs_code_mode) (val & 0x03);
 681fail:
 682        return ret;
 683}
 684
 685static int lg216x_get_sccc_block_mode(struct lg216x_state *state,
 686                                      enum atscmh_sccc_block_mode *sccc_block)
 687{
 688        u8 val;
 689        int ret;
 690
 691        switch (state->cfg->lg_chip) {
 692        case LG2160:
 693                ret = lg216x_read_reg(state, 0x0315, &val);
 694                break;
 695        case LG2161:
 696                ret = lg216x_read_reg(state, 0x0511, &val);
 697                break;
 698        default:
 699                ret = -EINVAL;
 700        }
 701        if (lg_fail(ret))
 702                goto fail;
 703
 704        switch (val & 0x03) {
 705        case 0x00:
 706                *sccc_block = ATSCMH_SCCC_BLK_SEP;
 707                break;
 708        case 0x01:
 709                *sccc_block = ATSCMH_SCCC_BLK_COMB;
 710                break;
 711        default:
 712                *sccc_block = ATSCMH_SCCC_BLK_RES;
 713                break;
 714        }
 715fail:
 716        return ret;
 717}
 718
 719static int lg216x_get_sccc_code_mode(struct lg216x_state *state,
 720                                     enum atscmh_sccc_code_mode *mode_a,
 721                                     enum atscmh_sccc_code_mode *mode_b,
 722                                     enum atscmh_sccc_code_mode *mode_c,
 723                                     enum atscmh_sccc_code_mode *mode_d)
 724{
 725        u8 val;
 726        int ret;
 727
 728        switch (state->cfg->lg_chip) {
 729        case LG2160:
 730                ret = lg216x_read_reg(state, 0x0316, &val);
 731                break;
 732        case LG2161:
 733                ret = lg216x_read_reg(state, 0x0512, &val);
 734                break;
 735        default:
 736                ret = -EINVAL;
 737        }
 738        if (lg_fail(ret))
 739                goto fail;
 740
 741        switch ((val >> 6) & 0x03) {
 742        case 0x00:
 743                *mode_a = ATSCMH_SCCC_CODE_HLF;
 744                break;
 745        case 0x01:
 746                *mode_a = ATSCMH_SCCC_CODE_QTR;
 747                break;
 748        default:
 749                *mode_a = ATSCMH_SCCC_CODE_RES;
 750                break;
 751        }
 752
 753        switch ((val >> 4) & 0x03) {
 754        case 0x00:
 755                *mode_b = ATSCMH_SCCC_CODE_HLF;
 756                break;
 757        case 0x01:
 758                *mode_b = ATSCMH_SCCC_CODE_QTR;
 759                break;
 760        default:
 761                *mode_b = ATSCMH_SCCC_CODE_RES;
 762                break;
 763        }
 764
 765        switch ((val >> 2) & 0x03) {
 766        case 0x00:
 767                *mode_c = ATSCMH_SCCC_CODE_HLF;
 768                break;
 769        case 0x01:
 770                *mode_c = ATSCMH_SCCC_CODE_QTR;
 771                break;
 772        default:
 773                *mode_c = ATSCMH_SCCC_CODE_RES;
 774                break;
 775        }
 776
 777        switch (val & 0x03) {
 778        case 0x00:
 779                *mode_d = ATSCMH_SCCC_CODE_HLF;
 780                break;
 781        case 0x01:
 782                *mode_d = ATSCMH_SCCC_CODE_QTR;
 783                break;
 784        default:
 785                *mode_d = ATSCMH_SCCC_CODE_RES;
 786                break;
 787        }
 788fail:
 789        return ret;
 790}
 791
 792/* ------------------------------------------------------------------------ */
 793
 794#if 0
 795static int lg216x_read_fic_err_count(struct lg216x_state *state, u8 *err)
 796{
 797        u8 fic_err;
 798        int ret;
 799
 800        *err = 0;
 801
 802        switch (state->cfg->lg_chip) {
 803        case LG2160:
 804                ret = lg216x_read_reg(state, 0x0012, &fic_err);
 805                break;
 806        case LG2161:
 807                ret = lg216x_read_reg(state, 0x001e, &fic_err);
 808                break;
 809        }
 810        if (lg_fail(ret))
 811                goto fail;
 812
 813        *err = fic_err;
 814fail:
 815        return ret;
 816}
 817
 818static int lg2160_read_crc_err_count(struct lg216x_state *state, u16 *err)
 819{
 820        u8 crc_err1, crc_err2;
 821        int ret;
 822
 823        *err = 0;
 824
 825        ret = lg216x_read_reg(state, 0x0411, &crc_err1);
 826        if (lg_fail(ret))
 827                goto fail;
 828
 829        ret = lg216x_read_reg(state, 0x0412, &crc_err2);
 830        if (lg_fail(ret))
 831                goto fail;
 832
 833        *err = (u16)(((crc_err2 & 0x0f) << 8) | crc_err1);
 834fail:
 835        return ret;
 836}
 837
 838static int lg2161_read_crc_err_count(struct lg216x_state *state, u16 *err)
 839{
 840        u8 crc_err;
 841        int ret;
 842
 843        *err = 0;
 844
 845        ret = lg216x_read_reg(state, 0x0612, &crc_err);
 846        if (lg_fail(ret))
 847                goto fail;
 848
 849        *err = (u16)crc_err;
 850fail:
 851        return ret;
 852}
 853
 854static int lg216x_read_crc_err_count(struct lg216x_state *state, u16 *err)
 855{
 856        int ret;
 857        switch (state->cfg->lg_chip) {
 858        case LG2160:
 859                ret = lg2160_read_crc_err_count(state, err);
 860                break;
 861        case LG2161:
 862                ret = lg2161_read_crc_err_count(state, err);
 863                break;
 864        default:
 865                ret = -EINVAL;
 866                break;
 867        }
 868        return ret;
 869}
 870
 871static int lg2160_read_rs_err_count(struct lg216x_state *state, u16 *err)
 872{
 873        u8 rs_err1, rs_err2;
 874        int ret;
 875
 876        *err = 0;
 877
 878        ret = lg216x_read_reg(state, 0x0413, &rs_err1);
 879        if (lg_fail(ret))
 880                goto fail;
 881
 882        ret = lg216x_read_reg(state, 0x0414, &rs_err2);
 883        if (lg_fail(ret))
 884                goto fail;
 885
 886        *err = (u16)(((rs_err2 & 0x0f) << 8) | rs_err1);
 887fail:
 888        return ret;
 889}
 890
 891static int lg2161_read_rs_err_count(struct lg216x_state *state, u16 *err)
 892{
 893        u8 rs_err1, rs_err2;
 894        int ret;
 895
 896        *err = 0;
 897
 898        ret = lg216x_read_reg(state, 0x0613, &rs_err1);
 899        if (lg_fail(ret))
 900                goto fail;
 901
 902        ret = lg216x_read_reg(state, 0x0614, &rs_err2);
 903        if (lg_fail(ret))
 904                goto fail;
 905
 906        *err = (u16)((rs_err1 << 8) | rs_err2);
 907fail:
 908        return ret;
 909}
 910
 911static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err)
 912{
 913        int ret;
 914        switch (state->cfg->lg_chip) {
 915        case LG2160:
 916                ret = lg2160_read_rs_err_count(state, err);
 917                break;
 918        case LG2161:
 919                ret = lg2161_read_rs_err_count(state, err);
 920                break;
 921        default:
 922                ret = -EINVAL;
 923                break;
 924        }
 925        return ret;
 926}
 927#endif
 928
 929/* ------------------------------------------------------------------------ */
 930
 931static int lg216x_get_frontend(struct dvb_frontend *fe,
 932                               struct dtv_frontend_properties *c)
 933{
 934        struct lg216x_state *state = fe->demodulator_priv;
 935        int ret;
 936
 937        lg_dbg("\n");
 938
 939        c->modulation = VSB_8;
 940        c->frequency = state->current_frequency;
 941        c->delivery_system = SYS_ATSCMH;
 942
 943        ret = lg216x_get_fic_version(state,
 944                                     &c->atscmh_fic_ver);
 945        if (lg_fail(ret))
 946                goto fail;
 947        if (state->fic_ver != c->atscmh_fic_ver) {
 948                state->fic_ver = c->atscmh_fic_ver;
 949
 950#if 0
 951                ret = lg2160_get_parade_id(state,
 952                                &c->atscmh_parade_id);
 953                if (lg_fail(ret))
 954                        goto fail;
 955/* #else */
 956                c->atscmh_parade_id = state->parade_id;
 957#endif
 958                ret = lg216x_get_nog(state,
 959                                     &c->atscmh_nog);
 960                if (lg_fail(ret))
 961                        goto fail;
 962                ret = lg216x_get_tnog(state,
 963                                      &c->atscmh_tnog);
 964                if (lg_fail(ret))
 965                        goto fail;
 966                ret = lg216x_get_sgn(state,
 967                                     &c->atscmh_sgn);
 968                if (lg_fail(ret))
 969                        goto fail;
 970                ret = lg216x_get_prc(state,
 971                                     &c->atscmh_prc);
 972                if (lg_fail(ret))
 973                        goto fail;
 974
 975                ret = lg216x_get_rs_frame_mode(state,
 976                        (enum atscmh_rs_frame_mode *)
 977                        &c->atscmh_rs_frame_mode);
 978                if (lg_fail(ret))
 979                        goto fail;
 980                ret = lg216x_get_rs_frame_ensemble(state,
 981                        (enum atscmh_rs_frame_ensemble *)
 982                        &c->atscmh_rs_frame_ensemble);
 983                if (lg_fail(ret))
 984                        goto fail;
 985                ret = lg216x_get_rs_code_mode(state,
 986                        (enum atscmh_rs_code_mode *)
 987                        &c->atscmh_rs_code_mode_pri,
 988                        (enum atscmh_rs_code_mode *)
 989                        &c->atscmh_rs_code_mode_sec);
 990                if (lg_fail(ret))
 991                        goto fail;
 992                ret = lg216x_get_sccc_block_mode(state,
 993                        (enum atscmh_sccc_block_mode *)
 994                        &c->atscmh_sccc_block_mode);
 995                if (lg_fail(ret))
 996                        goto fail;
 997                ret = lg216x_get_sccc_code_mode(state,
 998                        (enum atscmh_sccc_code_mode *)
 999                        &c->atscmh_sccc_code_mode_a,
1000                        (enum atscmh_sccc_code_mode *)
1001                        &c->atscmh_sccc_code_mode_b,
1002                        (enum atscmh_sccc_code_mode *)
1003                        &c->atscmh_sccc_code_mode_c,
1004                        (enum atscmh_sccc_code_mode *)
1005                        &c->atscmh_sccc_code_mode_d);
1006                if (lg_fail(ret))
1007                        goto fail;
1008        }
1009#if 0
1010        ret = lg216x_read_fic_err_count(state,
1011                                (u8 *)&c->atscmh_fic_err);
1012        if (lg_fail(ret))
1013                goto fail;
1014        ret = lg216x_read_crc_err_count(state,
1015                                &c->atscmh_crc_err);
1016        if (lg_fail(ret))
1017                goto fail;
1018        ret = lg216x_read_rs_err_count(state,
1019                                &c->atscmh_rs_err);
1020        if (lg_fail(ret))
1021                goto fail;
1022
1023        switch (state->cfg->lg_chip) {
1024        case LG2160:
1025                if (((c->atscmh_rs_err >= 240) &&
1026                     (c->atscmh_crc_err >= 240)) &&
1027                    ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000))
1028                        ret = lg216x_soft_reset(state);
1029                break;
1030        case LG2161:
1031                /* no fix needed here (as far as we know) */
1032                ret = 0;
1033                break;
1034        }
1035        lg_fail(ret);
1036#endif
1037fail:
1038        return ret;
1039}
1040
1041static int lg2160_set_frontend(struct dvb_frontend *fe)
1042{
1043        struct lg216x_state *state = fe->demodulator_priv;
1044        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1045        int ret;
1046
1047        lg_dbg("(%d)\n", fe->dtv_property_cache.frequency);
1048
1049        if (fe->ops.tuner_ops.set_params) {
1050                ret = fe->ops.tuner_ops.set_params(fe);
1051                if (fe->ops.i2c_gate_ctrl)
1052                        fe->ops.i2c_gate_ctrl(fe, 0);
1053                if (lg_fail(ret))
1054                        goto fail;
1055                state->current_frequency = fe->dtv_property_cache.frequency;
1056        }
1057
1058        ret = lg2160_agc_fix(state, 0, 0);
1059        if (lg_fail(ret))
1060                goto fail;
1061        ret = lg2160_agc_polarity(state, 0, 0);
1062        if (lg_fail(ret))
1063                goto fail;
1064        ret = lg2160_tuner_pwr_save_polarity(state, 1);
1065        if (lg_fail(ret))
1066                goto fail;
1067        ret = lg216x_set_if(state);
1068        if (lg_fail(ret))
1069                goto fail;
1070        ret = lg2160_spectrum_polarity(state, state->cfg->spectral_inversion);
1071        if (lg_fail(ret))
1072                goto fail;
1073
1074        /* be tuned before this point */
1075        ret = lg216x_soft_reset(state);
1076        if (lg_fail(ret))
1077                goto fail;
1078
1079        ret = lg2160_tuner_pwr_save(state, 0);
1080        if (lg_fail(ret))
1081                goto fail;
1082
1083        switch (state->cfg->lg_chip) {
1084        case LG2160:
1085                ret = lg2160_set_spi_clock(state);
1086                if (lg_fail(ret))
1087                        goto fail;
1088                break;
1089        case LG2161:
1090                ret = lg2161_set_output_interface(state);
1091                if (lg_fail(ret))
1092                        goto fail;
1093                break;
1094        }
1095
1096        ret = lg216x_set_parade(state, fe->dtv_property_cache.atscmh_parade_id);
1097        if (lg_fail(ret))
1098                goto fail;
1099
1100        ret = lg216x_set_ensemble(state,
1101                        fe->dtv_property_cache.atscmh_rs_frame_ensemble);
1102        if (lg_fail(ret))
1103                goto fail;
1104
1105        ret = lg216x_initialize(state);
1106        if (lg_fail(ret))
1107                goto fail;
1108
1109        ret = lg216x_enable_fic(state, 1);
1110        lg_fail(ret);
1111
1112        lg216x_get_frontend(fe, c);
1113fail:
1114        return ret;
1115}
1116
1117/* ------------------------------------------------------------------------ */
1118
1119static int lg2160_read_lock_status(struct lg216x_state *state,
1120                                   int *acq_lock, int *sync_lock)
1121{
1122        u8 val;
1123        int ret;
1124
1125        *acq_lock = 0;
1126        *sync_lock = 0;
1127
1128        ret = lg216x_read_reg(state, 0x011b, &val);
1129        if (lg_fail(ret))
1130                goto fail;
1131
1132        *sync_lock = (val & 0x20) ? 0 : 1;
1133        *acq_lock  = (val & 0x40) ? 0 : 1;
1134fail:
1135        return ret;
1136}
1137
1138#ifdef USE_LG2161_LOCK_BITS
1139static int lg2161_read_lock_status(struct lg216x_state *state,
1140                                   int *acq_lock, int *sync_lock)
1141{
1142        u8 val;
1143        int ret;
1144
1145        *acq_lock = 0;
1146        *sync_lock = 0;
1147
1148        ret = lg216x_read_reg(state, 0x0304, &val);
1149        if (lg_fail(ret))
1150                goto fail;
1151
1152        *sync_lock = (val & 0x80) ? 0 : 1;
1153
1154        ret = lg216x_read_reg(state, 0x011b, &val);
1155        if (lg_fail(ret))
1156                goto fail;
1157
1158        *acq_lock  = (val & 0x40) ? 0 : 1;
1159fail:
1160        return ret;
1161}
1162#endif
1163
1164static int lg216x_read_lock_status(struct lg216x_state *state,
1165                                   int *acq_lock, int *sync_lock)
1166{
1167#ifdef USE_LG2161_LOCK_BITS
1168        int ret;
1169        switch (state->cfg->lg_chip) {
1170        case LG2160:
1171                ret = lg2160_read_lock_status(state, acq_lock, sync_lock);
1172                break;
1173        case LG2161:
1174                ret = lg2161_read_lock_status(state, acq_lock, sync_lock);
1175                break;
1176        default:
1177                ret = -EINVAL;
1178                break;
1179        }
1180        return ret;
1181#else
1182        return lg2160_read_lock_status(state, acq_lock, sync_lock);
1183#endif
1184}
1185
1186static int lg216x_read_status(struct dvb_frontend *fe, enum fe_status *status)
1187{
1188        struct lg216x_state *state = fe->demodulator_priv;
1189        int ret, acq_lock, sync_lock;
1190
1191        *status = 0;
1192
1193        ret = lg216x_read_lock_status(state, &acq_lock, &sync_lock);
1194        if (lg_fail(ret))
1195                goto fail;
1196
1197        lg_dbg("%s%s\n",
1198               acq_lock  ? "SIGNALEXIST " : "",
1199               sync_lock ? "SYNCLOCK"     : "");
1200
1201        if (acq_lock)
1202                *status |= FE_HAS_SIGNAL;
1203        if (sync_lock)
1204                *status |= FE_HAS_SYNC;
1205
1206        if (*status)
1207                *status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
1208
1209fail:
1210        return ret;
1211}
1212
1213/* ------------------------------------------------------------------------ */
1214
1215static int lg2160_read_snr(struct dvb_frontend *fe, u16 *snr)
1216{
1217        struct lg216x_state *state = fe->demodulator_priv;
1218        u8 snr1, snr2;
1219        int ret;
1220
1221        *snr = 0;
1222
1223        ret = lg216x_read_reg(state, 0x0202, &snr1);
1224        if (lg_fail(ret))
1225                goto fail;
1226
1227        ret = lg216x_read_reg(state, 0x0203, &snr2);
1228        if (lg_fail(ret))
1229                goto fail;
1230
1231        if ((snr1 == 0xba) || (snr2 == 0xdf))
1232                *snr = 0;
1233        else
1234#if 1
1235        *snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 >> 4);
1236#else /* BCD */
1237        *snr =  (snr2 | (snr1 << 8));
1238#endif
1239fail:
1240        return ret;
1241}
1242
1243static int lg2161_read_snr(struct dvb_frontend *fe, u16 *snr)
1244{
1245        struct lg216x_state *state = fe->demodulator_priv;
1246        u8 snr1, snr2;
1247        int ret;
1248
1249        *snr = 0;
1250
1251        ret = lg216x_read_reg(state, 0x0302, &snr1);
1252        if (lg_fail(ret))
1253                goto fail;
1254
1255        ret = lg216x_read_reg(state, 0x0303, &snr2);
1256        if (lg_fail(ret))
1257                goto fail;
1258
1259        if ((snr1 == 0xba) || (snr2 == 0xfd))
1260                *snr = 0;
1261        else
1262
1263        *snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 & 0x0f);
1264fail:
1265        return ret;
1266}
1267
1268static int lg216x_read_signal_strength(struct dvb_frontend *fe,
1269                                       u16 *strength)
1270{
1271#if 0
1272        /* borrowed from lgdt330x.c
1273         *
1274         * Calculate strength from SNR up to 35dB
1275         * Even though the SNR can go higher than 35dB,
1276         * there is some comfort factor in having a range of
1277         * strong signals that can show at 100%
1278         */
1279        struct lg216x_state *state = fe->demodulator_priv;
1280        u16 snr;
1281        int ret;
1282#endif
1283        *strength = 0;
1284#if 0
1285        ret = fe->ops.read_snr(fe, &snr);
1286        if (lg_fail(ret))
1287                goto fail;
1288        /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
1289        /* scale the range 0 - 35*2^24 into 0 - 65535 */
1290        if (state->snr >= 8960 * 0x10000)
1291                *strength = 0xffff;
1292        else
1293                *strength = state->snr / 8960;
1294fail:
1295        return ret;
1296#else
1297        return 0;
1298#endif
1299}
1300
1301/* ------------------------------------------------------------------------ */
1302
1303static int lg216x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
1304{
1305#if 0
1306        struct lg216x_state *state = fe->demodulator_priv;
1307        int ret;
1308
1309        ret = lg216x_read_rs_err_count(state,
1310                                       &fe->dtv_property_cache.atscmh_rs_err);
1311        if (lg_fail(ret))
1312                goto fail;
1313
1314        *ucblocks = fe->dtv_property_cache.atscmh_rs_err;
1315fail:
1316#else
1317        *ucblocks = 0;
1318#endif
1319        return 0;
1320}
1321
1322static int lg216x_get_tune_settings(struct dvb_frontend *fe,
1323                                    struct dvb_frontend_tune_settings
1324                                    *fe_tune_settings)
1325{
1326        fe_tune_settings->min_delay_ms = 500;
1327        lg_dbg("\n");
1328        return 0;
1329}
1330
1331static void lg216x_release(struct dvb_frontend *fe)
1332{
1333        struct lg216x_state *state = fe->demodulator_priv;
1334        lg_dbg("\n");
1335        kfree(state);
1336}
1337
1338static const struct dvb_frontend_ops lg2160_ops = {
1339        .delsys = { SYS_ATSCMH },
1340        .info = {
1341                .name = "LG Electronics LG2160 ATSC/MH Frontend",
1342                .frequency_min_hz      =  54 * MHz,
1343                .frequency_max_hz      = 858 * MHz,
1344                .frequency_stepsize_hz = 62500,
1345        },
1346        .i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
1347#if 0
1348        .init                 = lg216x_init,
1349        .sleep                = lg216x_sleep,
1350#endif
1351        .set_frontend         = lg2160_set_frontend,
1352        .get_frontend         = lg216x_get_frontend,
1353        .get_tune_settings    = lg216x_get_tune_settings,
1354        .read_status          = lg216x_read_status,
1355#if 0
1356        .read_ber             = lg216x_read_ber,
1357#endif
1358        .read_signal_strength = lg216x_read_signal_strength,
1359        .read_snr             = lg2160_read_snr,
1360        .read_ucblocks        = lg216x_read_ucblocks,
1361        .release              = lg216x_release,
1362};
1363
1364static const struct dvb_frontend_ops lg2161_ops = {
1365        .delsys = { SYS_ATSCMH },
1366        .info = {
1367                .name = "LG Electronics LG2161 ATSC/MH Frontend",
1368                .frequency_min_hz      =  54 * MHz,
1369                .frequency_max_hz      = 858 * MHz,
1370                .frequency_stepsize_hz = 62500,
1371        },
1372        .i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
1373#if 0
1374        .init                 = lg216x_init,
1375        .sleep                = lg216x_sleep,
1376#endif
1377        .set_frontend         = lg2160_set_frontend,
1378        .get_frontend         = lg216x_get_frontend,
1379        .get_tune_settings    = lg216x_get_tune_settings,
1380        .read_status          = lg216x_read_status,
1381#if 0
1382        .read_ber             = lg216x_read_ber,
1383#endif
1384        .read_signal_strength = lg216x_read_signal_strength,
1385        .read_snr             = lg2161_read_snr,
1386        .read_ucblocks        = lg216x_read_ucblocks,
1387        .release              = lg216x_release,
1388};
1389
1390struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
1391                                   struct i2c_adapter *i2c_adap)
1392{
1393        struct lg216x_state *state = NULL;
1394
1395        lg_dbg("(%d-%04x)\n",
1396               i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
1397               config ? config->i2c_addr : 0);
1398
1399        state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL);
1400        if (!state)
1401                return NULL;
1402
1403        state->cfg = config;
1404        state->i2c_adap = i2c_adap;
1405        state->fic_ver = 0xff;
1406        state->parade_id = 0xff;
1407
1408        switch (config->lg_chip) {
1409        default:
1410                lg_warn("invalid chip requested, defaulting to LG2160");
1411                fallthrough;
1412        case LG2160:
1413                memcpy(&state->frontend.ops, &lg2160_ops,
1414                       sizeof(struct dvb_frontend_ops));
1415                break;
1416        case LG2161:
1417                memcpy(&state->frontend.ops, &lg2161_ops,
1418                       sizeof(struct dvb_frontend_ops));
1419                break;
1420        }
1421
1422        state->frontend.demodulator_priv = state;
1423        state->current_frequency = -1;
1424        /* parade 1 by default */
1425        state->frontend.dtv_property_cache.atscmh_parade_id = 1;
1426
1427        return &state->frontend;
1428}
1429EXPORT_SYMBOL(lg2160_attach);
1430
1431MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
1432MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
1433MODULE_LICENSE("GPL");
1434MODULE_VERSION("0.3");
1435