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);
469 return si21_writereg(state
, LNB_CTRL_REG_1
, (val
& ~0x40));
476 static int si21xx_init(struct dvb_frontend
*fe
)
478 struct si21xx_state
*state
= fe
->demodulator_priv
;
485 dprintk("%s\n", __func__
);
487 for (i
= 0; ; i
+= 2) {
488 reg1
= serit_sp1511lhb_inittab
[i
];
489 val
= serit_sp1511lhb_inittab
[i
+1];
490 if (reg1
== 0xff && val
== 0xff)
492 si21_writeregs(state
, reg1
, &val
, 1);
495 /*DVB QPSK SYSTEM MODE REG*/
497 si21_writeregs(state
, SYSTEM_MODE_REG
, ®1
, 0x01);
499 /*transport stream config*/
502 sdata_form = LSB_FIRST;
503 clk_edge = FALLING_EDGE;
504 clk_mode = CLK_GAPPED_MODE;
505 strt_len = BYTE_WIDE;
506 sync_pol = ACTIVE_HIGH;
507 val_pol = ACTIVE_HIGH;
508 err_pol = ACTIVE_HIGH;
516 PARALLEL
+ (LSB_FIRST
<< 1)
517 + (FALLING_EDGE
<< 2) + (CLK_GAPPED_MODE
<< 3)
518 + (BYTE_WIDE
<< 4) + (ACTIVE_HIGH
<< 5)
519 + (ACTIVE_HIGH
<< 6) + (ACTIVE_HIGH
<< 7);
522 /* sclk_rate + (parity << 2)
523 + (data_delay << 3) + (clk_delay << 4)
524 + (pclk_smooth << 5);
526 status
|= si21_writeregs(state
, TS_CTRL_REG_1
, reg2
, 0x02);
528 dprintk(" %s : TS Set Error\n", __func__
);
534 static int si21_read_status(struct dvb_frontend
*fe
, enum fe_status
*status
)
536 struct si21xx_state
*state
= fe
->demodulator_priv
;
541 u8 signal
= si21_readreg(state
, ANALOG_AGC_POWER_LEVEL_REG
);
543 si21_readregs(state
, LOCK_STATUS_REG_1
, regs_read
, 0x02);
546 for (i
= 0; i
< 7; ++i
)
547 reg_read
|= ((regs_read
[0] >> i
) & 0x01) << (6 - i
);
549 lock
= ((reg_read
& 0x7f) | (regs_read
[1] & 0x80));
551 dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__
, lock
);
555 *status
|= FE_HAS_SIGNAL
;
558 *status
|= FE_HAS_CARRIER
;
561 *status
|= FE_HAS_VITERBI
;
564 *status
|= FE_HAS_SYNC
;
566 if ((lock
& 0x7b) == 0x7b)
567 *status
|= FE_HAS_LOCK
;
572 static int si21_read_signal_strength(struct dvb_frontend
*fe
, u16
*strength
)
574 struct si21xx_state
*state
= fe
->demodulator_priv
;
576 /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
577 (u8*)agclevel, 0x01);*/
579 u16 signal
= (3 * si21_readreg(state
, 0x27) *
580 si21_readreg(state
, 0x28));
582 dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__
,
583 si21_readreg(state
, 0x27),
584 si21_readreg(state
, 0x28), (int) signal
);
592 static int si21_read_ber(struct dvb_frontend
*fe
, u32
*ber
)
594 struct si21xx_state
*state
= fe
->demodulator_priv
;
596 dprintk("%s\n", __func__
);
598 if (state
->errmode
!= STATUS_BER
)
601 *ber
= (si21_readreg(state
, 0x1d) << 8) |
602 si21_readreg(state
, 0x1e);
607 static int si21_read_snr(struct dvb_frontend
*fe
, u16
*snr
)
609 struct si21xx_state
*state
= fe
->demodulator_priv
;
611 s32 xsnr
= 0xffff - ((si21_readreg(state
, 0x24) << 8) |
612 si21_readreg(state
, 0x25));
613 xsnr
= 3 * (xsnr
- 0xa100);
614 *snr
= (xsnr
> 0xffff) ? 0xffff : (xsnr
< 0) ? 0 : xsnr
;
616 dprintk("%s\n", __func__
);
621 static int si21_read_ucblocks(struct dvb_frontend
*fe
, u32
*ucblocks
)
623 struct si21xx_state
*state
= fe
->demodulator_priv
;
625 dprintk("%s\n", __func__
);
627 if (state
->errmode
!= STATUS_UCBLOCKS
)
630 *ucblocks
= (si21_readreg(state
, 0x1d) << 8) |
631 si21_readreg(state
, 0x1e);
636 /* initiates a channel acquisition sequence
637 using the specified symbol rate and code rate */
638 static int si21xx_setacquire(struct dvb_frontend
*fe
, int symbrate
,
639 enum fe_code_rate crate
)
642 struct si21xx_state
*state
= fe
->demodulator_priv
;
644 0x0, 0x01, 0x02, 0x04, 0x00,
645 0x8, 0x10, 0x20, 0x00, 0x3f
653 dprintk("%s\n", __func__
);
656 coderate_ptr
= coderates
[crate
];
658 si21xx_set_symbolrate(fe
, symbrate
);
660 /* write code rates to use in the Viterbi search */
661 status
|= si21_writeregs(state
,
663 &coderate_ptr
, 0x01);
665 /* clear acq_start bit */
666 status
|= si21_readregs(state
, ACQ_CTRL_REG_2
, ®
, 0x01);
668 status
|= si21_writeregs(state
, ACQ_CTRL_REG_2
, ®
, 0x01);
670 /* use new Carrier Frequency Offset Estimator (QuickLock) */
675 status
|= si21_writeregs(state
,
676 TWO_DB_BNDWDTH_THRSHLD_REG
,
679 status
|= si21_writeregs(state
,
680 LSA_CTRL_REG_1
, ®
, 1);
682 status
|= si21_writeregs(state
,
683 BLIND_SCAN_CTRL_REG
, ®
, 1);
684 /* start automatic acq */
685 status
|= si21_writeregs(state
,
686 ACQ_CTRL_REG_2
, &start_acq
, 0x01);
691 static int si21xx_set_frontend(struct dvb_frontend
*fe
)
693 struct si21xx_state
*state
= fe
->demodulator_priv
;
694 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
696 /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz)
697 datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/
700 unsigned char coarse_tune_freq
;
702 unsigned char sample_rate
= 0;
704 bool inband_interferer_ind
;
706 /* INTERMEDIATE VALUES */
707 int icoarse_tune_freq
; /* MHz */
708 int ifine_tune_freq
; /* MHz */
709 unsigned int band_high
;
710 unsigned int band_low
;
714 bool inband_interferer_div2
[ALLOWABLE_FS_COUNT
];
715 bool inband_interferer_div4
[ALLOWABLE_FS_COUNT
];
718 /* allowable sample rates for ADC in MHz */
719 int afs
[ALLOWABLE_FS_COUNT
] = { 200, 192, 193, 194, 195,
720 196, 204, 205, 206, 207
730 unsigned char regs
[4];
732 dprintk("%s : FE_SET_FRONTEND\n", __func__
);
734 if (c
->delivery_system
!= SYS_DVBS
) {
735 dprintk("%s: unsupported delivery system selected (%d)\n",
736 __func__
, c
->delivery_system
);
740 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
)
741 inband_interferer_div2
[i
] = inband_interferer_div4
[i
] = false;
743 if_limit_high
= -700000;
744 if_limit_low
= -100000;
749 rf_freq
= 10 * c
->frequency
;
750 data_rate
= c
->symbol_rate
/ 100;
754 band_low
= (rf_freq
- lnb_lo
) - ((lnb_uncertanity
* 200)
755 + (data_rate
* 135)) / 200;
757 band_high
= (rf_freq
- lnb_lo
) + ((lnb_uncertanity
* 200)
758 + (data_rate
* 135)) / 200;
761 icoarse_tune_freq
= 100000 *
762 (((rf_freq
- lnb_lo
) -
763 (if_limit_low
+ if_limit_high
) / 2)
766 ifine_tune_freq
= (rf_freq
- lnb_lo
) - icoarse_tune_freq
;
768 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
769 x1
= ((rf_freq
- lnb_lo
) / (afs
[i
] * 2500)) *
770 (afs
[i
] * 2500) + afs
[i
] * 2500;
772 x2
= ((rf_freq
- lnb_lo
) / (afs
[i
] * 2500)) *
775 if (((band_low
< x1
) && (x1
< band_high
)) ||
776 ((band_low
< x2
) && (x2
< band_high
)))
777 inband_interferer_div4
[i
] = true;
781 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
782 x1
= ((rf_freq
- lnb_lo
) / (afs
[i
] * 5000)) *
783 (afs
[i
] * 5000) + afs
[i
] * 5000;
785 x2
= ((rf_freq
- lnb_lo
) / (afs
[i
] * 5000)) *
788 if (((band_low
< x1
) && (x1
< band_high
)) ||
789 ((band_low
< x2
) && (x2
< band_high
)))
790 inband_interferer_div2
[i
] = true;
793 inband_interferer_ind
= true;
794 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
795 if (inband_interferer_div2
[i
] || inband_interferer_div4
[i
]) {
796 inband_interferer_ind
= false;
801 if (inband_interferer_ind
) {
802 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
803 if (!inband_interferer_div2
[i
]) {
804 sample_rate
= (u8
) afs
[i
];
809 for (i
= 0; i
< ALLOWABLE_FS_COUNT
; ++i
) {
810 if ((inband_interferer_div2
[i
] ||
811 !inband_interferer_div4
[i
])) {
812 sample_rate
= (u8
) afs
[i
];
819 if (sample_rate
> 207 || sample_rate
< 192)
822 fine_tune_freq
= ((0x4000 * (ifine_tune_freq
/ 10)) /
823 ((sample_rate
) * 1000));
825 coarse_tune_freq
= (u8
)(icoarse_tune_freq
/ 100000);
827 regs
[0] = sample_rate
;
828 regs
[1] = coarse_tune_freq
;
829 regs
[2] = fine_tune_freq
& 0xFF;
830 regs
[3] = fine_tune_freq
>> 8 & 0xFF;
832 status
|= si21_writeregs(state
, PLL_DIVISOR_REG
, ®s
[0], 0x04);
834 state
->fs
= sample_rate
;/*ADC MHz*/
835 si21xx_setacquire(fe
, c
->symbol_rate
, c
->fec_inner
);
840 static int si21xx_sleep(struct dvb_frontend
*fe
)
842 struct si21xx_state
*state
= fe
->demodulator_priv
;
845 dprintk("%s\n", __func__
);
847 si21_readregs(state
, SYSTEM_MODE_REG
, ®data
, 0x01);
849 si21_writeregs(state
, SYSTEM_MODE_REG
, ®data
, 0x01);
850 state
->initialised
= 0;
855 static void si21xx_release(struct dvb_frontend
*fe
)
857 struct si21xx_state
*state
= fe
->demodulator_priv
;
859 dprintk("%s\n", __func__
);
864 static const struct dvb_frontend_ops si21xx_ops
= {
865 .delsys
= { SYS_DVBS
},
867 .name
= "SL SI21XX DVB-S",
868 .frequency_min_hz
= 950 * MHz
,
869 .frequency_max_hz
= 2150 * MHz
,
870 .frequency_stepsize_hz
= 125 * kHz
,
871 .symbol_rate_min
= 1000000,
872 .symbol_rate_max
= 45000000,
873 .symbol_rate_tolerance
= 500, /* ppm */
874 .caps
= FE_CAN_FEC_1_2
| FE_CAN_FEC_2_3
| FE_CAN_FEC_3_4
|
875 FE_CAN_FEC_5_6
| FE_CAN_FEC_7_8
|
880 .release
= si21xx_release
,
882 .sleep
= si21xx_sleep
,
884 .read_status
= si21_read_status
,
885 .read_ber
= si21_read_ber
,
886 .read_signal_strength
= si21_read_signal_strength
,
887 .read_snr
= si21_read_snr
,
888 .read_ucblocks
= si21_read_ucblocks
,
889 .diseqc_send_master_cmd
= si21xx_send_diseqc_msg
,
890 .diseqc_send_burst
= si21xx_send_diseqc_burst
,
891 .set_tone
= si21xx_set_tone
,
892 .set_voltage
= si21xx_set_voltage
,
894 .set_frontend
= si21xx_set_frontend
,
897 struct dvb_frontend
*si21xx_attach(const struct si21xx_config
*config
,
898 struct i2c_adapter
*i2c
)
900 struct si21xx_state
*state
= NULL
;
903 dprintk("%s\n", __func__
);
905 /* allocate memory for the internal state */
906 state
= kzalloc(sizeof(struct si21xx_state
), GFP_KERNEL
);
910 /* setup the state */
911 state
->config
= config
;
913 state
->initialised
= 0;
914 state
->errmode
= STATUS_BER
;
916 /* check if the demod is there */
917 id
= si21_readreg(state
, SYSTEM_MODE_REG
);
918 si21_writereg(state
, SYSTEM_MODE_REG
, id
| 0x40); /* standby off */
920 id
= si21_readreg(state
, 0x00);
922 /* register 0x00 contains:
928 if (id
!= 0x04 && id
!= 0x14)
931 /* create dvb_frontend */
932 memcpy(&state
->frontend
.ops
, &si21xx_ops
,
933 sizeof(struct dvb_frontend_ops
));
934 state
->frontend
.demodulator_priv
= state
;
935 return &state
->frontend
;
941 EXPORT_SYMBOL(si21xx_attach
);
943 module_param(debug
, int, 0644);
944 MODULE_PARM_DESC(debug
, "Turn on/off frontend debugging (default:off).");
946 MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
947 MODULE_AUTHOR("Igor M. Liplianin");
948 MODULE_LICENSE("GPL");