Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003     cx24110 - Single Chip Satellite Channel Receiver driver module
0004 
0005     Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
0006     work
0007     Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
0008 
0009 
0010 */
0011 
0012 #include <linux/slab.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/init.h>
0016 
0017 #include <media/dvb_frontend.h>
0018 #include "cx24110.h"
0019 
0020 
0021 struct cx24110_state {
0022 
0023     struct i2c_adapter* i2c;
0024 
0025     const struct cx24110_config* config;
0026 
0027     struct dvb_frontend frontend;
0028 
0029     u32 lastber;
0030     u32 lastbler;
0031     u32 lastesn0;
0032 };
0033 
0034 static int debug;
0035 #define dprintk(args...) \
0036     do { \
0037         if (debug) printk(KERN_DEBUG "cx24110: " args); \
0038     } while (0)
0039 
0040 static struct {u8 reg; u8 data;} cx24110_regdata[]=
0041               /* Comments beginning with @ denote this value should
0042              be the default */
0043     {{0x09,0x01}, /* SoftResetAll */
0044      {0x09,0x00}, /* release reset */
0045      {0x01,0xe8}, /* MSB of code rate 27.5MS/s */
0046      {0x02,0x17}, /* middle byte " */
0047      {0x03,0x29}, /* LSB         " */
0048      {0x05,0x03}, /* @ DVB mode, standard code rate 3/4 */
0049      {0x06,0xa5}, /* @ PLL 60MHz */
0050      {0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */
0051      {0x0a,0x00}, /* @ partial chip disables, do not set */
0052      {0x0b,0x01}, /* set output clock in gapped mode, start signal low
0053              active for first byte */
0054      {0x0c,0x11}, /* no parity bytes, large hold time, serial data out */
0055      {0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */
0056      {0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1
0057              to avoid starting the BER counter. Reset the
0058              CRC test bit. Finite counting selected */
0059      {0x15,0xff}, /* @ size of the limited time window for RS BER
0060              estimation. It is <value>*256 RS blocks, this
0061              gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
0062      {0x16,0x00}, /* @ enable all RS output ports */
0063      {0x17,0x04}, /* @ time window allowed for the RS to sync */
0064      {0x18,0xae}, /* @ allow all standard DVB code rates to be scanned
0065              for automatically */
0066               /* leave the current code rate and normalization
0067              registers as they are after reset... */
0068      {0x21,0x10}, /* @ during AutoAcq, search each viterbi setting
0069              only once */
0070      {0x23,0x18}, /* @ size of the limited time window for Viterbi BER
0071              estimation. It is <value>*65536 channel bits, i.e.
0072              approx. 38ms at 27.5MS/s, rate 3/4 */
0073      {0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */
0074               /* leave front-end AGC parameters at default values */
0075               /* leave decimation AGC parameters at default values */
0076      {0x35,0x40}, /* disable all interrupts. They are not connected anyway */
0077      {0x36,0xff}, /* clear all interrupt pending flags */
0078      {0x37,0x00}, /* @ fully enable AutoAcqq state machine */
0079      {0x38,0x07}, /* @ enable fade recovery, but not autostart AutoAcq */
0080               /* leave the equalizer parameters on their default values */
0081               /* leave the final AGC parameters on their default values */
0082      {0x41,0x00}, /* @ MSB of front-end derotator frequency */
0083      {0x42,0x00}, /* @ middle bytes " */
0084      {0x43,0x00}, /* @ LSB          " */
0085               /* leave the carrier tracking loop parameters on default */
0086               /* leave the bit timing loop parameters at default */
0087      {0x56,0x4d}, /* set the filtune voltage to 2.7V, as recommended by */
0088               /* the cx24108 data sheet for symbol rates above 15MS/s */
0089      {0x57,0x00}, /* @ Filter sigma delta enabled, positive */
0090      {0x61,0x95}, /* GPIO pins 1-4 have special function */
0091      {0x62,0x05}, /* GPIO pin 5 has special function, pin 6 is GPIO */
0092      {0x63,0x00}, /* All GPIO pins use CMOS output characteristics */
0093      {0x64,0x20}, /* GPIO 6 is input, all others are outputs */
0094      {0x6d,0x30}, /* tuner auto mode clock freq 62kHz */
0095      {0x70,0x15}, /* use auto mode, tuner word is 21 bits long */
0096      {0x73,0x00}, /* @ disable several demod bypasses */
0097      {0x74,0x00}, /* @  " */
0098      {0x75,0x00}  /* @  " */
0099               /* the remaining registers are for SEC */
0100     };
0101 
0102 
0103 static int cx24110_writereg (struct cx24110_state* state, int reg, int data)
0104 {
0105     u8 buf [] = { reg, data };
0106     struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
0107     int err;
0108 
0109     if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
0110         dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n",
0111             __func__, err, reg, data);
0112         return -EREMOTEIO;
0113     }
0114 
0115     return 0;
0116 }
0117 
0118 static int cx24110_readreg (struct cx24110_state* state, u8 reg)
0119 {
0120     int ret;
0121     u8 b0 [] = { reg };
0122     u8 b1 [] = { 0 };
0123     struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
0124                { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
0125 
0126     ret = i2c_transfer(state->i2c, msg, 2);
0127 
0128     if (ret != 2) return ret;
0129 
0130     return b1[0];
0131 }
0132 
0133 static int cx24110_set_inversion(struct cx24110_state *state,
0134                  enum fe_spectral_inversion inversion)
0135 {
0136 /* fixme (low): error handling */
0137 
0138     switch (inversion) {
0139     case INVERSION_OFF:
0140         cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x1);
0141         /* AcqSpectrInvDis on. No idea why someone should want this */
0142         cx24110_writereg(state,0x5,cx24110_readreg(state,0x5)&0xf7);
0143         /* Initial value 0 at start of acq */
0144         cx24110_writereg(state,0x22,cx24110_readreg(state,0x22)&0xef);
0145         /* current value 0 */
0146         /* The cx24110 manual tells us this reg is read-only.
0147            But what the heck... set it ayways */
0148         break;
0149     case INVERSION_ON:
0150         cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x1);
0151         /* AcqSpectrInvDis on. No idea why someone should want this */
0152         cx24110_writereg(state,0x5,cx24110_readreg(state,0x5)|0x08);
0153         /* Initial value 1 at start of acq */
0154         cx24110_writereg(state,0x22,cx24110_readreg(state,0x22)|0x10);
0155         /* current value 1 */
0156         break;
0157     case INVERSION_AUTO:
0158         cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)&0xfe);
0159         /* AcqSpectrInvDis off. Leave initial & current states as is */
0160         break;
0161     default:
0162         return -EINVAL;
0163     }
0164 
0165     return 0;
0166 }
0167 
0168 static int cx24110_set_fec(struct cx24110_state *state, enum fe_code_rate fec)
0169 {
0170     static const int rate[FEC_AUTO] = {-1,    1,    2,    3,    5,    7, -1};
0171     static const int g1[FEC_AUTO]   = {-1, 0x01, 0x02, 0x05, 0x15, 0x45, -1};
0172     static const int g2[FEC_AUTO]   = {-1, 0x01, 0x03, 0x06, 0x1a, 0x7a, -1};
0173 
0174     /* Well, the AutoAcq engine of the cx24106 and 24110 automatically
0175        searches all enabled viterbi rates, and can handle non-standard
0176        rates as well. */
0177 
0178     if (fec > FEC_AUTO)
0179         fec = FEC_AUTO;
0180 
0181     if (fec == FEC_AUTO) { /* (re-)establish AutoAcq behaviour */
0182         cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) & 0xdf);
0183         /* clear AcqVitDis bit */
0184         cx24110_writereg(state, 0x18, 0xae);
0185         /* allow all DVB standard code rates */
0186         cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 0x3);
0187         /* set nominal Viterbi rate 3/4 */
0188         cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 0x3);
0189         /* set current Viterbi rate 3/4 */
0190         cx24110_writereg(state, 0x1a, 0x05);
0191         cx24110_writereg(state, 0x1b, 0x06);
0192         /* set the puncture registers for code rate 3/4 */
0193         return 0;
0194     } else {
0195         cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20);
0196         /* set AcqVitDis bit */
0197         if (rate[fec] < 0)
0198             return -EINVAL;
0199 
0200         cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | rate[fec]);
0201         /* set nominal Viterbi rate */
0202         cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | rate[fec]);
0203         /* set current Viterbi rate */
0204         cx24110_writereg(state, 0x1a, g1[fec]);
0205         cx24110_writereg(state, 0x1b, g2[fec]);
0206         /* not sure if this is the right way: I always used AutoAcq mode */
0207     }
0208     return 0;
0209 }
0210 
0211 static enum fe_code_rate cx24110_get_fec(struct cx24110_state *state)
0212 {
0213     int i;
0214 
0215     i=cx24110_readreg(state,0x22)&0x0f;
0216     if(!(i&0x08)) {
0217         return FEC_1_2 + i - 1;
0218     } else {
0219 /* fixme (low): a special code rate has been selected. In theory, we need to
0220    return a denominator value, a numerator value, and a pair of puncture
0221    maps to correctly describe this mode. But this should never happen in
0222    practice, because it cannot be set by cx24110_get_fec. */
0223        return FEC_NONE;
0224     }
0225 }
0226 
0227 static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
0228 {
0229 /* fixme (low): add error handling */
0230     u32 ratio;
0231     u32 tmp, fclk, BDRI;
0232 
0233     static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
0234     int i;
0235 
0236     dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate);
0237     if (srate>90999000UL/2)
0238         srate=90999000UL/2;
0239     if (srate<500000)
0240         srate=500000;
0241 
0242     for(i = 0; (i < ARRAY_SIZE(bands)) && (srate>bands[i]); i++)
0243         ;
0244     /* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz,
0245        and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult,
0246        R06[3:0] PLLphaseDetGain */
0247     tmp=cx24110_readreg(state,0x07)&0xfc;
0248     if(srate<90999000UL/4) { /* sample rate 45MHz*/
0249         cx24110_writereg(state,0x07,tmp);
0250         cx24110_writereg(state,0x06,0x78);
0251         fclk=90999000UL/2;
0252     } else if(srate<60666000UL/2) { /* sample rate 60MHz */
0253         cx24110_writereg(state,0x07,tmp|0x1);
0254         cx24110_writereg(state,0x06,0xa5);
0255         fclk=60666000UL;
0256     } else if(srate<80888000UL/2) { /* sample rate 80MHz */
0257         cx24110_writereg(state,0x07,tmp|0x2);
0258         cx24110_writereg(state,0x06,0x87);
0259         fclk=80888000UL;
0260     } else { /* sample rate 90MHz */
0261         cx24110_writereg(state,0x07,tmp|0x3);
0262         cx24110_writereg(state,0x06,0x78);
0263         fclk=90999000UL;
0264     }
0265     dprintk("cx24110 debug: fclk %d Hz\n",fclk);
0266     /* we need to divide two integers with approx. 27 bits in 32 bit
0267        arithmetic giving a 25 bit result */
0268     /* the maximum dividend is 90999000/2, 0x02b6446c, this number is
0269        also the most complex divisor. Hence, the dividend has,
0270        assuming 32bit unsigned arithmetic, 6 clear bits on top, the
0271        divisor 2 unused bits at the bottom. Also, the quotient is
0272        always less than 1/2. Borrowed from VES1893.c, of course */
0273 
0274     tmp=srate<<6;
0275     BDRI=fclk>>2;
0276     ratio=(tmp/BDRI);
0277 
0278     tmp=(tmp%BDRI)<<8;
0279     ratio=(ratio<<8)+(tmp/BDRI);
0280 
0281     tmp=(tmp%BDRI)<<8;
0282     ratio=(ratio<<8)+(tmp/BDRI);
0283 
0284     tmp=(tmp%BDRI)<<1;
0285     ratio=(ratio<<1)+(tmp/BDRI);
0286 
0287     dprintk("srate= %d (range %d, up to %d)\n", srate,i,bands[i]);
0288     dprintk("fclk = %d\n", fclk);
0289     dprintk("ratio= %08x\n", ratio);
0290 
0291     cx24110_writereg(state, 0x1, (ratio>>16)&0xff);
0292     cx24110_writereg(state, 0x2, (ratio>>8)&0xff);
0293     cx24110_writereg(state, 0x3, (ratio)&0xff);
0294 
0295     return 0;
0296 
0297 }
0298 
0299 static int _cx24110_pll_write (struct dvb_frontend* fe, const u8 buf[], int len)
0300 {
0301     struct cx24110_state *state = fe->demodulator_priv;
0302 
0303     if (len != 3)
0304         return -EINVAL;
0305 
0306 /* tuner data is 21 bits long, must be left-aligned in data */
0307 /* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */
0308 /* FIXME (low): add error handling, avoid infinite loops if HW fails... */
0309 
0310     cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */
0311     cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */
0312 
0313     /* if the auto tuner writer is still busy, clear it out */
0314     while (cx24110_readreg(state,0x6d)&0x80)
0315         cx24110_writereg(state,0x72,0);
0316 
0317     /* write the topmost 8 bits */
0318     cx24110_writereg(state,0x72,buf[0]);
0319 
0320     /* wait for the send to be completed */
0321     while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
0322         ;
0323 
0324     /* send another 8 bytes */
0325     cx24110_writereg(state,0x72,buf[1]);
0326     while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
0327         ;
0328 
0329     /* and the topmost 5 bits of this byte */
0330     cx24110_writereg(state,0x72,buf[2]);
0331     while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
0332         ;
0333 
0334     /* now strobe the enable line once */
0335     cx24110_writereg(state,0x6d,0x32);
0336     cx24110_writereg(state,0x6d,0x30);
0337 
0338     return 0;
0339 }
0340 
0341 static int cx24110_initfe(struct dvb_frontend* fe)
0342 {
0343     struct cx24110_state *state = fe->demodulator_priv;
0344 /* fixme (low): error handling */
0345     int i;
0346 
0347     dprintk("%s: init chip\n", __func__);
0348 
0349     for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
0350         cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
0351     }
0352 
0353     return 0;
0354 }
0355 
0356 static int cx24110_set_voltage(struct dvb_frontend *fe,
0357                    enum fe_sec_voltage voltage)
0358 {
0359     struct cx24110_state *state = fe->demodulator_priv;
0360 
0361     switch (voltage) {
0362     case SEC_VOLTAGE_13:
0363         return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0xc0);
0364     case SEC_VOLTAGE_18:
0365         return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0x40);
0366     default:
0367         return -EINVAL;
0368     }
0369 }
0370 
0371 static int cx24110_diseqc_send_burst(struct dvb_frontend *fe,
0372                      enum fe_sec_mini_cmd burst)
0373 {
0374     int rv, bit;
0375     struct cx24110_state *state = fe->demodulator_priv;
0376     unsigned long timeout;
0377 
0378     if (burst == SEC_MINI_A)
0379         bit = 0x00;
0380     else if (burst == SEC_MINI_B)
0381         bit = 0x08;
0382     else
0383         return -EINVAL;
0384 
0385     rv = cx24110_readreg(state, 0x77);
0386     if (!(rv & 0x04))
0387         cx24110_writereg(state, 0x77, rv | 0x04);
0388 
0389     rv = cx24110_readreg(state, 0x76);
0390     cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit));
0391     timeout = jiffies + msecs_to_jiffies(100);
0392     while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
0393         ; /* wait for LNB ready */
0394 
0395     return 0;
0396 }
0397 
0398 static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
0399                    struct dvb_diseqc_master_cmd *cmd)
0400 {
0401     int i, rv;
0402     struct cx24110_state *state = fe->demodulator_priv;
0403     unsigned long timeout;
0404 
0405     if (cmd->msg_len < 3 || cmd->msg_len > 6)
0406         return -EINVAL;  /* not implemented */
0407 
0408     for (i = 0; i < cmd->msg_len; i++)
0409         cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
0410 
0411     rv = cx24110_readreg(state, 0x77);
0412     if (rv & 0x04) {
0413         cx24110_writereg(state, 0x77, rv & ~0x04);
0414         msleep(30); /* reportedly fixes switching problems */
0415     }
0416 
0417     rv = cx24110_readreg(state, 0x76);
0418 
0419     cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
0420     timeout = jiffies + msecs_to_jiffies(100);
0421     while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
0422         ; /* wait for LNB ready */
0423 
0424     return 0;
0425 }
0426 
0427 static int cx24110_read_status(struct dvb_frontend *fe,
0428                    enum fe_status *status)
0429 {
0430     struct cx24110_state *state = fe->demodulator_priv;
0431 
0432     int sync = cx24110_readreg (state, 0x55);
0433 
0434     *status = 0;
0435 
0436     if (sync & 0x10)
0437         *status |= FE_HAS_SIGNAL;
0438 
0439     if (sync & 0x08)
0440         *status |= FE_HAS_CARRIER;
0441 
0442     sync = cx24110_readreg (state, 0x08);
0443 
0444     if (sync & 0x40)
0445         *status |= FE_HAS_VITERBI;
0446 
0447     if (sync & 0x20)
0448         *status |= FE_HAS_SYNC;
0449 
0450     if ((sync & 0x60) == 0x60)
0451         *status |= FE_HAS_LOCK;
0452 
0453     return 0;
0454 }
0455 
0456 static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber)
0457 {
0458     struct cx24110_state *state = fe->demodulator_priv;
0459 
0460     /* fixme (maybe): value range is 16 bit. Scale? */
0461     if(cx24110_readreg(state,0x24)&0x10) {
0462         /* the Viterbi error counter has finished one counting window */
0463         cx24110_writereg(state,0x24,0x04); /* select the ber reg */
0464         state->lastber=cx24110_readreg(state,0x25)|
0465             (cx24110_readreg(state,0x26)<<8);
0466         cx24110_writereg(state,0x24,0x04); /* start new count window */
0467         cx24110_writereg(state,0x24,0x14);
0468     }
0469     *ber = state->lastber;
0470 
0471     return 0;
0472 }
0473 
0474 static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
0475 {
0476     struct cx24110_state *state = fe->demodulator_priv;
0477 
0478 /* no provision in hardware. Read the frontend AGC accumulator. No idea how to scale this, but I know it is 2s complement */
0479     u8 signal = cx24110_readreg (state, 0x27)+128;
0480     *signal_strength = (signal << 8) | signal;
0481 
0482     return 0;
0483 }
0484 
0485 static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr)
0486 {
0487     struct cx24110_state *state = fe->demodulator_priv;
0488 
0489     /* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */
0490     if(cx24110_readreg(state,0x6a)&0x80) {
0491         /* the Es/N0 error counter has finished one counting window */
0492         state->lastesn0=cx24110_readreg(state,0x69)|
0493             (cx24110_readreg(state,0x68)<<8);
0494         cx24110_writereg(state,0x6a,0x84); /* start new count window */
0495     }
0496     *snr = state->lastesn0;
0497 
0498     return 0;
0499 }
0500 
0501 static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
0502 {
0503     struct cx24110_state *state = fe->demodulator_priv;
0504 
0505     if(cx24110_readreg(state,0x10)&0x40) {
0506         /* the RS error counter has finished one counting window */
0507         cx24110_writereg(state,0x10,0x60); /* select the byer reg */
0508         (void)(cx24110_readreg(state, 0x12) |
0509             (cx24110_readreg(state, 0x13) << 8) |
0510             (cx24110_readreg(state, 0x14) << 16));
0511         cx24110_writereg(state,0x10,0x70); /* select the bler reg */
0512         state->lastbler=cx24110_readreg(state,0x12)|
0513             (cx24110_readreg(state,0x13)<<8)|
0514             (cx24110_readreg(state,0x14)<<16);
0515         cx24110_writereg(state,0x10,0x20); /* start new count window */
0516     }
0517     *ucblocks = state->lastbler;
0518 
0519     return 0;
0520 }
0521 
0522 static int cx24110_set_frontend(struct dvb_frontend *fe)
0523 {
0524     struct cx24110_state *state = fe->demodulator_priv;
0525     struct dtv_frontend_properties *p = &fe->dtv_property_cache;
0526 
0527     if (fe->ops.tuner_ops.set_params) {
0528         fe->ops.tuner_ops.set_params(fe);
0529         if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
0530     }
0531 
0532     cx24110_set_inversion(state, p->inversion);
0533     cx24110_set_fec(state, p->fec_inner);
0534     cx24110_set_symbolrate(state, p->symbol_rate);
0535     cx24110_writereg(state,0x04,0x05); /* start acquisition */
0536 
0537     return 0;
0538 }
0539 
0540 static int cx24110_get_frontend(struct dvb_frontend *fe,
0541                 struct dtv_frontend_properties *p)
0542 {
0543     struct cx24110_state *state = fe->demodulator_priv;
0544     s32 afc; unsigned sclk;
0545 
0546 /* cannot read back tuner settings (freq). Need to have some private storage */
0547 
0548     sclk = cx24110_readreg (state, 0x07) & 0x03;
0549 /* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz.
0550  * Need 64 bit arithmetic. Is thiss possible in the kernel? */
0551     if (sclk==0) sclk=90999000L/2L;
0552     else if (sclk==1) sclk=60666000L;
0553     else if (sclk==2) sclk=80888000L;
0554     else sclk=90999000L;
0555     sclk>>=8;
0556     afc = sclk*(cx24110_readreg (state, 0x44)&0x1f)+
0557           ((sclk*cx24110_readreg (state, 0x45))>>8)+
0558           ((sclk*cx24110_readreg (state, 0x46))>>16);
0559 
0560     p->frequency += afc;
0561     p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ?
0562                 INVERSION_ON : INVERSION_OFF;
0563     p->fec_inner = cx24110_get_fec(state);
0564 
0565     return 0;
0566 }
0567 
0568 static int cx24110_set_tone(struct dvb_frontend *fe,
0569                 enum fe_sec_tone_mode tone)
0570 {
0571     struct cx24110_state *state = fe->demodulator_priv;
0572 
0573     return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&~0x10)|(((tone==SEC_TONE_ON))?0x10:0));
0574 }
0575 
0576 static void cx24110_release(struct dvb_frontend* fe)
0577 {
0578     struct cx24110_state* state = fe->demodulator_priv;
0579     kfree(state);
0580 }
0581 
0582 static const struct dvb_frontend_ops cx24110_ops;
0583 
0584 struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
0585                     struct i2c_adapter* i2c)
0586 {
0587     struct cx24110_state* state = NULL;
0588     int ret;
0589 
0590     /* allocate memory for the internal state */
0591     state = kzalloc(sizeof(struct cx24110_state), GFP_KERNEL);
0592     if (state == NULL) goto error;
0593 
0594     /* setup the state */
0595     state->config = config;
0596     state->i2c = i2c;
0597     state->lastber = 0;
0598     state->lastbler = 0;
0599     state->lastesn0 = 0;
0600 
0601     /* check if the demod is there */
0602     ret = cx24110_readreg(state, 0x00);
0603     if ((ret != 0x5a) && (ret != 0x69)) goto error;
0604 
0605     /* create dvb_frontend */
0606     memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
0607     state->frontend.demodulator_priv = state;
0608     return &state->frontend;
0609 
0610 error:
0611     kfree(state);
0612     return NULL;
0613 }
0614 
0615 static const struct dvb_frontend_ops cx24110_ops = {
0616     .delsys = { SYS_DVBS },
0617     .info = {
0618         .name = "Conexant CX24110 DVB-S",
0619         .frequency_min_hz =  950 * MHz,
0620         .frequency_max_hz = 2150 * MHz,
0621         .frequency_stepsize_hz = 1011 * kHz,
0622         .frequency_tolerance_hz = 29500 * kHz,
0623         .symbol_rate_min = 1000000,
0624         .symbol_rate_max = 45000000,
0625         .caps = FE_CAN_INVERSION_AUTO |
0626             FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
0627             FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
0628             FE_CAN_QPSK | FE_CAN_RECOVER
0629     },
0630 
0631     .release = cx24110_release,
0632 
0633     .init = cx24110_initfe,
0634     .write = _cx24110_pll_write,
0635     .set_frontend = cx24110_set_frontend,
0636     .get_frontend = cx24110_get_frontend,
0637     .read_status = cx24110_read_status,
0638     .read_ber = cx24110_read_ber,
0639     .read_signal_strength = cx24110_read_signal_strength,
0640     .read_snr = cx24110_read_snr,
0641     .read_ucblocks = cx24110_read_ucblocks,
0642 
0643     .diseqc_send_master_cmd = cx24110_send_diseqc_msg,
0644     .set_tone = cx24110_set_tone,
0645     .set_voltage = cx24110_set_voltage,
0646     .diseqc_send_burst = cx24110_diseqc_send_burst,
0647 };
0648 
0649 module_param(debug, int, 0644);
0650 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
0651 
0652 MODULE_DESCRIPTION("Conexant CX24110 DVB-S Demodulator driver");
0653 MODULE_AUTHOR("Peter Hettkamp");
0654 MODULE_LICENSE("GPL");
0655 
0656 EXPORT_SYMBOL(cx24110_attach);