Use dentry_path() to create full path to inode object
[pohmelfs.git] / drivers / media / dvb / frontends / si21xx.c
bloba68a64800df77ff7123ae6d18434820d6c95a2b4
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/init.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/string.h>
15 #include <linux/slab.h>
16 #include <linux/jiffies.h>
17 #include <asm/div64.h>
19 #include "dvb_frontend.h"
20 #include "si21xx.h"
22 #define REVISION_REG 0x00
23 #define SYSTEM_MODE_REG 0x01
24 #define TS_CTRL_REG_1 0x02
25 #define TS_CTRL_REG_2 0x03
26 #define PIN_CTRL_REG_1 0x04
27 #define PIN_CTRL_REG_2 0x05
28 #define LOCK_STATUS_REG_1 0x0f
29 #define LOCK_STATUS_REG_2 0x10
30 #define ACQ_STATUS_REG 0x11
31 #define ACQ_CTRL_REG_1 0x13
32 #define ACQ_CTRL_REG_2 0x14
33 #define PLL_DIVISOR_REG 0x15
34 #define COARSE_TUNE_REG 0x16
35 #define FINE_TUNE_REG_L 0x17
36 #define FINE_TUNE_REG_H 0x18
38 #define ANALOG_AGC_POWER_LEVEL_REG 0x28
39 #define CFO_ESTIMATOR_CTRL_REG_1 0x29
40 #define CFO_ESTIMATOR_CTRL_REG_2 0x2a
41 #define CFO_ESTIMATOR_CTRL_REG_3 0x2b
43 #define SYM_RATE_ESTIMATE_REG_L 0x31
44 #define SYM_RATE_ESTIMATE_REG_M 0x32
45 #define SYM_RATE_ESTIMATE_REG_H 0x33
47 #define CFO_ESTIMATOR_OFFSET_REG_L 0x36
48 #define CFO_ESTIMATOR_OFFSET_REG_H 0x37
49 #define CFO_ERROR_REG_L 0x38
50 #define CFO_ERROR_REG_H 0x39
51 #define SYM_RATE_ESTIMATOR_CTRL_REG 0x3a
53 #define SYM_RATE_REG_L 0x3f
54 #define SYM_RATE_REG_M 0x40
55 #define SYM_RATE_REG_H 0x41
56 #define SYM_RATE_ESTIMATOR_MAXIMUM_REG 0x42
57 #define SYM_RATE_ESTIMATOR_MINIMUM_REG 0x43
59 #define C_N_ESTIMATOR_CTRL_REG 0x7c
60 #define C_N_ESTIMATOR_THRSHLD_REG 0x7d
61 #define C_N_ESTIMATOR_LEVEL_REG_L 0x7e
62 #define C_N_ESTIMATOR_LEVEL_REG_H 0x7f
64 #define BLIND_SCAN_CTRL_REG 0x80
66 #define LSA_CTRL_REG_1 0x8D
67 #define SPCTRM_TILT_CORR_THRSHLD_REG 0x8f
68 #define ONE_DB_BNDWDTH_THRSHLD_REG 0x90
69 #define TWO_DB_BNDWDTH_THRSHLD_REG 0x91
70 #define THREE_DB_BNDWDTH_THRSHLD_REG 0x92
71 #define INBAND_POWER_THRSHLD_REG 0x93
72 #define REF_NOISE_LVL_MRGN_THRSHLD_REG 0x94
74 #define VIT_SRCH_CTRL_REG_1 0xa0
75 #define VIT_SRCH_CTRL_REG_2 0xa1
76 #define VIT_SRCH_CTRL_REG_3 0xa2
77 #define VIT_SRCH_STATUS_REG 0xa3
78 #define VITERBI_BER_COUNT_REG_L 0xab
79 #define REED_SOLOMON_CTRL_REG 0xb0
80 #define REED_SOLOMON_ERROR_COUNT_REG_L 0xb1
81 #define PRBS_CTRL_REG 0xb5
83 #define LNB_CTRL_REG_1 0xc0
84 #define LNB_CTRL_REG_2 0xc1
85 #define LNB_CTRL_REG_3 0xc2
86 #define LNB_CTRL_REG_4 0xc3
87 #define LNB_CTRL_STATUS_REG 0xc4
88 #define LNB_FIFO_REGS_0 0xc5
89 #define LNB_FIFO_REGS_1 0xc6
90 #define LNB_FIFO_REGS_2 0xc7
91 #define LNB_FIFO_REGS_3 0xc8
92 #define LNB_FIFO_REGS_4 0xc9
93 #define LNB_FIFO_REGS_5 0xca
94 #define LNB_SUPPLY_CTRL_REG_1 0xcb
95 #define LNB_SUPPLY_CTRL_REG_2 0xcc
96 #define LNB_SUPPLY_CTRL_REG_3 0xcd
97 #define LNB_SUPPLY_CTRL_REG_4 0xce
98 #define LNB_SUPPLY_STATUS_REG 0xcf
100 #define FAIL -1
101 #define PASS 0
103 #define ALLOWABLE_FS_COUNT 10
104 #define STATUS_BER 0
105 #define STATUS_UCBLOCKS 1
107 static int debug;
108 #define dprintk(args...) \
109 do { \
110 if (debug) \
111 printk(KERN_DEBUG "si21xx: " args); \
112 } while (0)
114 enum {
115 ACTIVE_HIGH,
116 ACTIVE_LOW
118 enum {
119 BYTE_WIDE,
120 BIT_WIDE
122 enum {
123 CLK_GAPPED_MODE,
124 CLK_CONTINUOUS_MODE
126 enum {
127 RISING_EDGE,
128 FALLING_EDGE
130 enum {
131 MSB_FIRST,
132 LSB_FIRST
134 enum {
135 SERIAL,
136 PARALLEL
139 struct si21xx_state {
140 struct i2c_adapter *i2c;
141 const struct si21xx_config *config;
142 struct dvb_frontend frontend;
143 u8 initialised:1;
144 int errmode;
145 int fs; /*Sampling rate of the ADC in MHz*/
148 /* register default initialization */
149 static u8 serit_sp1511lhb_inittab[] = {
150 0x01, 0x28, /* set i2c_inc_disable */
151 0x20, 0x03,
152 0x27, 0x20,
153 0xe0, 0x45,
154 0xe1, 0x08,
155 0xfe, 0x01,
156 0x01, 0x28,
157 0x89, 0x09,
158 0x04, 0x80,
159 0x05, 0x01,
160 0x06, 0x00,
161 0x20, 0x03,
162 0x24, 0x88,
163 0x29, 0x09,
164 0x2a, 0x0f,
165 0x2c, 0x10,
166 0x2d, 0x19,
167 0x2e, 0x08,
168 0x2f, 0x10,
169 0x30, 0x19,
170 0x34, 0x20,
171 0x35, 0x03,
172 0x45, 0x02,
173 0x46, 0x45,
174 0x47, 0xd0,
175 0x48, 0x00,
176 0x49, 0x40,
177 0x4a, 0x03,
178 0x4c, 0xfd,
179 0x4f, 0x2e,
180 0x50, 0x2e,
181 0x51, 0x10,
182 0x52, 0x10,
183 0x56, 0x92,
184 0x59, 0x00,
185 0x5a, 0x2d,
186 0x5b, 0x33,
187 0x5c, 0x1f,
188 0x5f, 0x76,
189 0x62, 0xc0,
190 0x63, 0xc0,
191 0x64, 0xf3,
192 0x65, 0xf3,
193 0x79, 0x40,
194 0x6a, 0x40,
195 0x6b, 0x0a,
196 0x6c, 0x80,
197 0x6d, 0x27,
198 0x71, 0x06,
199 0x75, 0x60,
200 0x78, 0x00,
201 0x79, 0xb5,
202 0x7c, 0x05,
203 0x7d, 0x1a,
204 0x87, 0x55,
205 0x88, 0x72,
206 0x8f, 0x08,
207 0x90, 0xe0,
208 0x94, 0x40,
209 0xa0, 0x3f,
210 0xa1, 0xc0,
211 0xa4, 0xcc,
212 0xa5, 0x66,
213 0xa6, 0x66,
214 0xa7, 0x7b,
215 0xa8, 0x7b,
216 0xa9, 0x7b,
217 0xaa, 0x9a,
218 0xed, 0x04,
219 0xad, 0x00,
220 0xae, 0x03,
221 0xcc, 0xab,
222 0x01, 0x08,
223 0xff, 0xff
226 /* low level read/writes */
227 static int si21_writeregs(struct si21xx_state *state, u8 reg1,
228 u8 *data, int len)
230 int ret;
231 u8 buf[60];/* = { reg1, data };*/
232 struct i2c_msg msg = {
233 .addr = state->config->demod_address,
234 .flags = 0,
235 .buf = buf,
236 .len = len + 1
239 msg.buf[0] = reg1;
240 memcpy(msg.buf + 1, data, len);
242 ret = i2c_transfer(state->i2c, &msg, 1);
244 if (ret != 1)
245 dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
246 "ret == %i)\n", __func__, reg1, data[0], ret);
248 return (ret != 1) ? -EREMOTEIO : 0;
251 static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)
253 int ret;
254 u8 buf[] = { reg, data };
255 struct i2c_msg msg = {
256 .addr = state->config->demod_address,
257 .flags = 0,
258 .buf = buf,
259 .len = 2
262 ret = i2c_transfer(state->i2c, &msg, 1);
264 if (ret != 1)
265 dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
266 "ret == %i)\n", __func__, reg, data, ret);
268 return (ret != 1) ? -EREMOTEIO : 0;
271 static int si21_write(struct dvb_frontend *fe, const u8 buf[], int len)
273 struct si21xx_state *state = fe->demodulator_priv;
275 if (len != 2)
276 return -EINVAL;
278 return si21_writereg(state, buf[0], buf[1]);
281 static u8 si21_readreg(struct si21xx_state *state, u8 reg)
283 int ret;
284 u8 b0[] = { reg };
285 u8 b1[] = { 0 };
286 struct i2c_msg msg[] = {
288 .addr = state->config->demod_address,
289 .flags = 0,
290 .buf = b0,
291 .len = 1
292 }, {
293 .addr = state->config->demod_address,
294 .flags = I2C_M_RD,
295 .buf = b1,
296 .len = 1
300 ret = i2c_transfer(state->i2c, msg, 2);
302 if (ret != 2)
303 dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
304 __func__, reg, ret);
306 return b1[0];
309 static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len)
311 int ret;
312 struct i2c_msg msg[] = {
314 .addr = state->config->demod_address,
315 .flags = 0,
316 .buf = &reg1,
317 .len = 1
318 }, {
319 .addr = state->config->demod_address,
320 .flags = I2C_M_RD,
321 .buf = b,
322 .len = len
326 ret = i2c_transfer(state->i2c, msg, 2);
328 if (ret != 2)
329 dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
331 return ret == 2 ? 0 : -1;
334 static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
336 unsigned long start = jiffies;
338 dprintk("%s\n", __func__);
340 while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) {
341 if (jiffies - start > timeout) {
342 dprintk("%s: timeout!!\n", __func__);
343 return -ETIMEDOUT;
345 msleep(10);
348 return 0;
351 static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate)
353 struct si21xx_state *state = fe->demodulator_priv;
354 u32 sym_rate, data_rate;
355 int i;
356 u8 sym_rate_bytes[3];
358 dprintk("%s : srate = %i\n", __func__ , srate);
360 if ((srate < 1000000) || (srate > 45000000))
361 return -EINVAL;
363 data_rate = srate;
364 sym_rate = 0;
366 for (i = 0; i < 4; ++i) {
367 sym_rate /= 100;
368 sym_rate = sym_rate + ((data_rate % 100) * 0x800000) /
369 state->fs;
370 data_rate /= 100;
372 for (i = 0; i < 3; ++i)
373 sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);
375 si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);
377 return 0;
380 static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,
381 struct dvb_diseqc_master_cmd *m)
383 struct si21xx_state *state = fe->demodulator_priv;
384 u8 lnb_status;
385 u8 LNB_CTRL_1;
386 int status;
388 dprintk("%s\n", __func__);
390 status = PASS;
391 LNB_CTRL_1 = 0;
393 status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);
394 status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);
396 /*fill the FIFO*/
397 status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);
399 LNB_CTRL_1 = (lnb_status & 0x70);
400 LNB_CTRL_1 |= m->msg_len;
402 LNB_CTRL_1 |= 0x80; /* begin LNB signaling */
404 status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);
406 return status;
409 static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
410 fe_sec_mini_cmd_t burst)
412 struct si21xx_state *state = fe->demodulator_priv;
413 u8 val;
415 dprintk("%s\n", __func__);
417 if (si21xx_wait_diseqc_idle(state, 100) < 0)
418 return -ETIMEDOUT;
420 val = (0x80 | si21_readreg(state, 0xc1));
421 if (si21_writereg(state, LNB_CTRL_REG_1,
422 burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10)))
423 return -EREMOTEIO;
425 if (si21xx_wait_diseqc_idle(state, 100) < 0)
426 return -ETIMEDOUT;
428 if (si21_writereg(state, LNB_CTRL_REG_1, val))
429 return -EREMOTEIO;
431 return 0;
433 /* 30.06.2008 */
434 static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
436 struct si21xx_state *state = fe->demodulator_priv;
437 u8 val;
439 dprintk("%s\n", __func__);
440 val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
442 switch (tone) {
443 case SEC_TONE_ON:
444 return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);
446 case SEC_TONE_OFF:
447 return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));
449 default:
450 return -EINVAL;
454 static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
456 struct si21xx_state *state = fe->demodulator_priv;
458 u8 val;
459 dprintk("%s: %s\n", __func__,
460 volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
461 volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
464 val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
466 switch (volt) {
467 case SEC_VOLTAGE_18:
468 return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40);
469 break;
470 case SEC_VOLTAGE_13:
471 return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40));
472 break;
473 default:
474 return -EINVAL;
478 static int si21xx_init(struct dvb_frontend *fe)
480 struct si21xx_state *state = fe->demodulator_priv;
481 int i;
482 int status = 0;
483 u8 reg1;
484 u8 val;
485 u8 reg2[2];
487 dprintk("%s\n", __func__);
489 for (i = 0; ; i += 2) {
490 reg1 = serit_sp1511lhb_inittab[i];
491 val = serit_sp1511lhb_inittab[i+1];
492 if (reg1 == 0xff && val == 0xff)
493 break;
494 si21_writeregs(state, reg1, &val, 1);
497 /*DVB QPSK SYSTEM MODE REG*/
498 reg1 = 0x08;
499 si21_writeregs(state, SYSTEM_MODE_REG, &reg1, 0x01);
501 /*transport stream config*/
503 mode = PARALLEL;
504 sdata_form = LSB_FIRST;
505 clk_edge = FALLING_EDGE;
506 clk_mode = CLK_GAPPED_MODE;
507 strt_len = BYTE_WIDE;
508 sync_pol = ACTIVE_HIGH;
509 val_pol = ACTIVE_HIGH;
510 err_pol = ACTIVE_HIGH;
511 sclk_rate = 0x00;
512 parity = 0x00 ;
513 data_delay = 0x00;
514 clk_delay = 0x00;
515 pclk_smooth = 0x00;
517 reg2[0] =
518 PARALLEL + (LSB_FIRST << 1)
519 + (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3)
520 + (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5)
521 + (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7);
523 reg2[1] = 0;
524 /* sclk_rate + (parity << 2)
525 + (data_delay << 3) + (clk_delay << 4)
526 + (pclk_smooth << 5);
528 status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02);
529 if (status != 0)
530 dprintk(" %s : TS Set Error\n", __func__);
532 return 0;
536 static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status)
538 struct si21xx_state *state = fe->demodulator_priv;
539 u8 regs_read[2];
540 u8 reg_read;
541 u8 i;
542 u8 lock;
543 u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG);
545 si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02);
546 reg_read = 0;
548 for (i = 0; i < 7; ++i)
549 reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i);
551 lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80));
553 dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock);
554 *status = 0;
556 if (signal > 10)
557 *status |= FE_HAS_SIGNAL;
559 if (lock & 0x2)
560 *status |= FE_HAS_CARRIER;
562 if (lock & 0x20)
563 *status |= FE_HAS_VITERBI;
565 if (lock & 0x40)
566 *status |= FE_HAS_SYNC;
568 if ((lock & 0x7b) == 0x7b)
569 *status |= FE_HAS_LOCK;
571 return 0;
574 static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
576 struct si21xx_state *state = fe->demodulator_priv;
578 /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
579 (u8*)agclevel, 0x01);*/
581 u16 signal = (3 * si21_readreg(state, 0x27) *
582 si21_readreg(state, 0x28));
584 dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__,
585 si21_readreg(state, 0x27),
586 si21_readreg(state, 0x28), (int) signal);
588 signal <<= 4;
589 *strength = signal;
591 return 0;
594 static int si21_read_ber(struct dvb_frontend *fe, u32 *ber)
596 struct si21xx_state *state = fe->demodulator_priv;
598 dprintk("%s\n", __func__);
600 if (state->errmode != STATUS_BER)
601 return 0;
603 *ber = (si21_readreg(state, 0x1d) << 8) |
604 si21_readreg(state, 0x1e);
606 return 0;
609 static int si21_read_snr(struct dvb_frontend *fe, u16 *snr)
611 struct si21xx_state *state = fe->demodulator_priv;
613 s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) |
614 si21_readreg(state, 0x25));
615 xsnr = 3 * (xsnr - 0xa100);
616 *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
618 dprintk("%s\n", __func__);
620 return 0;
623 static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
625 struct si21xx_state *state = fe->demodulator_priv;
627 dprintk("%s\n", __func__);
629 if (state->errmode != STATUS_UCBLOCKS)
630 *ucblocks = 0;
631 else
632 *ucblocks = (si21_readreg(state, 0x1d) << 8) |
633 si21_readreg(state, 0x1e);
635 return 0;
638 /* initiates a channel acquisition sequence
639 using the specified symbol rate and code rate */
640 static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
641 fe_code_rate_t crate)
644 struct si21xx_state *state = fe->demodulator_priv;
645 u8 coderates[] = {
646 0x0, 0x01, 0x02, 0x04, 0x00,
647 0x8, 0x10, 0x20, 0x00, 0x3f
650 u8 coderate_ptr;
651 int status;
652 u8 start_acq = 0x80;
653 u8 reg, regs[3];
655 dprintk("%s\n", __func__);
657 status = PASS;
658 coderate_ptr = coderates[crate];
660 si21xx_set_symbolrate(fe, symbrate);
662 /* write code rates to use in the Viterbi search */
663 status |= si21_writeregs(state,
664 VIT_SRCH_CTRL_REG_1,
665 &coderate_ptr, 0x01);
667 /* clear acq_start bit */
668 status |= si21_readregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
669 reg &= ~start_acq;
670 status |= si21_writeregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
672 /* use new Carrier Frequency Offset Estimator (QuickLock) */
673 regs[0] = 0xCB;
674 regs[1] = 0x40;
675 regs[2] = 0xCB;
677 status |= si21_writeregs(state,
678 TWO_DB_BNDWDTH_THRSHLD_REG,
679 &regs[0], 0x03);
680 reg = 0x56;
681 status |= si21_writeregs(state,
682 LSA_CTRL_REG_1, &reg, 1);
683 reg = 0x05;
684 status |= si21_writeregs(state,
685 BLIND_SCAN_CTRL_REG, &reg, 1);
686 /* start automatic acq */
687 status |= si21_writeregs(state,
688 ACQ_CTRL_REG_2, &start_acq, 0x01);
690 return status;
693 static int si21xx_set_frontend(struct dvb_frontend *fe)
695 struct si21xx_state *state = fe->demodulator_priv;
696 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
698 /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz)
699 datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/
701 /* in MHz */
702 unsigned char coarse_tune_freq;
703 int fine_tune_freq;
704 unsigned char sample_rate = 0;
705 /* boolean */
706 bool inband_interferer_ind;
708 /* INTERMEDIATE VALUES */
709 int icoarse_tune_freq; /* MHz */
710 int ifine_tune_freq; /* MHz */
711 unsigned int band_high;
712 unsigned int band_low;
713 unsigned int x1;
714 unsigned int x2;
715 int i;
716 bool inband_interferer_div2[ALLOWABLE_FS_COUNT];
717 bool inband_interferer_div4[ALLOWABLE_FS_COUNT];
718 int status;
720 /* allowable sample rates for ADC in MHz */
721 int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,
722 196, 204, 205, 206, 207
724 /* in MHz */
725 int if_limit_high;
726 int if_limit_low;
727 int lnb_lo;
728 int lnb_uncertanity;
730 int rf_freq;
731 int data_rate;
732 unsigned char regs[4];
734 dprintk("%s : FE_SET_FRONTEND\n", __func__);
736 if (c->delivery_system != SYS_DVBS) {
737 dprintk("%s: unsupported delivery system selected (%d)\n",
738 __func__, c->delivery_system);
739 return -EOPNOTSUPP;
742 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
743 inband_interferer_div2[i] = inband_interferer_div4[i] = false;
745 if_limit_high = -700000;
746 if_limit_low = -100000;
747 /* in MHz */
748 lnb_lo = 0;
749 lnb_uncertanity = 0;
751 rf_freq = 10 * c->frequency ;
752 data_rate = c->symbol_rate / 100;
754 status = PASS;
756 band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)
757 + (data_rate * 135)) / 200;
759 band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200)
760 + (data_rate * 135)) / 200;
763 icoarse_tune_freq = 100000 *
764 (((rf_freq - lnb_lo) -
765 (if_limit_low + if_limit_high) / 2)
766 / 100000);
768 ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ;
770 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
771 x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
772 (afs[i] * 2500) + afs[i] * 2500;
774 x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
775 (afs[i] * 2500);
777 if (((band_low < x1) && (x1 < band_high)) ||
778 ((band_low < x2) && (x2 < band_high)))
779 inband_interferer_div4[i] = true;
783 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
784 x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
785 (afs[i] * 5000) + afs[i] * 5000;
787 x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
788 (afs[i] * 5000);
790 if (((band_low < x1) && (x1 < band_high)) ||
791 ((band_low < x2) && (x2 < band_high)))
792 inband_interferer_div2[i] = true;
795 inband_interferer_ind = true;
796 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
797 if (inband_interferer_div2[i] || inband_interferer_div4[i]) {
798 inband_interferer_ind = false;
799 break;
803 if (inband_interferer_ind) {
804 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
805 if (!inband_interferer_div2[i]) {
806 sample_rate = (u8) afs[i];
807 break;
810 } else {
811 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
812 if ((inband_interferer_div2[i] ||
813 !inband_interferer_div4[i])) {
814 sample_rate = (u8) afs[i];
815 break;
821 if (sample_rate > 207 || sample_rate < 192)
822 sample_rate = 200;
824 fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) /
825 ((sample_rate) * 1000));
827 coarse_tune_freq = (u8)(icoarse_tune_freq / 100000);
829 regs[0] = sample_rate;
830 regs[1] = coarse_tune_freq;
831 regs[2] = fine_tune_freq & 0xFF;
832 regs[3] = fine_tune_freq >> 8 & 0xFF;
834 status |= si21_writeregs(state, PLL_DIVISOR_REG, &regs[0], 0x04);
836 state->fs = sample_rate;/*ADC MHz*/
837 si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);
839 return 0;
842 static int si21xx_sleep(struct dvb_frontend *fe)
844 struct si21xx_state *state = fe->demodulator_priv;
845 u8 regdata;
847 dprintk("%s\n", __func__);
849 si21_readregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
850 regdata |= 1 << 6;
851 si21_writeregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
852 state->initialised = 0;
854 return 0;
857 static void si21xx_release(struct dvb_frontend *fe)
859 struct si21xx_state *state = fe->demodulator_priv;
861 dprintk("%s\n", __func__);
863 kfree(state);
866 static struct dvb_frontend_ops si21xx_ops = {
867 .delsys = { SYS_DVBS },
868 .info = {
869 .name = "SL SI21XX DVB-S",
870 .frequency_min = 950000,
871 .frequency_max = 2150000,
872 .frequency_stepsize = 125, /* kHz for QPSK frontends */
873 .frequency_tolerance = 0,
874 .symbol_rate_min = 1000000,
875 .symbol_rate_max = 45000000,
876 .symbol_rate_tolerance = 500, /* ppm */
877 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
878 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
879 FE_CAN_QPSK |
880 FE_CAN_FEC_AUTO
883 .release = si21xx_release,
884 .init = si21xx_init,
885 .sleep = si21xx_sleep,
886 .write = si21_write,
887 .read_status = si21_read_status,
888 .read_ber = si21_read_ber,
889 .read_signal_strength = si21_read_signal_strength,
890 .read_snr = si21_read_snr,
891 .read_ucblocks = si21_read_ucblocks,
892 .diseqc_send_master_cmd = si21xx_send_diseqc_msg,
893 .diseqc_send_burst = si21xx_send_diseqc_burst,
894 .set_tone = si21xx_set_tone,
895 .set_voltage = si21xx_set_voltage,
897 .set_frontend = si21xx_set_frontend,
900 struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
901 struct i2c_adapter *i2c)
903 struct si21xx_state *state = NULL;
904 int id;
906 dprintk("%s\n", __func__);
908 /* allocate memory for the internal state */
909 state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL);
910 if (state == NULL)
911 goto error;
913 /* setup the state */
914 state->config = config;
915 state->i2c = i2c;
916 state->initialised = 0;
917 state->errmode = STATUS_BER;
919 /* check if the demod is there */
920 id = si21_readreg(state, SYSTEM_MODE_REG);
921 si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */
922 msleep(200);
923 id = si21_readreg(state, 0x00);
925 /* register 0x00 contains:
926 0x34 for SI2107
927 0x24 for SI2108
928 0x14 for SI2109
929 0x04 for SI2110
931 if (id != 0x04 && id != 0x14)
932 goto error;
934 /* create dvb_frontend */
935 memcpy(&state->frontend.ops, &si21xx_ops,
936 sizeof(struct dvb_frontend_ops));
937 state->frontend.demodulator_priv = state;
938 return &state->frontend;
940 error:
941 kfree(state);
942 return NULL;
944 EXPORT_SYMBOL(si21xx_attach);
946 module_param(debug, int, 0644);
947 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
949 MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
950 MODULE_AUTHOR("Igor M. Liplianin");
951 MODULE_LICENSE("GPL");