blob: 62ad7a7be9f86f17c4561821c6c7feab6ec93155 [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
Dan Carpentercf3b5762014-09-09 09:05:28 -0300239 if (len > sizeof(buf) - 1)
240 return -EINVAL;
241
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300242 msg.buf[0] = reg1;
243 memcpy(msg.buf + 1, data, len);
244
245 ret = i2c_transfer(state->i2c, &msg, 1);
246
247 if (ret != 1)
248 dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
249 "ret == %i)\n", __func__, reg1, data[0], ret);
250
251 return (ret != 1) ? -EREMOTEIO : 0;
252}
253
254static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)
255{
256 int ret;
257 u8 buf[] = { reg, data };
258 struct i2c_msg msg = {
259 .addr = state->config->demod_address,
260 .flags = 0,
261 .buf = buf,
262 .len = 2
263 };
264
265 ret = i2c_transfer(state->i2c, &msg, 1);
266
267 if (ret != 1)
268 dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
269 "ret == %i)\n", __func__, reg, data, ret);
270
271 return (ret != 1) ? -EREMOTEIO : 0;
272}
273
lawrence rust2e4e98e2010-08-25 09:50:20 -0300274static int si21_write(struct dvb_frontend *fe, const u8 buf[], int len)
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300275{
276 struct si21xx_state *state = fe->demodulator_priv;
277
278 if (len != 2)
279 return -EINVAL;
280
281 return si21_writereg(state, buf[0], buf[1]);
282}
283
284static u8 si21_readreg(struct si21xx_state *state, u8 reg)
285{
286 int ret;
287 u8 b0[] = { reg };
288 u8 b1[] = { 0 };
289 struct i2c_msg msg[] = {
290 {
291 .addr = state->config->demod_address,
292 .flags = 0,
293 .buf = b0,
294 .len = 1
295 }, {
296 .addr = state->config->demod_address,
297 .flags = I2C_M_RD,
298 .buf = b1,
299 .len = 1
300 }
301 };
302
303 ret = i2c_transfer(state->i2c, msg, 2);
304
305 if (ret != 2)
306 dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
307 __func__, reg, ret);
308
309 return b1[0];
310}
311
312static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len)
313{
314 int ret;
315 struct i2c_msg msg[] = {
316 {
317 .addr = state->config->demod_address,
318 .flags = 0,
319 .buf = &reg1,
320 .len = 1
321 }, {
322 .addr = state->config->demod_address,
323 .flags = I2C_M_RD,
324 .buf = b,
325 .len = len
326 }
327 };
328
329 ret = i2c_transfer(state->i2c, msg, 2);
330
331 if (ret != 2)
332 dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
333
334 return ret == 2 ? 0 : -1;
335}
336
337static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
338{
339 unsigned long start = jiffies;
340
341 dprintk("%s\n", __func__);
342
343 while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) {
344 if (jiffies - start > timeout) {
345 dprintk("%s: timeout!!\n", __func__);
346 return -ETIMEDOUT;
347 }
348 msleep(10);
Peter Senna Tschudinc2c1b412012-09-28 05:37:22 -0300349 }
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300350
351 return 0;
352}
353
354static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate)
355{
356 struct si21xx_state *state = fe->demodulator_priv;
357 u32 sym_rate, data_rate;
358 int i;
359 u8 sym_rate_bytes[3];
360
361 dprintk("%s : srate = %i\n", __func__ , srate);
362
363 if ((srate < 1000000) || (srate > 45000000))
364 return -EINVAL;
365
366 data_rate = srate;
367 sym_rate = 0;
368
369 for (i = 0; i < 4; ++i) {
370 sym_rate /= 100;
371 sym_rate = sym_rate + ((data_rate % 100) * 0x800000) /
372 state->fs;
373 data_rate /= 100;
374 }
375 for (i = 0; i < 3; ++i)
376 sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);
377
378 si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);
379
380 return 0;
381}
382
383static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,
384 struct dvb_diseqc_master_cmd *m)
385{
386 struct si21xx_state *state = fe->demodulator_priv;
387 u8 lnb_status;
388 u8 LNB_CTRL_1;
389 int status;
390
391 dprintk("%s\n", __func__);
392
393 status = PASS;
394 LNB_CTRL_1 = 0;
395
396 status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);
397 status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);
398
399 /*fill the FIFO*/
400 status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);
401
402 LNB_CTRL_1 = (lnb_status & 0x70);
403 LNB_CTRL_1 |= m->msg_len;
404
405 LNB_CTRL_1 |= 0x80; /* begin LNB signaling */
406
407 status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);
408
409 return status;
410}
411
412static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300413 enum fe_sec_mini_cmd burst)
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300414{
415 struct si21xx_state *state = fe->demodulator_priv;
416 u8 val;
417
418 dprintk("%s\n", __func__);
419
420 if (si21xx_wait_diseqc_idle(state, 100) < 0)
421 return -ETIMEDOUT;
422
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)))
426 return -EREMOTEIO;
427
428 if (si21xx_wait_diseqc_idle(state, 100) < 0)
429 return -ETIMEDOUT;
430
431 if (si21_writereg(state, LNB_CTRL_REG_1, val))
432 return -EREMOTEIO;
433
434 return 0;
435}
436/* 30.06.2008 */
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300437static int si21xx_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300438{
439 struct si21xx_state *state = fe->demodulator_priv;
440 u8 val;
441
442 dprintk("%s\n", __func__);
443 val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
444
445 switch (tone) {
446 case SEC_TONE_ON:
447 return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);
448
449 case SEC_TONE_OFF:
450 return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));
451
452 default:
453 return -EINVAL;
454 }
455}
456
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300457static int si21xx_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage volt)
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300458{
459 struct si21xx_state *state = fe->demodulator_priv;
460
461 u8 val;
462 dprintk("%s: %s\n", __func__,
463 volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
464 volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
465
466
467 val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
468
469 switch (volt) {
470 case SEC_VOLTAGE_18:
471 return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40);
472 break;
473 case SEC_VOLTAGE_13:
474 return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40));
475 break;
476 default:
477 return -EINVAL;
Peter Senna Tschudinc2c1b412012-09-28 05:37:22 -0300478 }
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300479}
480
481static int si21xx_init(struct dvb_frontend *fe)
482{
483 struct si21xx_state *state = fe->demodulator_priv;
484 int i;
485 int status = 0;
486 u8 reg1;
487 u8 val;
488 u8 reg2[2];
489
490 dprintk("%s\n", __func__);
491
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)
496 break;
497 si21_writeregs(state, reg1, &val, 1);
498 }
499
500 /*DVB QPSK SYSTEM MODE REG*/
501 reg1 = 0x08;
502 si21_writeregs(state, SYSTEM_MODE_REG, &reg1, 0x01);
503
504 /*transport stream config*/
505 /*
506 mode = PARALLEL;
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;
514 sclk_rate = 0x00;
515 parity = 0x00 ;
516 data_delay = 0x00;
517 clk_delay = 0x00;
518 pclk_smooth = 0x00;
519 */
520 reg2[0] =
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);
525
526 reg2[1] = 0;
527 /* sclk_rate + (parity << 2)
528 + (data_delay << 3) + (clk_delay << 4)
529 + (pclk_smooth << 5);
530 */
531 status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02);
532 if (status != 0)
533 dprintk(" %s : TS Set Error\n", __func__);
534
535 return 0;
536
537}
538
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300539static int si21_read_status(struct dvb_frontend *fe, enum fe_status *status)
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300540{
541 struct si21xx_state *state = fe->demodulator_priv;
542 u8 regs_read[2];
543 u8 reg_read;
544 u8 i;
545 u8 lock;
546 u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG);
547
548 si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02);
549 reg_read = 0;
550
551 for (i = 0; i < 7; ++i)
552 reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i);
553
554 lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80));
555
556 dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock);
557 *status = 0;
558
559 if (signal > 10)
560 *status |= FE_HAS_SIGNAL;
561
562 if (lock & 0x2)
563 *status |= FE_HAS_CARRIER;
564
565 if (lock & 0x20)
566 *status |= FE_HAS_VITERBI;
567
568 if (lock & 0x40)
569 *status |= FE_HAS_SYNC;
570
571 if ((lock & 0x7b) == 0x7b)
572 *status |= FE_HAS_LOCK;
573
574 return 0;
575}
576
577static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
578{
579 struct si21xx_state *state = fe->demodulator_priv;
580
581 /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
582 (u8*)agclevel, 0x01);*/
583
584 u16 signal = (3 * si21_readreg(state, 0x27) *
585 si21_readreg(state, 0x28));
586
587 dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__,
588 si21_readreg(state, 0x27),
589 si21_readreg(state, 0x28), (int) signal);
590
591 signal <<= 4;
592 *strength = signal;
593
594 return 0;
595}
596
597static int si21_read_ber(struct dvb_frontend *fe, u32 *ber)
598{
599 struct si21xx_state *state = fe->demodulator_priv;
600
601 dprintk("%s\n", __func__);
602
603 if (state->errmode != STATUS_BER)
604 return 0;
605
606 *ber = (si21_readreg(state, 0x1d) << 8) |
607 si21_readreg(state, 0x1e);
608
609 return 0;
610}
611
612static int si21_read_snr(struct dvb_frontend *fe, u16 *snr)
613{
614 struct si21xx_state *state = fe->demodulator_priv;
615
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;
620
621 dprintk("%s\n", __func__);
622
623 return 0;
624}
625
626static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
627{
628 struct si21xx_state *state = fe->demodulator_priv;
629
630 dprintk("%s\n", __func__);
631
632 if (state->errmode != STATUS_UCBLOCKS)
633 *ucblocks = 0;
634 else
635 *ucblocks = (si21_readreg(state, 0x1d) << 8) |
636 si21_readreg(state, 0x1e);
637
638 return 0;
639}
640
641/* initiates a channel acquisition sequence
642 using the specified symbol rate and code rate */
643static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300644 enum fe_code_rate crate)
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300645{
646
647 struct si21xx_state *state = fe->demodulator_priv;
648 u8 coderates[] = {
649 0x0, 0x01, 0x02, 0x04, 0x00,
650 0x8, 0x10, 0x20, 0x00, 0x3f
651 };
652
653 u8 coderate_ptr;
654 int status;
655 u8 start_acq = 0x80;
656 u8 reg, regs[3];
657
658 dprintk("%s\n", __func__);
659
660 status = PASS;
661 coderate_ptr = coderates[crate];
662
663 si21xx_set_symbolrate(fe, symbrate);
664
665 /* write code rates to use in the Viterbi search */
666 status |= si21_writeregs(state,
667 VIT_SRCH_CTRL_REG_1,
668 &coderate_ptr, 0x01);
669
670 /* clear acq_start bit */
671 status |= si21_readregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
672 reg &= ~start_acq;
673 status |= si21_writeregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
674
675 /* use new Carrier Frequency Offset Estimator (QuickLock) */
676 regs[0] = 0xCB;
677 regs[1] = 0x40;
678 regs[2] = 0xCB;
679
680 status |= si21_writeregs(state,
681 TWO_DB_BNDWDTH_THRSHLD_REG,
682 &regs[0], 0x03);
683 reg = 0x56;
684 status |= si21_writeregs(state,
685 LSA_CTRL_REG_1, &reg, 1);
686 reg = 0x05;
687 status |= si21_writeregs(state,
688 BLIND_SCAN_CTRL_REG, &reg, 1);
689 /* start automatic acq */
690 status |= si21_writeregs(state,
691 ACQ_CTRL_REG_2, &start_acq, 0x01);
692
693 return status;
694}
695
Mauro Carvalho Chehab14e3dcc2011-12-26 14:11:35 -0300696static int si21xx_set_frontend(struct dvb_frontend *fe)
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300697{
698 struct si21xx_state *state = fe->demodulator_priv;
699 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
700
701 /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz)
702 datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/
703
704 /* in MHz */
705 unsigned char coarse_tune_freq;
706 int fine_tune_freq;
707 unsigned char sample_rate = 0;
708 /* boolean */
Joe Perches42a39e02010-01-13 03:59:15 -0300709 bool inband_interferer_ind;
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300710
711 /* INTERMEDIATE VALUES */
712 int icoarse_tune_freq; /* MHz */
713 int ifine_tune_freq; /* MHz */
714 unsigned int band_high;
715 unsigned int band_low;
716 unsigned int x1;
717 unsigned int x2;
718 int i;
Joe Perches42a39e02010-01-13 03:59:15 -0300719 bool inband_interferer_div2[ALLOWABLE_FS_COUNT];
720 bool inband_interferer_div4[ALLOWABLE_FS_COUNT];
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300721 int status;
722
723 /* allowable sample rates for ADC in MHz */
724 int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,
725 196, 204, 205, 206, 207
726 };
727 /* in MHz */
728 int if_limit_high;
729 int if_limit_low;
730 int lnb_lo;
731 int lnb_uncertanity;
732
733 int rf_freq;
734 int data_rate;
735 unsigned char regs[4];
736
737 dprintk("%s : FE_SET_FRONTEND\n", __func__);
738
739 if (c->delivery_system != SYS_DVBS) {
740 dprintk("%s: unsupported delivery system selected (%d)\n",
741 __func__, c->delivery_system);
742 return -EOPNOTSUPP;
743 }
744
745 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
Joe Perches42a39e02010-01-13 03:59:15 -0300746 inband_interferer_div2[i] = inband_interferer_div4[i] = false;
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300747
748 if_limit_high = -700000;
749 if_limit_low = -100000;
750 /* in MHz */
751 lnb_lo = 0;
752 lnb_uncertanity = 0;
753
754 rf_freq = 10 * c->frequency ;
755 data_rate = c->symbol_rate / 100;
756
757 status = PASS;
758
759 band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)
760 + (data_rate * 135)) / 200;
761
762 band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200)
763 + (data_rate * 135)) / 200;
764
765
766 icoarse_tune_freq = 100000 *
767 (((rf_freq - lnb_lo) -
768 (if_limit_low + if_limit_high) / 2)
769 / 100000);
770
771 ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ;
772
773 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
774 x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
775 (afs[i] * 2500) + afs[i] * 2500;
776
777 x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
778 (afs[i] * 2500);
779
780 if (((band_low < x1) && (x1 < band_high)) ||
781 ((band_low < x2) && (x2 < band_high)))
Joe Perches42a39e02010-01-13 03:59:15 -0300782 inband_interferer_div4[i] = true;
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300783
784 }
785
786 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
787 x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
788 (afs[i] * 5000) + afs[i] * 5000;
789
790 x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
791 (afs[i] * 5000);
792
793 if (((band_low < x1) && (x1 < band_high)) ||
794 ((band_low < x2) && (x2 < band_high)))
Joe Perches42a39e02010-01-13 03:59:15 -0300795 inband_interferer_div2[i] = true;
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300796 }
797
Joe Perches42a39e02010-01-13 03:59:15 -0300798 inband_interferer_ind = true;
799 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
800 if (inband_interferer_div2[i] || inband_interferer_div4[i]) {
801 inband_interferer_ind = false;
802 break;
803 }
804 }
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300805
806 if (inband_interferer_ind) {
807 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
Joe Perches42a39e02010-01-13 03:59:15 -0300808 if (!inband_interferer_div2[i]) {
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300809 sample_rate = (u8) afs[i];
810 break;
811 }
812 }
813 } else {
814 for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
Joe Perches42a39e02010-01-13 03:59:15 -0300815 if ((inband_interferer_div2[i] ||
816 !inband_interferer_div4[i])) {
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300817 sample_rate = (u8) afs[i];
818 break;
819 }
820 }
821
822 }
823
824 if (sample_rate > 207 || sample_rate < 192)
825 sample_rate = 200;
826
827 fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) /
828 ((sample_rate) * 1000));
829
830 coarse_tune_freq = (u8)(icoarse_tune_freq / 100000);
831
832 regs[0] = sample_rate;
833 regs[1] = coarse_tune_freq;
834 regs[2] = fine_tune_freq & 0xFF;
835 regs[3] = fine_tune_freq >> 8 & 0xFF;
836
837 status |= si21_writeregs(state, PLL_DIVISOR_REG, &regs[0], 0x04);
838
839 state->fs = sample_rate;/*ADC MHz*/
840 si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);
841
842 return 0;
843}
844
845static int si21xx_sleep(struct dvb_frontend *fe)
846{
847 struct si21xx_state *state = fe->demodulator_priv;
848 u8 regdata;
849
850 dprintk("%s\n", __func__);
851
852 si21_readregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
853 regdata |= 1 << 6;
854 si21_writeregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
855 state->initialised = 0;
856
857 return 0;
858}
859
860static void si21xx_release(struct dvb_frontend *fe)
861{
862 struct si21xx_state *state = fe->demodulator_priv;
863
864 dprintk("%s\n", __func__);
865
866 kfree(state);
867}
868
869static struct dvb_frontend_ops si21xx_ops = {
Mauro Carvalho Chehab14e3dcc2011-12-26 14:11:35 -0300870 .delsys = { SYS_DVBS },
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300871 .info = {
872 .name = "SL SI21XX DVB-S",
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300873 .frequency_min = 950000,
874 .frequency_max = 2150000,
875 .frequency_stepsize = 125, /* kHz for QPSK frontends */
876 .frequency_tolerance = 0,
877 .symbol_rate_min = 1000000,
878 .symbol_rate_max = 45000000,
879 .symbol_rate_tolerance = 500, /* ppm */
880 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
881 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
882 FE_CAN_QPSK |
883 FE_CAN_FEC_AUTO
884 },
885
886 .release = si21xx_release,
887 .init = si21xx_init,
888 .sleep = si21xx_sleep,
889 .write = si21_write,
890 .read_status = si21_read_status,
891 .read_ber = si21_read_ber,
892 .read_signal_strength = si21_read_signal_strength,
893 .read_snr = si21_read_snr,
894 .read_ucblocks = si21_read_ucblocks,
895 .diseqc_send_master_cmd = si21xx_send_diseqc_msg,
896 .diseqc_send_burst = si21xx_send_diseqc_burst,
897 .set_tone = si21xx_set_tone,
898 .set_voltage = si21xx_set_voltage,
899
Mauro Carvalho Chehab14e3dcc2011-12-26 14:11:35 -0300900 .set_frontend = si21xx_set_frontend,
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300901};
902
903struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
904 struct i2c_adapter *i2c)
905{
906 struct si21xx_state *state = NULL;
907 int id;
908
909 dprintk("%s\n", __func__);
910
911 /* allocate memory for the internal state */
Matthias Schwarzott084e24a2009-08-10 22:51:01 -0300912 state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL);
Igor M. Liplianin04ad28c2008-09-16 18:21:11 -0300913 if (state == NULL)
914 goto error;
915
916 /* setup the state */
917 state->config = config;
918 state->i2c = i2c;
919 state->initialised = 0;
920 state->errmode = STATUS_BER;
921
922 /* check if the demod is there */
923 id = si21_readreg(state, SYSTEM_MODE_REG);
924 si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */
925 msleep(200);
926 id = si21_readreg(state, 0x00);
927
928 /* register 0x00 contains:
929 0x34 for SI2107
930 0x24 for SI2108
931 0x14 for SI2109
932 0x04 for SI2110
933 */
934 if (id != 0x04 && id != 0x14)
935 goto error;
936
937 /* create dvb_frontend */
938 memcpy(&state->frontend.ops, &si21xx_ops,
939 sizeof(struct dvb_frontend_ops));
940 state->frontend.demodulator_priv = state;
941 return &state->frontend;
942
943error:
944 kfree(state);
945 return NULL;
946}
947EXPORT_SYMBOL(si21xx_attach);
948
949module_param(debug, int, 0644);
950MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
951
952MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
953MODULE_AUTHOR("Igor M. Liplianin");
954MODULE_LICENSE("GPL");