linux/drivers/media/dvb/frontends/lgs8gxx.c
<<
>>
Prefs
   1/*
   2 *    Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
   3 *    LGS8913, LGS8GL5, LGS8G75
   4 *    experimental support LGS8G42, LGS8G52
   5 *
   6 *    Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
   7 *    Copyright (C) 2008 Sirius International (Hong Kong) Limited
   8 *    Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
   9 *
  10 *    This program is free software; you can redistribute it and/or modify
  11 *    it under the terms of the GNU General Public License as published by
  12 *    the Free Software Foundation; either version 2 of the License, or
  13 *    (at your option) any later version.
  14 *
  15 *    This program is distributed in the hope that it will be useful,
  16 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 *    GNU General Public License for more details.
  19 *
  20 *    You should have received a copy of the GNU General Public License
  21 *    along with this program; if not, write to the Free Software
  22 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23 *
  24 */
  25
  26#include <asm/div64.h>
  27
  28#include "dvb_frontend.h"
  29
  30#include "lgs8gxx.h"
  31#include "lgs8gxx_priv.h"
  32
  33#define dprintk(args...) \
  34        do { \
  35                if (debug) \
  36                        printk(KERN_DEBUG "lgs8gxx: " args); \
  37        } while (0)
  38
  39static int debug;
  40static int fake_signal_str = 1;
  41
  42module_param(debug, int, 0644);
  43MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
  44
  45module_param(fake_signal_str, int, 0644);
  46MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
  47"Signal strength calculation is slow.(default:on).");
  48
  49static const u8 lgs8g75_initdat[] = {
  50        0x01, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  51        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  52        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  53        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  54        0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  55        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  56        0xE4, 0xF5, 0xA8, 0xF5, 0xB8, 0xF5, 0x88, 0xF5,
  57        0x89, 0xF5, 0x87, 0x75, 0xD0, 0x00, 0x11, 0x50,
  58        0x11, 0x50, 0xF4, 0xF5, 0x80, 0xF5, 0x90, 0xF5,
  59        0xA0, 0xF5, 0xB0, 0x75, 0x81, 0x30, 0x80, 0x01,
  60        0x32, 0x90, 0x80, 0x12, 0x74, 0xFF, 0xF0, 0x90,
  61        0x80, 0x13, 0x74, 0x1F, 0xF0, 0x90, 0x80, 0x23,
  62        0x74, 0x01, 0xF0, 0x90, 0x80, 0x22, 0xF0, 0x90,
  63        0x00, 0x48, 0x74, 0x00, 0xF0, 0x90, 0x80, 0x4D,
  64        0x74, 0x05, 0xF0, 0x90, 0x80, 0x09, 0xE0, 0x60,
  65        0x21, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x1B, 0x12,
  66        0x00, 0xDD, 0x14, 0x60, 0x15, 0x12, 0x00, 0xDD,
  67        0x14, 0x60, 0x0F, 0x12, 0x00, 0xDD, 0x14, 0x60,
  68        0x09, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x03, 0x12,
  69        0x00, 0xDD, 0x90, 0x80, 0x42, 0xE0, 0x60, 0x0B,
  70        0x14, 0x60, 0x0C, 0x14, 0x60, 0x0D, 0x14, 0x60,
  71        0x0E, 0x01, 0xB3, 0x74, 0x04, 0x01, 0xB9, 0x74,
  72        0x05, 0x01, 0xB9, 0x74, 0x07, 0x01, 0xB9, 0x74,
  73        0x0A, 0xC0, 0xE0, 0x74, 0xC8, 0x12, 0x00, 0xE2,
  74        0xD0, 0xE0, 0x14, 0x70, 0xF4, 0x90, 0x80, 0x09,
  75        0xE0, 0x70, 0xAE, 0x12, 0x00, 0xF6, 0x12, 0x00,
  76        0xFE, 0x90, 0x00, 0x48, 0xE0, 0x04, 0xF0, 0x90,
  77        0x80, 0x4E, 0xF0, 0x01, 0x73, 0x90, 0x80, 0x08,
  78        0xF0, 0x22, 0xF8, 0x7A, 0x0C, 0x79, 0xFD, 0x00,
  79        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9,
  80        0xF6, 0xDA, 0xF2, 0xD8, 0xEE, 0x22, 0x90, 0x80,
  81        0x65, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x80,
  82        0x65, 0xE0, 0x44, 0xC2, 0xF0, 0x22
  83};
  84
  85/* LGS8GXX internal helper functions */
  86
  87static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
  88{
  89        int ret;
  90        u8 buf[] = { reg, data };
  91        struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
  92
  93        msg.addr = priv->config->demod_address;
  94        if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
  95                msg.addr += 0x02;
  96
  97        if (debug >= 2)
  98                printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
  99                        __func__, reg, data);
 100
 101        ret = i2c_transfer(priv->i2c, &msg, 1);
 102
 103        if (ret != 1)
 104                dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n",
 105                        __func__, reg, data, ret);
 106
 107        return (ret != 1) ? -1 : 0;
 108}
 109
 110static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data)
 111{
 112        int ret;
 113        u8 dev_addr;
 114
 115        u8 b0[] = { reg };
 116        u8 b1[] = { 0 };
 117        struct i2c_msg msg[] = {
 118                { .flags = 0, .buf = b0, .len = 1 },
 119                { .flags = I2C_M_RD, .buf = b1, .len = 1 },
 120        };
 121
 122        dev_addr = priv->config->demod_address;
 123        if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
 124                dev_addr += 0x02;
 125        msg[1].addr =  msg[0].addr = dev_addr;
 126
 127        ret = i2c_transfer(priv->i2c, msg, 2);
 128        if (ret != 2) {
 129                dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n",
 130                        __func__, reg, ret);
 131                return -1;
 132        }
 133
 134        *p_data = b1[0];
 135        if (debug >= 2)
 136                printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n",
 137                        __func__, reg, b1[0]);
 138        return 0;
 139}
 140
 141static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv)
 142{
 143        lgs8gxx_write_reg(priv, 0x02, 0x00);
 144        msleep(1);
 145        lgs8gxx_write_reg(priv, 0x02, 0x01);
 146        msleep(100);
 147
 148        return 0;
 149}
 150
 151static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask,
 152        u8 val, u8 delay, u8 tries)
 153{
 154        u8 t;
 155        int i;
 156
 157        for (i = 0; i < tries; i++) {
 158                lgs8gxx_read_reg(priv, reg, &t);
 159
 160                if ((t & mask) == val)
 161                        return 0;
 162                msleep(delay);
 163        }
 164
 165        return 1;
 166}
 167
 168static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv)
 169{
 170        const struct lgs8gxx_config *config = priv->config;
 171        u8 if_conf;
 172
 173        if_conf = 0x10; /* AGC output on, RF_AGC output off; */
 174
 175        if_conf |=
 176                ((config->ext_adc) ? 0x80 : 0x00) |
 177                ((config->if_neg_center) ? 0x04 : 0x00) |
 178                ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */
 179                ((config->adc_signed) ? 0x02 : 0x00) |
 180                ((config->if_neg_edge) ? 0x01 : 0x00);
 181
 182        if (config->ext_adc &&
 183                (config->prod == LGS8GXX_PROD_LGS8G52)) {
 184                lgs8gxx_write_reg(priv, 0xBA, 0x40);
 185        }
 186
 187        lgs8gxx_write_reg(priv, 0x07, if_conf);
 188
 189        return 0;
 190}
 191
 192static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/)
 193{
 194        u64 val;
 195        u32 v32;
 196        u32 if_clk;
 197
 198        if_clk = priv->config->if_clk_freq;
 199
 200        val = freq;
 201        if (freq != 0) {
 202                val *= (u64)1 << 32;
 203                if (if_clk != 0)
 204                        do_div(val, if_clk);
 205                v32 = val & 0xFFFFFFFF;
 206                dprintk("Set IF Freq to %dkHz\n", freq);
 207        } else {
 208                v32 = 0;
 209                dprintk("Set IF Freq to baseband\n");
 210        }
 211        dprintk("AFC_INIT_FREQ = 0x%08X\n", v32);
 212
 213        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 214                lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32));
 215                lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8));
 216                lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16));
 217                lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24));
 218        } else {
 219                lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32));
 220                lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8));
 221                lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16));
 222                lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24));
 223        }
 224
 225        return 0;
 226}
 227
 228static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv)
 229{
 230        u64 val;
 231        u32 v32 = 0;
 232        u8 reg_addr, t;
 233        int i;
 234
 235        if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
 236                reg_addr = 0x23;
 237        else
 238                reg_addr = 0x48;
 239
 240        for (i = 0; i < 4; i++) {
 241                lgs8gxx_read_reg(priv, reg_addr, &t);
 242                v32 <<= 8;
 243                v32 |= t;
 244                reg_addr--;
 245        }
 246
 247        val = v32;
 248        val *= priv->config->if_clk_freq;
 249        val /= (u64)1 << 32;
 250        dprintk("AFC = %u kHz\n", (u32)val);
 251        return 0;
 252}
 253
 254static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv)
 255{
 256        u8 t;
 257        u8 prod = priv->config->prod;
 258
 259        if (prod == LGS8GXX_PROD_LGS8913)
 260                lgs8gxx_write_reg(priv, 0xC6, 0x01);
 261
 262        if (prod == LGS8GXX_PROD_LGS8G75) {
 263                lgs8gxx_read_reg(priv, 0x0C, &t);
 264                t &= (~0x04);
 265                lgs8gxx_write_reg(priv, 0x0C, t | 0x80);
 266                lgs8gxx_write_reg(priv, 0x39, 0x00);
 267                lgs8gxx_write_reg(priv, 0x3D, 0x04);
 268        } else if (prod == LGS8GXX_PROD_LGS8913 ||
 269                prod == LGS8GXX_PROD_LGS8GL5 ||
 270                prod == LGS8GXX_PROD_LGS8G42 ||
 271                prod == LGS8GXX_PROD_LGS8G52 ||
 272                prod == LGS8GXX_PROD_LGS8G54) {
 273                lgs8gxx_read_reg(priv, 0x7E, &t);
 274                lgs8gxx_write_reg(priv, 0x7E, t | 0x01);
 275
 276                /* clear FEC self reset */
 277                lgs8gxx_read_reg(priv, 0xC5, &t);
 278                lgs8gxx_write_reg(priv, 0xC5, t & 0xE0);
 279        }
 280
 281        if (prod == LGS8GXX_PROD_LGS8913) {
 282                /* FEC auto detect */
 283                lgs8gxx_write_reg(priv, 0xC1, 0x03);
 284
 285                lgs8gxx_read_reg(priv, 0x7C, &t);
 286                t = (t & 0x8C) | 0x03;
 287                lgs8gxx_write_reg(priv, 0x7C, t);
 288
 289                /* BER test mode */
 290                lgs8gxx_read_reg(priv, 0xC3, &t);
 291                t = (t & 0xEF) |  0x10;
 292                lgs8gxx_write_reg(priv, 0xC3, t);
 293        }
 294
 295        if (priv->config->prod == LGS8GXX_PROD_LGS8G52)
 296                lgs8gxx_write_reg(priv, 0xD9, 0x40);
 297
 298        return 0;
 299}
 300
 301static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv)
 302{
 303        int ret = 0;
 304        u8 t;
 305
 306        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 307                u8 t2;
 308                lgs8gxx_read_reg(priv, 0x0C, &t);
 309                t &= (~0x80);
 310                lgs8gxx_write_reg(priv, 0x0C, t);
 311
 312                lgs8gxx_read_reg(priv, 0x0C, &t);
 313                lgs8gxx_read_reg(priv, 0x19, &t2);
 314
 315                if (((t&0x03) == 0x01) && (t2&0x01)) {
 316                        lgs8gxx_write_reg(priv, 0x6E, 0x05);
 317                        lgs8gxx_write_reg(priv, 0x39, 0x02);
 318                        lgs8gxx_write_reg(priv, 0x39, 0x03);
 319                        lgs8gxx_write_reg(priv, 0x3D, 0x05);
 320                        lgs8gxx_write_reg(priv, 0x3E, 0x28);
 321                        lgs8gxx_write_reg(priv, 0x53, 0x80);
 322                } else {
 323                        lgs8gxx_write_reg(priv, 0x6E, 0x3F);
 324                        lgs8gxx_write_reg(priv, 0x39, 0x00);
 325                        lgs8gxx_write_reg(priv, 0x3D, 0x04);
 326                }
 327
 328                lgs8gxx_soft_reset(priv);
 329                return 0;
 330        }
 331
 332        /* turn off auto-detect; manual settings */
 333        lgs8gxx_write_reg(priv, 0x7E, 0);
 334        if (priv->config->prod == LGS8GXX_PROD_LGS8913)
 335                lgs8gxx_write_reg(priv, 0xC1, 0);
 336
 337        ret = lgs8gxx_read_reg(priv, 0xC5, &t);
 338        t = (t & 0xE0) | 0x06;
 339        lgs8gxx_write_reg(priv, 0xC5, t);
 340
 341        lgs8gxx_soft_reset(priv);
 342
 343        return 0;
 344}
 345
 346static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked)
 347{
 348        int ret = 0;
 349        u8 t;
 350
 351        if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
 352                ret = lgs8gxx_read_reg(priv, 0x13, &t);
 353        else
 354                ret = lgs8gxx_read_reg(priv, 0x4B, &t);
 355        if (ret != 0)
 356                return ret;
 357
 358        if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
 359                *locked = ((t & 0x80) == 0x80) ? 1 : 0;
 360        else
 361                *locked = ((t & 0xC0) == 0xC0) ? 1 : 0;
 362        return 0;
 363}
 364
 365/* Wait for Code Acquisition Lock */
 366static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked)
 367{
 368        int ret = 0;
 369        u8 reg, mask, val;
 370
 371        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 372                reg = 0x13;
 373                mask = 0x80;
 374                val = 0x80;
 375        } else {
 376                reg = 0x4B;
 377                mask = 0xC0;
 378                val = 0xC0;
 379        }
 380
 381        ret = wait_reg_mask(priv, reg, mask, val, 50, 40);
 382        *locked = (ret == 0) ? 1 : 0;
 383
 384        return 0;
 385}
 386
 387static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv,
 388                                          u8 *finished)
 389{
 390        int ret = 0;
 391        u8 reg, mask, val;
 392
 393        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 394                reg = 0x1f;
 395                mask = 0xC0;
 396                val = 0x80;
 397        } else {
 398                reg = 0xA4;
 399                mask = 0x03;
 400                val = 0x01;
 401        }
 402
 403        ret = wait_reg_mask(priv, reg, mask, val, 10, 20);
 404        *finished = (ret == 0) ? 1 : 0;
 405
 406        return 0;
 407}
 408
 409static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn,
 410        u8 *locked)
 411{
 412        int err = 0;
 413        u8 ad_fini = 0;
 414        u8 t1, t2;
 415
 416        if (gi == GI_945)
 417                dprintk("try GI 945\n");
 418        else if (gi == GI_595)
 419                dprintk("try GI 595\n");
 420        else if (gi == GI_420)
 421                dprintk("try GI 420\n");
 422        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 423                lgs8gxx_read_reg(priv, 0x0C, &t1);
 424                lgs8gxx_read_reg(priv, 0x18, &t2);
 425                t1 &= ~(GI_MASK);
 426                t1 |= gi;
 427                t2 &= 0xFE;
 428                t2 |= cpn ? 0x01 : 0x00;
 429                lgs8gxx_write_reg(priv, 0x0C, t1);
 430                lgs8gxx_write_reg(priv, 0x18, t2);
 431        } else {
 432                lgs8gxx_write_reg(priv, 0x04, gi);
 433        }
 434        lgs8gxx_soft_reset(priv);
 435        err = lgs8gxx_wait_ca_lock(priv, locked);
 436        if (err || !(*locked))
 437                return err;
 438        err = lgs8gxx_is_autodetect_finished(priv, &ad_fini);
 439        if (err != 0)
 440                return err;
 441        if (ad_fini) {
 442                dprintk("auto detect finished\n");
 443        } else
 444                *locked = 0;
 445
 446        return 0;
 447}
 448
 449static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv,
 450                               u8 *detected_param, u8 *gi)
 451{
 452        int i, j;
 453        int err = 0;
 454        u8 locked = 0, tmp_gi;
 455
 456        dprintk("%s\n", __func__);
 457
 458        lgs8gxx_set_mode_auto(priv);
 459        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 460                lgs8gxx_write_reg(priv, 0x67, 0xAA);
 461                lgs8gxx_write_reg(priv, 0x6E, 0x3F);
 462        } else {
 463                /* Guard Interval */
 464                lgs8gxx_write_reg(priv, 0x03, 00);
 465        }
 466
 467        for (i = 0; i < 2; i++) {
 468                for (j = 0; j < 2; j++) {
 469                        tmp_gi = GI_945;
 470                        err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked);
 471                        if (err)
 472                                goto out;
 473                        if (locked)
 474                                goto locked;
 475                }
 476                for (j = 0; j < 2; j++) {
 477                        tmp_gi = GI_420;
 478                        err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked);
 479                        if (err)
 480                                goto out;
 481                        if (locked)
 482                                goto locked;
 483                }
 484                tmp_gi = GI_595;
 485                err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked);
 486                if (err)
 487                        goto out;
 488                if (locked)
 489                        goto locked;
 490        }
 491
 492locked:
 493        if ((err == 0) && (locked == 1)) {
 494                u8 t;
 495
 496                if (priv->config->prod != LGS8GXX_PROD_LGS8G75) {
 497                        lgs8gxx_read_reg(priv, 0xA2, &t);
 498                        *detected_param = t;
 499                } else {
 500                        lgs8gxx_read_reg(priv, 0x1F, &t);
 501                        *detected_param = t & 0x3F;
 502                }
 503
 504                if (tmp_gi == GI_945)
 505                        dprintk("GI 945 locked\n");
 506                else if (tmp_gi == GI_595)
 507                        dprintk("GI 595 locked\n");
 508                else if (tmp_gi == GI_420)
 509                        dprintk("GI 420 locked\n");
 510                *gi = tmp_gi;
 511        }
 512        if (!locked)
 513                err = -1;
 514
 515out:
 516        return err;
 517}
 518
 519static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv)
 520{
 521        s8 err;
 522        u8 gi = 0x2;
 523        u8 detected_param = 0;
 524
 525        err = lgs8gxx_auto_detect(priv, &detected_param, &gi);
 526
 527        if (err != 0) {
 528                dprintk("lgs8gxx_auto_detect failed\n");
 529        } else
 530                dprintk("detected param = 0x%02X\n", detected_param);
 531
 532        /* Apply detected parameters */
 533        if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
 534                u8 inter_leave_len = detected_param & TIM_MASK ;
 535                /* Fix 8913 time interleaver detection bug */
 536                inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40;
 537                detected_param &= CF_MASK | SC_MASK  | LGS_FEC_MASK;
 538                detected_param |= inter_leave_len;
 539        }
 540        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 541                u8 t;
 542                lgs8gxx_read_reg(priv, 0x19, &t);
 543                t &= 0x81;
 544                t |= detected_param << 1;
 545                lgs8gxx_write_reg(priv, 0x19, t);
 546        } else {
 547                lgs8gxx_write_reg(priv, 0x7D, detected_param);
 548                if (priv->config->prod == LGS8GXX_PROD_LGS8913)
 549                        lgs8gxx_write_reg(priv, 0xC0, detected_param);
 550        }
 551        /* lgs8gxx_soft_reset(priv); */
 552
 553        /* Enter manual mode */
 554        lgs8gxx_set_mode_manual(priv);
 555
 556        switch (gi) {
 557        case GI_945:
 558                priv->curr_gi = 945; break;
 559        case GI_595:
 560                priv->curr_gi = 595; break;
 561        case GI_420:
 562                priv->curr_gi = 420; break;
 563        default:
 564                priv->curr_gi = 945; break;
 565        }
 566}
 567
 568static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv,
 569        u8 serial, u8 clk_pol, u8 clk_gated)
 570{
 571        int ret = 0;
 572        u8 t, reg_addr;
 573
 574        reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2;
 575        ret = lgs8gxx_read_reg(priv, reg_addr, &t);
 576        if (ret != 0)
 577                return ret;
 578
 579        t &= 0xF8;
 580        t |= serial ? TS_SERIAL : TS_PARALLEL;
 581        t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL;
 582        t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN;
 583
 584        ret = lgs8gxx_write_reg(priv, reg_addr, t);
 585        if (ret != 0)
 586                return ret;
 587
 588        return 0;
 589}
 590
 591/* A/D input peak-to-peak voltage range */
 592static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv,
 593        u8 sel)
 594{
 595        u8 r26 = 0x73, r27 = 0x90;
 596
 597        if (priv->config->prod != LGS8GXX_PROD_LGS8G75)
 598                return 0;
 599
 600        r26 |= (sel & 0x01) << 7;
 601        r27 |= (sel & 0x02) >> 1;
 602        lgs8gxx_write_reg(priv, 0x26, r26);
 603        lgs8gxx_write_reg(priv, 0x27, r27);
 604
 605        return 0;
 606}
 607
 608/* LGS8913 demod frontend functions */
 609
 610static int lgs8913_init(struct lgs8gxx_state *priv)
 611{
 612        u8 t;
 613
 614        /* LGS8913 specific */
 615        lgs8gxx_write_reg(priv, 0xc1, 0x3);
 616
 617        lgs8gxx_read_reg(priv, 0x7c, &t);
 618        lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3);
 619
 620        /* LGS8913 specific */
 621        lgs8gxx_read_reg(priv, 0xc3, &t);
 622        lgs8gxx_write_reg(priv, 0xc3, t&0x10);
 623
 624
 625        return 0;
 626}
 627
 628static int lgs8g75_init_data(struct lgs8gxx_state *priv)
 629{
 630        const u8 *p = lgs8g75_initdat;
 631        int i;
 632
 633        lgs8gxx_write_reg(priv, 0xC6, 0x40);
 634
 635        lgs8gxx_write_reg(priv, 0x3D, 0x04);
 636        lgs8gxx_write_reg(priv, 0x39, 0x00);
 637
 638        lgs8gxx_write_reg(priv, 0x3A, 0x00);
 639        lgs8gxx_write_reg(priv, 0x38, 0x00);
 640        lgs8gxx_write_reg(priv, 0x3B, 0x00);
 641        lgs8gxx_write_reg(priv, 0x38, 0x00);
 642
 643        for (i = 0; i < sizeof(lgs8g75_initdat); i++) {
 644                lgs8gxx_write_reg(priv, 0x38, 0x00);
 645                lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff));
 646                lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8));
 647                lgs8gxx_write_reg(priv, 0x3C, *p);
 648                p++;
 649        }
 650
 651        lgs8gxx_write_reg(priv, 0x38, 0x00);
 652
 653        return 0;
 654}
 655
 656static int lgs8gxx_init(struct dvb_frontend *fe)
 657{
 658        struct lgs8gxx_state *priv =
 659                (struct lgs8gxx_state *)fe->demodulator_priv;
 660        const struct lgs8gxx_config *config = priv->config;
 661        u8 data = 0;
 662        s8 err;
 663        dprintk("%s\n", __func__);
 664
 665        lgs8gxx_read_reg(priv, 0, &data);
 666        dprintk("reg 0 = 0x%02X\n", data);
 667
 668        if (config->prod == LGS8GXX_PROD_LGS8G75)
 669                lgs8g75_set_adc_vpp(priv, config->adc_vpp);
 670
 671        /* Setup MPEG output format */
 672        err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts,
 673                                    config->ts_clk_pol,
 674                                    config->ts_clk_gated);
 675        if (err != 0)
 676                return -EIO;
 677
 678        if (config->prod == LGS8GXX_PROD_LGS8913)
 679                lgs8913_init(priv);
 680        lgs8gxx_set_if_freq(priv, priv->config->if_freq);
 681        lgs8gxx_set_ad_mode(priv);
 682
 683        return 0;
 684}
 685
 686static void lgs8gxx_release(struct dvb_frontend *fe)
 687{
 688        struct lgs8gxx_state *state = fe->demodulator_priv;
 689        dprintk("%s\n", __func__);
 690
 691        kfree(state);
 692}
 693
 694
 695static int lgs8gxx_write(struct dvb_frontend *fe, u8 *buf, int len)
 696{
 697        struct lgs8gxx_state *priv = fe->demodulator_priv;
 698
 699        if (len != 2)
 700                return -EINVAL;
 701
 702        return lgs8gxx_write_reg(priv, buf[0], buf[1]);
 703}
 704
 705static int lgs8gxx_set_fe(struct dvb_frontend *fe,
 706                          struct dvb_frontend_parameters *fe_params)
 707{
 708        struct lgs8gxx_state *priv = fe->demodulator_priv;
 709
 710        dprintk("%s\n", __func__);
 711
 712        /* set frequency */
 713        if (fe->ops.tuner_ops.set_params) {
 714                fe->ops.tuner_ops.set_params(fe, fe_params);
 715                if (fe->ops.i2c_gate_ctrl)
 716                        fe->ops.i2c_gate_ctrl(fe, 0);
 717        }
 718
 719        /* start auto lock */
 720        lgs8gxx_auto_lock(priv);
 721
 722        msleep(10);
 723
 724        return 0;
 725}
 726
 727static int lgs8gxx_get_fe(struct dvb_frontend *fe,
 728                          struct dvb_frontend_parameters *fe_params)
 729{
 730        dprintk("%s\n", __func__);
 731
 732        /* TODO: get real readings from device */
 733        /* inversion status */
 734        fe_params->inversion = INVERSION_OFF;
 735
 736        /* bandwidth */
 737        fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
 738
 739        fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
 740        fe_params->u.ofdm.code_rate_LP = FEC_AUTO;
 741
 742        fe_params->u.ofdm.constellation = QAM_AUTO;
 743
 744        /* transmission mode */
 745        fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
 746
 747        /* guard interval */
 748        fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
 749
 750        /* hierarchy */
 751        fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
 752
 753        return 0;
 754}
 755
 756static
 757int lgs8gxx_get_tune_settings(struct dvb_frontend *fe,
 758                              struct dvb_frontend_tune_settings *fesettings)
 759{
 760        /* FIXME: copy from tda1004x.c */
 761        fesettings->min_delay_ms = 800;
 762        fesettings->step_size = 0;
 763        fesettings->max_drift = 0;
 764        return 0;
 765}
 766
 767static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
 768{
 769        struct lgs8gxx_state *priv = fe->demodulator_priv;
 770        s8 ret;
 771        u8 t, locked = 0;
 772
 773        dprintk("%s\n", __func__);
 774        *fe_status = 0;
 775
 776        lgs8gxx_get_afc_phase(priv);
 777        lgs8gxx_is_locked(priv, &locked);
 778        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 779                if (locked)
 780                        *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
 781                                FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 782                return 0;
 783        }
 784
 785        ret = lgs8gxx_read_reg(priv, 0x4B, &t);
 786        if (ret != 0)
 787                return -EIO;
 788
 789        dprintk("Reg 0x4B: 0x%02X\n", t);
 790
 791        *fe_status = 0;
 792        if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
 793                if ((t & 0x40) == 0x40)
 794                        *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
 795                if ((t & 0x80) == 0x80)
 796                        *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC |
 797                                FE_HAS_LOCK;
 798        } else {
 799                if ((t & 0x80) == 0x80)
 800                        *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
 801                                FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 802        }
 803
 804        /* success */
 805        dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
 806        return 0;
 807}
 808
 809static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal)
 810{
 811        u16 v;
 812        u8 agc_lvl[2], cat;
 813
 814        dprintk("%s()\n", __func__);
 815        lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]);
 816        lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]);
 817
 818        v = agc_lvl[0];
 819        v <<= 8;
 820        v |= agc_lvl[1];
 821
 822        dprintk("agc_lvl: 0x%04X\n", v);
 823
 824        if (v < 0x100)
 825                cat = 0;
 826        else if (v < 0x190)
 827                cat = 5;
 828        else if (v < 0x2A8)
 829                cat = 4;
 830        else if (v < 0x381)
 831                cat = 3;
 832        else if (v < 0x400)
 833                cat = 2;
 834        else if (v == 0x400)
 835                cat = 1;
 836        else
 837                cat = 0;
 838
 839        *signal = cat * 65535 / 5;
 840
 841        return 0;
 842}
 843
 844static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
 845{
 846        u8 t; s8 ret;
 847        s16 max_strength = 0;
 848        u8 str;
 849        u16 i, gi = priv->curr_gi;
 850
 851        dprintk("%s\n", __func__);
 852
 853        ret = lgs8gxx_read_reg(priv, 0x4B, &t);
 854        if (ret != 0)
 855                return -EIO;
 856
 857        if (fake_signal_str) {
 858                if ((t & 0xC0) == 0xC0) {
 859                        dprintk("Fake signal strength\n");
 860                        *signal = 0x7FFF;
 861                } else
 862                        *signal = 0;
 863                return 0;
 864        }
 865
 866        dprintk("gi = %d\n", gi);
 867        for (i = 0; i < gi; i++) {
 868
 869                if ((i & 0xFF) == 0)
 870                        lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8));
 871                lgs8gxx_write_reg(priv, 0x83, i & 0xFF);
 872
 873                lgs8gxx_read_reg(priv, 0x94, &str);
 874                if (max_strength < str)
 875                        max_strength = str;
 876        }
 877
 878        *signal = max_strength;
 879        dprintk("%s: signal=0x%02X\n", __func__, *signal);
 880
 881        lgs8gxx_read_reg(priv, 0x95, &t);
 882        dprintk("%s: AVG Noise=0x%02X\n", __func__, t);
 883
 884        return 0;
 885}
 886
 887static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
 888{
 889        u8 t;
 890        s16 v = 0;
 891
 892        dprintk("%s\n", __func__);
 893
 894        lgs8gxx_read_reg(priv, 0xB1, &t);
 895        v |= t;
 896        v <<= 8;
 897        lgs8gxx_read_reg(priv, 0xB0, &t);
 898        v |= t;
 899
 900        *signal = v;
 901        dprintk("%s: signal=0x%02X\n", __func__, *signal);
 902
 903        return 0;
 904}
 905
 906static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
 907{
 908        struct lgs8gxx_state *priv = fe->demodulator_priv;
 909
 910        if (priv->config->prod == LGS8GXX_PROD_LGS8913)
 911                return lgs8913_read_signal_strength(priv, signal);
 912        else if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
 913                return lgs8g75_read_signal_strength(priv, signal);
 914        else
 915                return lgs8gxx_read_signal_agc(priv, signal);
 916}
 917
 918static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr)
 919{
 920        struct lgs8gxx_state *priv = fe->demodulator_priv;
 921        u8 t;
 922        *snr = 0;
 923
 924        if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
 925                lgs8gxx_read_reg(priv, 0x34, &t);
 926        else
 927                lgs8gxx_read_reg(priv, 0x95, &t);
 928        dprintk("AVG Noise=0x%02X\n", t);
 929        *snr = 256 - t;
 930        *snr <<= 8;
 931        dprintk("snr=0x%x\n", *snr);
 932
 933        return 0;
 934}
 935
 936static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 937{
 938        *ucblocks = 0;
 939        dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
 940        return 0;
 941}
 942
 943static void packet_counter_start(struct lgs8gxx_state *priv)
 944{
 945        u8 orig, t;
 946
 947        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 948                lgs8gxx_read_reg(priv, 0x30, &orig);
 949                orig &= 0xE7;
 950                t = orig | 0x10;
 951                lgs8gxx_write_reg(priv, 0x30, t);
 952                t = orig | 0x18;
 953                lgs8gxx_write_reg(priv, 0x30, t);
 954                t = orig | 0x10;
 955                lgs8gxx_write_reg(priv, 0x30, t);
 956        } else {
 957                lgs8gxx_write_reg(priv, 0xC6, 0x01);
 958                lgs8gxx_write_reg(priv, 0xC6, 0x41);
 959                lgs8gxx_write_reg(priv, 0xC6, 0x01);
 960        }
 961}
 962
 963static void packet_counter_stop(struct lgs8gxx_state *priv)
 964{
 965        u8 t;
 966
 967        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 968                lgs8gxx_read_reg(priv, 0x30, &t);
 969                t &= 0xE7;
 970                lgs8gxx_write_reg(priv, 0x30, t);
 971        } else {
 972                lgs8gxx_write_reg(priv, 0xC6, 0x81);
 973        }
 974}
 975
 976static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber)
 977{
 978        struct lgs8gxx_state *priv = fe->demodulator_priv;
 979        u8 reg_err, reg_total, t;
 980        u32 total_cnt = 0, err_cnt = 0;
 981        int i;
 982
 983        dprintk("%s\n", __func__);
 984
 985        packet_counter_start(priv);
 986        msleep(200);
 987        packet_counter_stop(priv);
 988
 989        if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
 990                reg_total = 0x28; reg_err = 0x2C;
 991        } else {
 992                reg_total = 0xD0; reg_err = 0xD4;
 993        }
 994
 995        for (i = 0; i < 4; i++) {
 996                total_cnt <<= 8;
 997                lgs8gxx_read_reg(priv, reg_total+3-i, &t);
 998                total_cnt |= t;
 999        }
