Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003     TDA10023  - DVB-C decoder
0004     (as used in Philips CU1216-3 NIM and the Reelbox DVB-C tuner card)
0005 
0006     Copyright (C) 2005 Georg Acher, BayCom GmbH (acher at baycom dot de)
0007     Copyright (c) 2006 Hartmut Birr (e9hack at gmail dot com)
0008 
0009     Remotely based on tda10021.c
0010     Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
0011     Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
0012            Support for TDA10021
0013 
0014 */
0015 
0016 #include <linux/delay.h>
0017 #include <linux/errno.h>
0018 #include <linux/init.h>
0019 #include <linux/kernel.h>
0020 #include <linux/module.h>
0021 #include <linux/string.h>
0022 #include <linux/slab.h>
0023 
0024 #include <asm/div64.h>
0025 
0026 #include <media/dvb_frontend.h>
0027 #include "tda1002x.h"
0028 
0029 #define REG0_INIT_VAL 0x23
0030 
0031 struct tda10023_state {
0032     struct i2c_adapter* i2c;
0033     /* configuration settings */
0034     const struct tda10023_config *config;
0035     struct dvb_frontend frontend;
0036 
0037     u8 pwm;
0038     u8 reg0;
0039 
0040     /* clock settings */
0041     u32 xtal;
0042     u8 pll_m;
0043     u8 pll_p;
0044     u8 pll_n;
0045     u32 sysclk;
0046 };
0047 
0048 #define dprintk(x...)
0049 
0050 static int verbose;
0051 
0052 static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
0053 {
0054     u8 b0 [] = { reg };
0055     u8 b1 [] = { 0 };
0056     struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
0057                   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
0058     int ret;
0059 
0060     ret = i2c_transfer (state->i2c, msg, 2);
0061     if (ret != 2) {
0062         int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
0063         printk(KERN_ERR "DVB: TDA10023(%d): %s: readreg error (reg == 0x%02x, ret == %i)\n",
0064             num, __func__, reg, ret);
0065     }
0066     return b1[0];
0067 }
0068 
0069 static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
0070 {
0071     u8 buf[] = { reg, data };
0072     struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
0073     int ret;
0074 
0075     ret = i2c_transfer (state->i2c, &msg, 1);
0076     if (ret != 1) {
0077         int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
0078         printk(KERN_ERR "DVB: TDA10023(%d): %s, writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
0079             num, __func__, reg, data, ret);
0080     }
0081     return (ret != 1) ? -EREMOTEIO : 0;
0082 }
0083 
0084 
0085 static int tda10023_writebit (struct tda10023_state* state, u8 reg, u8 mask,u8 data)
0086 {
0087     if (mask==0xff)
0088         return tda10023_writereg(state, reg, data);
0089     else {
0090         u8 val;
0091         val=tda10023_readreg(state,reg);
0092         val&=~mask;
0093         val|=(data&mask);
0094         return tda10023_writereg(state, reg, val);
0095     }
0096 }
0097 
0098 static void tda10023_writetab(struct tda10023_state* state, u8* tab)
0099 {
0100     u8 r,m,v;
0101     while (1) {
0102         r=*tab++;
0103         m=*tab++;
0104         v=*tab++;
0105         if (r==0xff) {
0106             if (m==0xff)
0107                 break;
0108             else
0109                 msleep(m);
0110         }
0111         else
0112             tda10023_writebit(state,r,m,v);
0113     }
0114 }
0115 
0116 //get access to tuner
0117 static int lock_tuner(struct tda10023_state* state)
0118 {
0119     u8 buf[2] = { 0x0f, 0xc0 };
0120     struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
0121 
0122     if(i2c_transfer(state->i2c, &msg, 1) != 1)
0123     {
0124         printk("tda10023: lock tuner fails\n");
0125         return -EREMOTEIO;
0126     }
0127     return 0;
0128 }
0129 
0130 //release access from tuner
0131 static int unlock_tuner(struct tda10023_state* state)
0132 {
0133     u8 buf[2] = { 0x0f, 0x40 };
0134     struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
0135 
0136     if(i2c_transfer(state->i2c, &msg_post, 1) != 1)
0137     {
0138         printk("tda10023: unlock tuner fails\n");
0139         return -EREMOTEIO;
0140     }
0141     return 0;
0142 }
0143 
0144 static int tda10023_setup_reg0 (struct tda10023_state* state, u8 reg0)
0145 {
0146     reg0 |= state->reg0 & 0x63;
0147 
0148     tda10023_writereg (state, 0x00, reg0 & 0xfe);
0149     tda10023_writereg (state, 0x00, reg0 | 0x01);
0150 
0151     state->reg0 = reg0;
0152     return 0;
0153 }
0154 
0155 static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
0156 {
0157     s32 BDR;
0158     s32 BDRI;
0159     s16 SFIL=0;
0160     u16 NDEC = 0;
0161 
0162     /* avoid floating point operations multiplying syscloc and divider
0163        by 10 */
0164     u32 sysclk_x_10 = state->sysclk * 10;
0165 
0166     if (sr < (u32)(sysclk_x_10/984)) {
0167         NDEC=3;
0168         SFIL=1;
0169     } else if (sr < (u32)(sysclk_x_10/640)) {
0170         NDEC=3;
0171         SFIL=0;
0172     } else if (sr < (u32)(sysclk_x_10/492)) {
0173         NDEC=2;
0174         SFIL=1;
0175     } else if (sr < (u32)(sysclk_x_10/320)) {
0176         NDEC=2;
0177         SFIL=0;
0178     } else if (sr < (u32)(sysclk_x_10/246)) {
0179         NDEC=1;
0180         SFIL=1;
0181     } else if (sr < (u32)(sysclk_x_10/160)) {
0182         NDEC=1;
0183         SFIL=0;
0184     } else if (sr < (u32)(sysclk_x_10/123)) {
0185         NDEC=0;
0186         SFIL=1;
0187     }
0188 
0189     BDRI = (state->sysclk)*16;
0190     BDRI>>=NDEC;
0191     BDRI +=sr/2;
0192     BDRI /=sr;
0193 
0194     if (BDRI>255)
0195         BDRI=255;
0196 
0197     {
0198         u64 BDRX;
0199 
0200         BDRX=1<<(24+NDEC);
0201         BDRX*=sr;
0202         do_div(BDRX, state->sysclk);    /* BDRX/=SYSCLK; */
0203 
0204         BDR=(s32)BDRX;
0205     }
0206     dprintk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",
0207         sr, BDR, BDRI, NDEC);
0208     tda10023_writebit (state, 0x03, 0xc0, NDEC<<6);
0209     tda10023_writereg (state, 0x0a, BDR&255);
0210     tda10023_writereg (state, 0x0b, (BDR>>8)&255);
0211     tda10023_writereg (state, 0x0c, (BDR>>16)&31);
0212     tda10023_writereg (state, 0x0d, BDRI);
0213     tda10023_writereg (state, 0x3d, (SFIL<<7));
0214     return 0;
0215 }
0216 
0217 static int tda10023_init (struct dvb_frontend *fe)
0218 {
0219     struct tda10023_state* state = fe->demodulator_priv;
0220     u8 tda10023_inittab[] = {
0221 /*        reg  mask val */
0222 /* 000 */ 0x2a, 0xff, 0x02,  /* PLL3, Bypass, Power Down */
0223 /* 003 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
0224 /* 006 */ 0x2a, 0xff, 0x03,  /* PLL3, Bypass, Power Down */
0225 /* 009 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
0226                /* PLL1 */
0227 /* 012 */ 0x28, 0xff, (state->pll_m-1),
0228                /* PLL2 */
0229 /* 015 */ 0x29, 0xff, ((state->pll_p-1)<<6)|(state->pll_n-1),
0230                /* GPR FSAMPLING=1 */
0231 /* 018 */ 0x00, 0xff, REG0_INIT_VAL,
0232 /* 021 */ 0x2a, 0xff, 0x08,  /* PLL3 PSACLK=1 */
0233 /* 024 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
0234 /* 027 */ 0x1f, 0xff, 0x00,  /* RESET */
0235 /* 030 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
0236 /* 033 */ 0xe6, 0x0c, 0x04,  /* RSCFG_IND */
0237 /* 036 */ 0x10, 0xc0, 0x80,  /* DECDVBCFG1 PBER=1 */
0238 
0239 /* 039 */ 0x0e, 0xff, 0x82,  /* GAIN1 */
0240 /* 042 */ 0x03, 0x08, 0x08,  /* CLKCONF DYN=1 */
0241 /* 045 */ 0x2e, 0xbf, 0x30,  /* AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1
0242                        PPWMTUN=0 PPWMIF=0 */
0243 /* 048 */ 0x01, 0xff, 0x30,  /* AGCREF */
0244 /* 051 */ 0x1e, 0x84, 0x84,  /* CONTROL SACLK_ON=1 */
0245 /* 054 */ 0x1b, 0xff, 0xc8,  /* ADC TWOS=1 */
0246 /* 057 */ 0x3b, 0xff, 0xff,  /* IFMAX */
0247 /* 060 */ 0x3c, 0xff, 0x00,  /* IFMIN */
0248 /* 063 */ 0x34, 0xff, 0x00,  /* PWMREF */
0249 /* 066 */ 0x35, 0xff, 0xff,  /* TUNMAX */
0250 /* 069 */ 0x36, 0xff, 0x00,  /* TUNMIN */
0251 /* 072 */ 0x06, 0xff, 0x7f,  /* EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 */
0252 /* 075 */ 0x1c, 0x30, 0x30,  /* EQCONF2 STEPALGO=SGNALGO=1 */
0253 /* 078 */ 0x37, 0xff, 0xf6,  /* DELTAF_LSB */
0254 /* 081 */ 0x38, 0xff, 0xff,  /* DELTAF_MSB */
0255 /* 084 */ 0x02, 0xff, 0x93,  /* AGCCONF1  IFS=1 KAGCIF=2 KAGCTUN=3 */
0256 /* 087 */ 0x2d, 0xff, 0xf6,  /* SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 */
0257 /* 090 */ 0x04, 0x10, 0x00,  /* SWRAMP=1 */
0258 /* 093 */ 0x12, 0xff, TDA10023_OUTPUT_MODE_PARALLEL_B, /*
0259                 INTP1 POCLKP=1 FEL=1 MFS=0 */
0260 /* 096 */ 0x2b, 0x01, 0xa1,  /* INTS1 */
0261 /* 099 */ 0x20, 0xff, 0x04,  /* INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? */
0262 /* 102 */ 0x2c, 0xff, 0x0d,  /* INTP/S TRIP=0 TRIS=0 */
0263 /* 105 */ 0xc4, 0xff, 0x00,
0264 /* 108 */ 0xc3, 0x30, 0x00,
0265 /* 111 */ 0xb5, 0xff, 0x19,  /* ERAGC_THD */
0266 /* 114 */ 0x00, 0x03, 0x01,  /* GPR, CLBS soft reset */
0267 /* 117 */ 0x00, 0x03, 0x03,  /* GPR, CLBS soft reset */
0268 /* 120 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
0269 /* 123 */ 0xff, 0xff, 0xff
0270 };
0271     dprintk("DVB: TDA10023(%d): init chip\n", fe->dvb->num);
0272 
0273     /* override default values if set in config */
0274     if (state->config->deltaf) {
0275         tda10023_inittab[80] = (state->config->deltaf & 0xff);
0276         tda10023_inittab[83] = (state->config->deltaf >> 8);
0277     }
0278 
0279     if (state->config->output_mode)
0280         tda10023_inittab[95] = state->config->output_mode;
0281 
0282     tda10023_writetab(state, tda10023_inittab);
0283 
0284     return 0;
0285 }
0286 
0287 struct qam_params {
0288     u8 qam, lockthr, mseth, aref, agcrefnyq, eragnyq_thd;
0289 };
0290 
0291 static int tda10023_set_parameters(struct dvb_frontend *fe)
0292 {
0293     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0294     u32 delsys  = c->delivery_system;
0295     unsigned qam = c->modulation;
0296     bool is_annex_c;
0297     struct tda10023_state* state = fe->demodulator_priv;
0298     static const struct qam_params qam_params[] = {
0299         /* Modulation  QAM    LOCKTHR   MSETH   AREF AGCREFNYQ ERAGCNYQ_THD */
0300         [QPSK]    = { (5<<2),  0x78,    0x8c,   0x96,   0x78,   0x4c  },
0301         [QAM_16]  = { (0<<2),  0x87,    0xa2,   0x91,   0x8c,   0x57  },
0302         [QAM_32]  = { (1<<2),  0x64,    0x74,   0x96,   0x8c,   0x57  },
0303         [QAM_64]  = { (2<<2),  0x46,    0x43,   0x6a,   0x6a,   0x44  },
0304         [QAM_128] = { (3<<2),  0x36,    0x34,   0x7e,   0x78,   0x4c  },
0305         [QAM_256] = { (4<<2),  0x26,    0x23,   0x6c,   0x5c,   0x3c  },
0306     };
0307 
0308     switch (delsys) {
0309     case SYS_DVBC_ANNEX_A:
0310         is_annex_c = false;
0311         break;
0312     case SYS_DVBC_ANNEX_C:
0313         is_annex_c = true;
0314         break;
0315     default:
0316         return -EINVAL;
0317     }
0318 
0319     /*
0320      * gcc optimizes the code below the same way as it would code:
0321      *       "if (qam > 5) return -EINVAL;"
0322      * Yet, the code is clearer, as it shows what QAM standards are
0323      * supported by the driver, and avoids the usage of magic numbers on
0324      * it.
0325      */
0326     switch (qam) {
0327     case QPSK:
0328     case QAM_16:
0329     case QAM_32:
0330     case QAM_64:
0331     case QAM_128:
0332     case QAM_256:
0333         break;
0334     default:
0335         return -EINVAL;
0336     }
0337 
0338     if (fe->ops.tuner_ops.set_params) {
0339         fe->ops.tuner_ops.set_params(fe);
0340         if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
0341     }
0342 
0343     tda10023_set_symbolrate(state, c->symbol_rate);
0344     tda10023_writereg(state, 0x05, qam_params[qam].lockthr);
0345     tda10023_writereg(state, 0x08, qam_params[qam].mseth);
0346     tda10023_writereg(state, 0x09, qam_params[qam].aref);
0347     tda10023_writereg(state, 0xb4, qam_params[qam].agcrefnyq);
0348     tda10023_writereg(state, 0xb6, qam_params[qam].eragnyq_thd);
0349 #if 0
0350     tda10023_writereg(state, 0x04, (c->inversion ? 0x12 : 0x32));
0351     tda10023_writebit(state, 0x04, 0x60, (c->inversion ? 0 : 0x20));
0352 #endif
0353     tda10023_writebit(state, 0x04, 0x40, 0x40);
0354 
0355     if (is_annex_c)
0356         tda10023_writebit(state, 0x3d, 0xfc, 0x03);
0357     else
0358         tda10023_writebit(state, 0x3d, 0xfc, 0x02);
0359 
0360     tda10023_setup_reg0(state, qam_params[qam].qam);
0361 
0362     return 0;
0363 }
0364 
0365 static int tda10023_read_status(struct dvb_frontend *fe,
0366                 enum fe_status *status)
0367 {
0368     struct tda10023_state* state = fe->demodulator_priv;
0369     int sync;
0370 
0371     *status = 0;
0372 
0373     //0x11[1] == CARLOCK -> Carrier locked
0374     //0x11[2] == FSYNC -> Frame synchronisation
0375     //0x11[3] == FEL -> Front End locked
0376     //0x11[6] == NODVB -> DVB Mode Information
0377     sync = tda10023_readreg (state, 0x11);
0378 
0379     if (sync & 2)
0380         *status |= FE_HAS_SIGNAL|FE_HAS_CARRIER;
0381 
0382     if (sync & 4)
0383         *status |= FE_HAS_SYNC|FE_HAS_VITERBI;
0384 
0385     if (sync & 8)
0386         *status |= FE_HAS_LOCK;
0387 
0388     return 0;
0389 }
0390 
0391 static int tda10023_read_ber(struct dvb_frontend* fe, u32* ber)
0392 {
0393     struct tda10023_state* state = fe->demodulator_priv;
0394     u8 a,b,c;
0395     a=tda10023_readreg(state, 0x14);
0396     b=tda10023_readreg(state, 0x15);
0397     c=tda10023_readreg(state, 0x16)&0xf;
0398     tda10023_writebit (state, 0x10, 0xc0, 0x00);
0399 
0400     *ber = a | (b<<8)| (c<<16);
0401     return 0;
0402 }
0403 
0404 static int tda10023_read_signal_strength(struct dvb_frontend* fe, u16* strength)
0405 {
0406     struct tda10023_state* state = fe->demodulator_priv;
0407     u8 ifgain=tda10023_readreg(state, 0x2f);
0408 
0409     u16 gain = ((255-tda10023_readreg(state, 0x17))) + (255-ifgain)/16;
0410     // Max raw value is about 0xb0 -> Normalize to >0xf0 after 0x90
0411     if (gain>0x90)
0412         gain=gain+2*(gain-0x90);
0413     if (gain>255)
0414         gain=255;
0415 
0416     *strength = (gain<<8)|gain;
0417     return 0;
0418 }
0419 
0420 static int tda10023_read_snr(struct dvb_frontend* fe, u16* snr)
0421 {
0422     struct tda10023_state* state = fe->demodulator_priv;
0423 
0424     u8 quality = ~tda10023_readreg(state, 0x18);
0425     *snr = (quality << 8) | quality;
0426     return 0;
0427 }
0428 
0429 static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
0430 {
0431     struct tda10023_state* state = fe->demodulator_priv;
0432     u8 a,b,c,d;
0433     a= tda10023_readreg (state, 0x74);
0434     b= tda10023_readreg (state, 0x75);
0435     c= tda10023_readreg (state, 0x76);
0436     d= tda10023_readreg (state, 0x77);
0437     *ucblocks = a | (b<<8)|(c<<16)|(d<<24);
0438 
0439     tda10023_writebit (state, 0x10, 0x20,0x00);
0440     tda10023_writebit (state, 0x10, 0x20,0x20);
0441     tda10023_writebit (state, 0x13, 0x01, 0x00);
0442 
0443     return 0;
0444 }
0445 
0446 static int tda10023_get_frontend(struct dvb_frontend *fe,
0447                  struct dtv_frontend_properties *p)
0448 {
0449     struct tda10023_state* state = fe->demodulator_priv;
0450     int sync,inv;
0451     s8 afc = 0;
0452 
0453     sync = tda10023_readreg(state, 0x11);
0454     afc = tda10023_readreg(state, 0x19);
0455     inv = tda10023_readreg(state, 0x04);
0456 
0457     if (verbose) {
0458         /* AFC only valid when carrier has been recovered */
0459         printk(sync & 2 ? "DVB: TDA10023(%d): AFC (%d) %dHz\n" :
0460                   "DVB: TDA10023(%d): [AFC (%d) %dHz]\n",
0461             state->frontend.dvb->num, afc,
0462                -((s32)p->symbol_rate * afc) >> 10);
0463     }
0464 
0465     p->inversion = (inv&0x20?0:1);
0466     p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
0467 
0468     p->fec_inner = FEC_NONE;
0469     p->frequency = ((p->frequency + 31250) / 62500) * 62500;
0470 
0471     if (sync & 2)
0472         p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
0473 
0474     return 0;
0475 }
0476 
0477 static int tda10023_sleep(struct dvb_frontend* fe)
0478 {
0479     struct tda10023_state* state = fe->demodulator_priv;
0480 
0481     tda10023_writereg (state, 0x1b, 0x02);  /* pdown ADC */
0482     tda10023_writereg (state, 0x00, 0x80);  /* standby */
0483 
0484     return 0;
0485 }
0486 
0487 static int tda10023_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
0488 {
0489     struct tda10023_state* state = fe->demodulator_priv;
0490 
0491     if (enable) {
0492         lock_tuner(state);
0493     } else {
0494         unlock_tuner(state);
0495     }
0496     return 0;
0497 }
0498 
0499 static void tda10023_release(struct dvb_frontend* fe)
0500 {
0501     struct tda10023_state* state = fe->demodulator_priv;
0502     kfree(state);
0503 }
0504 
0505 static const struct dvb_frontend_ops tda10023_ops;
0506 
0507 struct dvb_frontend *tda10023_attach(const struct tda10023_config *config,
0508                      struct i2c_adapter *i2c,
0509                      u8 pwm)
0510 {
0511     struct tda10023_state* state = NULL;
0512 
0513     /* allocate memory for the internal state */
0514     state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL);
0515     if (state == NULL) goto error;
0516 
0517     /* setup the state */
0518     state->config = config;
0519     state->i2c = i2c;
0520 
0521     /* wakeup if in standby */
0522     tda10023_writereg (state, 0x00, 0x33);
0523     /* check if the demod is there */
0524     if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
0525 
0526     /* create dvb_frontend */
0527     memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
0528     state->pwm = pwm;
0529     state->reg0 = REG0_INIT_VAL;
0530     if (state->config->xtal) {
0531         state->xtal  = state->config->xtal;
0532         state->pll_m = state->config->pll_m;
0533         state->pll_p = state->config->pll_p;
0534         state->pll_n = state->config->pll_n;
0535     } else {
0536         /* set default values if not defined in config */
0537         state->xtal  = 28920000;
0538         state->pll_m = 8;
0539         state->pll_p = 4;
0540         state->pll_n = 1;
0541     }
0542 
0543     /* calc sysclk */
0544     state->sysclk = (state->xtal * state->pll_m / \
0545             (state->pll_n * state->pll_p));
0546 
0547     state->frontend.ops.info.symbol_rate_min = (state->sysclk/2)/64;
0548     state->frontend.ops.info.symbol_rate_max = (state->sysclk/2)/4;
0549 
0550     dprintk("DVB: TDA10023 %s: xtal:%d pll_m:%d pll_p:%d pll_n:%d\n",
0551         __func__, state->xtal, state->pll_m, state->pll_p,
0552         state->pll_n);
0553 
0554     state->frontend.demodulator_priv = state;
0555     return &state->frontend;
0556 
0557 error:
0558     kfree(state);
0559     return NULL;
0560 }
0561 
0562 static const struct dvb_frontend_ops tda10023_ops = {
0563     .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
0564     .info = {
0565         .name = "Philips TDA10023 DVB-C",
0566         .frequency_min_hz =  47 * MHz,
0567         .frequency_max_hz = 862 * MHz,
0568         .frequency_stepsize_hz = 62500,
0569         .symbol_rate_min = 0,  /* set in tda10023_attach */
0570         .symbol_rate_max = 0,  /* set in tda10023_attach */
0571         .caps = 0x400 | //FE_CAN_QAM_4
0572             FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
0573             FE_CAN_QAM_128 | FE_CAN_QAM_256 |
0574             FE_CAN_FEC_AUTO
0575     },
0576 
0577     .release = tda10023_release,
0578 
0579     .init = tda10023_init,
0580     .sleep = tda10023_sleep,
0581     .i2c_gate_ctrl = tda10023_i2c_gate_ctrl,
0582 
0583     .set_frontend = tda10023_set_parameters,
0584     .get_frontend = tda10023_get_frontend,
0585     .read_status = tda10023_read_status,
0586     .read_ber = tda10023_read_ber,
0587     .read_signal_strength = tda10023_read_signal_strength,
0588     .read_snr = tda10023_read_snr,
0589     .read_ucblocks = tda10023_read_ucblocks,
0590 };
0591 
0592 
0593 MODULE_DESCRIPTION("Philips TDA10023 DVB-C demodulator driver");
0594 MODULE_AUTHOR("Georg Acher, Hartmut Birr");
0595 MODULE_LICENSE("GPL");
0596 
0597 EXPORT_SYMBOL(tda10023_attach);