blob: 4b0c99a08a852ebb01b155cb7c21d27c9b969cd4 [file] [log] [blame]
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -03001/* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator
2*
3* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
4*
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.
9*
10*/
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -030011#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>
18
19#include "dvb_frontend.h"
20#include "si21xx.h"
21
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
37
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
42
43#define SYM_RATE_ESTIMATE_REG_L 0x31
44#define SYM_RATE_ESTIMATE_REG_M 0x32
45#define SYM_RATE_ESTIMATE_REG_H 0x33
46
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
52
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
58
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
63
64#define BLIND_SCAN_CTRL_REG 0x80
65
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
73
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
82
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
99
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300100#define FAIL -1
101#define PASS 0
102
103#define ALLOWABLE_FS_COUNT 10
104#define STATUS_BER 0
105#define STATUS_UCBLOCKS 1
106
107static int debug;
108#define dprintk(args...) \
109 do { \
110 if (debug) \
111 printk(KERN_DEBUG "si21xx: " args); \
112 } while (0)
113
114enum {
115 ACTIVE_HIGH,
116 ACTIVE_LOW
117};
118enum {
119 BYTE_WIDE,
120 BIT_WIDE
121};
122enum {
123 CLK_GAPPED_MODE,
124 CLK_CONTINUOUS_MODE
125};
126enum {
127 RISING_EDGE,
128 FALLING_EDGE
129};
130enum {
131 MSB_FIRST,
132 LSB_FIRST
133};
134enum {
135 SERIAL,
136 PARALLEL
137};
138
139struct 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*/
146};
147
148/* register default initialization */
149static 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
224};
225
226/* low level read/writes */
227static int si21_writeregs(struct si21xx_state *state, u8 reg1,
228 u8 *data, int len)
229{
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
237 };
238
239 msg.buf[0] = reg1;
240 memcpy(msg.buf + 1, data, len);
241
242 ret = i2c_transfer(state->i2c, &msg, 1);
243
244 if (ret != 1)
245 dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
246 "ret == %i)\n", __func__, reg1, data[0], ret);
247
248 return (ret != 1) ? -EREMOTEIO : 0;
249}
250
251static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)
252{
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
260 };
261
262 ret = i2c_transfer(state->i2c, &msg, 1);
263
264 if (ret != 1)
265 dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
266 "ret == %i)\n", __func__, reg, data, ret);
267
268 return (ret != 1) ? -EREMOTEIO : 0;
269}
270
lawrence rust2e4e98e2010-08-25 09:50:20 -0300271static int si21_write(struct dvb_frontend *fe, const u8 buf[], int len)
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300272{
273 struct si21xx_state *state = fe->demodulator_priv;
274
275 if (len != 2)
276 return -EINVAL;
277
278 return si21_writereg(state, buf[0], buf[1]);
279}
280
281static u8 si21_readreg(struct si21xx_state *state, u8 reg)
282{
283 int ret;
284 u8 b0[] = { reg };
285 u8 b1[] = { 0 };
286 struct i2c_msg msg[] = {
287 {
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
297 }
298 };
299
300 ret = i2c_transfer(state->i2c, msg, 2);
301
302 if (ret != 2)
303 dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
304 __func__, reg, ret);
305
306 return b1[0];
307}
308
309static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len)
310{
311 int ret;
312 struct i2c_msg msg[] = {
313 {
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
323 }
324 };
325
326 ret = i2c_transfer(state->i2c, msg, 2);
327
328 if (ret != 2)
329 dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
330
331 return ret == 2 ? 0 : -1;
332}
333
334static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
335{
336 unsigned long start = jiffies;
337
338 dprintk("%s\n", __func__);
339
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;
344 }
345 msleep(10);
346 };
347
348 return 0;
349}
350
351static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate)
352{
353 struct si21xx_state *state = fe->demodulator_priv;
354 u32 sym_rate, data_rate;
355 int i;
356 u8 sym_rate_bytes[3];
357
358 dprintk("%s : srate = %i\n", __func__ , srate);
359
360 if ((srate < 1000000) || (srate > 45000000))
361 return -EINVAL;
362
363 data_rate = srate;
364 sym_rate = 0;
365
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;
371 }
372 for (i = 0; i < 3; ++i)
373 sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);
374
375 si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);
376
377 return 0;
378}
379
380static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,
381 struct dvb_diseqc_master_cmd *m)
382{
383 struct si21xx_state *state = fe->demodulator_priv;
384 u8 lnb_status;
385 u8 LNB_CTRL_1;
386 int status;
387
388 dprintk("%s\n", __func__);
389
390 status = PASS;
391 LNB_CTRL_1 = 0;
392
393 status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);
394 status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);
395
396 /*fill the FIFO*/
397 status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);
398
399 LNB_CTRL_1 = (lnb_status & 0x70);
400 LNB_CTRL_1 |= m->msg_len;
401
402 LNB_CTRL_1 |= 0x80; /* begin LNB signaling */
403
404 status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);
405
406 return status;
407}
408
409static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
410 fe_sec_mini_cmd_t burst)
411{
412 struct si21xx_state *state = fe->demodulator_priv;
413 u8 val;
414
415 dprintk("%s\n", __func__);
416
417 if (si21xx_wait_diseqc_idle(state, 100) < 0)
418 return -ETIMEDOUT;
419
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;
424
425 if (si21xx_wait_diseqc_idle(state, 100) < 0)
426 return -ETIMEDOUT;
427
428 if (si21_writereg(state, LNB_CTRL_REG_1, val))
429 return -EREMOTEIO;
430
431 return 0;
432}
433/* 30.06.2008 */
434static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
435{
436 struct si21xx_state *state = fe->demodulator_priv;
437 u8 val;
438
439 dprintk("%s\n", __func__);
440 val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
441
442 switch (tone) {
443 case SEC_TONE_ON:
444 return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);
445
446 case SEC_TONE_OFF:
447 return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));
448
449 default:
450 return -EINVAL;
451 }
452}
453
454static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
455{
456 struct si21xx_state *state = fe->demodulator_priv;
457
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" : "??");
462
463
464 val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
465
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;
475 };
476}
477
478static int si21xx_init(struct dvb_frontend *fe)
479{
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];
486
487 dprintk("%s\n", __func__);
488
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);
495 }
496
497 /*DVB QPSK SYSTEM MODE REG*/
498 reg1 = 0x08;
499 si21_writeregs(state, SYSTEM_MODE_REG, &reg1, 0x01);
500
501 /*transport stream config*/
502 /*
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;
516 */
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);
522
523 reg2[1] = 0;
524 /* sclk_rate + (parity << 2)
525 + (data_delay << 3) + (clk_delay << 4)
526 + (pclk_smooth << 5);
527 */
528 status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02);
529 if (status != 0)
530 dprintk(" %s : TS Set Error\n", __func__);
531
532 return 0;
533
534}
535
536static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status)
537{
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);
544
545 si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02);
546 reg_read = 0;
547
548 for (i = 0; i < 7; ++i)
549 reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i);
550
551 lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80));
552
553 dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock);
554 *status = 0;
555
556 if (signal > 10)
557 *status |= FE_HAS_SIGNAL;
558
559 if (lock & 0x2)
560 *status |= FE_HAS_CARRIER;
561
562 if (lock & 0x20)
563 *status |= FE_HAS_VITERBI;
564
565 if (lock & 0x40)
566 *status |= FE_HAS_SYNC;
567
568 if ((lock & 0x7b) == 0x7b)
569 *status |= FE_HAS_LOCK;
570
571 return 0;
572}
573
574static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
575{
576 struct si21xx_state *state = fe->demodulator_priv;
577
578 /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
579 (u8*)agclevel, 0x01);*/
580
581 u16 signal = (3 * si21_readreg(state, 0x27) *
582 si21_readreg(state, 0x28));
583
584 dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__,
585 si21_readreg(state, 0x27),
586 si21_readreg(state, 0x28), (int) signal);
587
588 signal <<= 4;
589 *strength = signal;
590
591 return 0;
592}
593
594static int si21_read_ber(struct dvb_frontend *fe, u32 *ber)
595{
596 struct si21xx_state *state = fe->demodulator_priv;
597
598 dprintk("%s\n", __func__);
599
600 if (state->errmode != STATUS_BER)
601 return 0;
602
603 *ber = (si21_readreg(state, 0x1d) << 8) |
604 si21_readreg(state, 0x1e);
605
606 return 0;
607}
608
609static int si21_read_snr(struct dvb_frontend *fe, u16 *snr)
610{
611 struct si21xx_state *state = fe->demodulator_priv;
612
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;
617
618 dprintk("%s\n", __func__);
619
620 return 0;
621}
622
623static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
624{
625 struct si21xx_state *state = fe->demodulator_priv;
626
627 dprintk("%s\n", __func__);
628
629 if (state->errmode != STATUS_UCBLOCKS)
630 *ucblocks = 0;
631 else
632 *ucblocks = (si21_readreg(state, 0x1d) << 8) |
633 si21_readreg(state, 0x1e);
634
635 return 0;
636}
637
638/* initiates a channel acquisition sequence
639 using the specified symbol rate and code rate */
640static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
641 fe_code_rate_t crate)
642{
643
644 struct si21xx_state *state = fe->demodulator_priv;
645 u8 coderates[] = {
646 0x0, 0x01, 0x02, 0x04, 0x00,
647 0x8, 0x10, 0x20, 0x00, 0x3f
648 };
649
650 u8 coderate_ptr;
651 int status;
652 u8 start_acq = 0x80;
653 u8 reg, regs[3];
654
655 dprintk("%s\n", __func__);
656
657 status = PASS;
658 coderate_ptr = coderates[crate];
659
660 si21xx_set_symbolrate(fe, symbrate);
661
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);
666
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);
671
672 /* use new Carrier Frequency Offset Estimator (QuickLock) */
673 regs[0] = 0xCB;
674 regs[1] = 0x40;
675 regs[2] = 0xCB;
676
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);
689
690 return status;
691}
692
693static int si21xx_set_property(struct dvb_frontend *fe, struct dtv_property *p)
694{
695 dprintk("%s(..)\n", __func__);
696 return 0;
697}
698
699static int si21xx_get_property(struct dvb_frontend *fe, struct dtv_property *p)
700{
701 dprintk("%s(..)\n", __func__);
702 return 0;
703}
704
705static int si21xx_set_frontend(struct dvb_frontend *fe,
706 struct dvb_frontend_parameters *dfp)
707{
708 struct si21xx_state *state = fe->demodulator_priv;
709 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
710
711 /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz)
712 datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/
713
714 /* in MHz */
715 unsigned char coarse_tune_freq;
716 int fine_tune_freq;
717 unsigned char sample_rate = 0;
718 /* boolean */
Joe Perches42a39e02010-01-13 03:59:15 -0300719 bool inband_interferer_ind;
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300720
721 /* INTERMEDIATE VALUES */
722 int icoarse_tune_freq; /* MHz */
723 int ifine_tune_freq; /* MHz */
724 unsigned int band_high;
725 unsigned int band_low;
726 unsigned int x1;
727 unsigned int x2;
728 int i;
Joe Perches42a39e02010-01-13 03:59:15 -0300729 bool inband_interferer_div2[ALLOWABLE_FS_COUNT];
730 bool inband_interferer_div4[ALLOWABLE_FS_COUNT];
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300731 int status;
732
733 /* allowable sample rates for ADC in MHz */
734 int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,
735 196, 204, 205, 206, 207
736 };
737 /* in MHz */
738 int if_limit_high;
739 int if_limit_low;
740 int lnb_lo;
741 int lnb_uncertanity;
742
743 int rf_freq;
744 int data_rate;
745 unsigned char regs[4];
746
747 dprintk("%s : FE_SET_FRONTEND\n", __func__);
748
749 if (c->delivery_system != SYS_DVBS) {
750 dprintk("%s: unsupported delivery system selected (%d)\n",
751 __func__, c->delivery_system);
752 return -EOPNOTSUPP;
753 }
754
755 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
Joe Perches42a39e02010-01-13 03:59:15 -0300756 inband_interferer_div2[i] = inband_interferer_div4[i] = false;
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300757
758 if_limit_high = -700000;
759 if_limit_low = -100000;
760 /* in MHz */
761 lnb_lo = 0;
762 lnb_uncertanity = 0;
763
764 rf_freq = 10 * c->frequency ;
765 data_rate = c->symbol_rate / 100;
766
767 status = PASS;
768
769 band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)
770 + (data_rate * 135)) / 200;
771
772 band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200)
773 + (data_rate * 135)) / 200;
774
775
776 icoarse_tune_freq = 100000 *
777 (((rf_freq - lnb_lo) -
778 (if_limit_low + if_limit_high) / 2)
779 / 100000);
780
781 ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ;
782
783 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
784 x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
785 (afs[i] * 2500) + afs[i] * 2500;
786
787 x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
788 (afs[i] * 2500);
789
790 if (((band_low < x1) && (x1 < band_high)) ||
791 ((band_low < x2) && (x2 < band_high)))
Joe Perches42a39e02010-01-13 03:59:15 -0300792 inband_interferer_div4[i] = true;
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300793
794 }
795
796 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
797 x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
798 (afs[i] * 5000) + afs[i] * 5000;
799
800 x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
801 (afs[i] * 5000);
802
803 if (((band_low < x1) && (x1 < band_high)) ||
804 ((band_low < x2) && (x2 < band_high)))
Joe Perches42a39e02010-01-13 03:59:15 -0300805 inband_interferer_div2[i] = true;
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300806 }
807
Joe Perches42a39e02010-01-13 03:59:15 -0300808 inband_interferer_ind = true;
809 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
810 if (inband_interferer_div2[i] || inband_interferer_div4[i]) {
811 inband_interferer_ind = false;
812 break;
813 }
814 }
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300815
816 if (inband_interferer_ind) {
817 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
Joe Perches42a39e02010-01-13 03:59:15 -0300818 if (!inband_interferer_div2[i]) {
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300819 sample_rate = (u8) afs[i];
820 break;
821 }
822 }
823 } else {
824 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
Joe Perches42a39e02010-01-13 03:59:15 -0300825 if ((inband_interferer_div2[i] ||
826 !inband_interferer_div4[i])) {
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300827 sample_rate = (u8) afs[i];
828 break;
829 }
830 }
831
832 }
833
834 if (sample_rate > 207 || sample_rate < 192)
835 sample_rate = 200;
836
837 fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) /
838 ((sample_rate) * 1000));
839
840 coarse_tune_freq = (u8)(icoarse_tune_freq / 100000);
841
842 regs[0] = sample_rate;
843 regs[1] = coarse_tune_freq;
844 regs[2] = fine_tune_freq & 0xFF;
845 regs[3] = fine_tune_freq >> 8 & 0xFF;
846
847 status |= si21_writeregs(state, PLL_DIVISOR_REG, &regs[0], 0x04);
848
849 state->fs = sample_rate;/*ADC MHz*/
850 si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);
851
852 return 0;
853}
854
855static int si21xx_sleep(struct dvb_frontend *fe)
856{
857 struct si21xx_state *state = fe->demodulator_priv;
858 u8 regdata;
859
860 dprintk("%s\n", __func__);
861
862 si21_readregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
863 regdata |= 1 << 6;
864 si21_writeregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
865 state->initialised = 0;
866
867 return 0;
868}
869
870static void si21xx_release(struct dvb_frontend *fe)
871{
872 struct si21xx_state *state = fe->demodulator_priv;
873
874 dprintk("%s\n", __func__);
875
876 kfree(state);
877}
878
879static struct dvb_frontend_ops si21xx_ops = {
880
881 .info = {
882 .name = "SL SI21XX DVB-S",
883 .type = FE_QPSK,
884 .frequency_min = 950000,
885 .frequency_max = 2150000,
886 .frequency_stepsize = 125, /* kHz for QPSK frontends */
887 .frequency_tolerance = 0,
888 .symbol_rate_min = 1000000,
889 .symbol_rate_max = 45000000,
890 .symbol_rate_tolerance = 500, /* ppm */
891 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
892 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
893 FE_CAN_QPSK |
894 FE_CAN_FEC_AUTO
895 },
896
897 .release = si21xx_release,
898 .init = si21xx_init,
899 .sleep = si21xx_sleep,
900 .write = si21_write,
901 .read_status = si21_read_status,
902 .read_ber = si21_read_ber,
903 .read_signal_strength = si21_read_signal_strength,
904 .read_snr = si21_read_snr,
905 .read_ucblocks = si21_read_ucblocks,
906 .diseqc_send_master_cmd = si21xx_send_diseqc_msg,
907 .diseqc_send_burst = si21xx_send_diseqc_burst,
908 .set_tone = si21xx_set_tone,
909 .set_voltage = si21xx_set_voltage,
910
911 .set_property = si21xx_set_property,
912 .get_property = si21xx_get_property,
913 .set_frontend = si21xx_set_frontend,
914};
915
916struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
917 struct i2c_adapter *i2c)
918{
919 struct si21xx_state *state = NULL;
920 int id;
921
922 dprintk("%s\n", __func__);
923
924 /* allocate memory for the internal state */
Matthias Schwarzott084e24a2009-08-10 22:51:01 -0300925 state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL);
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300926 if (state == NULL)
927 goto error;
928
929 /* setup the state */
930 state->config = config;
931 state->i2c = i2c;
932 state->initialised = 0;
933 state->errmode = STATUS_BER;
934
935 /* check if the demod is there */
936 id = si21_readreg(state, SYSTEM_MODE_REG);
937 si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */
938 msleep(200);
939 id = si21_readreg(state, 0x00);
940
941 /* register 0x00 contains:
942 0x34 for SI2107
943 0x24 for SI2108
944 0x14 for SI2109
945 0x04 for SI2110
946 */
947 if (id != 0x04 && id != 0x14)
948 goto error;
949
950 /* create dvb_frontend */
951 memcpy(&state->frontend.ops, &si21xx_ops,
952 sizeof(struct dvb_frontend_ops));
953 state->frontend.demodulator_priv = state;
954 return &state->frontend;
955
956error:
957 kfree(state);
958 return NULL;
959}
960EXPORT_SYMBOL(si21xx_attach);
961
962module_param(debug, int, 0644);
963MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
964
965MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
966MODULE_AUTHOR("Igor M. Liplianin");
967MODULE_LICENSE("GPL");