1 /* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator
3 * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
11 #include <linux/version.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/string.h>
16 #include <linux/slab.h>
17 #include <linux/jiffies.h>
18 #include <asm/div64.h>
20 #include "dvb_frontend.h"
23 #define REVISION_REG 0x00
24 #define SYSTEM_MODE_REG 0x01
25 #define TS_CTRL_REG_1 0x02
26 #define TS_CTRL_REG_2 0x03
27 #define PIN_CTRL_REG_1 0x04
28 #define PIN_CTRL_REG_2 0x05
29 #define LOCK_STATUS_REG_1 0x0f
30 #define LOCK_STATUS_REG_2 0x10
31 #define ACQ_STATUS_REG 0x11
32 #define ACQ_CTRL_REG_1 0x13
33 #define ACQ_CTRL_REG_2 0x14
34 #define PLL_DIVISOR_REG 0x15
35 #define COARSE_TUNE_REG 0x16
36 #define FINE_TUNE_REG_L 0x17
37 #define FINE_TUNE_REG_H 0x18
39 #define ANALOG_AGC_POWER_LEVEL_REG 0x28
40 #define CFO_ESTIMATOR_CTRL_REG_1 0x29
41 #define CFO_ESTIMATOR_CTRL_REG_2 0x2a
42 #define CFO_ESTIMATOR_CTRL_REG_3 0x2b
44 #define SYM_RATE_ESTIMATE_REG_L 0x31
45 #define SYM_RATE_ESTIMATE_REG_M 0x32
46 #define SYM_RATE_ESTIMATE_REG_H 0x33
48 #define CFO_ESTIMATOR_OFFSET_REG_L 0x36
49 #define CFO_ESTIMATOR_OFFSET_REG_H 0x37
50 #define CFO_ERROR_REG_L 0x38
51 #define CFO_ERROR_REG_H 0x39
52 #define SYM_RATE_ESTIMATOR_CTRL_REG 0x3a
54 #define SYM_RATE_REG_L 0x3f
55 #define SYM_RATE_REG_M 0x40
56 #define SYM_RATE_REG_H 0x41
57 #define SYM_RATE_ESTIMATOR_MAXIMUM_REG 0x42
58 #define SYM_RATE_ESTIMATOR_MINIMUM_REG 0x43
60 #define C_N_ESTIMATOR_CTRL_REG 0x7c
61 #define C_N_ESTIMATOR_THRSHLD_REG 0x7d
62 #define C_N_ESTIMATOR_LEVEL_REG_L 0x7e
63 #define C_N_ESTIMATOR_LEVEL_REG_H 0x7f
65 #define BLIND_SCAN_CTRL_REG 0x80
67 #define LSA_CTRL_REG_1 0x8D
68 #define SPCTRM_TILT_CORR_THRSHLD_REG 0x8f
69 #define ONE_DB_BNDWDTH_THRSHLD_REG 0x90
70 #define TWO_DB_BNDWDTH_THRSHLD_REG 0x91
71 #define THREE_DB_BNDWDTH_THRSHLD_REG 0x92
72 #define INBAND_POWER_THRSHLD_REG 0x93
73 #define REF_NOISE_LVL_MRGN_THRSHLD_REG 0x94
75 #define VIT_SRCH_CTRL_REG_1 0xa0
76 #define VIT_SRCH_CTRL_REG_2 0xa1
77 #define VIT_SRCH_CTRL_REG_3 0xa2
78 #define VIT_SRCH_STATUS_REG 0xa3
79 #define VITERBI_BER_COUNT_REG_L 0xab
80 #define REED_SOLOMON_CTRL_REG 0xb0
81 #define REED_SOLOMON_ERROR_COUNT_REG_L 0xb1
82 #define PRBS_CTRL_REG 0xb5
84 #define LNB_CTRL_REG_1 0xc0
85 #define LNB_CTRL_REG_2 0xc1
86 #define LNB_CTRL_REG_3 0xc2
87 #define LNB_CTRL_REG_4 0xc3
88 #define LNB_CTRL_STATUS_REG 0xc4
89 #define LNB_FIFO_REGS_0 0xc5
90 #define LNB_FIFO_REGS_1 0xc6
91 #define LNB_FIFO_REGS_2 0xc7
92 #define LNB_FIFO_REGS_3 0xc8
93 #define LNB_FIFO_REGS_4 0xc9
94 #define LNB_FIFO_REGS_5 0xca
95 #define LNB_SUPPLY_CTRL_REG_1 0xcb
96 #define LNB_SUPPLY_CTRL_REG_2 0xcc
97 #define LNB_SUPPLY_CTRL_REG_3 0xcd
98 #define LNB_SUPPLY_CTRL_REG_4 0xce
99 #define LNB_SUPPLY_STATUS_REG 0xcf
106 #define ALLOWABLE_FS_COUNT 10
108 #define STATUS_UCBLOCKS 1
111 #define dprintk(args...) \
114 printk(KERN_DEBUG "si21xx: " args); \
142 struct si21xx_state {
143 struct i2c_adapter *i2c;
144 const struct si21xx_config *config;
145 struct dvb_frontend frontend;
148 int fs; /*Sampling rate of the ADC in MHz*/
151 /* register default initialization */
152 static u8 serit_sp1511lhb_inittab[] = {
153 0x01, 0x28, /* set i2c_inc_disable */
229 /* low level read/writes */
230 static int si21_writeregs(struct si21xx_state *state, u8 reg1,
234 u8 buf[60];/* = { reg1, data };*/
235 struct i2c_msg msg = {
236 .addr = state->config->demod_address,
243 memcpy(msg.buf + 1, data, len);
245 ret = i2c_transfer(state->i2c, &msg, 1);
248 dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
249 "ret == %i)\n", __func__, reg1, data[0], ret);
251 return (ret != 1) ? -EREMOTEIO : 0;
254 static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)
257 u8 buf[] = { reg, data };
258 struct i2c_msg msg = {
259 .addr = state->config->demod_address,
265 ret = i2c_transfer(state->i2c, &msg, 1);
268 dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
269 "ret == %i)\n", __func__, reg, data, ret);
271 return (ret != 1) ? -EREMOTEIO : 0;
274 static int si21_write(struct dvb_frontend *fe, u8 *buf, int len)
276 struct si21xx_state *state = fe->demodulator_priv;
281 return si21_writereg(state, buf[0], buf[1]);
284 static u8 si21_readreg(struct si21xx_state *state, u8 reg)
289 struct i2c_msg msg[] = {
291 .addr = state->config->demod_address,
296 .addr = state->config->demod_address,
303 ret = i2c_transfer(state->i2c, msg, 2);
306 dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
312 static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len)
315 struct i2c_msg msg[] = {
317 .addr = state->config->demod_address,
322 .addr = state->config->demod_address,
329 ret = i2c_transfer(state->i2c, msg, 2);
332 dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
334 return ret == 2 ? 0 : -1;
337 static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
339 unsigned long start = jiffies;
341 dprintk("%s\n", __func__);
343 while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) {
344 if (jiffies - start > timeout) {
345 dprintk("%s: timeout!!\n", __func__);
354 static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate)
356 struct si21xx_state *state = fe->demodulator_priv;
357 u32 sym_rate, data_rate;
359 u8 sym_rate_bytes[3];
361 dprintk("%s : srate = %i\n", __func__ , srate);
363 if ((srate < 1000000) || (srate > 45000000))
369 for (i = 0; i < 4; ++i) {
371 sym_rate = sym_rate + ((data_rate % 100) * 0x800000) /
375 for (i = 0; i < 3; ++i)
376 sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);
378 si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);
383 static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,
384 struct dvb_diseqc_master_cmd *m)
386 struct si21xx_state *state = fe->demodulator_priv;
391 dprintk("%s\n", __func__);
396 status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);
397 status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);
400 status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);
402 LNB_CTRL_1 = (lnb_status & 0x70);
403 LNB_CTRL_1 |= m->msg_len;
405 LNB_CTRL_1 |= 0x80; /* begin LNB signaling */
407 status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);
412 static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
413 fe_sec_mini_cmd_t burst)
415 struct si21xx_state *state = fe->demodulator_priv;
418 dprintk("%s\n", __func__);
420 if (si21xx_wait_diseqc_idle(state, 100) < 0)
423 val = (0x80 | si21_readreg(state, 0xc1));
424 if (si21_writereg(state, LNB_CTRL_REG_1,
425 burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10)))
428 if (si21xx_wait_diseqc_idle(state, 100) < 0)
431 if (si21_writereg(state, LNB_CTRL_REG_1, val))
437 static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
439 struct si21xx_state *state = fe->demodulator_priv;
442 dprintk("%s\n", __func__);
443 val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
447 return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);
450 return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));
457 static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
459 struct si21xx_state *state = fe->demodulator_priv;
462 dprintk("%s: %s\n", __func__,
463 volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
464 volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
467 val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
471 return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40);
474 return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40));
481 static int si21xx_init(struct dvb_frontend *fe)
483 struct si21xx_state *state = fe->demodulator_priv;
490 dprintk("%s\n", __func__);
492 for (i = 0; ; i += 2) {
493 reg1 = serit_sp1511lhb_inittab[i];
494 val = serit_sp1511lhb_inittab[i+1];
495 if (reg1 == 0xff && val == 0xff)
497 si21_writeregs(state, reg1, &val, 1);
500 /*DVB QPSK SYSTEM MODE REG*/
502 si21_writeregs(state, SYSTEM_MODE_REG, ®1, 0x01);
504 /*transport stream config*/
507 sdata_form = LSB_FIRST;
508 clk_edge = FALLING_EDGE;
509 clk_mode = CLK_GAPPED_MODE;
510 strt_len = BYTE_WIDE;
511 sync_pol = ACTIVE_HIGH;
512 val_pol = ACTIVE_HIGH;
513 err_pol = ACTIVE_HIGH;
521 PARALLEL + (LSB_FIRST << 1)
522 + (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3)
523 + (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5)
524 + (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7);
527 /* sclk_rate + (parity << 2)
528 + (data_delay << 3) + (clk_delay << 4)
529 + (pclk_smooth << 5);
531 status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02);
533 dprintk(" %s : TS Set Error\n", __func__);
539 static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status)
541 struct si21xx_state *state = fe->demodulator_priv;
546 u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG);
548 si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02);
551 for (i = 0; i < 7; ++i)
552 reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i);
554 lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80));
556 dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock);
560 *status |= FE_HAS_SIGNAL;
563 *status |= FE_HAS_CARRIER;
566 *status |= FE_HAS_VITERBI;
569 *status |= FE_HAS_SYNC;
571 if ((lock & 0x7b) == 0x7b)
572 *status |= FE_HAS_LOCK;
577 static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
579 struct si21xx_state *state = fe->demodulator_priv;
581 /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
582 (u8*)agclevel, 0x01);*/
584 u16 signal = (3 * si21_readreg(state, 0x27) *
585 si21_readreg(state, 0x28));
587 dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__,
588 si21_readreg(state, 0x27),
589 si21_readreg(state, 0x28), (int) signal);
597 static int si21_read_ber(struct dvb_frontend *fe, u32 *ber)
599 struct si21xx_state *state = fe->demodulator_priv;
601 dprintk("%s\n", __func__);
603 if (state->errmode != STATUS_BER)
606 *ber = (si21_readreg(state, 0x1d) << 8) |
607 si21_readreg(state, 0x1e);
612 static int si21_read_snr(struct dvb_frontend *fe, u16 *snr)
614 struct si21xx_state *state = fe->demodulator_priv;
616 s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) |
617 si21_readreg(state, 0x25));
618 xsnr = 3 * (xsnr - 0xa100);
619 *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
621 dprintk("%s\n", __func__);
626 static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
628 struct si21xx_state *state = fe->demodulator_priv;
630 dprintk("%s\n", __func__);
632 if (state->errmode != STATUS_UCBLOCKS)
635 *ucblocks = (si21_readreg(state, 0x1d) << 8) |
636 si21_readreg(state, 0x1e);
641 /* initiates a channel acquisition sequence
642 using the specified symbol rate and code rate */
643 static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
644 fe_code_rate_t crate)
647 struct si21xx_state *state = fe->demodulator_priv;
649 0x0, 0x01, 0x02, 0x04, 0x00,
650 0x8, 0x10, 0x20, 0x00, 0x3f
658 dprintk("%s\n", __func__);
661 coderate_ptr = coderates[crate];
663 si21xx_set_symbolrate(fe, symbrate);
665 /* write code rates to use in the Viterbi search */
666 status |= si21_writeregs(state,
668 &coderate_ptr, 0x01);
670 /* clear acq_start bit */
671 status |= si21_readregs(state, ACQ_CTRL_REG_2, ®, 0x01);
673 status |= si21_writeregs(state, ACQ_CTRL_REG_2, ®, 0x01);
675 /* use new Carrier Frequency Offset Estimator (QuickLock) */
680 status |= si21_writeregs(state,
681 TWO_DB_BNDWDTH_THRSHLD_REG,
684 status |= si21_writeregs(state,
685 LSA_CTRL_REG_1, ®, 1);
687 status |= si21_writeregs(state,
688 BLIND_SCAN_CTRL_REG, ®, 1);
689 /* start automatic acq */
690 status |= si21_writeregs(state,
691 ACQ_CTRL_REG_2, &start_acq, 0x01);
696 static int si21xx_set_property(struct dvb_frontend *fe, struct dtv_property *p)
698 dprintk("%s(..)\n", __func__);
702 static int si21xx_get_property(struct dvb_frontend *fe, struct dtv_property *p)
704 dprintk("%s(..)\n", __func__);
708 static int si21xx_set_frontend(struct dvb_frontend *fe,
709 struct dvb_frontend_parameters *dfp)
711 struct si21xx_state *state = fe->demodulator_priv;
712 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
714 /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz)
715 datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/
718 unsigned char coarse_tune_freq;
720 unsigned char sample_rate = 0;
722 unsigned int inband_interferer_ind;
724 /* INTERMEDIATE VALUES */
725 int icoarse_tune_freq; /* MHz */
726 int ifine_tune_freq; /* MHz */
727 unsigned int band_high;
728 unsigned int band_low;
732 unsigned int inband_interferer_div2[ALLOWABLE_FS_COUNT] = {
733 FALSE, FALSE, FALSE, FALSE, FALSE,
734 FALSE, FALSE, FALSE, FALSE, FALSE
736 unsigned int inband_interferer_div4[ALLOWABLE_FS_COUNT] = {
737 FALSE, FALSE, FALSE, FALSE, FALSE,
738 FALSE, FALSE, FALSE, FALSE, FALSE
743 /* allowable sample rates for ADC in MHz */
744 int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,
745 196, 204, 205, 206, 207
755 unsigned char regs[4];
757 dprintk("%s : FE_SET_FRONTEND\n", __func__);
759 if (c->delivery_system != SYS_DVBS) {
760 dprintk("%s: unsupported delivery system selected (%d)\n",
761 __func__, c->delivery_system);
765 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
766 inband_interferer_div2[i] = inband_interferer_div4[i] = FALSE;
768 if_limit_high = -700000;
769 if_limit_low = -100000;
774 rf_freq = 10 * c->frequency ;
775 data_rate = c->symbol_rate / 100;
779 band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)
780 + (data_rate * 135)) / 200;
782 band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200)
783 + (data_rate * 135)) / 200;
786 icoarse_tune_freq = 100000 *
787 (((rf_freq - lnb_lo) -
788 (if_limit_low + if_limit_high) / 2)
791 ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ;
793 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
794 x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
795 (afs[i] * 2500) + afs[i] * 2500;
797 x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
800 if (((band_low < x1) && (x1 < band_high)) ||
801 ((band_low < x2) && (x2 < band_high)))
802 inband_interferer_div4[i] = TRUE;
806 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
807 x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
808 (afs[i] * 5000) + afs[i] * 5000;
810 x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
813 if (((band_low < x1) && (x1 < band_high)) ||
814 ((band_low < x2) && (x2 < band_high)))
815 inband_interferer_div2[i] = TRUE;
818 inband_interferer_ind = TRUE;
819 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
820 inband_interferer_ind &= inband_interferer_div2[i] |
821 inband_interferer_div4[i];
823 if (inband_interferer_ind) {
824 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
825 if (inband_interferer_div2[i] == FALSE) {
826 sample_rate = (u8) afs[i];
831 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
832 if ((inband_interferer_div2[i] |
833 inband_interferer_div4[i]) == FALSE) {
834 sample_rate = (u8) afs[i];
841 if (sample_rate > 207 || sample_rate < 192)
844 fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) /
845 ((sample_rate) * 1000));
847 coarse_tune_freq = (u8)(icoarse_tune_freq / 100000);
849 regs[0] = sample_rate;
850 regs[1] = coarse_tune_freq;
851 regs[2] = fine_tune_freq & 0xFF;
852 regs[3] = fine_tune_freq >> 8 & 0xFF;
854 status |= si21_writeregs(state, PLL_DIVISOR_REG, ®s[0], 0x04);
856 state->fs = sample_rate;/*ADC MHz*/
857 si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);
862 static int si21xx_sleep(struct dvb_frontend *fe)
864 struct si21xx_state *state = fe->demodulator_priv;
867 dprintk("%s\n", __func__);
869 si21_readregs(state, SYSTEM_MODE_REG, ®data, 0x01);
871 si21_writeregs(state, SYSTEM_MODE_REG, ®data, 0x01);
872 state->initialised = 0;
877 static void si21xx_release(struct dvb_frontend *fe)
879 struct si21xx_state *state = fe->demodulator_priv;
881 dprintk("%s\n", __func__);
886 static struct dvb_frontend_ops si21xx_ops = {
889 .name = "SL SI21XX DVB-S",
891 .frequency_min = 950000,
892 .frequency_max = 2150000,
893 .frequency_stepsize = 125, /* kHz for QPSK frontends */
894 .frequency_tolerance = 0,
895 .symbol_rate_min = 1000000,
896 .symbol_rate_max = 45000000,
897 .symbol_rate_tolerance = 500, /* ppm */
898 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
899 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
904 .release = si21xx_release,
906 .sleep = si21xx_sleep,
908 .read_status = si21_read_status,
909 .read_ber = si21_read_ber,
910 .read_signal_strength = si21_read_signal_strength,
911 .read_snr = si21_read_snr,
912 .read_ucblocks = si21_read_ucblocks,
913 .diseqc_send_master_cmd = si21xx_send_diseqc_msg,
914 .diseqc_send_burst = si21xx_send_diseqc_burst,
915 .set_tone = si21xx_set_tone,
916 .set_voltage = si21xx_set_voltage,
918 .set_property = si21xx_set_property,
919 .get_property = si21xx_get_property,
920 .set_frontend = si21xx_set_frontend,
923 struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
924 struct i2c_adapter *i2c)
926 struct si21xx_state *state = NULL;
929 dprintk("%s\n", __func__);
931 /* allocate memory for the internal state */
932 state = kmalloc(sizeof(struct si21xx_state), GFP_KERNEL);
936 /* setup the state */
937 state->config = config;
939 state->initialised = 0;
940 state->errmode = STATUS_BER;
942 /* check if the demod is there */
943 id = si21_readreg(state, SYSTEM_MODE_REG);
944 si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */
946 id = si21_readreg(state, 0x00);
948 /* register 0x00 contains:
954 if (id != 0x04 && id != 0x14)
957 /* create dvb_frontend */
958 memcpy(&state->frontend.ops, &si21xx_ops,
959 sizeof(struct dvb_frontend_ops));
960 state->frontend.demodulator_priv = state;
961 return &state->frontend;
967 EXPORT_SYMBOL(si21xx_attach);
969 module_param(debug, int, 0644);
970 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
972 MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
973 MODULE_AUTHOR("Igor M. Liplianin");
974 MODULE_LICENSE("GPL");