1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator
4 * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
6 #include <linux/init.h>
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/string.h>
10 #include <linux/slab.h>
11 #include <linux/jiffies.h>
12 #include <asm/div64.h>
14 #include <media/dvb_frontend.h>
17 #define REVISION_REG 0x00
18 #define SYSTEM_MODE_REG 0x01
19 #define TS_CTRL_REG_1 0x02
20 #define TS_CTRL_REG_2 0x03
21 #define PIN_CTRL_REG_1 0x04
22 #define PIN_CTRL_REG_2 0x05
23 #define LOCK_STATUS_REG_1 0x0f
24 #define LOCK_STATUS_REG_2 0x10
25 #define ACQ_STATUS_REG 0x11
26 #define ACQ_CTRL_REG_1 0x13
27 #define ACQ_CTRL_REG_2 0x14
28 #define PLL_DIVISOR_REG 0x15
29 #define COARSE_TUNE_REG 0x16
30 #define FINE_TUNE_REG_L 0x17
31 #define FINE_TUNE_REG_H 0x18
33 #define ANALOG_AGC_POWER_LEVEL_REG 0x28
34 #define CFO_ESTIMATOR_CTRL_REG_1 0x29
35 #define CFO_ESTIMATOR_CTRL_REG_2 0x2a
36 #define CFO_ESTIMATOR_CTRL_REG_3 0x2b
38 #define SYM_RATE_ESTIMATE_REG_L 0x31
39 #define SYM_RATE_ESTIMATE_REG_M 0x32
40 #define SYM_RATE_ESTIMATE_REG_H 0x33
42 #define CFO_ESTIMATOR_OFFSET_REG_L 0x36
43 #define CFO_ESTIMATOR_OFFSET_REG_H 0x37
44 #define CFO_ERROR_REG_L 0x38
45 #define CFO_ERROR_REG_H 0x39
46 #define SYM_RATE_ESTIMATOR_CTRL_REG 0x3a
48 #define SYM_RATE_REG_L 0x3f
49 #define SYM_RATE_REG_M 0x40
50 #define SYM_RATE_REG_H 0x41
51 #define SYM_RATE_ESTIMATOR_MAXIMUM_REG 0x42
52 #define SYM_RATE_ESTIMATOR_MINIMUM_REG 0x43
54 #define C_N_ESTIMATOR_CTRL_REG 0x7c
55 #define C_N_ESTIMATOR_THRSHLD_REG 0x7d
56 #define C_N_ESTIMATOR_LEVEL_REG_L 0x7e
57 #define C_N_ESTIMATOR_LEVEL_REG_H 0x7f
59 #define BLIND_SCAN_CTRL_REG 0x80
61 #define LSA_CTRL_REG_1 0x8D
62 #define SPCTRM_TILT_CORR_THRSHLD_REG 0x8f
63 #define ONE_DB_BNDWDTH_THRSHLD_REG 0x90
64 #define TWO_DB_BNDWDTH_THRSHLD_REG 0x91
65 #define THREE_DB_BNDWDTH_THRSHLD_REG 0x92
66 #define INBAND_POWER_THRSHLD_REG 0x93
67 #define REF_NOISE_LVL_MRGN_THRSHLD_REG 0x94
69 #define VIT_SRCH_CTRL_REG_1 0xa0
70 #define VIT_SRCH_CTRL_REG_2 0xa1
71 #define VIT_SRCH_CTRL_REG_3 0xa2
72 #define VIT_SRCH_STATUS_REG 0xa3
73 #define VITERBI_BER_COUNT_REG_L 0xab
74 #define REED_SOLOMON_CTRL_REG 0xb0
75 #define REED_SOLOMON_ERROR_COUNT_REG_L 0xb1
76 #define PRBS_CTRL_REG 0xb5
78 #define LNB_CTRL_REG_1 0xc0
79 #define LNB_CTRL_REG_2 0xc1
80 #define LNB_CTRL_REG_3 0xc2
81 #define LNB_CTRL_REG_4 0xc3
82 #define LNB_CTRL_STATUS_REG 0xc4
83 #define LNB_FIFO_REGS_0 0xc5
84 #define LNB_FIFO_REGS_1 0xc6
85 #define LNB_FIFO_REGS_2 0xc7
86 #define LNB_FIFO_REGS_3 0xc8
87 #define LNB_FIFO_REGS_4 0xc9
88 #define LNB_FIFO_REGS_5 0xca
89 #define LNB_SUPPLY_CTRL_REG_1 0xcb
90 #define LNB_SUPPLY_CTRL_REG_2 0xcc
91 #define LNB_SUPPLY_CTRL_REG_3 0xcd
92 #define LNB_SUPPLY_CTRL_REG_4 0xce
93 #define LNB_SUPPLY_STATUS_REG 0xcf
98 #define ALLOWABLE_FS_COUNT 10
100 #define STATUS_UCBLOCKS 1
103 #define dprintk(args...) \
106 printk(KERN_DEBUG "si21xx: " args); \
134 struct si21xx_state
{
135 struct i2c_adapter
*i2c
;
136 const struct si21xx_config
*config
;
137 struct dvb_frontend frontend
;
140 int fs
; /*Sampling rate of the ADC in MHz*/
143 /* register default initialization */
144 static u8 serit_sp1511lhb_inittab
[] = {
145 0x01, 0x28, /* set i2c_inc_disable */
221 /* low level read/writes */
222 static int si21_writeregs(struct si21xx_state
*state
, u8 reg1
,
226 u8 buf
[60];/* = { reg1, data };*/
227 struct i2c_msg msg
= {
228 .addr
= state
->config
->demod_address
,
234 if (len
> sizeof(buf
) - 1)
238 memcpy(msg
.buf
+ 1, data
, len
);
240 ret
= i2c_transfer(state
->i2c
, &msg
, 1);
243 dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, ret == %i)\n",
244 __func__
, reg1
, data
[0], ret
);
246 return (ret
!= 1) ? -EREMOTEIO
: 0;
249 static int si21_writereg(struct si21xx_state
*state
, u8 reg
, u8 data
)
252 u8 buf
[] = { reg
, data
};
253 struct i2c_msg msg
= {
254 .addr
= state
->config
->demod_address
,
260 ret
= i2c_transfer(state
->i2c
, &msg
, 1);
263 dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, ret == %i)\n",
264 __func__
, reg
, data
, ret
);
266 return (ret
!= 1) ? -EREMOTEIO
: 0;
269 static int si21_write(struct dvb_frontend
*fe
, const u8 buf
[], int len
)
271 struct si21xx_state
*state
= fe
->demodulator_priv
;
276 return si21_writereg(state
, buf
[0], buf
[1]);
279 static u8
si21_readreg(struct si21xx_state
*state
, u8 reg
)
284 struct i2c_msg msg
[] = {
286 .addr
= state
->config
->demod_address
,
291 .addr
= state
->config
->demod_address
,
298 ret
= i2c_transfer(state
->i2c
, msg
, 2);
301 dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
307 static int si21_readregs(struct si21xx_state
*state
, u8 reg1
, u8
*b
, u8 len
)
310 struct i2c_msg msg
[] = {
312 .addr
= state
->config
->demod_address
,
317 .addr
= state
->config
->demod_address
,
324 ret
= i2c_transfer(state
->i2c
, msg
, 2);
327 dprintk("%s: readreg error (ret == %i)\n", __func__
, ret
);
329 return ret
== 2 ? 0 : -1;
332 static int si21xx_wait_diseqc_idle(struct si21xx_state
*state
, int timeout
)
334 unsigned long start
= jiffies
;
336 dprintk("%s\n", __func__
);
338 while ((si21_readreg(state
, LNB_CTRL_REG_1
) & 0x8) == 8) {
339 if (jiffies
- start
> timeout
) {
340 dprintk("%s: timeout!!\n", __func__
);
349 static int si21xx_set_symbolrate(struct dvb_frontend
*fe
, u32 srate
)
351 struct si21xx_state
*state
= fe
->demodulator_priv
;
352 u32 sym_rate
, data_rate
;
354 u8 sym_rate_bytes
[3];
356 dprintk("%s : srate = %i\n", __func__
, srate
);
358 if ((srate
< 1000000) || (srate
> 45000000))
364 for (i
= 0; i
< 4; ++i
) {
366 sym_rate
= sym_rate
+ ((data_rate
% 100) * 0x800000) /
370 for (i
= 0; i
< 3; ++i
)
371 sym_rate_bytes
[i
] = (u8
)((sym_rate
>> (i
* 8)) & 0xff);
373 si21_writeregs(state
, SYM_RATE_REG_L
, sym_rate_bytes
, 0x03);
378 static int si21xx_send_diseqc_msg(struct dvb_frontend
*fe
,
379 struct dvb_diseqc_master_cmd
*m
)
381 struct si21xx_state
*state
= fe
->demodulator_priv
;
386 dprintk("%s\n", __func__
);
391 status
|= si21_readregs(state
, LNB_CTRL_STATUS_REG
, &lnb_status
, 0x01);
392 status
|= si21_readregs(state
, LNB_CTRL_REG_1
, &lnb_status
, 0x01);
395 status
|= si21_writeregs(state
, LNB_FIFO_REGS_0
, m
->msg
, m
->msg_len
);
397 LNB_CTRL_1
= (lnb_status
& 0x70);
398 LNB_CTRL_1
|= m
->msg_len
;
400 LNB_CTRL_1
|= 0x80; /* begin LNB signaling */
402 status
|= si21_writeregs(state
, LNB_CTRL_REG_1
, &LNB_CTRL_1
, 0x01);
407 static int si21xx_send_diseqc_burst(struct dvb_frontend
*fe
,
408 enum fe_sec_mini_cmd burst
)
410 struct si21xx_state
*state
= fe
->demodulator_priv
;
413 dprintk("%s\n", __func__
);
415 if (si21xx_wait_diseqc_idle(state
, 100) < 0)
418 val
= (0x80 | si21_readreg(state
, 0xc1));
419 if (si21_writereg(state
, LNB_CTRL_REG_1
,
420 burst
== SEC_MINI_A
? (val
& ~0x10) : (val
| 0x10)))
423 if (si21xx_wait_diseqc_idle(state
, 100) < 0)
426 if (si21_writereg(state
, LNB_CTRL_REG_1
, val
))
432 static int si21xx_set_tone(struct dvb_frontend
*fe
, enum fe_sec_tone_mode tone
)
434 struct si21xx_state
*state
= fe
->demodulator_priv
;
437 dprintk("%s\n", __func__
);
438 val
= (0x80 | si21_readreg(state
, LNB_CTRL_REG_1
));
442 return si21_writereg(state
, LNB_CTRL_REG_1
, val
| 0x20);
445 return si21_writereg(state
, LNB_CTRL_REG_1
, (val
& ~0x20));
452 static int si21xx_set_voltage(struct dvb_frontend
*fe
, enum fe_sec_voltage volt
)
454 struct si21xx_state
*state
= fe
->demodulator_priv
;
457 dprintk("%s: %s\n", __func__
,
458 volt
== SEC_VOLTAGE_13
? "SEC_VOLTAGE_13" :
459 volt
== SEC_VOLTAGE_18
? "SEC_VOLTAGE_18" : "??");
462 val
= (0x80 | si21_readreg(state
, LNB_CTRL_REG_1
));
466 return si21_writereg(state
, LNB_CTRL_REG_1
, val
| 0x40);
468 return si21_writereg(state
, LNB_CTRL_REG_1
, (val
& ~0x40));
474 static int si21xx_init(struct dvb_frontend
*fe
)
476 struct si21xx_state
*state
= fe
->demodulator_priv
;
483 dprintk("%s\n", __func__
);
485 for (i
= 0; ; i
+= 2) {
486 reg1
= serit_sp1511lhb_inittab
[i
];
487 val
= serit_sp1511lhb_inittab
[i
+1];
488 if (reg1
== 0xff && val
== 0xff)
490 si21_writeregs(state
, reg1
, &val
, 1);
493 /*DVB QPSK SYSTEM MODE REG*/
495 si21_writeregs(state
, SYSTEM_MODE_REG
, ®1
, 0x01);
497 /*transport stream config*/
500 sdata_form = LSB_FIRST;
501 clk_edge = FALLING_EDGE;
502 clk_mode = CLK_GAPPED_MODE;
503 strt_len = BYTE_WIDE;
504 sync_pol = ACTIVE_HIGH;
505 val_pol = ACTIVE_HIGH;
506 err_pol = ACTIVE_HIGH;
514 PARALLEL
+ (LSB_FIRST
<< 1)
515 + (FALLING_EDGE
<< 2) + (CLK_GAPPED_MODE
<< 3)
516 + (BYTE_WIDE
<< 4) + (ACTIVE_HIGH
<< 5)
517 + (ACTIVE_HIGH
<< 6) + (ACTIVE_HIGH
<< 7);
520 /* sclk_rate + (parity << 2)
521 + (data_delay << 3) + (clk_delay << 4)
522 + (pclk_smooth << 5);
524 status
|= si21_writeregs(state
, TS_CTRL_REG_1
, reg2
, 0x02);
526 dprintk(" %s : TS Set Error\n", __func__
);
532 static int si21_read_status(struct dvb_frontend
*fe
, enum fe_status
*status
)
534 struct si21xx_state
*state
= fe
->demodulator_priv
;
539 u8 signal
= si21_readreg(state
, ANALOG_AGC_POWER_LEVEL_REG
);
541 si21_readregs(state
, LOCK_STATUS_REG_1
, regs_read
, 0x02);
544 for (i
= 0; i
< 7; ++i
)
545 reg_read
|= ((regs_read
[0] >> i
) & 0x01) << (6 - i
);
547 lock
= ((reg_read
& 0x7f) | (regs_read
[1] & 0x80));
549 dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__
, lock
);
553 *status
|= FE_HAS_SIGNAL
;
556 *status
|= FE_HAS_CARRIER
;
559 *status
|= FE_HAS_VITERBI
;
562 *status
|= FE_HAS_SYNC
;
564 if ((lock
& 0x7b) == 0x7b)
565 *status
|= FE_HAS_LOCK
;
570 static int si21_read_signal_strength(struct dvb_frontend
*fe
, u16
*strength
)
572 struct si21xx_state
*state
= fe
->demodulator_priv
;
574 /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
575 (u8*)agclevel, 0x01);*/
577 u16 signal
= (3 * si21_readreg(state
, 0x27) *
578 si21_readreg(state
, 0x28));
580 dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__
,
581 si21_readreg(state
, 0x27),
582 si21_readreg(state
, 0x28), (int) signal
);
590 static int si21_read_ber(struct dvb_frontend
*fe
, u32
*ber
)
592 struct si21xx_state
*state
= fe
->demodulator_priv
;
594 dprintk("%s\n", __func__
);
596 if (state
->errmode
!= STATUS_BER
)
599 *ber
= (si21_readreg(state
, 0x1d) << 8) |
600 si21_readreg(state
, 0x1e);
605 static int si21_read_snr(struct dvb_frontend
*fe
, u16
*snr
)
607 struct si21xx_state
*state
= fe
->demodulator_priv
;
609 s32 xsnr
= 0xffff - ((si21_readreg(state
, 0x24) << 8) |
610 si21_readreg(state
, 0x25));
611 xsnr
= 3 * (xsnr
- 0xa100);
612 *snr
= (xsnr
> 0xffff) ? 0xffff : (xsnr
< 0) ? 0 : xsnr
;
614 dprintk("%s\n", __func__
);
619 static int si21_read_ucblocks(struct dvb_frontend
*fe
, u32
*ucblocks
)
621 struct si21xx_state
*state
= fe
->demodulator_priv
;
623 dprintk("%s\n", __func__
);
625 if (state
->errmode
!= STATUS_UCBLOCKS
)
628 *ucblocks
= (si21_readreg(state
, 0x1d) << 8) |
629 si21_readreg(state
, 0x1e);
634 /* initiates a channel acquisition sequence
635 using the specified symbol rate and code rate */
636 static int si21xx_setacquire(struct dvb_frontend
*fe
, int symbrate
,
637 enum fe_code_rate crate
)
640 struct si21xx_state
*state
= fe
->demodulator_priv
;
642 0x0, 0x01, 0x02, 0x04, 0x00,
643 0x8, 0x10, 0x20, 0x00, 0x3f
651 dprintk("%s\n", __func__
);
654 coderate_ptr
= coderates
[crate
];
656 si21xx_set_symbolrate(fe
, symbrate
);
658 /* write code rates to use in the Viterbi search */
659 status
|= si21_writeregs(state
,
661 &coderate_ptr
, 0x01);
663 /* clear acq_start bit */
664 status
|= si21_readregs(state
, ACQ_CTRL_REG_2
, ®
, 0x01);
666 status
|= si21_writeregs(state
, ACQ_CTRL_REG_2
, ®
, 0x01);
668 /* use new Carrier Frequency Offset Estimator (QuickLock) */
673 status
|= si21_writeregs(state
,
674 TWO_DB_BNDWDTH_THRSHLD_REG
,
677 status
|= si21_writeregs(state
,
678 LSA_CTRL_REG_1
, ®
, 1);
680 status
|= si21_writeregs(state
,
681 BLIND_SCAN_CTRL_REG
, ®
, 1);
682 /* start automatic acq */
683 status
|= si21_writeregs(state
,
684 ACQ_CTRL_REG_2
, &start_acq
, 0x01);
689 static int si21xx_set_frontend(struct dvb_frontend
*fe
)
691 struct si21xx_state
*state
= fe
->demodulator_priv
;
692 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
694 /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz)
695 datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/
698 unsigned char coarse_tune_freq
;
700 unsigned char sample_rate
= 0;
702 bool inband_interferer_ind
;
704 /* INTERMEDIATE VALUES */
705 int icoarse_tune_freq
; /* MHz */
706 int ifine_tune_freq
; /* MHz */
707 unsigned int band_high
;
708 unsigned int band_low
;
712 bool inband_interferer_div2
[ALLOWABLE_FS_COUNT
];
713 bool inband_interferer_div4
[ALLOWABLE_FS_COUNT
];
716 /* allowable sample rates for ADC in MHz */
717 int afs
[ALLOWABLE_FS_COUNT
] = { 200, 192, 193, 194, 195,
718 196, 204, 205, 206, 207
728 unsigned char regs
[4];
730 dprintk("%s : FE_SET_FRONTEND\n", __func__
);
732 if (c
->delivery_system
!= SYS_DVBS
) {
733 dprintk("%s: unsupported delivery system selected (%d)\n",
734 __func__
, c
->delivery_system
);
738 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
)
739 inband_interferer_div2
[i
] = inband_interferer_div4
[i
] = false;
741 if_limit_high
= -700000;
742 if_limit_low
= -100000;
747 rf_freq
= 10 * c
->frequency
;
748 data_rate
= c
->symbol_rate
/ 100;
752 band_low
= (rf_freq
- lnb_lo
) - ((lnb_uncertanity
* 200)
753 + (data_rate
* 135)) / 200;
755 band_high
= (rf_freq
- lnb_lo
) + ((lnb_uncertanity
* 200)
756 + (data_rate
* 135)) / 200;
759 icoarse_tune_freq
= 100000 *
760 (((rf_freq
- lnb_lo
) -
761 (if_limit_low
+ if_limit_high
) / 2)
764 ifine_tune_freq
= (rf_freq
- lnb_lo
) - icoarse_tune_freq
;
766 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
767 x1
= ((rf_freq
- lnb_lo
) / (afs
[i
] * 2500)) *
768 (afs
[i
] * 2500) + afs
[i
] * 2500;
770 x2
= ((rf_freq
- lnb_lo
) / (afs
[i
] * 2500)) *
773 if (((band_low
< x1
) && (x1
< band_high
)) ||
774 ((band_low
< x2
) && (x2
< band_high
)))
775 inband_interferer_div4
[i
] = true;
779 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
780 x1
= ((rf_freq
- lnb_lo
) / (afs
[i
] * 5000)) *
781 (afs
[i
] * 5000) + afs
[i
] * 5000;
783 x2
= ((rf_freq
- lnb_lo
) / (afs
[i
] * 5000)) *
786 if (((band_low
< x1
) && (x1
< band_high
)) ||
787 ((band_low
< x2
) && (x2
< band_high
)))
788 inband_interferer_div2
[i
] = true;
791 inband_interferer_ind
= true;
792 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
793 if (inband_interferer_div2
[i
] || inband_interferer_div4
[i
]) {
794 inband_interferer_ind
= false;
799 if (inband_interferer_ind
) {
800 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
801 if (!inband_interferer_div2
[i
]) {
802 sample_rate
= (u8
) afs
[i
];
807 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
808 if ((inband_interferer_div2
[i
] ||
809 !inband_interferer_div4
[i
])) {
810 sample_rate
= (u8
) afs
[i
];
817 if (sample_rate
> 207 || sample_rate
< 192)
820 fine_tune_freq
= ((0x4000 * (ifine_tune_freq
/ 10)) /
821 ((sample_rate
) * 1000));
823 coarse_tune_freq
= (u8
)(icoarse_tune_freq
/ 100000);
825 regs
[0] = sample_rate
;
826 regs
[1] = coarse_tune_freq
;
827 regs
[2] = fine_tune_freq
& 0xFF;
828 regs
[3] = fine_tune_freq
>> 8 & 0xFF;
830 status
|= si21_writeregs(state
, PLL_DIVISOR_REG
, ®s
[0], 0x04);
832 state
->fs
= sample_rate
;/*ADC MHz*/
833 si21xx_setacquire(fe
, c
->symbol_rate
, c
->fec_inner
);
838 static int si21xx_sleep(struct dvb_frontend
*fe
)
840 struct si21xx_state
*state
= fe
->demodulator_priv
;
843 dprintk("%s\n", __func__
);
845 si21_readregs(state
, SYSTEM_MODE_REG
, ®data
, 0x01);
847 si21_writeregs(state
, SYSTEM_MODE_REG
, ®data
, 0x01);
848 state
->initialised
= 0;
853 static void si21xx_release(struct dvb_frontend
*fe
)
855 struct si21xx_state
*state
= fe
->demodulator_priv
;
857 dprintk("%s\n", __func__
);
862 static const struct dvb_frontend_ops si21xx_ops
= {
863 .delsys
= { SYS_DVBS
},
865 .name
= "SL SI21XX DVB-S",
866 .frequency_min_hz
= 950 * MHz
,
867 .frequency_max_hz
= 2150 * MHz
,
868 .frequency_stepsize_hz
= 125 * kHz
,
869 .symbol_rate_min
= 1000000,
870 .symbol_rate_max
= 45000000,
871 .symbol_rate_tolerance
= 500, /* ppm */
872 .caps
= FE_CAN_FEC_1_2
| FE_CAN_FEC_2_3
| FE_CAN_FEC_3_4
|
873 FE_CAN_FEC_5_6
| FE_CAN_FEC_7_8
|
878 .release
= si21xx_release
,
880 .sleep
= si21xx_sleep
,
882 .read_status
= si21_read_status
,
883 .read_ber
= si21_read_ber
,
884 .read_signal_strength
= si21_read_signal_strength
,
885 .read_snr
= si21_read_snr
,
886 .read_ucblocks
= si21_read_ucblocks
,
887 .diseqc_send_master_cmd
= si21xx_send_diseqc_msg
,
888 .diseqc_send_burst
= si21xx_send_diseqc_burst
,
889 .set_tone
= si21xx_set_tone
,
890 .set_voltage
= si21xx_set_voltage
,
892 .set_frontend
= si21xx_set_frontend
,
895 struct dvb_frontend
*si21xx_attach(const struct si21xx_config
*config
,
896 struct i2c_adapter
*i2c
)
898 struct si21xx_state
*state
= NULL
;
901 dprintk("%s\n", __func__
);
903 /* allocate memory for the internal state */
904 state
= kzalloc(sizeof(struct si21xx_state
), GFP_KERNEL
);
908 /* setup the state */
909 state
->config
= config
;
911 state
->initialised
= 0;
912 state
->errmode
= STATUS_BER
;
914 /* check if the demod is there */
915 id
= si21_readreg(state
, SYSTEM_MODE_REG
);
916 si21_writereg(state
, SYSTEM_MODE_REG
, id
| 0x40); /* standby off */
918 id
= si21_readreg(state
, 0x00);
920 /* register 0x00 contains:
926 if (id
!= 0x04 && id
!= 0x14)
929 /* create dvb_frontend */
930 memcpy(&state
->frontend
.ops
, &si21xx_ops
,
931 sizeof(struct dvb_frontend_ops
));
932 state
->frontend
.demodulator_priv
= state
;
933 return &state
->frontend
;
939 EXPORT_SYMBOL(si21xx_attach
);
941 module_param(debug
, int, 0644);
942 MODULE_PARM_DESC(debug
, "Turn on/off frontend debugging (default:off).");
944 MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
945 MODULE_AUTHOR("Igor M. Liplianin");
946 MODULE_LICENSE("GPL");