1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include <linux/slab.h>
38#include <linux/kernel.h>
39#include <linux/module.h>
40#include <linux/moduleparam.h>
41#include <linux/init.h>
42#include <linux/firmware.h>
43
44#include "dvb_frontend.h"
45#include "cx24116.h"
46
47static int debug;
48module_param(debug, int, 0644);
49MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
50
51#define dprintk(args...) \
52 do { \
53 if (debug) \
54 printk(KERN_INFO "cx24116: " args); \
55 } while (0)
56
57#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
58#define CX24116_SEARCH_RANGE_KHZ 5000
59
60
61#define CX24116_REG_COMMAND (0x00)
62#define CX24116_REG_EXECUTE (0x1f)
63#define CX24116_REG_MAILBOX (0x96)
64#define CX24116_REG_RESET (0x20)
65#define CX24116_REG_SIGNAL (0x9e)
66#define CX24116_REG_SSTATUS (0x9d)
67#define CX24116_REG_QUALITY8 (0xa3)
68#define CX24116_REG_QSTATUS (0xbc)
69#define CX24116_REG_QUALITY0 (0xd5)
70#define CX24116_REG_BER0 (0xc9)
71#define CX24116_REG_BER8 (0xc8)
72#define CX24116_REG_BER16 (0xc7)
73#define CX24116_REG_BER24 (0xc6)
74#define CX24116_REG_UCB0 (0xcb)
75#define CX24116_REG_UCB8 (0xca)
76#define CX24116_REG_CLKDIV (0xf3)
77#define CX24116_REG_RATEDIV (0xf9)
78
79
80#define CX24116_REG_FECSTATUS (0x9c)
81
82
83
84#define CX24116_FEC_FECMASK (0x1f)
85
86
87#define CX24116_FEC_DVBS (0x20)
88#define CX24116_FEC_UNKNOWN (0x40)
89
90
91#define CX24116_FEC_PILOT (0x80)
92
93
94#define CX24116_ARGLEN (0x1e)
95
96
97#define CX24116_ROLLOFF_020 (0x00)
98#define CX24116_ROLLOFF_025 (0x01)
99#define CX24116_ROLLOFF_035 (0x02)
100
101
102#define CX24116_PILOT_OFF (0x00)
103#define CX24116_PILOT_ON (0x40)
104
105
106#define CX24116_HAS_SIGNAL (0x01)
107#define CX24116_HAS_CARRIER (0x02)
108#define CX24116_HAS_VITERBI (0x04)
109#define CX24116_HAS_SYNCLOCK (0x08)
110#define CX24116_HAS_UNKNOWN1 (0x10)
111#define CX24116_HAS_UNKNOWN2 (0x20)
112#define CX24116_STATUS_MASK (0x0f)
113#define CX24116_SIGNAL_MASK (0xc0)
114
115#define CX24116_DISEQC_TONEOFF (0)
116#define CX24116_DISEQC_TONECACHE (1)
117#define CX24116_DISEQC_MESGCACHE (2)
118
119
120#define CX24116_DISEQC_BURST (1)
121#define CX24116_DISEQC_ARG2_2 (2)
122#define CX24116_DISEQC_ARG3_0 (3)
123#define CX24116_DISEQC_ARG4_0 (4)
124#define CX24116_DISEQC_MSGLEN (5)
125#define CX24116_DISEQC_MSGOFS (6)
126
127
128#define CX24116_DISEQC_MINI_A (0)
129#define CX24116_DISEQC_MINI_B (1)
130
131
132static int toneburst = 1;
133module_param(toneburst, int, 0644);
134MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
135 "2=MESSAGE CACHE (default:1)");
136
137
138static int esno_snr;
139module_param(esno_snr, int, 0644);
140MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\
141 "1=ESNO(db * 10) (default:0)");
142
143enum cmds {
144 CMD_SET_VCO = 0x10,
145 CMD_TUNEREQUEST = 0x11,
146 CMD_MPEGCONFIG = 0x13,
147 CMD_TUNERINIT = 0x14,
148 CMD_BANDWIDTH = 0x15,
149 CMD_GETAGC = 0x19,
150 CMD_LNBCONFIG = 0x20,
151 CMD_LNBSEND = 0x21,
152 CMD_LNBDCLEVEL = 0x22,
153 CMD_SET_TONE = 0x23,
154 CMD_UPDFWVERS = 0x35,
155 CMD_TUNERSLEEP = 0x36,
156 CMD_AGCCONTROL = 0x3b,
157};
158
159
160struct cx24116_tuning {
161 u32 frequency;
162 u32 symbol_rate;
163 fe_spectral_inversion_t inversion;
164 fe_code_rate_t fec;
165
166 fe_delivery_system_t delsys;
167 fe_modulation_t modulation;
168 fe_pilot_t pilot;
169 fe_rolloff_t rolloff;
170
171
172 u8 fec_val;
173 u8 fec_mask;
174 u8 inversion_val;
175 u8 pilot_val;
176 u8 rolloff_val;
177};
178
179
180struct cx24116_cmd {
181 u8 len;
182 u8 args[CX24116_ARGLEN];
183};
184
185struct cx24116_state {
186 struct i2c_adapter *i2c;
187 const struct cx24116_config *config;
188
189 struct dvb_frontend frontend;
190
191 struct cx24116_tuning dcur;
192 struct cx24116_tuning dnxt;
193
194 u8 skip_fw_load;
195 u8 burst;
196 struct cx24116_cmd dsec_cmd;
197};
198
199static int cx24116_writereg(struct cx24116_state *state, int reg, int data)
200{
201 u8 buf[] = { reg, data };
202 struct i2c_msg msg = { .addr = state->config->demod_address,
203 .flags = 0, .buf = buf, .len = 2 };
204 int err;
205
206 if (debug > 1)
207 printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
208 __func__, reg, data);
209
210 err = i2c_transfer(state->i2c, &msg, 1);
211 if (err != 1) {
212 printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
213 " value == 0x%02x)\n", __func__, err, reg, data);
214 return -EREMOTEIO;
215 }
216
217 return 0;
218}
219
220
221static int cx24116_writeregN(struct cx24116_state *state, int reg,
222 const u8 *data, u16 len)
223{
224 int ret = -EREMOTEIO;
225 struct i2c_msg msg;
226 u8 *buf;
227
228 buf = kmalloc(len + 1, GFP_KERNEL);
229 if (buf == NULL) {
230 printk("Unable to kmalloc\n");
231 ret = -ENOMEM;
232 goto error;
233 }
234
235 *(buf) = reg;
236 memcpy(buf + 1, data, len);
237
238 msg.addr = state->config->demod_address;
239 msg.flags = 0;
240 msg.buf = buf;
241 msg.len = len + 1;
242
243 if (debug > 1)
244 printk(KERN_INFO "cx24116: %s: write regN 0x%02x, len = %d\n",
245 __func__, reg, len);
246
247 ret = i2c_transfer(state->i2c, &msg, 1);
248 if (ret != 1) {
249 printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
250 __func__, ret, reg);
251 ret = -EREMOTEIO;
252 }
253
254error:
255 kfree(buf);
256
257 return ret;
258}
259
260static int cx24116_readreg(struct cx24116_state *state, u8 reg)
261{
262 int ret;
263 u8 b0[] = { reg };
264 u8 b1[] = { 0 };
265 struct i2c_msg msg[] = {
266 { .addr = state->config->demod_address, .flags = 0,
267 .buf = b0, .len = 1 },
268 { .addr = state->config->demod_address, .flags = I2C_M_RD,
269 .buf = b1, .len = 1 }
270 };
271
272 ret = i2c_transfer(state->i2c, msg, 2);
273
274 if (ret != 2) {
275 printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
276 __func__, reg, ret);
277 return ret;
278 }
279
280 if (debug > 1)
281 printk(KERN_INFO "cx24116: read reg 0x%02x, value 0x%02x\n",
282 reg, b1[0]);
283
284 return b1[0];
285}
286
287static int cx24116_set_inversion(struct cx24116_state *state,
288 fe_spectral_inversion_t inversion)
289{
290 dprintk("%s(%d)\n", __func__, inversion);
291
292 switch (inversion) {
293 case INVERSION_OFF:
294 state->dnxt.inversion_val = 0x00;
295 break;
296 case INVERSION_ON:
297 state->dnxt.inversion_val = 0x04;
298 break;
299 case INVERSION_AUTO:
300 state->dnxt.inversion_val = 0x0C;
301 break;
302 default:
303 return -EINVAL;
304 }
305
306 state->dnxt.inversion = inversion;
307
308 return 0;
309}
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375static struct cx24116_modfec {
376 fe_delivery_system_t delivery_system;
377 fe_modulation_t modulation;
378 fe_code_rate_t fec;
379 u8 mask;
380 u8 val;
381} CX24116_MODFEC_MODES[] = {
382
383
384
385 { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
386 { SYS_DVBS, QPSK, FEC_1_2, 0x02, 0x2e },
387 { SYS_DVBS, QPSK, FEC_2_3, 0x04, 0x2f },
388 { SYS_DVBS, QPSK, FEC_3_4, 0x08, 0x30 },
389 { SYS_DVBS, QPSK, FEC_4_5, 0xfe, 0x30 },
390 { SYS_DVBS, QPSK, FEC_5_6, 0x20, 0x31 },
391 { SYS_DVBS, QPSK, FEC_6_7, 0xfe, 0x30 },
392 { SYS_DVBS, QPSK, FEC_7_8, 0x80, 0x32 },
393 { SYS_DVBS, QPSK, FEC_8_9, 0xfe, 0x30 },
394 { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
395
396 { SYS_DVBS2, QPSK, FEC_1_2, 0x00, 0x04 },
397 { SYS_DVBS2, QPSK, FEC_3_5, 0x00, 0x05 },
398 { SYS_DVBS2, QPSK, FEC_2_3, 0x00, 0x06 },
399 { SYS_DVBS2, QPSK, FEC_3_4, 0x00, 0x07 },
400 { SYS_DVBS2, QPSK, FEC_4_5, 0x00, 0x08 },
401 { SYS_DVBS2, QPSK, FEC_5_6, 0x00, 0x09 },
402 { SYS_DVBS2, QPSK, FEC_8_9, 0x00, 0x0a },
403 { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
404
405 { SYS_DVBS2, PSK_8, FEC_3_5, 0x00, 0x0c },
406 { SYS_DVBS2, PSK_8, FEC_2_3, 0x00, 0x0d },
407 { SYS_DVBS2, PSK_8, FEC_3_4, 0x00, 0x0e },
408 { SYS_DVBS2, PSK_8, FEC_5_6, 0x00, 0x0f },
409 { SYS_DVBS2, PSK_8, FEC_8_9, 0x00, 0x10 },
410 { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
411
412
413
414
415};
416
417static int cx24116_lookup_fecmod(struct cx24116_state *state,
418 fe_delivery_system_t d, fe_modulation_t m, fe_code_rate_t f)
419{
420 int i, ret = -EOPNOTSUPP;
421
422 dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
423
424 for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {
425 if ((d == CX24116_MODFEC_MODES[i].delivery_system) &&
426 (m == CX24116_MODFEC_MODES[i].modulation) &&
427 (f == CX24116_MODFEC_MODES[i].fec)) {
428 ret = i;
429 break;
430 }
431 }
432
433 return ret;
434}
435
436static int cx24116_set_fec(struct cx24116_state *state,
437 fe_delivery_system_t delsys, fe_modulation_t mod, fe_code_rate_t fec)
438{
439 int ret = 0;
440
441 dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
442
443 ret = cx24116_lookup_fecmod(state, delsys, mod, fec);
444
445 if (ret < 0)
446 return ret;
447
448 state->dnxt.fec = fec;
449 state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
450 state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
451 dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
452 state->dnxt.fec_mask, state->dnxt.fec_val);
453
454 return 0;
455}
456
457static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)
458{
459 dprintk("%s(%d)\n", __func__, rate);
460
461
462 if ((rate > state->frontend.ops.info.symbol_rate_max) ||
463 (rate < state->frontend.ops.info.symbol_rate_min)) {
464 dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
465 return -EOPNOTSUPP;
466 }
467
468 state->dnxt.symbol_rate = rate;
469 dprintk("%s() symbol_rate = %d\n", __func__, rate);
470
471 return 0;
472}
473
474static int cx24116_load_firmware(struct dvb_frontend *fe,
475 const struct firmware *fw);
476
477static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
478{
479 struct cx24116_state *state = fe->demodulator_priv;
480 const struct firmware *fw;
481 int ret = 0;
482
483 dprintk("%s()\n", __func__);
484
485 if (cx24116_readreg(state, 0x20) > 0) {
486
487 if (state->skip_fw_load)
488 return 0;
489
490
491
492 printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
493 __func__, CX24116_DEFAULT_FIRMWARE);
494 ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
495 state->i2c->dev.parent);
496 printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
497 __func__);
498 if (ret) {
499 printk(KERN_ERR "%s: No firmware uploaded "
500 "(timeout or file not found?)\n", __func__);
501 return ret;
502 }
503
504
505
506 state->skip_fw_load = 1;
507
508 ret = cx24116_load_firmware(fe, fw);
509 if (ret)
510 printk(KERN_ERR "%s: Writing firmware to device failed\n",
511 __func__);
512
513 release_firmware(fw);
514
515 printk(KERN_INFO "%s: Firmware upload %s\n", __func__,
516 ret == 0 ? "complete" : "failed");
517
518
519 state->skip_fw_load = 0;
520 }
521
522 return ret;
523}
524
525
526
527
528static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)
529{
530 struct cx24116_state *state = fe->demodulator_priv;
531 int i, ret;
532
533 dprintk("%s()\n", __func__);
534
535
536 ret = cx24116_firmware_ondemand(fe);
537 if (ret != 0) {
538 printk(KERN_ERR "%s(): Unable initialise the firmware\n",
539 __func__);
540 return ret;
541 }
542
543
544 for (i = 0; i < cmd->len ; i++) {
545 dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
546 cx24116_writereg(state, i, cmd->args[i]);
547 }
548
549
550 cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
551 while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {
552 msleep(10);
553 if (i++ > 64) {
554
555
556 printk(KERN_WARNING "%s() Firmware not responding\n",
557 __func__);
558 return -EREMOTEIO;
559 }
560 }
561 return 0;
562}
563
564static int cx24116_load_firmware(struct dvb_frontend *fe,
565 const struct firmware *fw)
566{
567 struct cx24116_state *state = fe->demodulator_priv;
568 struct cx24116_cmd cmd;
569 int i, ret, len, max, remaining;
570 unsigned char vers[4];
571
572 dprintk("%s\n", __func__);
573 dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
574 fw->size,
575 fw->data[0],
576 fw->data[1],
577 fw->data[fw->size-2],
578 fw->data[fw->size-1]);
579
580
581 if (state->config->reset_device)
582 state->config->reset_device(fe);
583
584
585
586
587
588 cx24116_writereg(state, 0xE5, 0x00);
589 cx24116_writereg(state, 0xF1, 0x08);
590 cx24116_writereg(state, 0xF2, 0x13);
591
592
593 cx24116_writereg(state, 0xe0, 0x03);
594 cx24116_writereg(state, 0xe0, 0x00);
595
596
597 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
598 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
599
600
601 cx24116_writereg(state, 0xF0, 0x03);
602 cx24116_writereg(state, 0xF4, 0x81);
603 cx24116_writereg(state, 0xF5, 0x00);
604 cx24116_writereg(state, 0xF6, 0x00);
605
606
607
608 if (state->config->i2c_wr_max)
609 max = state->config->i2c_wr_max;
610 else
611 max = INT_MAX;
612
613 for (remaining = fw->size; remaining > 0; remaining -= max - 1) {
614 len = remaining;
615 if (len > max - 1)
616 len = max - 1;
617
618 cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],
619 len);
620 }
621
622 cx24116_writereg(state, 0xF4, 0x10);
623 cx24116_writereg(state, 0xF0, 0x00);
624 cx24116_writereg(state, 0xF8, 0x06);
625
626
627 cmd.args[0x00] = CMD_SET_VCO;
628 cmd.args[0x01] = 0x05;
629 cmd.args[0x02] = 0xdc;
630 cmd.args[0x03] = 0xda;
631 cmd.args[0x04] = 0xae;
632 cmd.args[0x05] = 0xaa;
633 cmd.args[0x06] = 0x04;
634 cmd.args[0x07] = 0x9d;
635 cmd.args[0x08] = 0xfc;
636 cmd.args[0x09] = 0x06;
637 cmd.len = 0x0a;
638 ret = cx24116_cmd_execute(fe, &cmd);
639 if (ret != 0)
640 return ret;
641
642 cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
643
644
645 cmd.args[0x00] = CMD_TUNERINIT;
646 cmd.args[0x01] = 0x00;
647 cmd.args[0x02] = 0x00;
648 cmd.len = 0x03;
649 ret = cx24116_cmd_execute(fe, &cmd);
650 if (ret != 0)
651 return ret;
652
653 cx24116_writereg(state, 0xe5, 0x00);
654
655
656 cmd.args[0x00] = CMD_MPEGCONFIG;
657 cmd.args[0x01] = 0x01;
658 cmd.args[0x02] = 0x75;
659 cmd.args[0x03] = 0x00;
660 if (state->config->mpg_clk_pos_pol)
661 cmd.args[0x04] = state->config->mpg_clk_pos_pol;
662 else
663 cmd.args[0x04] = 0x02;
664 cmd.args[0x05] = 0x00;
665 cmd.len = 0x06;
666 ret = cx24116_cmd_execute(fe, &cmd);
667 if (ret != 0)
668 return ret;
669
670
671 cmd.args[0x00] = CMD_UPDFWVERS;
672 cmd.len = 0x02;
673 for (i = 0; i < 4; i++) {
674 cmd.args[0x01] = i;
675 ret = cx24116_cmd_execute(fe, &cmd);
676 if (ret != 0)
677 return ret;
678 vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
679 }
680 printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
681 vers[0], vers[1], vers[2], vers[3]);
682
683 return 0;
684}
685
686static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
687{
688 struct cx24116_state *state = fe->demodulator_priv;
689
690 int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) &
691 CX24116_STATUS_MASK;
692
693 dprintk("%s: status = 0x%02x\n", __func__, lock);
694
695 *status = 0;
696
697 if (lock & CX24116_HAS_SIGNAL)
698 *status |= FE_HAS_SIGNAL;
699 if (lock & CX24116_HAS_CARRIER)
700 *status |= FE_HAS_CARRIER;
701 if (lock & CX24116_HAS_VITERBI)
702 *status |= FE_HAS_VITERBI;
703 if (lock & CX24116_HAS_SYNCLOCK)
704 *status |= FE_HAS_SYNC | FE_HAS_LOCK;
705
706 return 0;
707}
708
709static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
710{
711 struct cx24116_state *state = fe->demodulator_priv;
712
713 dprintk("%s()\n", __func__);
714
715 *ber = (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
716 (cx24116_readreg(state, CX24116_REG_BER16) << 16) |
717 (cx24116_readreg(state, CX24116_REG_BER8) << 8) |
718 cx24116_readreg(state, CX24116_REG_BER0);
719
720 return 0;
721}
722
723
724static int cx24116_read_signal_strength(struct dvb_frontend *fe,
725 u16 *signal_strength)
726{
727 struct cx24116_state *state = fe->demodulator_priv;
728 struct cx24116_cmd cmd;
729 int ret;
730 u16 sig_reading;
731
732 dprintk("%s()\n", __func__);
733
734
735 cmd.args[0x00] = CMD_GETAGC;
736 cmd.len = 0x01;
737 ret = cx24116_cmd_execute(fe, &cmd);
738 if (ret != 0)
739 return ret;
740
741 sig_reading =
742 (cx24116_readreg(state,
743 CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
744 (cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
745 *signal_strength = 0 - sig_reading;
746
747 dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
748 __func__, sig_reading, *signal_strength);
749
750 return 0;
751}
752
753
754static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
755{
756 struct cx24116_state *state = fe->demodulator_priv;
757 u8 snr_reading;
758 static const u32 snr_tab[] = {
759 0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
760 0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
761 0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
762 0x18000 };
763
764 dprintk("%s()\n", __func__);
765
766 snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
767
768 if (snr_reading >= 0xa0 )
769 *snr = 0xffff;
770 else
771 *snr = snr_tab[(snr_reading & 0xf0) >> 4] +
772 (snr_tab[(snr_reading & 0x0f)] >> 4);
773
774 dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
775 snr_reading, *snr);
776
777 return 0;
778}
779
780
781
782
783
784static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
785{
786 struct cx24116_state *state = fe->demodulator_priv;
787
788 dprintk("%s()\n", __func__);
789
790 *snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
791 cx24116_readreg(state, CX24116_REG_QUALITY0);
792
793 dprintk("%s: raw 0x%04x\n", __func__, *snr);
794
795 return 0;
796}
797
798static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
799{
800 if (esno_snr == 1)
801 return cx24116_read_snr_esno(fe, snr);
802 else
803 return cx24116_read_snr_pct(fe, snr);
804}
805
806static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
807{
808 struct cx24116_state *state = fe->demodulator_priv;
809
810 dprintk("%s()\n", __func__);
811
812 *ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
813 cx24116_readreg(state, CX24116_REG_UCB0);
814
815 return 0;
816}
817
818
819static void cx24116_clone_params(struct dvb_frontend *fe)
820{
821 struct cx24116_state *state = fe->demodulator_priv;
822 memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
823}
824
825
826static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
827{
828 struct cx24116_state *state = fe->demodulator_priv;
829 int i;
830
831 dprintk("%s() qstatus = 0x%02x\n", __func__,
832 cx24116_readreg(state, CX24116_REG_QSTATUS));
833
834
835 for (i = 0; i < 30 ; i++) {
836 if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
837 return 0;
838 msleep(10);
839 }
840
841 dprintk("%s(): LNB not ready\n", __func__);
842
843 return -ETIMEDOUT;
844}
845
846static int cx24116_set_voltage(struct dvb_frontend *fe,
847 fe_sec_voltage_t voltage)
848{
849 struct cx24116_cmd cmd;
850 int ret;
851
852 dprintk("%s: %s\n", __func__,
853 voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
854 voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
855
856
857 ret = cx24116_wait_for_lnb(fe);
858 if (ret != 0)
859 return ret;
860
861
862 msleep(100);
863
864 cmd.args[0x00] = CMD_LNBDCLEVEL;
865 cmd.args[0x01] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);
866 cmd.len = 0x02;
867
868
869 msleep(15);
870
871 return cx24116_cmd_execute(fe, &cmd);
872}
873
874static int cx24116_set_tone(struct dvb_frontend *fe,
875 fe_sec_tone_mode_t tone)
876{
877 struct cx24116_cmd cmd;
878 int ret;
879
880 dprintk("%s(%d)\n", __func__, tone);
881 if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
882 printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
883 return -EINVAL;
884 }
885
886
887 ret = cx24116_wait_for_lnb(fe);
888 if (ret != 0)
889 return ret;
890
891
892 msleep(15);
893
894
895 cmd.args[0x00] = CMD_SET_TONE;
896 cmd.args[0x01] = 0x00;
897 cmd.args[0x02] = 0x00;
898
899 switch (tone) {
900 case SEC_TONE_ON:
901 dprintk("%s: setting tone on\n", __func__);
902 cmd.args[0x03] = 0x01;
903 break;
904 case SEC_TONE_OFF:
905 dprintk("%s: setting tone off\n", __func__);
906 cmd.args[0x03] = 0x00;
907 break;
908 }
909 cmd.len = 0x04;
910
911
912 msleep(15);
913
914 return cx24116_cmd_execute(fe, &cmd);
915}
916
917
918static int cx24116_diseqc_init(struct dvb_frontend *fe)
919{
920 struct cx24116_state *state = fe->demodulator_priv;
921 struct cx24116_cmd cmd;
922 int ret;
923
924
925 cmd.args[0x00] = CMD_LNBCONFIG;
926 cmd.args[0x01] = 0x00;
927 cmd.args[0x02] = 0x10;
928 cmd.args[0x03] = 0x00;
929 cmd.args[0x04] = 0x8f;
930 cmd.args[0x05] = 0x28;
931 cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
932 cmd.args[0x07] = 0x01;
933 cmd.len = 0x08;
934 ret = cx24116_cmd_execute(fe, &cmd);
935 if (ret != 0)
936 return ret;
937
938
939 state->dsec_cmd.args[0x00] = CMD_LNBSEND;
940
941
942 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
943
944
945 state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
946 state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
947
948 state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
949
950
951 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
952
953
954 state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
955
956 return 0;
957}
958
959
960static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
961 struct dvb_diseqc_master_cmd *d)
962{
963 struct cx24116_state *state = fe->demodulator_priv;
964 int i, ret;
965
966
967 if (debug) {
968 printk(KERN_INFO "cx24116: %s(", __func__);
969 for (i = 0 ; i < d->msg_len ;) {
970 printk(KERN_INFO "0x%02x", d->msg[i]);
971 if (++i < d->msg_len)
972 printk(KERN_INFO ", ");
973 }
974 printk(") toneburst=%d\n", toneburst);
975 }
976
977
978 if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
979 return -EINVAL;
980
981
982 for (i = 0; i < d->msg_len; i++)
983 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
984
985
986 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
987
988
989 state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
990 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
991
992
993 if (toneburst == CX24116_DISEQC_MESGCACHE)
994
995 return 0;
996
997 else if (toneburst == CX24116_DISEQC_TONEOFF)
998
999 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
1000
1001 else if (toneburst == CX24116_DISEQC_TONECACHE) {
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 if (d->msg_len >= 4 && d->msg[2] == 0x38)
1021 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1022 ((d->msg[3] & 4) >> 2);
1023 if (debug)
1024 dprintk("%s burst=%d\n", __func__,
1025 state->dsec_cmd.args[CX24116_DISEQC_BURST]);
1026 }
1027
1028
1029 ret = cx24116_wait_for_lnb(fe);
1030 if (ret != 0)
1031 return ret;
1032
1033
1034 msleep(100);
1035
1036
1037 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1038 if (ret != 0)
1039 return ret;
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050 msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
1051 ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
1052
1053 return 0;
1054}
1055
1056
1057static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
1058 fe_sec_mini_cmd_t burst)
1059{
1060 struct cx24116_state *state = fe->demodulator_priv;
1061 int ret;
1062
1063 dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
1064
1065
1066 if (burst == SEC_MINI_A)
1067 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1068 CX24116_DISEQC_MINI_A;
1069 else if (burst == SEC_MINI_B)
1070 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1071 CX24116_DISEQC_MINI_B;
1072 else
1073 return -EINVAL;
1074
1075
1076 if (toneburst != CX24116_DISEQC_MESGCACHE)
1077
1078 return 0;
1079
1080
1081
1082
1083 ret = cx24116_wait_for_lnb(fe);
1084 if (ret != 0)
1085 return ret;
1086
1087
1088 msleep(100);
1089
1090
1091 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1092 if (ret != 0)
1093 return ret;
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
1106
1107 return 0;
1108}
1109
1110static void cx24116_release(struct dvb_frontend *fe)
1111{
1112 struct cx24116_state *state = fe->demodulator_priv;
1113 dprintk("%s\n", __func__);
1114 kfree(state);
1115}
1116
1117static struct dvb_frontend_ops cx24116_ops;
1118
1119struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
1120 struct i2c_adapter *i2c)
1121{
1122 struct cx24116_state *state = NULL;
1123 int ret;
1124
1125 dprintk("%s\n", __func__);
1126
1127
1128 state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL);
1129 if (state == NULL)
1130 goto error1;
1131
1132 state->config = config;
1133 state->i2c = i2c;
1134
1135
1136 ret = (cx24116_readreg(state, 0xFF) << 8) |
1137 cx24116_readreg(state, 0xFE);
1138 if (ret != 0x0501) {
1139 printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
1140 goto error2;
1141 }
1142
1143
1144 memcpy(&state->frontend.ops, &cx24116_ops,
1145 sizeof(struct dvb_frontend_ops));
1146 state->frontend.demodulator_priv = state;
1147 return &state->frontend;
1148
1149error2: kfree(state);
1150error1: return NULL;
1151}
1152EXPORT_SYMBOL(cx24116_attach);
1153
1154
1155
1156
1157
1158
1159static int cx24116_initfe(struct dvb_frontend *fe)
1160{
1161 struct cx24116_state *state = fe->demodulator_priv;
1162 struct cx24116_cmd cmd;
1163 int ret;
1164
1165 dprintk("%s()\n", __func__);
1166
1167
1168 cx24116_writereg(state, 0xe0, 0);
1169 cx24116_writereg(state, 0xe1, 0);
1170 cx24116_writereg(state, 0xea, 0);
1171
1172
1173 cmd.args[0x00] = CMD_TUNERSLEEP;
1174 cmd.args[0x01] = 0;
1175 cmd.len = 0x02;
1176 ret = cx24116_cmd_execute(fe, &cmd);
1177 if (ret != 0)
1178 return ret;
1179
1180 ret = cx24116_diseqc_init(fe);
1181 if (ret != 0)
1182 return ret;
1183
1184
1185 return cx24116_set_voltage(fe, SEC_VOLTAGE_13);
1186}
1187
1188
1189
1190
1191static int cx24116_sleep(struct dvb_frontend *fe)
1192{
1193 struct cx24116_state *state = fe->demodulator_priv;
1194 struct cx24116_cmd cmd;
1195 int ret;
1196
1197 dprintk("%s()\n", __func__);
1198
1199
1200 cmd.args[0x00] = CMD_TUNERSLEEP;
1201 cmd.args[0x01] = 1;
1202 cmd.len = 0x02;
1203 ret = cx24116_cmd_execute(fe, &cmd);
1204 if (ret != 0)
1205 return ret;
1206
1207
1208 cx24116_writereg(state, 0xea, 0xff);
1209 cx24116_writereg(state, 0xe1, 1);
1210 cx24116_writereg(state, 0xe0, 1);
1211
1212 return 0;
1213}
1214
1215static int cx24116_set_property(struct dvb_frontend *fe,
1216 struct dtv_property *tvp)
1217{
1218 dprintk("%s(..)\n", __func__);
1219 return 0;
1220}
1221
1222static int cx24116_get_property(struct dvb_frontend *fe,
1223 struct dtv_property *tvp)
1224{
1225 dprintk("%s(..)\n", __func__);
1226 return 0;
1227}
1228
1229
1230
1231
1232static int cx24116_set_frontend(struct dvb_frontend *fe,
1233 struct dvb_frontend_parameters *p)
1234{
1235 struct cx24116_state *state = fe->demodulator_priv;
1236 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1237 struct cx24116_cmd cmd;
1238 fe_status_t tunerstat;
1239 int i, status, ret, retune = 1;
1240
1241 dprintk("%s()\n", __func__);
1242
1243 switch (c->delivery_system) {
1244 case SYS_DVBS:
1245 dprintk("%s: DVB-S delivery system selected\n", __func__);
1246
1247
1248 if (c->modulation != QPSK) {
1249 dprintk("%s: unsupported modulation selected (%d)\n",
1250 __func__, c->modulation);
1251 return -EOPNOTSUPP;
1252 }
1253
1254
1255 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1256
1257
1258 if (c->rolloff != ROLLOFF_35) {
1259 dprintk("%s: unsupported rolloff selected (%d)\n",
1260 __func__, c->rolloff);
1261 return -EOPNOTSUPP;
1262 }
1263 state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
1264 break;
1265
1266 case SYS_DVBS2:
1267 dprintk("%s: DVB-S2 delivery system selected\n", __func__);
1268
1269
1270
1271
1272
1273 if (c->modulation != PSK_8 && c->modulation != QPSK) {
1274 dprintk("%s: unsupported modulation selected (%d)\n",
1275 __func__, c->modulation);
1276 return -EOPNOTSUPP;
1277 }
1278
1279 switch (c->pilot) {
1280 case PILOT_AUTO:
1281 state->dnxt.pilot_val = (c->modulation == QPSK)
1282 ? CX24116_PILOT_OFF : CX24116_PILOT_ON;
1283 retune++;
1284 break;
1285 case PILOT_OFF:
1286 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1287 break;
1288 case PILOT_ON:
1289 state->dnxt.pilot_val = CX24116_PILOT_ON;
1290 break;
1291 default:
1292 dprintk("%s: unsupported pilot mode selected (%d)\n",
1293 __func__, c->pilot);
1294 return -EOPNOTSUPP;
1295 }
1296
1297 switch (c->rolloff) {
1298 case ROLLOFF_20:
1299 state->dnxt.rolloff_val = CX24116_ROLLOFF_020;
1300 break;
1301 case ROLLOFF_25:
1302 state->dnxt.rolloff_val = CX24116_ROLLOFF_025;
1303 break;
1304 case ROLLOFF_35:
1305 state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
1306 break;
1307 case ROLLOFF_AUTO:
1308 default:
1309 dprintk("%s: unsupported rolloff selected (%d)\n",
1310 __func__, c->rolloff);
1311 return -EOPNOTSUPP;
1312 }
1313 break;
1314
1315 default:
1316 dprintk("%s: unsupported delivery system selected (%d)\n",
1317 __func__, c->delivery_system);
1318 return -EOPNOTSUPP;
1319 }
1320 state->dnxt.delsys = c->delivery_system;
1321 state->dnxt.modulation = c->modulation;
1322 state->dnxt.frequency = c->frequency;
1323 state->dnxt.pilot = c->pilot;
1324 state->dnxt.rolloff = c->rolloff;
1325
1326 ret = cx24116_set_inversion(state, c->inversion);
1327 if (ret != 0)
1328 return ret;
1329
1330
1331 ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner);
1332 if (ret != 0)
1333 return ret;
1334
1335 ret = cx24116_set_symbolrate(state, c->symbol_rate);
1336 if (ret != 0)
1337 return ret;
1338
1339
1340 cx24116_clone_params(fe);
1341
1342 dprintk("%s: delsys = %d\n", __func__, state->dcur.delsys);
1343 dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation);
1344 dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency);
1345 dprintk("%s: pilot = %d (val = 0x%02x)\n", __func__,
1346 state->dcur.pilot, state->dcur.pilot_val);
1347 dprintk("%s: retune = %d\n", __func__, retune);
1348 dprintk("%s: rolloff = %d (val = 0x%02x)\n", __func__,
1349 state->dcur.rolloff, state->dcur.rolloff_val);
1350 dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
1351 dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
1352 state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
1353 dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__,
1354 state->dcur.inversion, state->dcur.inversion_val);
1355
1356
1357 if (state->config->set_ts_params)
1358 state->config->set_ts_params(fe, 0);
1359
1360
1361 cmd.args[0x00] = CMD_BANDWIDTH;
1362 cmd.args[0x01] = 0x01;
1363 cmd.len = 0x02;
1364 ret = cx24116_cmd_execute(fe, &cmd);
1365 if (ret != 0)
1366 return ret;
1367
1368
1369 cmd.args[0x00] = CMD_TUNEREQUEST;
1370
1371
1372 cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
1373 cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
1374 cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
1375
1376
1377 cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
1378 cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
1379
1380
1381 cmd.args[0x06] = state->dcur.inversion_val;
1382
1383
1384 cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
1385
1386 cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
1387 cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
1388 cmd.args[0x0a] = 0x00;
1389 cmd.args[0x0b] = 0x00;
1390 cmd.args[0x0c] = state->dcur.rolloff_val;
1391 cmd.args[0x0d] = state->dcur.fec_mask;
1392
1393 if (state->dcur.symbol_rate > 30000000) {
1394 cmd.args[0x0e] = 0x04;
1395 cmd.args[0x0f] = 0x00;
1396 cmd.args[0x10] = 0x01;
1397 cmd.args[0x11] = 0x77;
1398 cmd.args[0x12] = 0x36;
1399 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
1400 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
1401 } else {
1402 cmd.args[0x0e] = 0x06;
1403 cmd.args[0x0f] = 0x00;
1404 cmd.args[0x10] = 0x00;
1405 cmd.args[0x11] = 0xFA;
1406 cmd.args[0x12] = 0x24;
1407 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
1408 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
1409 }
1410
1411 cmd.len = 0x13;
1412
1413
1414
1415
1416
1417 do {
1418
1419 status = cx24116_readreg(state, CX24116_REG_SSTATUS)
1420 & CX24116_SIGNAL_MASK;
1421 cx24116_writereg(state, CX24116_REG_SSTATUS, status);
1422
1423
1424 ret = cx24116_cmd_execute(fe, &cmd);
1425 if (ret != 0)
1426 break;
1427
1428
1429
1430
1431
1432
1433
1434 for (i = 0; i < 50 ; i++) {
1435 cx24116_read_status(fe, &tunerstat);
1436 status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
1437 if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
1438 dprintk("%s: Tuned\n", __func__);
1439 goto tuned;
1440 }
1441 msleep(10);
1442 }
1443
1444 dprintk("%s: Not tuned\n", __func__);
1445
1446
1447 if (state->dcur.pilot == PILOT_AUTO)
1448 cmd.args[0x07] ^= CX24116_PILOT_ON;
1449 } while (--retune);
1450
1451tuned:
1452 cmd.args[0x00] = CMD_BANDWIDTH;
1453 cmd.args[0x01] = 0x00;
1454 cmd.len = 0x02;
1455 return cx24116_cmd_execute(fe, &cmd);
1456}
1457
1458static int cx24116_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params,
1459 unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
1460{
1461 *delay = HZ / 5;
1462 if (params) {
1463 int ret = cx24116_set_frontend(fe, params);
1464 if (ret)
1465 return ret;
1466 }
1467 return cx24116_read_status(fe, status);
1468}
1469
1470static int cx24116_get_algo(struct dvb_frontend *fe)
1471{
1472 return DVBFE_ALGO_HW;
1473}
1474
1475static struct dvb_frontend_ops cx24116_ops = {
1476
1477 .info = {
1478 .name = "Conexant CX24116/CX24118",
1479 .type = FE_QPSK,
1480 .frequency_min = 950000,
1481 .frequency_max = 2150000,
1482 .frequency_stepsize = 1011,
1483 .frequency_tolerance = 5000,
1484 .symbol_rate_min = 1000000,
1485 .symbol_rate_max = 45000000,
1486 .caps = FE_CAN_INVERSION_AUTO |
1487 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1488 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
1489 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1490 FE_CAN_2G_MODULATION |
1491 FE_CAN_QPSK | FE_CAN_RECOVER
1492 },
1493
1494 .release = cx24116_release,
1495
1496 .init = cx24116_initfe,
1497 .sleep = cx24116_sleep,
1498 .read_status = cx24116_read_status,
1499 .read_ber = cx24116_read_ber,
1500 .read_signal_strength = cx24116_read_signal_strength,
1501 .read_snr = cx24116_read_snr,
1502 .read_ucblocks = cx24116_read_ucblocks,
1503 .set_tone = cx24116_set_tone,
1504 .set_voltage = cx24116_set_voltage,
1505 .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
1506 .diseqc_send_burst = cx24116_diseqc_send_burst,
1507 .get_frontend_algo = cx24116_get_algo,
1508 .tune = cx24116_tune,
1509
1510 .set_property = cx24116_set_property,
1511 .get_property = cx24116_get_property,
1512 .set_frontend = cx24116_set_frontend,
1513};
1514
1515MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
1516MODULE_AUTHOR("Steven Toth");
1517MODULE_LICENSE("GPL");
1518
1519