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(debug, "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;
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 cx24116_writeregN(state, 0xF7, fw->data, fw->size);
608
609 cx24116_writereg(state, 0xF4, 0x10);
610 cx24116_writereg(state, 0xF0, 0x00);
611 cx24116_writereg(state, 0xF8, 0x06);
612
613
614 cmd.args[0x00] = CMD_SET_VCO;
615 cmd.args[0x01] = 0x05;
616 cmd.args[0x02] = 0xdc;
617 cmd.args[0x03] = 0xda;
618 cmd.args[0x04] = 0xae;
619 cmd.args[0x05] = 0xaa;
620 cmd.args[0x06] = 0x04;
621 cmd.args[0x07] = 0x9d;
622 cmd.args[0x08] = 0xfc;
623 cmd.args[0x09] = 0x06;
624 cmd.len = 0x0a;
625 ret = cx24116_cmd_execute(fe, &cmd);
626 if (ret != 0)
627 return ret;
628
629 cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
630
631
632 cmd.args[0x00] = CMD_TUNERINIT;
633 cmd.args[0x01] = 0x00;
634 cmd.args[0x02] = 0x00;
635 cmd.len = 0x03;
636 ret = cx24116_cmd_execute(fe, &cmd);
637 if (ret != 0)
638 return ret;
639
640 cx24116_writereg(state, 0xe5, 0x00);
641
642
643 cmd.args[0x00] = CMD_MPEGCONFIG;
644 cmd.args[0x01] = 0x01;
645 cmd.args[0x02] = 0x75;
646 cmd.args[0x03] = 0x00;
647 if (state->config->mpg_clk_pos_pol)
648 cmd.args[0x04] = state->config->mpg_clk_pos_pol;
649 else
650 cmd.args[0x04] = 0x02;
651 cmd.args[0x05] = 0x00;
652 cmd.len = 0x06;
653 ret = cx24116_cmd_execute(fe, &cmd);
654 if (ret != 0)
655 return ret;
656
657
658 cmd.args[0x00] = CMD_UPDFWVERS;
659 cmd.len = 0x02;
660 for (i = 0; i < 4; i++) {
661 cmd.args[0x01] = i;
662 ret = cx24116_cmd_execute(fe, &cmd);
663 if (ret != 0)
664 return ret;
665 vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
666 }
667 printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
668 vers[0], vers[1], vers[2], vers[3]);
669
670 return 0;
671}
672
673static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
674{
675 struct cx24116_state *state = fe->demodulator_priv;
676
677 int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) &
678 CX24116_STATUS_MASK;
679
680 dprintk("%s: status = 0x%02x\n", __func__, lock);
681
682 *status = 0;
683
684 if (lock & CX24116_HAS_SIGNAL)
685 *status |= FE_HAS_SIGNAL;
686 if (lock & CX24116_HAS_CARRIER)
687 *status |= FE_HAS_CARRIER;
688 if (lock & CX24116_HAS_VITERBI)
689 *status |= FE_HAS_VITERBI;
690 if (lock & CX24116_HAS_SYNCLOCK)
691 *status |= FE_HAS_SYNC | FE_HAS_LOCK;
692
693 return 0;
694}
695
696static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
697{
698 struct cx24116_state *state = fe->demodulator_priv;
699
700 dprintk("%s()\n", __func__);
701
702 *ber = (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
703 (cx24116_readreg(state, CX24116_REG_BER16) << 16) |
704 (cx24116_readreg(state, CX24116_REG_BER8) << 8) |
705 cx24116_readreg(state, CX24116_REG_BER0);
706
707 return 0;
708}
709
710
711static int cx24116_read_signal_strength(struct dvb_frontend *fe,
712 u16 *signal_strength)
713{
714 struct cx24116_state *state = fe->demodulator_priv;
715 struct cx24116_cmd cmd;
716 int ret;
717 u16 sig_reading;
718
719 dprintk("%s()\n", __func__);
720
721
722 cmd.args[0x00] = CMD_GETAGC;
723 cmd.len = 0x01;
724 ret = cx24116_cmd_execute(fe, &cmd);
725 if (ret != 0)
726 return ret;
727
728 sig_reading =
729 (cx24116_readreg(state,
730 CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
731 (cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
732 *signal_strength = 0 - sig_reading;
733
734 dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
735 __func__, sig_reading, *signal_strength);
736
737 return 0;
738}
739
740
741static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
742{
743 struct cx24116_state *state = fe->demodulator_priv;
744 u8 snr_reading;
745 static const u32 snr_tab[] = {
746 0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
747 0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
748 0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
749 0x18000 };
750
751 dprintk("%s()\n", __func__);
752
753 snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
754
755 if (snr_reading >= 0xa0 )
756 *snr = 0xffff;
757 else
758 *snr = snr_tab[(snr_reading & 0xf0) >> 4] +
759 (snr_tab[(snr_reading & 0x0f)] >> 4);
760
761 dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
762 snr_reading, *snr);
763
764 return 0;
765}
766
767
768
769
770
771static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
772{
773 struct cx24116_state *state = fe->demodulator_priv;
774
775 dprintk("%s()\n", __func__);
776
777 *snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
778 cx24116_readreg(state, CX24116_REG_QUALITY0);
779
780 dprintk("%s: raw 0x%04x\n", __func__, *snr);
781
782 return 0;
783}
784
785static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
786{
787 if (esno_snr == 1)
788 return cx24116_read_snr_esno(fe, snr);
789 else
790 return cx24116_read_snr_pct(fe, snr);
791}
792
793static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
794{
795 struct cx24116_state *state = fe->demodulator_priv;
796
797 dprintk("%s()\n", __func__);
798
799 *ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
800 cx24116_readreg(state, CX24116_REG_UCB0);
801
802 return 0;
803}
804
805
806static void cx24116_clone_params(struct dvb_frontend *fe)
807{
808 struct cx24116_state *state = fe->demodulator_priv;
809 memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
810}
811
812
813static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
814{
815 struct cx24116_state *state = fe->demodulator_priv;
816 int i;
817
818 dprintk("%s() qstatus = 0x%02x\n", __func__,
819 cx24116_readreg(state, CX24116_REG_QSTATUS));
820
821
822 for (i = 0; i < 30 ; i++) {
823 if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
824 return 0;
825 msleep(10);
826 }
827
828 dprintk("%s(): LNB not ready\n", __func__);
829
830 return -ETIMEDOUT;
831}
832
833static int cx24116_set_voltage(struct dvb_frontend *fe,
834 fe_sec_voltage_t voltage)
835{
836 struct cx24116_cmd cmd;
837 int ret;
838
839 dprintk("%s: %s\n", __func__,
840 voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
841 voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
842
843
844 ret = cx24116_wait_for_lnb(fe);
845 if (ret != 0)
846 return ret;
847
848
849 msleep(100);
850
851 cmd.args[0x00] = CMD_LNBDCLEVEL;
852 cmd.args[0x01] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);
853 cmd.len = 0x02;
854
855
856 msleep(15);
857
858 return cx24116_cmd_execute(fe, &cmd);
859}
860
861static int cx24116_set_tone(struct dvb_frontend *fe,
862 fe_sec_tone_mode_t tone)
863{
864 struct cx24116_cmd cmd;
865 int ret;
866
867 dprintk("%s(%d)\n", __func__, tone);
868 if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
869 printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
870 return -EINVAL;
871 }
872
873
874 ret = cx24116_wait_for_lnb(fe);
875 if (ret != 0)
876 return ret;
877
878
879 msleep(15);
880
881
882 cmd.args[0x00] = CMD_SET_TONE;
883 cmd.args[0x01] = 0x00;
884 cmd.args[0x02] = 0x00;
885
886 switch (tone) {
887 case SEC_TONE_ON:
888 dprintk("%s: setting tone on\n", __func__);
889 cmd.args[0x03] = 0x01;
890 break;
891 case SEC_TONE_OFF:
892 dprintk("%s: setting tone off\n", __func__);
893 cmd.args[0x03] = 0x00;
894 break;
895 }
896 cmd.len = 0x04;
897
898
899 msleep(15);
900
901 return cx24116_cmd_execute(fe, &cmd);
902}
903
904
905static int cx24116_diseqc_init(struct dvb_frontend *fe)
906{
907 struct cx24116_state *state = fe->demodulator_priv;
908 struct cx24116_cmd cmd;
909 int ret;
910
911
912 cmd.args[0x00] = CMD_LNBCONFIG;
913 cmd.args[0x01] = 0x00;
914 cmd.args[0x02] = 0x10;
915 cmd.args[0x03] = 0x00;
916 cmd.args[0x04] = 0x8f;
917 cmd.args[0x05] = 0x28;
918 cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
919 cmd.args[0x07] = 0x01;
920 cmd.len = 0x08;
921 ret = cx24116_cmd_execute(fe, &cmd);
922 if (ret != 0)
923 return ret;
924
925
926 state->dsec_cmd.args[0x00] = CMD_LNBSEND;
927
928
929 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
930
931
932 state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
933 state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
934
935 state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
936
937
938 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
939
940
941 state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
942
943 return 0;
944}
945
946
947static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
948 struct dvb_diseqc_master_cmd *d)
949{
950 struct cx24116_state *state = fe->demodulator_priv;
951 int i, ret;
952
953
954 if (debug) {
955 printk(KERN_INFO "cx24116: %s(", __func__);
956 for (i = 0 ; i < d->msg_len ;) {
957 printk(KERN_INFO "0x%02x", d->msg[i]);
958 if (++i < d->msg_len)
959 printk(KERN_INFO ", ");
960 }
961 printk(") toneburst=%d\n", toneburst);
962 }
963
964
965 if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
966 return -EINVAL;
967
968
969 for (i = 0; i < d->msg_len; i++)
970 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
971
972
973 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
974
975
976 state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
977 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
978
979
980 if (toneburst == CX24116_DISEQC_MESGCACHE)
981
982 return 0;
983
984 else if (toneburst == CX24116_DISEQC_TONEOFF)
985
986 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
987
988 else if (toneburst == CX24116_DISEQC_TONECACHE) {
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007 if (d->msg_len >= 4 && d->msg[2] == 0x38)
1008 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1009 ((d->msg[3] & 4) >> 2);
1010 if (debug)
1011 dprintk("%s burst=%d\n", __func__,
1012 state->dsec_cmd.args[CX24116_DISEQC_BURST]);
1013 }
1014
1015
1016 ret = cx24116_wait_for_lnb(fe);
1017 if (ret != 0)
1018 return ret;
1019
1020
1021 msleep(100);
1022
1023
1024 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1025 if (ret != 0)
1026 return ret;
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037 msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
1038 ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
1039
1040 return 0;
1041}
1042
1043
1044static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
1045 fe_sec_mini_cmd_t burst)
1046{
1047 struct cx24116_state *state = fe->demodulator_priv;
1048 int ret;
1049
1050 dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
1051
1052
1053 if (burst == SEC_MINI_A)
1054 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1055 CX24116_DISEQC_MINI_A;
1056 else if (burst == SEC_MINI_B)
1057 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1058 CX24116_DISEQC_MINI_B;
1059 else
1060 return -EINVAL;
1061
1062
1063 if (toneburst != CX24116_DISEQC_MESGCACHE)
1064
1065 return 0;
1066
1067
1068
1069
1070 ret = cx24116_wait_for_lnb(fe);
1071 if (ret != 0)
1072 return ret;
1073
1074
1075 msleep(100);
1076
1077
1078 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1079 if (ret != 0)
1080 return ret;
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092 msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
1093
1094 return 0;
1095}
1096
1097static void cx24116_release(struct dvb_frontend *fe)
1098{
1099 struct cx24116_state *state = fe->demodulator_priv;
1100 dprintk("%s\n", __func__);
1101 kfree(state);
1102}
1103
1104static struct dvb_frontend_ops cx24116_ops;
1105
1106struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
1107 struct i2c_adapter *i2c)
1108{
1109 struct cx24116_state *state = NULL;
1110 int ret;
1111
1112 dprintk("%s\n", __func__);
1113
1114
1115 state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL);
1116 if (state == NULL)
1117 goto error1;
1118
1119 state->config = config;
1120 state->i2c = i2c;
1121
1122
1123 ret = (cx24116_readreg(state, 0xFF) << 8) |
1124 cx24116_readreg(state, 0xFE);
1125 if (ret != 0x0501) {
1126 printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
1127 goto error2;
1128 }
1129
1130
1131 memcpy(&state->frontend.ops, &cx24116_ops,
1132 sizeof(struct dvb_frontend_ops));
1133 state->frontend.demodulator_priv = state;
1134 return &state->frontend;
1135
1136error2: kfree(state);
1137error1: return NULL;
1138}
1139EXPORT_SYMBOL(cx24116_attach);
1140
1141
1142
1143
1144
1145
1146static int cx24116_initfe(struct dvb_frontend *fe)
1147{
1148 struct cx24116_state *state = fe->demodulator_priv;
1149 struct cx24116_cmd cmd;
1150 int ret;
1151
1152 dprintk("%s()\n", __func__);
1153
1154
1155 cx24116_writereg(state, 0xe0, 0);
1156 cx24116_writereg(state, 0xe1, 0);
1157 cx24116_writereg(state, 0xea, 0);
1158
1159
1160 cmd.args[0x00] = CMD_TUNERSLEEP;
1161 cmd.args[0x01] = 0;
1162 cmd.len = 0x02;
1163 ret = cx24116_cmd_execute(fe, &cmd);
1164 if (ret != 0)
1165 return ret;
1166
1167 ret = cx24116_diseqc_init(fe);
1168 if (ret != 0)
1169 return ret;
1170
1171
1172 return cx24116_set_voltage(fe, SEC_VOLTAGE_13);
1173}
1174
1175
1176
1177
1178static int cx24116_sleep(struct dvb_frontend *fe)
1179{
1180 struct cx24116_state *state = fe->demodulator_priv;
1181 struct cx24116_cmd cmd;
1182 int ret;
1183
1184 dprintk("%s()\n", __func__);
1185
1186
1187 cmd.args[0x00] = CMD_TUNERSLEEP;
1188 cmd.args[0x01] = 1;
1189 cmd.len = 0x02;
1190 ret = cx24116_cmd_execute(fe, &cmd);
1191 if (ret != 0)
1192 return ret;
1193
1194
1195 cx24116_writereg(state, 0xea, 0xff);
1196 cx24116_writereg(state, 0xe1, 1);
1197 cx24116_writereg(state, 0xe0, 1);
1198
1199 return 0;
1200}
1201
1202static int cx24116_set_property(struct dvb_frontend *fe,
1203 struct dtv_property *tvp)
1204{
1205 dprintk("%s(..)\n", __func__);
1206 return 0;
1207}
1208
1209static int cx24116_get_property(struct dvb_frontend *fe,
1210 struct dtv_property *tvp)
1211{
1212 dprintk("%s(..)\n", __func__);
1213 return 0;
1214}
1215
1216
1217
1218
1219static int cx24116_set_frontend(struct dvb_frontend *fe,
1220 struct dvb_frontend_parameters *p)
1221{
1222 struct cx24116_state *state = fe->demodulator_priv;
1223 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1224 struct cx24116_cmd cmd;
1225 fe_status_t tunerstat;
1226 int i, status, ret, retune = 1;
1227
1228 dprintk("%s()\n", __func__);
1229
1230 switch (c->delivery_system) {
1231 case SYS_DVBS:
1232 dprintk("%s: DVB-S delivery system selected\n", __func__);
1233
1234
1235 if (c->modulation != QPSK) {
1236 dprintk("%s: unsupported modulation selected (%d)\n",
1237 __func__, c->modulation);
1238 return -EOPNOTSUPP;
1239 }
1240
1241
1242 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1243
1244
1245 if (c->rolloff != ROLLOFF_35) {
1246 dprintk("%s: unsupported rolloff selected (%d)\n",
1247 __func__, c->rolloff);
1248 return -EOPNOTSUPP;
1249 }
1250 state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
1251 break;
1252
1253 case SYS_DVBS2:
1254 dprintk("%s: DVB-S2 delivery system selected\n", __func__);
1255
1256
1257
1258
1259
1260 if (c->modulation != PSK_8 && c->modulation != QPSK) {
1261 dprintk("%s: unsupported modulation selected (%d)\n",
1262 __func__, c->modulation);
1263 return -EOPNOTSUPP;
1264 }
1265
1266 switch (c->pilot) {
1267 case PILOT_AUTO:
1268 state->dnxt.pilot_val = (c->modulation == QPSK)
1269 ? CX24116_PILOT_OFF : CX24116_PILOT_ON;
1270 retune++;
1271 break;
1272 case PILOT_OFF:
1273 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1274 break;
1275 case PILOT_ON:
1276 state->dnxt.pilot_val = CX24116_PILOT_ON;
1277 break;
1278 default:
1279 dprintk("%s: unsupported pilot mode selected (%d)\n",
1280 __func__, c->pilot);
1281 return -EOPNOTSUPP;
1282 }
1283
1284 switch (c->rolloff) {
1285 case ROLLOFF_20:
1286 state->dnxt.rolloff_val = CX24116_ROLLOFF_020;
1287 break;
1288 case ROLLOFF_25:
1289 state->dnxt.rolloff_val = CX24116_ROLLOFF_025;
1290 break;
1291 case ROLLOFF_35:
1292 state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
1293 break;
1294 case ROLLOFF_AUTO:
1295 default:
1296 dprintk("%s: unsupported rolloff selected (%d)\n",
1297 __func__, c->rolloff);
1298 return -EOPNOTSUPP;
1299 }
1300 break;
1301
1302 default:
1303 dprintk("%s: unsupported delivery system selected (%d)\n",
1304 __func__, c->delivery_system);
1305 return -EOPNOTSUPP;
1306 }
1307 state->dnxt.delsys = c->delivery_system;
1308 state->dnxt.modulation = c->modulation;
1309 state->dnxt.frequency = c->frequency;
1310 state->dnxt.pilot = c->pilot;
1311 state->dnxt.rolloff = c->rolloff;
1312
1313 ret = cx24116_set_inversion(state, c->inversion);
1314 if (ret != 0)
1315 return ret;
1316
1317
1318 ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner);
1319 if (ret != 0)
1320 return ret;
1321
1322 ret = cx24116_set_symbolrate(state, c->symbol_rate);
1323 if (ret != 0)
1324 return ret;
1325
1326
1327 cx24116_clone_params(fe);
1328
1329 dprintk("%s: delsys = %d\n", __func__, state->dcur.delsys);
1330 dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation);
1331 dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency);
1332 dprintk("%s: pilot = %d (val = 0x%02x)\n", __func__,
1333 state->dcur.pilot, state->dcur.pilot_val);
1334 dprintk("%s: retune = %d\n", __func__, retune);
1335 dprintk("%s: rolloff = %d (val = 0x%02x)\n", __func__,
1336 state->dcur.rolloff, state->dcur.rolloff_val);
1337 dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
1338 dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
1339 state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
1340 dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__,
1341 state->dcur.inversion, state->dcur.inversion_val);
1342
1343
1344 if (state->config->set_ts_params)
1345 state->config->set_ts_params(fe, 0);
1346
1347
1348 cmd.args[0x00] = CMD_BANDWIDTH;
1349 cmd.args[0x01] = 0x01;
1350 cmd.len = 0x02;
1351 ret = cx24116_cmd_execute(fe, &cmd);
1352 if (ret != 0)
1353 return ret;
1354
1355
1356 cmd.args[0x00] = CMD_TUNEREQUEST;
1357
1358
1359 cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
1360 cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
1361 cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
1362
1363
1364 cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
1365 cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
1366
1367
1368 cmd.args[0x06] = state->dcur.inversion_val;
1369
1370
1371 cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
1372
1373 cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
1374 cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
1375 cmd.args[0x0a] = 0x00;
1376 cmd.args[0x0b] = 0x00;
1377 cmd.args[0x0c] = state->dcur.rolloff_val;
1378 cmd.args[0x0d] = state->dcur.fec_mask;
1379
1380 if (state->dcur.symbol_rate > 30000000) {
1381 cmd.args[0x0e] = 0x04;
1382 cmd.args[0x0f] = 0x00;
1383 cmd.args[0x10] = 0x01;
1384 cmd.args[0x11] = 0x77;
1385 cmd.args[0x12] = 0x36;
1386 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
1387 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
1388 } else {
1389 cmd.args[0x0e] = 0x06;
1390 cmd.args[0x0f] = 0x00;
1391 cmd.args[0x10] = 0x00;
1392 cmd.args[0x11] = 0xFA;
1393 cmd.args[0x12] = 0x24;
1394 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
1395 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
1396 }
1397
1398 cmd.len = 0x13;
1399
1400
1401
1402
1403
1404 do {
1405
1406 status = cx24116_readreg(state, CX24116_REG_SSTATUS)
1407 & CX24116_SIGNAL_MASK;
1408 cx24116_writereg(state, CX24116_REG_SSTATUS, status);
1409
1410
1411 ret = cx24116_cmd_execute(fe, &cmd);
1412 if (ret != 0)
1413 break;
1414
1415
1416
1417
1418
1419
1420
1421 for (i = 0; i < 50 ; i++) {
1422 cx24116_read_status(fe, &tunerstat);
1423 status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
1424 if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
1425 dprintk("%s: Tuned\n", __func__);
1426 goto tuned;
1427 }
1428 msleep(10);
1429 }
1430
1431 dprintk("%s: Not tuned\n", __func__);
1432
1433
1434 if (state->dcur.pilot == PILOT_AUTO)
1435 cmd.args[0x07] ^= CX24116_PILOT_ON;
1436 } while (--retune);
1437
1438tuned:
1439 cmd.args[0x00] = CMD_BANDWIDTH;
1440 cmd.args[0x01] = 0x00;
1441 cmd.len = 0x02;
1442 ret = cx24116_cmd_execute(fe, &cmd);
1443 if (ret != 0)
1444 return ret;
1445
1446 return ret;
1447}
1448
1449static int cx24116_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params,
1450 unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
1451{
1452 *delay = HZ / 5;
1453 if (params) {
1454 int ret = cx24116_set_frontend(fe, params);
1455 if (ret)
1456 return ret;
1457 }
1458 return cx24116_read_status(fe, status);
1459}
1460
1461static int cx24116_get_algo(struct dvb_frontend *fe)
1462{
1463 return DVBFE_ALGO_HW;
1464}
1465
1466static struct dvb_frontend_ops cx24116_ops = {
1467
1468 .info = {
1469 .name = "Conexant CX24116/CX24118",
1470 .type = FE_QPSK,
1471 .frequency_min = 950000,
1472 .frequency_max = 2150000,
1473 .frequency_stepsize = 1011,
1474 .frequency_tolerance = 5000,
1475 .symbol_rate_min = 1000000,
1476 .symbol_rate_max = 45000000,
1477 .caps = FE_CAN_INVERSION_AUTO |
1478 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1479 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
1480 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1481 FE_CAN_2G_MODULATION |
1482 FE_CAN_QPSK | FE_CAN_RECOVER
1483 },
1484
1485 .release = cx24116_release,
1486
1487 .init = cx24116_initfe,
1488 .sleep = cx24116_sleep,
1489 .read_status = cx24116_read_status,
1490 .read_ber = cx24116_read_ber,
1491 .read_signal_strength = cx24116_read_signal_strength,
1492 .read_snr = cx24116_read_snr,
1493 .read_ucblocks = cx24116_read_ucblocks,
1494 .set_tone = cx24116_set_tone,
1495 .set_voltage = cx24116_set_voltage,
1496 .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
1497 .diseqc_send_burst = cx24116_diseqc_send_burst,
1498 .get_frontend_algo = cx24116_get_algo,
1499 .tune = cx24116_tune,
1500
1501 .set_property = cx24116_set_property,
1502 .get_property = cx24116_get_property,
1503 .set_frontend = cx24116_set_frontend,
1504};
1505
1506MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
1507MODULE_AUTHOR("Steven Toth");
1508MODULE_LICENSE("GPL");
1509
1510