1000        for (i = 0; i < 4; i++) {
1001                err_cnt <<= 8;
1002                lgs8gxx_read_reg(priv, reg_err+3-i, &t);
1003                err_cnt |= t;
1004        }
1005        dprintk("error=%d total=%d\n", err_cnt, total_cnt);
1006
1007        if (total_cnt == 0)
1008                *ber = 0;
1009        else
1010                *ber = err_cnt * 100 / total_cnt;
1011
1012        dprintk("%s: ber=0x%x\n", __func__, *ber);
1013        return 0;
1014}
1015
1016static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
1017{
1018        struct lgs8gxx_state *priv = fe->demodulator_priv;
1019
1020        if (priv->config->tuner_address == 0)
1021                return 0;
1022        if (enable) {
1023                u8 v = 0x80 | priv->config->tuner_address;
1024                return lgs8gxx_write_reg(priv, 0x01, v);
1025        }
1026        return lgs8gxx_write_reg(priv, 0x01, 0);
1027}
1028
1029static struct dvb_frontend_ops lgs8gxx_ops = {
1030        .info = {
1031                .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
1032                .type = FE_OFDM,
1033                .frequency_min = 474000000,
1034                .frequency_max = 858000000,
1035                .frequency_stepsize = 10000,
1036                .caps =
1037                        FE_CAN_FEC_AUTO |
1038                        FE_CAN_QAM_AUTO |
1039                        FE_CAN_TRANSMISSION_MODE_AUTO |
1040                        FE_CAN_GUARD_INTERVAL_AUTO
1041        },
1042
1043        .release = lgs8gxx_release,
1044
1045        .init = lgs8gxx_init,
1046        .write = lgs8gxx_write,
1047        .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl,
1048
1049        .set_frontend = lgs8gxx_set_fe,
1050        .get_frontend = lgs8gxx_get_fe,
1051        .get_tune_settings = lgs8gxx_get_tune_settings,
1052
1053        .read_status = lgs8gxx_read_status,
1054        .read_ber = lgs8gxx_read_ber,
1055        .read_signal_strength = lgs8gxx_read_signal_strength,
1056        .read_snr = lgs8gxx_read_snr,
1057        .read_ucblocks = lgs8gxx_read_ucblocks,
1058};
1059
1060struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
1061        struct i2c_adapter *i2c)
1062{
1063        struct lgs8gxx_state *priv = NULL;
1064        u8 data = 0;
1065
1066        dprintk("%s()\n", __func__);
1067
1068        if (config == NULL || i2c == NULL)
1069                return NULL;
1070
1071        priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL);
1072        if (priv == NULL)
1073                goto error_out;
1074
1075        priv->config = config;
1076        priv->i2c = i2c;
1077
1078        /* check if the demod is there */
1079        if (lgs8gxx_read_reg(priv, 0, &data) != 0) {
1080                dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n",
1081                        __func__, priv->config->demod_address);
1082                goto error_out;
1083        }
1084
1085        lgs8gxx_read_reg(priv, 1, &data);
1086
1087        memcpy(&priv->frontend.ops, &lgs8gxx_ops,
1088               sizeof(struct dvb_frontend_ops));
1089        priv->frontend.demodulator_priv = priv;
1090
1091        if (config->prod == LGS8GXX_PROD_LGS8G75)
1092                lgs8g75_init_data(priv);
1093
1094        return &priv->frontend;
1095
1096error_out:
1097        dprintk("%s() error_out\n", __func__);
1098        kfree(priv);
1099        return NULL;
1100
1101}
1102EXPORT_SYMBOL(lgs8gxx_attach);
1103
1104MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver");
1105MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
1106MODULE_LICENSE("GPL");
1107