This source file includes following definitions.
- cx24116_writereg
- cx24116_writeregN
- cx24116_readreg
- cx24116_set_inversion
- cx24116_lookup_fecmod
- cx24116_set_fec
- cx24116_set_symbolrate
- cx24116_firmware_ondemand
- cx24116_cmd_execute
- cx24116_load_firmware
- cx24116_read_status
- cx24116_read_ber
- cx24116_read_signal_strength
- cx24116_read_snr_pct
- cx24116_read_snr_esno
- cx24116_read_snr
- cx24116_read_ucblocks
- cx24116_clone_params
- cx24116_wait_for_lnb
- cx24116_set_voltage
- cx24116_set_tone
- cx24116_diseqc_init
- cx24116_send_diseqc_msg
- cx24116_diseqc_send_burst
- cx24116_release
- cx24116_attach
- cx24116_initfe
- cx24116_sleep
- cx24116_set_frontend
- cx24116_tune
- cx24116_get_algo
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 #include <linux/slab.h>
  26 #include <linux/kernel.h>
  27 #include <linux/module.h>
  28 #include <linux/moduleparam.h>
  29 #include <linux/init.h>
  30 #include <linux/firmware.h>
  31 
  32 #include <media/dvb_frontend.h>
  33 #include "cx24116.h"
  34 
  35 static int debug;
  36 module_param(debug, int, 0644);
  37 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
  38 
  39 #define dprintk(args...) \
  40         do { \
  41                 if (debug) \
  42                         printk(KERN_INFO "cx24116: " args); \
  43         } while (0)
  44 
  45 #define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
  46 #define CX24116_SEARCH_RANGE_KHZ 5000
  47 
  48 
  49 #define CX24116_REG_COMMAND (0x00)      
  50 #define CX24116_REG_EXECUTE (0x1f)      
  51 #define CX24116_REG_MAILBOX (0x96)      
  52 #define CX24116_REG_RESET   (0x20)      
  53 #define CX24116_REG_SIGNAL  (0x9e)      
  54 #define CX24116_REG_SSTATUS (0x9d)      
  55 #define CX24116_REG_QUALITY8 (0xa3)
  56 #define CX24116_REG_QSTATUS (0xbc)
  57 #define CX24116_REG_QUALITY0 (0xd5)
  58 #define CX24116_REG_BER0    (0xc9)
  59 #define CX24116_REG_BER8    (0xc8)
  60 #define CX24116_REG_BER16   (0xc7)
  61 #define CX24116_REG_BER24   (0xc6)
  62 #define CX24116_REG_UCB0    (0xcb)
  63 #define CX24116_REG_UCB8    (0xca)
  64 #define CX24116_REG_CLKDIV  (0xf3)
  65 #define CX24116_REG_RATEDIV (0xf9)
  66 
  67 
  68 #define CX24116_REG_FECSTATUS (0x9c)
  69 
  70 
  71 
  72 #define CX24116_FEC_FECMASK   (0x1f)
  73 
  74 
  75 #define CX24116_FEC_DVBS      (0x20)
  76 #define CX24116_FEC_UNKNOWN   (0x40)    
  77 
  78 
  79 #define CX24116_FEC_PILOT     (0x80)
  80 
  81 
  82 #define CX24116_ARGLEN (0x1e)
  83 
  84 
  85 #define CX24116_ROLLOFF_020 (0x00)
  86 #define CX24116_ROLLOFF_025 (0x01)
  87 #define CX24116_ROLLOFF_035 (0x02)
  88 
  89 
  90 #define CX24116_PILOT_OFF (0x00)
  91 #define CX24116_PILOT_ON (0x40)
  92 
  93 
  94 #define CX24116_HAS_SIGNAL   (0x01)
  95 #define CX24116_HAS_CARRIER  (0x02)
  96 #define CX24116_HAS_VITERBI  (0x04)
  97 #define CX24116_HAS_SYNCLOCK (0x08)
  98 #define CX24116_HAS_UNKNOWN1 (0x10)
  99 #define CX24116_HAS_UNKNOWN2 (0x20)
 100 #define CX24116_STATUS_MASK  (0x0f)
 101 #define CX24116_SIGNAL_MASK  (0xc0)
 102 
 103 #define CX24116_DISEQC_TONEOFF   (0)    
 104 #define CX24116_DISEQC_TONECACHE (1)    
 105 #define CX24116_DISEQC_MESGCACHE (2)    
 106 
 107 
 108 #define CX24116_DISEQC_BURST  (1)
 109 #define CX24116_DISEQC_ARG2_2 (2)   
 110 #define CX24116_DISEQC_ARG3_0 (3)   
 111 #define CX24116_DISEQC_ARG4_0 (4)   
 112 #define CX24116_DISEQC_MSGLEN (5)
 113 #define CX24116_DISEQC_MSGOFS (6)
 114 
 115 
 116 #define CX24116_DISEQC_MINI_A (0)
 117 #define CX24116_DISEQC_MINI_B (1)
 118 
 119 
 120 static int toneburst = 1;
 121 module_param(toneburst, int, 0644);
 122 MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
 123         "2=MESSAGE CACHE (default:1)");
 124 
 125 
 126 static int esno_snr;
 127 module_param(esno_snr, int, 0644);
 128 MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\
 129         "1=ESNO(db * 10) (default:0)");
 130 
 131 enum cmds {
 132         CMD_SET_VCO     = 0x10,
 133         CMD_TUNEREQUEST = 0x11,
 134         CMD_MPEGCONFIG  = 0x13,
 135         CMD_TUNERINIT   = 0x14,
 136         CMD_BANDWIDTH   = 0x15,
 137         CMD_GETAGC      = 0x19,
 138         CMD_LNBCONFIG   = 0x20,
 139         CMD_LNBSEND     = 0x21, 
 140         CMD_LNBDCLEVEL  = 0x22,
 141         CMD_SET_TONE    = 0x23,
 142         CMD_UPDFWVERS   = 0x35,
 143         CMD_TUNERSLEEP  = 0x36,
 144         CMD_AGCCONTROL  = 0x3b, 
 145 };
 146 
 147 
 148 struct cx24116_tuning {
 149         u32 frequency;
 150         u32 symbol_rate;
 151         enum fe_spectral_inversion inversion;
 152         enum fe_code_rate fec;
 153 
 154         enum fe_delivery_system delsys;
 155         enum fe_modulation modulation;
 156         enum fe_pilot pilot;
 157         enum fe_rolloff rolloff;
 158 
 159         
 160         u8 fec_val;
 161         u8 fec_mask;
 162         u8 inversion_val;
 163         u8 pilot_val;
 164         u8 rolloff_val;
 165 };
 166 
 167 
 168 struct cx24116_cmd {
 169         u8 len;
 170         u8 args[CX24116_ARGLEN];
 171 };
 172 
 173 struct cx24116_state {
 174         struct i2c_adapter *i2c;
 175         const struct cx24116_config *config;
 176 
 177         struct dvb_frontend frontend;
 178 
 179         struct cx24116_tuning dcur;
 180         struct cx24116_tuning dnxt;
 181 
 182         u8 skip_fw_load;
 183         u8 burst;
 184         struct cx24116_cmd dsec_cmd;
 185 };
 186 
 187 static int cx24116_writereg(struct cx24116_state *state, int reg, int data)
 188 {
 189         u8 buf[] = { reg, data };
 190         struct i2c_msg msg = { .addr = state->config->demod_address,
 191                 .flags = 0, .buf = buf, .len = 2 };
 192         int err;
 193 
 194         if (debug > 1)
 195                 printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
 196                         __func__, reg, data);
 197 
 198         err = i2c_transfer(state->i2c, &msg, 1);
 199         if (err != 1) {
 200                 printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x, value == 0x%02x)\n",
 201                        __func__, err, reg, data);
 202                 return -EREMOTEIO;
 203         }
 204 
 205         return 0;
 206 }
 207 
 208 
 209 static int cx24116_writeregN(struct cx24116_state *state, int reg,
 210                              const u8 *data, u16 len)
 211 {
 212         int ret;
 213         struct i2c_msg msg;
 214         u8 *buf;
 215 
 216         buf = kmalloc(len + 1, GFP_KERNEL);
 217         if (!buf)
 218                 return -ENOMEM;
 219 
 220         *(buf) = reg;
 221         memcpy(buf + 1, data, len);
 222 
 223         msg.addr = state->config->demod_address;
 224         msg.flags = 0;
 225         msg.buf = buf;
 226         msg.len = len + 1;
 227 
 228         if (debug > 1)
 229                 printk(KERN_INFO "cx24116: %s:  write regN 0x%02x, len = %d\n",
 230                         __func__, reg, len);
 231 
 232         ret = i2c_transfer(state->i2c, &msg, 1);
 233         if (ret != 1) {
 234                 printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
 235                          __func__, ret, reg);
 236                 ret = -EREMOTEIO;
 237         }
 238 
 239         kfree(buf);
 240 
 241         return ret;
 242 }
 243 
 244 static int cx24116_readreg(struct cx24116_state *state, u8 reg)
 245 {
 246         int ret;
 247         u8 b0[] = { reg };
 248         u8 b1[] = { 0 };
 249         struct i2c_msg msg[] = {
 250                 { .addr = state->config->demod_address, .flags = 0,
 251                         .buf = b0, .len = 1 },
 252                 { .addr = state->config->demod_address, .flags = I2C_M_RD,
 253                         .buf = b1, .len = 1 }
 254         };
 255 
 256         ret = i2c_transfer(state->i2c, msg, 2);
 257 
 258         if (ret != 2) {
 259                 printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
 260                         __func__, reg, ret);
 261                 return ret;
 262         }
 263 
 264         if (debug > 1)
 265                 printk(KERN_INFO "cx24116: read reg 0x%02x, value 0x%02x\n",
 266                         reg, b1[0]);
 267 
 268         return b1[0];
 269 }
 270 
 271 static int cx24116_set_inversion(struct cx24116_state *state,
 272         enum fe_spectral_inversion inversion)
 273 {
 274         dprintk("%s(%d)\n", __func__, inversion);
 275 
 276         switch (inversion) {
 277         case INVERSION_OFF:
 278                 state->dnxt.inversion_val = 0x00;
 279                 break;
 280         case INVERSION_ON:
 281                 state->dnxt.inversion_val = 0x04;
 282                 break;
 283         case INVERSION_AUTO:
 284                 state->dnxt.inversion_val = 0x0C;
 285                 break;
 286         default:
 287                 return -EINVAL;
 288         }
 289 
 290         state->dnxt.inversion = inversion;
 291 
 292         return 0;
 293 }
 294 
 295 
 296 
 297 
 298 
 299 
 300 
 301 
 302 
 303 
 304 
 305 
 306 
 307 
 308 
 309 
 310 
 311 
 312 
 313 
 314 
 315 
 316 
 317 
 318 
 319 
 320 
 321 
 322 
 323 
 324 
 325 
 326 
 327 
 328 
 329 
 330 
 331 
 332 
 333 
 334 
 335 
 336 
 337 
 338 
 339 
 340 
 341 
 342 
 343 
 344 
 345 
 346 
 347 
 348 
 349 
 350 
 351 
 352 
 353 
 354 
 355 
 356 
 357 
 358 
 359 static struct cx24116_modfec {
 360         enum fe_delivery_system delivery_system;
 361         enum fe_modulation modulation;
 362         enum fe_code_rate fec;
 363         u8 mask;        
 364         u8 val;         
 365 } CX24116_MODFEC_MODES[] = {
 366  
 367 
 368  
 369  { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
 370  { SYS_DVBS, QPSK, FEC_1_2,  0x02, 0x2e }, 
 371  { SYS_DVBS, QPSK, FEC_2_3,  0x04, 0x2f }, 
 372  { SYS_DVBS, QPSK, FEC_3_4,  0x08, 0x30 }, 
 373  { SYS_DVBS, QPSK, FEC_4_5,  0xfe, 0x30 }, 
 374  { SYS_DVBS, QPSK, FEC_5_6,  0x20, 0x31 }, 
 375  { SYS_DVBS, QPSK, FEC_6_7,  0xfe, 0x30 }, 
 376  { SYS_DVBS, QPSK, FEC_7_8,  0x80, 0x32 }, 
 377  { SYS_DVBS, QPSK, FEC_8_9,  0xfe, 0x30 }, 
 378  { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
 379  
 380  { SYS_DVBS2, QPSK, FEC_1_2,  0x00, 0x04 },
 381  { SYS_DVBS2, QPSK, FEC_3_5,  0x00, 0x05 },
 382  { SYS_DVBS2, QPSK, FEC_2_3,  0x00, 0x06 },
 383  { SYS_DVBS2, QPSK, FEC_3_4,  0x00, 0x07 },
 384  { SYS_DVBS2, QPSK, FEC_4_5,  0x00, 0x08 },
 385  { SYS_DVBS2, QPSK, FEC_5_6,  0x00, 0x09 },
 386  { SYS_DVBS2, QPSK, FEC_8_9,  0x00, 0x0a },
 387  { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
 388  
 389  { SYS_DVBS2, PSK_8, FEC_3_5,  0x00, 0x0c },
 390  { SYS_DVBS2, PSK_8, FEC_2_3,  0x00, 0x0d },
 391  { SYS_DVBS2, PSK_8, FEC_3_4,  0x00, 0x0e },
 392  { SYS_DVBS2, PSK_8, FEC_5_6,  0x00, 0x0f },
 393  { SYS_DVBS2, PSK_8, FEC_8_9,  0x00, 0x10 },
 394  { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
 395  
 396 
 397 
 398 
 399 };
 400 
 401 static int cx24116_lookup_fecmod(struct cx24116_state *state,
 402         enum fe_delivery_system d, enum fe_modulation m, enum fe_code_rate f)
 403 {
 404         int i, ret = -EOPNOTSUPP;
 405 
 406         dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
 407 
 408         for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {
 409                 if ((d == CX24116_MODFEC_MODES[i].delivery_system) &&
 410                         (m == CX24116_MODFEC_MODES[i].modulation) &&
 411                         (f == CX24116_MODFEC_MODES[i].fec)) {
 412                                 ret = i;
 413                                 break;
 414                         }
 415         }
 416 
 417         return ret;
 418 }
 419 
 420 static int cx24116_set_fec(struct cx24116_state *state,
 421                            enum fe_delivery_system delsys,
 422                            enum fe_modulation mod,
 423                            enum fe_code_rate fec)
 424 {
 425         int ret = 0;
 426 
 427         dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
 428 
 429         ret = cx24116_lookup_fecmod(state, delsys, mod, fec);
 430 
 431         if (ret < 0)
 432                 return ret;
 433 
 434         state->dnxt.fec = fec;
 435         state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
 436         state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
 437         dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
 438                 state->dnxt.fec_mask, state->dnxt.fec_val);
 439 
 440         return 0;
 441 }
 442 
 443 static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)
 444 {
 445         dprintk("%s(%d)\n", __func__, rate);
 446 
 447         
 448         if ((rate > state->frontend.ops.info.symbol_rate_max) ||
 449             (rate < state->frontend.ops.info.symbol_rate_min)) {
 450                 dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
 451                 return -EOPNOTSUPP;
 452         }
 453 
 454         state->dnxt.symbol_rate = rate;
 455         dprintk("%s() symbol_rate = %d\n", __func__, rate);
 456 
 457         return 0;
 458 }
 459 
 460 static int cx24116_load_firmware(struct dvb_frontend *fe,
 461         const struct firmware *fw);
 462 
 463 static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
 464 {
 465         struct cx24116_state *state = fe->demodulator_priv;
 466         const struct firmware *fw;
 467         int ret = 0;
 468 
 469         dprintk("%s()\n", __func__);
 470 
 471         if (cx24116_readreg(state, 0x20) > 0) {
 472 
 473                 if (state->skip_fw_load)
 474                         return 0;
 475 
 476                 
 477                 
 478                 printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
 479                         __func__, CX24116_DEFAULT_FIRMWARE);
 480                 ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
 481                         state->i2c->dev.parent);
 482                 printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
 483                         __func__);
 484                 if (ret) {
 485                         printk(KERN_ERR "%s: No firmware uploaded (timeout or file not found?)\n",
 486                                __func__);
 487                         return ret;
 488                 }
 489 
 490                 
 491 
 492                 state->skip_fw_load = 1;
 493 
 494                 ret = cx24116_load_firmware(fe, fw);
 495                 if (ret)
 496                         printk(KERN_ERR "%s: Writing firmware to device failed\n",
 497                                 __func__);
 498 
 499                 release_firmware(fw);
 500 
 501                 printk(KERN_INFO "%s: Firmware upload %s\n", __func__,
 502                         ret == 0 ? "complete" : "failed");
 503 
 504                 
 505                 state->skip_fw_load = 0;
 506         }
 507 
 508         return ret;
 509 }
 510 
 511 
 512 
 513 
 514 static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)
 515 {
 516         struct cx24116_state *state = fe->demodulator_priv;
 517         int i, ret;
 518 
 519         dprintk("%s()\n", __func__);
 520 
 521         
 522         ret = cx24116_firmware_ondemand(fe);
 523         if (ret != 0) {
 524                 printk(KERN_ERR "%s(): Unable initialise the firmware\n",
 525                         __func__);
 526                 return ret;
 527         }
 528 
 529         
 530         for (i = 0; i < cmd->len ; i++) {
 531                 dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
 532                 cx24116_writereg(state, i, cmd->args[i]);
 533         }
 534 
 535         
 536         cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
 537         while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {
 538                 msleep(10);
 539                 if (i++ > 64) {
 540                         
 541 
 542                         printk(KERN_WARNING "%s() Firmware not responding\n",
 543                                 __func__);
 544                         return -EREMOTEIO;
 545                 }
 546         }
 547         return 0;
 548 }
 549 
 550 static int cx24116_load_firmware(struct dvb_frontend *fe,
 551         const struct firmware *fw)
 552 {
 553         struct cx24116_state *state = fe->demodulator_priv;
 554         struct cx24116_cmd cmd;
 555         int i, ret, len, max, remaining;
 556         unsigned char vers[4];
 557 
 558         dprintk("%s\n", __func__);
 559         dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
 560                         fw->size,
 561                         fw->data[0],
 562                         fw->data[1],
 563                         fw->data[fw->size-2],
 564                         fw->data[fw->size-1]);
 565 
 566         
 567         if (state->config->reset_device)
 568                 state->config->reset_device(fe);
 569 
 570         
 571         
 572 
 573         
 574         cx24116_writereg(state, 0xE5, 0x00);
 575         cx24116_writereg(state, 0xF1, 0x08);
 576         cx24116_writereg(state, 0xF2, 0x13);
 577 
 578         
 579         cx24116_writereg(state, 0xe0, 0x03);
 580         cx24116_writereg(state, 0xe0, 0x00);
 581 
 582         
 583         cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
 584         cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
 585 
 586         
 587         cx24116_writereg(state, 0xF0, 0x03);
 588         cx24116_writereg(state, 0xF4, 0x81);
 589         cx24116_writereg(state, 0xF5, 0x00);
 590         cx24116_writereg(state, 0xF6, 0x00);
 591 
 592         
 593 
 594         if (state->config->i2c_wr_max)
 595                 max = state->config->i2c_wr_max;
 596         else
 597                 max = INT_MAX; 
 598 
 599         for (remaining = fw->size; remaining > 0; remaining -= max - 1) {
 600                 len = remaining;
 601                 if (len > max - 1)
 602                         len = max - 1;
 603 
 604                 cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],
 605                         len);
 606         }
 607 
 608         cx24116_writereg(state, 0xF4, 0x10);
 609         cx24116_writereg(state, 0xF0, 0x00);
 610         cx24116_writereg(state, 0xF8, 0x06);
 611 
 612         
 613         cmd.args[0x00] = CMD_SET_VCO;
 614         cmd.args[0x01] = 0x05;
 615         cmd.args[0x02] = 0xdc;
 616         cmd.args[0x03] = 0xda;
 617         cmd.args[0x04] = 0xae;
 618         cmd.args[0x05] = 0xaa;
 619         cmd.args[0x06] = 0x04;
 620         cmd.args[0x07] = 0x9d;
 621         cmd.args[0x08] = 0xfc;
 622         cmd.args[0x09] = 0x06;
 623         cmd.len = 0x0a;
 624         ret = cx24116_cmd_execute(fe, &cmd);
 625         if (ret != 0)
 626                 return ret;
 627 
 628         cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
 629 
 630         
 631         cmd.args[0x00] = CMD_TUNERINIT;
 632         cmd.args[0x01] = 0x00;
 633         cmd.args[0x02] = 0x00;
 634         cmd.len = 0x03;
 635         ret = cx24116_cmd_execute(fe, &cmd);
 636         if (ret != 0)
 637                 return ret;
 638 
 639         cx24116_writereg(state, 0xe5, 0x00);
 640 
 641         
 642         cmd.args[0x00] = CMD_MPEGCONFIG;
 643         cmd.args[0x01] = 0x01;
 644         cmd.args[0x02] = 0x75;
 645         cmd.args[0x03] = 0x00;
 646         if (state->config->mpg_clk_pos_pol)
 647                 cmd.args[0x04] = state->config->mpg_clk_pos_pol;
 648         else
 649                 cmd.args[0x04] = 0x02;
 650         cmd.args[0x05] = 0x00;
 651         cmd.len = 0x06;
 652         ret = cx24116_cmd_execute(fe, &cmd);
 653         if (ret != 0)
 654                 return ret;
 655 
 656         
 657         cmd.args[0x00] = CMD_UPDFWVERS;
 658         cmd.len = 0x02;
 659         for (i = 0; i < 4; i++) {
 660                 cmd.args[0x01] = i;
 661                 ret = cx24116_cmd_execute(fe, &cmd);
 662                 if (ret != 0)
 663                         return ret;
 664                 vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
 665         }
 666         printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
 667                 vers[0], vers[1], vers[2], vers[3]);
 668 
 669         return 0;
 670 }
 671 
 672 static int cx24116_read_status(struct dvb_frontend *fe, enum fe_status *status)
 673 {
 674         struct cx24116_state *state = fe->demodulator_priv;
 675 
 676         int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) &
 677                 CX24116_STATUS_MASK;
 678 
 679         dprintk("%s: status = 0x%02x\n", __func__, lock);
 680 
 681         *status = 0;
 682 
 683         if (lock & CX24116_HAS_SIGNAL)
 684                 *status |= FE_HAS_SIGNAL;
 685         if (lock & CX24116_HAS_CARRIER)
 686                 *status |= FE_HAS_CARRIER;
 687         if (lock & CX24116_HAS_VITERBI)
 688                 *status |= FE_HAS_VITERBI;
 689         if (lock & CX24116_HAS_SYNCLOCK)
 690                 *status |= FE_HAS_SYNC | FE_HAS_LOCK;
 691 
 692         return 0;
 693 }
 694 
 695 static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
 696 {
 697         struct cx24116_state *state = fe->demodulator_priv;
 698 
 699         dprintk("%s()\n", __func__);
 700 
 701         *ber =  (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
 702                 (cx24116_readreg(state, CX24116_REG_BER16) << 16) |
 703                 (cx24116_readreg(state, CX24116_REG_BER8)  << 8)  |
 704                  cx24116_readreg(state, CX24116_REG_BER0);
 705 
 706         return 0;
 707 }
 708 
 709 
 710 static int cx24116_read_signal_strength(struct dvb_frontend *fe,
 711         u16 *signal_strength)
 712 {
 713         struct cx24116_state *state = fe->demodulator_priv;
 714         struct cx24116_cmd cmd;
 715         int ret;
 716         u16 sig_reading;
 717 
 718         dprintk("%s()\n", __func__);
 719 
 720         
 721         cmd.args[0x00] = CMD_GETAGC;
 722         cmd.len = 0x01;
 723         ret = cx24116_cmd_execute(fe, &cmd);
 724         if (ret != 0)
 725                 return ret;
 726 
 727         sig_reading =
 728                 (cx24116_readreg(state,
 729                         CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
 730                 (cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
 731         *signal_strength = 0 - sig_reading;
 732 
 733         dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
 734                 __func__, sig_reading, *signal_strength);
 735 
 736         return 0;
 737 }
 738 
 739 
 740 static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
 741 {
 742         struct cx24116_state *state = fe->demodulator_priv;
 743         u8 snr_reading;
 744         static const u32 snr_tab[] = { 
 745                 0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
 746                 0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
 747                 0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
 748                 0x18000 };
 749 
 750         dprintk("%s()\n", __func__);
 751 
 752         snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
 753 
 754         if (snr_reading >= 0xa0 )
 755                 *snr = 0xffff;
 756         else
 757                 *snr = snr_tab[(snr_reading & 0xf0) >> 4] +
 758                         (snr_tab[(snr_reading & 0x0f)] >> 4);
 759 
 760         dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
 761                 snr_reading, *snr);
 762 
 763         return 0;
 764 }
 765 
 766 
 767 
 768 
 769 
 770 static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
 771 {
 772         struct cx24116_state *state = fe->demodulator_priv;
 773 
 774         dprintk("%s()\n", __func__);
 775 
 776         *snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
 777                 cx24116_readreg(state, CX24116_REG_QUALITY0);
 778 
 779         dprintk("%s: raw 0x%04x\n", __func__, *snr);
 780 
 781         return 0;
 782 }
 783 
 784 static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
 785 {
 786         if (esno_snr == 1)
 787                 return cx24116_read_snr_esno(fe, snr);
 788         else
 789                 return cx24116_read_snr_pct(fe, snr);
 790 }
 791 
 792 static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 793 {
 794         struct cx24116_state *state = fe->demodulator_priv;
 795 
 796         dprintk("%s()\n", __func__);
 797 
 798         *ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
 799                 cx24116_readreg(state, CX24116_REG_UCB0);
 800 
 801         return 0;
 802 }
 803 
 804 
 805 static void cx24116_clone_params(struct dvb_frontend *fe)
 806 {
 807         struct cx24116_state *state = fe->demodulator_priv;
 808         state->dcur = state->dnxt;
 809 }
 810 
 811 
 812 static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
 813 {
 814         struct cx24116_state *state = fe->demodulator_priv;
 815         int i;
 816 
 817         dprintk("%s() qstatus = 0x%02x\n", __func__,
 818                 cx24116_readreg(state, CX24116_REG_QSTATUS));
 819 
 820         
 821         for (i = 0; i < 30 ; i++) {
 822                 if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
 823                         return 0;
 824                 msleep(10);
 825         }
 826 
 827         dprintk("%s(): LNB not ready\n", __func__);
 828 
 829         return -ETIMEDOUT; 
 830 }
 831 
 832 static int cx24116_set_voltage(struct dvb_frontend *fe,
 833         enum fe_sec_voltage voltage)
 834 {
 835         struct cx24116_cmd cmd;
 836         int ret;
 837 
 838         dprintk("%s: %s\n", __func__,
 839                 voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
 840                 voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
 841 
 842         
 843         ret = cx24116_wait_for_lnb(fe);
 844         if (ret != 0)
 845                 return ret;
 846 
 847         
 848         msleep(100);
 849 
 850         cmd.args[0x00] = CMD_LNBDCLEVEL;
 851         cmd.args[0x01] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);
 852         cmd.len = 0x02;
 853 
 854         
 855         msleep(15);
 856 
 857         return cx24116_cmd_execute(fe, &cmd);
 858 }
 859 
 860 static int cx24116_set_tone(struct dvb_frontend *fe,
 861         enum fe_sec_tone_mode tone)
 862 {
 863         struct cx24116_cmd cmd;
 864         int ret;
 865 
 866         dprintk("%s(%d)\n", __func__, tone);
 867         if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
 868                 printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
 869                 return -EINVAL;
 870         }
 871 
 872         
 873         ret = cx24116_wait_for_lnb(fe);
 874         if (ret != 0)
 875                 return ret;
 876 
 877         
 878         msleep(15); 
 879 
 880         
 881         cmd.args[0x00] = CMD_SET_TONE;
 882         cmd.args[0x01] = 0x00;
 883         cmd.args[0x02] = 0x00;
 884 
 885         switch (tone) {
 886         case SEC_TONE_ON:
 887                 dprintk("%s: setting tone on\n", __func__);
 888                 cmd.args[0x03] = 0x01;
 889                 break;
 890         case SEC_TONE_OFF:
 891                 dprintk("%s: setting tone off\n", __func__);
 892                 cmd.args[0x03] = 0x00;
 893                 break;
 894         }
 895         cmd.len = 0x04;
 896 
 897         
 898         msleep(15); 
 899 
 900         return cx24116_cmd_execute(fe, &cmd);
 901 }
 902 
 903 
 904 static int cx24116_diseqc_init(struct dvb_frontend *fe)
 905 {
 906         struct cx24116_state *state = fe->demodulator_priv;
 907         struct cx24116_cmd cmd;
 908         int ret;
 909 
 910         
 911         cmd.args[0x00] = CMD_LNBCONFIG;
 912         cmd.args[0x01] = 0x00;
 913         cmd.args[0x02] = 0x10;
 914         cmd.args[0x03] = 0x00;
 915         cmd.args[0x04] = 0x8f;
 916         cmd.args[0x05] = 0x28;
 917         cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
 918         cmd.args[0x07] = 0x01;
 919         cmd.len = 0x08;
 920         ret = cx24116_cmd_execute(fe, &cmd);
 921         if (ret != 0)
 922                 return ret;
 923 
 924         
 925         state->dsec_cmd.args[0x00] = CMD_LNBSEND;
 926 
 927         
 928         state->dsec_cmd.args[CX24116_DISEQC_BURST]  = CX24116_DISEQC_MINI_A;
 929 
 930         
 931         state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
 932         state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
 933         
 934         state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
 935 
 936         
 937         state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
 938 
 939         
 940         state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
 941 
 942         return 0;
 943 }
 944 
 945 
 946 static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
 947         struct dvb_diseqc_master_cmd *d)
 948 {
 949         struct cx24116_state *state = fe->demodulator_priv;
 950         int i, ret;
 951 
 952         
 953         if (d->msg_len > sizeof(d->msg))
 954                 return -EINVAL;
 955 
 956         
 957         if (debug) {
 958                 printk(KERN_INFO "cx24116: %s(", __func__);
 959                 for (i = 0 ; i < d->msg_len ;) {
 960                         printk(KERN_INFO "0x%02x", d->msg[i]);
 961                         if (++i < d->msg_len)
 962                                 printk(KERN_INFO ", ");
 963                 }
 964                 printk(") toneburst=%d\n", toneburst);
 965         }
 966 
 967         
 968         for (i = 0; i < d->msg_len; i++)
 969                 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
 970 
 971         
 972         state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
 973 
 974         
 975         state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
 976                 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
 977 
 978         
 979         if (toneburst == CX24116_DISEQC_MESGCACHE)
 980                 
 981                 return 0;
 982 
 983         else if (toneburst == CX24116_DISEQC_TONEOFF)
 984                 
 985                 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
 986 
 987         else if (toneburst == CX24116_DISEQC_TONECACHE) {
 988                 
 989 
 990 
 991 
 992 
 993 
 994 
 995 
 996 
 997 
 998 
 999 
1000 
1001 
1002 
1003 
1004 
1005 
1006                 if (d->msg_len >= 4 && d->msg[2] == 0x38)
1007                         state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1008                                 ((d->msg[3] & 4) >> 2);
1009                 if (debug)
1010                         dprintk("%s burst=%d\n", __func__,
1011                                 state->dsec_cmd.args[CX24116_DISEQC_BURST]);
1012         }
1013 
1014         
1015         ret = cx24116_wait_for_lnb(fe);
1016         if (ret != 0)
1017                 return ret;
1018 
1019         
1020         msleep(100);
1021 
1022         
1023         ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1024         if (ret != 0)
1025                 return ret;
1026         
1027 
1028 
1029 
1030 
1031 
1032 
1033 
1034 
1035 
1036         msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
1037                 ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
1038 
1039         return 0;
1040 }
1041 
1042 
1043 static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
1044         enum fe_sec_mini_cmd burst)
1045 {
1046         struct cx24116_state *state = fe->demodulator_priv;
1047         int ret;
1048 
1049         dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
1050 
1051         
1052         if (burst == SEC_MINI_A)
1053                 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1054                         CX24116_DISEQC_MINI_A;
1055         else if (burst == SEC_MINI_B)
1056                 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1057                         CX24116_DISEQC_MINI_B;
1058         else
1059                 return -EINVAL;
1060 
1061         
1062         if (toneburst != CX24116_DISEQC_MESGCACHE)
1063                 
1064                 return 0;
1065 
1066         
1067 
1068         
1069         ret = cx24116_wait_for_lnb(fe);
1070         if (ret != 0)
1071                 return ret;
1072 
1073         
1074         msleep(100);
1075 
1076         
1077         ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1078         if (ret != 0)
1079                 return ret;
1080 
1081         
1082 
1083 
1084 
1085 
1086 
1087 
1088 
1089 
1090 
1091         msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
1092 
1093         return 0;
1094 }
1095 
1096 static void cx24116_release(struct dvb_frontend *fe)
1097 {
1098         struct cx24116_state *state = fe->demodulator_priv;
1099         dprintk("%s\n", __func__);
1100         kfree(state);
1101 }
1102 
1103 static const struct dvb_frontend_ops cx24116_ops;
1104 
1105 struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
1106         struct i2c_adapter *i2c)
1107 {
1108         struct cx24116_state *state;
1109         int ret;
1110 
1111         dprintk("%s\n", __func__);
1112 
1113         
1114         state = kzalloc(sizeof(*state), GFP_KERNEL);
1115         if (state == NULL)
1116                 return NULL;
1117 
1118         state->config = config;
1119         state->i2c = i2c;
1120 
1121         
1122         ret = (cx24116_readreg(state, 0xFF) << 8) |
1123                 cx24116_readreg(state, 0xFE);
1124         if (ret != 0x0501) {
1125                 kfree(state);
1126                 printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
1127                 return NULL;
1128         }
1129 
1130         
1131         memcpy(&state->frontend.ops, &cx24116_ops,
1132                 sizeof(struct dvb_frontend_ops));
1133         state->frontend.demodulator_priv = state;
1134         return &state->frontend;
1135 }
1136 EXPORT_SYMBOL(cx24116_attach);
1137 
1138 
1139 
1140 
1141 
1142 
1143 static int cx24116_initfe(struct dvb_frontend *fe)
1144 {
1145         struct cx24116_state *state = fe->demodulator_priv;
1146         struct cx24116_cmd cmd;
1147         int ret;
1148 
1149         dprintk("%s()\n", __func__);
1150 
1151         
1152         cx24116_writereg(state, 0xe0, 0);
1153         cx24116_writereg(state, 0xe1, 0);
1154         cx24116_writereg(state, 0xea, 0);
1155 
1156         
1157         cmd.args[0x00] = CMD_TUNERSLEEP;
1158         cmd.args[0x01] = 0;
1159         cmd.len = 0x02;
1160         ret = cx24116_cmd_execute(fe, &cmd);
1161         if (ret != 0)
1162                 return ret;
1163 
1164         ret = cx24116_diseqc_init(fe);
1165         if (ret != 0)
1166                 return ret;
1167 
1168         
1169         return cx24116_set_voltage(fe, SEC_VOLTAGE_13);
1170 }
1171 
1172 
1173 
1174 
1175 static int cx24116_sleep(struct dvb_frontend *fe)
1176 {
1177         struct cx24116_state *state = fe->demodulator_priv;
1178         struct cx24116_cmd cmd;
1179         int ret;
1180 
1181         dprintk("%s()\n", __func__);
1182 
1183         
1184         cmd.args[0x00] = CMD_TUNERSLEEP;
1185         cmd.args[0x01] = 1;
1186         cmd.len = 0x02;
1187         ret = cx24116_cmd_execute(fe, &cmd);
1188         if (ret != 0)
1189                 return ret;
1190 
1191         
1192         cx24116_writereg(state, 0xea, 0xff);
1193         cx24116_writereg(state, 0xe1, 1);
1194         cx24116_writereg(state, 0xe0, 1);
1195 
1196         return 0;
1197 }
1198 
1199 
1200 
1201 
1202 static int cx24116_set_frontend(struct dvb_frontend *fe)
1203 {
1204         struct cx24116_state *state = fe->demodulator_priv;
1205         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1206         struct cx24116_cmd cmd;
1207         enum fe_status tunerstat;
1208         int i, status, ret, retune = 1;
1209 
1210         dprintk("%s()\n", __func__);
1211 
1212         switch (c->delivery_system) {
1213         case SYS_DVBS:
1214                 dprintk("%s: DVB-S delivery system selected\n", __func__);
1215 
1216                 
1217                 if (c->modulation != QPSK) {
1218                         dprintk("%s: unsupported modulation selected (%d)\n",
1219                                 __func__, c->modulation);
1220                         return -EOPNOTSUPP;
1221                 }
1222 
1223                 
1224                 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1225 
1226                 
1227                 if (c->rolloff != ROLLOFF_35) {
1228                         dprintk("%s: unsupported rolloff selected (%d)\n",
1229                                 __func__, c->rolloff);
1230                         return -EOPNOTSUPP;
1231                 }
1232                 state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
1233                 break;
1234 
1235         case SYS_DVBS2:
1236                 dprintk("%s: DVB-S2 delivery system selected\n", __func__);
1237 
1238                 
1239 
1240 
1241 
1242                 if (c->modulation != PSK_8 && c->modulation != QPSK) {
1243                         dprintk("%s: unsupported modulation selected (%d)\n",
1244                                 __func__, c->modulation);
1245                         return -EOPNOTSUPP;
1246                 }
1247 
1248                 switch (c->pilot) {
1249                 case PILOT_AUTO:        
1250                         state->dnxt.pilot_val = (c->modulation == QPSK)
1251                                 ? CX24116_PILOT_OFF : CX24116_PILOT_ON;
1252                         retune++;
1253                         break;
1254                 case PILOT_OFF:
1255                         state->dnxt.pilot_val = CX24116_PILOT_OFF;
1256                         break;
1257                 case PILOT_ON:
1258                         state->dnxt.pilot_val = CX24116_PILOT_ON;
1259                         break;
1260                 default:
1261                         dprintk("%s: unsupported pilot mode selected (%d)\n",
1262                                 __func__, c->pilot);
1263                         return -EOPNOTSUPP;
1264                 }
1265 
1266                 switch (c->rolloff) {
1267                 case ROLLOFF_20:
1268                         state->dnxt.rolloff_val = CX24116_ROLLOFF_020;
1269                         break;
1270                 case ROLLOFF_25:
1271                         state->dnxt.rolloff_val = CX24116_ROLLOFF_025;
1272                         break;
1273                 case ROLLOFF_35:
1274                         state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
1275                         break;
1276                 case ROLLOFF_AUTO:      
1277                 default:
1278                         dprintk("%s: unsupported rolloff selected (%d)\n",
1279                                 __func__, c->rolloff);
1280                         return -EOPNOTSUPP;
1281                 }
1282                 break;
1283 
1284         default:
1285                 dprintk("%s: unsupported delivery system selected (%d)\n",
1286                         __func__, c->delivery_system);
1287                 return -EOPNOTSUPP;
1288         }
1289         state->dnxt.delsys = c->delivery_system;
1290         state->dnxt.modulation = c->modulation;
1291         state->dnxt.frequency = c->frequency;
1292         state->dnxt.pilot = c->pilot;
1293         state->dnxt.rolloff = c->rolloff;
1294 
1295         ret = cx24116_set_inversion(state, c->inversion);
1296         if (ret !=  0)
1297                 return ret;
1298 
1299         
1300         ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner);
1301         if (ret !=  0)
1302                 return ret;
1303 
1304         ret = cx24116_set_symbolrate(state, c->symbol_rate);
1305         if (ret !=  0)
1306                 return ret;
1307 
1308         
1309         cx24116_clone_params(fe);
1310 
1311         dprintk("%s:   delsys      = %d\n", __func__, state->dcur.delsys);
1312         dprintk("%s:   modulation  = %d\n", __func__, state->dcur.modulation);
1313         dprintk("%s:   frequency   = %d\n", __func__, state->dcur.frequency);
1314         dprintk("%s:   pilot       = %d (val = 0x%02x)\n", __func__,
1315                 state->dcur.pilot, state->dcur.pilot_val);
1316         dprintk("%s:   retune      = %d\n", __func__, retune);
1317         dprintk("%s:   rolloff     = %d (val = 0x%02x)\n", __func__,
1318                 state->dcur.rolloff, state->dcur.rolloff_val);
1319         dprintk("%s:   symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
1320         dprintk("%s:   FEC         = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
1321                 state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
1322         dprintk("%s:   Inversion   = %d (val = 0x%02x)\n", __func__,
1323                 state->dcur.inversion, state->dcur.inversion_val);
1324 
1325         
1326         if (state->config->set_ts_params)
1327                 state->config->set_ts_params(fe, 0);
1328 
1329         
1330         cmd.args[0x00] = CMD_BANDWIDTH;
1331         cmd.args[0x01] = 0x01;
1332         cmd.len = 0x02;
1333         ret = cx24116_cmd_execute(fe, &cmd);
1334         if (ret != 0)
1335                 return ret;
1336 
1337         
1338         cmd.args[0x00] = CMD_TUNEREQUEST;
1339 
1340         
1341         cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
1342         cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
1343         cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
1344 
1345         
1346         cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
1347         cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
1348 
1349         
1350         cmd.args[0x06] = state->dcur.inversion_val;
1351 
1352         
1353         cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
1354 
1355         cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
1356         cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
1357         cmd.args[0x0a] = 0x00;
1358         cmd.args[0x0b] = 0x00;
1359         cmd.args[0x0c] = state->dcur.rolloff_val;
1360         cmd.args[0x0d] = state->dcur.fec_mask;
1361 
1362         if (state->dcur.symbol_rate > 30000000) {
1363                 cmd.args[0x0e] = 0x04;
1364                 cmd.args[0x0f] = 0x00;
1365                 cmd.args[0x10] = 0x01;
1366                 cmd.args[0x11] = 0x77;
1367                 cmd.args[0x12] = 0x36;
1368                 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
1369                 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
1370         } else {
1371                 cmd.args[0x0e] = 0x06;
1372                 cmd.args[0x0f] = 0x00;
1373                 cmd.args[0x10] = 0x00;
1374                 cmd.args[0x11] = 0xFA;
1375                 cmd.args[0x12] = 0x24;
1376                 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
1377                 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
1378         }
1379 
1380         cmd.len = 0x13;
1381 
1382         
1383 
1384 
1385 
1386         do {
1387                 
1388                 status = cx24116_readreg(state, CX24116_REG_SSTATUS)
1389                         & CX24116_SIGNAL_MASK;
1390                 cx24116_writereg(state, CX24116_REG_SSTATUS, status);
1391 
1392                 
1393                 ret = cx24116_cmd_execute(fe, &cmd);
1394                 if (ret != 0)
1395                         break;
1396 
1397                 
1398 
1399 
1400 
1401 
1402 
1403                 for (i = 0; i < 50 ; i++) {
1404                         cx24116_read_status(fe, &tunerstat);
1405                         status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
1406                         if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
1407                                 dprintk("%s: Tuned\n", __func__);
1408                                 goto tuned;
1409                         }
1410                         msleep(10);
1411                 }
1412 
1413                 dprintk("%s: Not tuned\n", __func__);
1414 
1415                 
1416                 if (state->dcur.pilot == PILOT_AUTO)
1417                         cmd.args[0x07] ^= CX24116_PILOT_ON;
1418         } while (--retune);
1419 
1420 tuned:  
1421         cmd.args[0x00] = CMD_BANDWIDTH;
1422         cmd.args[0x01] = 0x00;
1423         cmd.len = 0x02;
1424         return cx24116_cmd_execute(fe, &cmd);
1425 }
1426 
1427 static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,
1428         unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
1429 {
1430         
1431 
1432 
1433 
1434 
1435 
1436 
1437 
1438         *delay = HZ / 5;
1439         if (re_tune) {
1440                 int ret = cx24116_set_frontend(fe);
1441                 if (ret)
1442                         return ret;
1443         }
1444         return cx24116_read_status(fe, status);
1445 }
1446 
1447 static enum dvbfe_algo cx24116_get_algo(struct dvb_frontend *fe)
1448 {
1449         return DVBFE_ALGO_HW;
1450 }
1451 
1452 static const struct dvb_frontend_ops cx24116_ops = {
1453         .delsys = { SYS_DVBS, SYS_DVBS2 },
1454         .info = {
1455                 .name = "Conexant CX24116/CX24118",
1456                 .frequency_min_hz = 950 * MHz,
1457                 .frequency_max_hz = 2150 * MHz,
1458                 .frequency_stepsize_hz = 1011 * kHz,
1459                 .frequency_tolerance_hz = 5 * MHz,
1460                 .symbol_rate_min = 1000000,
1461                 .symbol_rate_max = 45000000,
1462                 .caps = FE_CAN_INVERSION_AUTO |
1463                         FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1464                         FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
1465                         FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1466                         FE_CAN_2G_MODULATION |
1467                         FE_CAN_QPSK | FE_CAN_RECOVER
1468         },
1469 
1470         .release = cx24116_release,
1471 
1472         .init = cx24116_initfe,
1473         .sleep = cx24116_sleep,
1474         .read_status = cx24116_read_status,
1475         .read_ber = cx24116_read_ber,
1476         .read_signal_strength = cx24116_read_signal_strength,
1477         .read_snr = cx24116_read_snr,
1478         .read_ucblocks = cx24116_read_ucblocks,
1479         .set_tone = cx24116_set_tone,
1480         .set_voltage = cx24116_set_voltage,
1481         .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
1482         .diseqc_send_burst = cx24116_diseqc_send_burst,
1483         .get_frontend_algo = cx24116_get_algo,
1484         .tune = cx24116_tune,
1485 
1486         .set_frontend = cx24116_set_frontend,
1487 };
1488 
1489 MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
1490 MODULE_AUTHOR("Steven Toth");
1491 MODULE_LICENSE("GPL");
1492