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 enum fe_spectral_inversion inversion;
164 enum fe_code_rate fec;
165
166 enum fe_delivery_system delsys;
167 enum fe_modulation modulation;
168 enum fe_pilot pilot;
169 enum fe_rolloff 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, value == 0x%02x)\n",
213 __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 enum fe_spectral_inversion 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 enum fe_delivery_system delivery_system;
377 enum fe_modulation modulation;
378 enum fe_code_rate 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 enum fe_delivery_system d, enum fe_modulation m, enum fe_code_rate 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 enum fe_delivery_system delsys,
438 enum fe_modulation mod,
439 enum fe_code_rate fec)
440{
441 int ret = 0;
442
443 dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
444
445 ret = cx24116_lookup_fecmod(state, delsys, mod, fec);
446
447 if (ret < 0)
448 return ret;
449
450 state->dnxt.fec = fec;
451 state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
452 state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
453 dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
454 state->dnxt.fec_mask, state->dnxt.fec_val);
455
456 return 0;
457}
458
459static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)
460{
461 dprintk("%s(%d)\n", __func__, rate);
462
463
464 if ((rate > state->frontend.ops.info.symbol_rate_max) ||
465 (rate < state->frontend.ops.info.symbol_rate_min)) {
466 dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
467 return -EOPNOTSUPP;
468 }
469
470 state->dnxt.symbol_rate = rate;
471 dprintk("%s() symbol_rate = %d\n", __func__, rate);
472
473 return 0;
474}
475
476static int cx24116_load_firmware(struct dvb_frontend *fe,
477 const struct firmware *fw);
478
479static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
480{
481 struct cx24116_state *state = fe->demodulator_priv;
482 const struct firmware *fw;
483 int ret = 0;
484
485 dprintk("%s()\n", __func__);
486
487 if (cx24116_readreg(state, 0x20) > 0) {
488
489 if (state->skip_fw_load)
490 return 0;
491
492
493
494 printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
495 __func__, CX24116_DEFAULT_FIRMWARE);
496 ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
497 state->i2c->dev.parent);
498 printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
499 __func__);
500 if (ret) {
501 printk(KERN_ERR "%s: No firmware uploaded (timeout or file not found?)\n",
502 __func__);
503 return ret;
504 }
505
506
507
508 state->skip_fw_load = 1;
509
510 ret = cx24116_load_firmware(fe, fw);
511 if (ret)
512 printk(KERN_ERR "%s: Writing firmware to device failed\n",
513 __func__);
514
515 release_firmware(fw);
516
517 printk(KERN_INFO "%s: Firmware upload %s\n", __func__,
518 ret == 0 ? "complete" : "failed");
519
520
521 state->skip_fw_load = 0;
522 }
523
524 return ret;
525}
526
527
528
529
530static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)
531{
532 struct cx24116_state *state = fe->demodulator_priv;
533 int i, ret;
534
535 dprintk("%s()\n", __func__);
536
537
538 ret = cx24116_firmware_ondemand(fe);
539 if (ret != 0) {
540 printk(KERN_ERR "%s(): Unable initialise the firmware\n",
541 __func__);
542 return ret;
543 }
544
545
546 for (i = 0; i < cmd->len ; i++) {
547 dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
548 cx24116_writereg(state, i, cmd->args[i]);
549 }
550
551
552 cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
553 while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {
554 msleep(10);
555 if (i++ > 64) {
556
557
558 printk(KERN_WARNING "%s() Firmware not responding\n",
559 __func__);
560 return -EREMOTEIO;
561 }
562 }
563 return 0;
564}
565
566static int cx24116_load_firmware(struct dvb_frontend *fe,
567 const struct firmware *fw)
568{
569 struct cx24116_state *state = fe->demodulator_priv;
570 struct cx24116_cmd cmd;
571 int i, ret, len, max, remaining;
572 unsigned char vers[4];
573
574 dprintk("%s\n", __func__);
575 dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
576 fw->size,
577 fw->data[0],
578 fw->data[1],
579 fw->data[fw->size-2],
580 fw->data[fw->size-1]);
581
582
583 if (state->config->reset_device)
584 state->config->reset_device(fe);
585
586
587
588
589
590 cx24116_writereg(state, 0xE5, 0x00);
591 cx24116_writereg(state, 0xF1, 0x08);
592 cx24116_writereg(state, 0xF2, 0x13);
593
594
595 cx24116_writereg(state, 0xe0, 0x03);
596 cx24116_writereg(state, 0xe0, 0x00);
597
598
599 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
600 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
601
602
603 cx24116_writereg(state, 0xF0, 0x03);
604 cx24116_writereg(state, 0xF4, 0x81);
605 cx24116_writereg(state, 0xF5, 0x00);
606 cx24116_writereg(state, 0xF6, 0x00);
607
608
609
610 if (state->config->i2c_wr_max)
611 max = state->config->i2c_wr_max;
612 else
613 max = INT_MAX;
614
615 for (remaining = fw->size; remaining > 0; remaining -= max - 1) {
616 len = remaining;
617 if (len > max - 1)
618 len = max - 1;
619
620 cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],
621 len);
622 }
623
624 cx24116_writereg(state, 0xF4, 0x10);
625 cx24116_writereg(state, 0xF0, 0x00);
626 cx24116_writereg(state, 0xF8, 0x06);
627
628
629 cmd.args[0x00] = CMD_SET_VCO;
630 cmd.args[0x01] = 0x05;
631 cmd.args[0x02] = 0xdc;
632 cmd.args[0x03] = 0xda;
633 cmd.args[0x04] = 0xae;
634 cmd.args[0x05] = 0xaa;
635 cmd.args[0x06] = 0x04;
636 cmd.args[0x07] = 0x9d;
637 cmd.args[0x08] = 0xfc;
638 cmd.args[0x09] = 0x06;
639 cmd.len = 0x0a;
640 ret = cx24116_cmd_execute(fe, &cmd);
641 if (ret != 0)
642 return ret;
643
644 cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
645
646
647 cmd.args[0x00] = CMD_TUNERINIT;
648 cmd.args[0x01] = 0x00;
649 cmd.args[0x02] = 0x00;
650 cmd.len = 0x03;
651 ret = cx24116_cmd_execute(fe, &cmd);
652 if (ret != 0)
653 return ret;
654
655 cx24116_writereg(state, 0xe5, 0x00);
656
657
658 cmd.args[0x00] = CMD_MPEGCONFIG;
659 cmd.args[0x01] = 0x01;
660 cmd.args[0x02] = 0x75;
661 cmd.args[0x03] = 0x00;
662 if (state->config->mpg_clk_pos_pol)
663 cmd.args[0x04] = state->config->mpg_clk_pos_pol;
664 else
665 cmd.args[0x04] = 0x02;
666 cmd.args[0x05] = 0x00;
667 cmd.len = 0x06;
668 ret = cx24116_cmd_execute(fe, &cmd);
669 if (ret != 0)
670 return ret;
671
672
673 cmd.args[0x00] = CMD_UPDFWVERS;
674 cmd.len = 0x02;
675 for (i = 0; i < 4; i++) {
676 cmd.args[0x01] = i;
677 ret = cx24116_cmd_execute(fe, &cmd);
678 if (ret != 0)
679 return ret;
680 vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
681 }
682 printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
683 vers[0], vers[1], vers[2], vers[3]);
684
685 return 0;
686}
687
688static int cx24116_read_status(struct dvb_frontend *fe, enum fe_status *status)
689{
690 struct cx24116_state *state = fe->demodulator_priv;
691
692 int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) &
693 CX24116_STATUS_MASK;
694
695 dprintk("%s: status = 0x%02x\n", __func__, lock);
696
697 *status = 0;
698
699 if (lock & CX24116_HAS_SIGNAL)
700 *status |= FE_HAS_SIGNAL;
701 if (lock & CX24116_HAS_CARRIER)
702 *status |= FE_HAS_CARRIER;
703 if (lock & CX24116_HAS_VITERBI)
704 *status |= FE_HAS_VITERBI;
705 if (lock & CX24116_HAS_SYNCLOCK)
706 *status |= FE_HAS_SYNC | FE_HAS_LOCK;
707
708 return 0;
709}
710
711static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
712{
713 struct cx24116_state *state = fe->demodulator_priv;
714
715 dprintk("%s()\n", __func__);
716
717 *ber = (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
718 (cx24116_readreg(state, CX24116_REG_BER16) << 16) |
719 (cx24116_readreg(state, CX24116_REG_BER8) << 8) |
720 cx24116_readreg(state, CX24116_REG_BER0);
721
722 return 0;
723}
724
725
726static int cx24116_read_signal_strength(struct dvb_frontend *fe,
727 u16 *signal_strength)
728{
729 struct cx24116_state *state = fe->demodulator_priv;
730 struct cx24116_cmd cmd;
731 int ret;
732 u16 sig_reading;
733
734 dprintk("%s()\n", __func__);
735
736
737 cmd.args[0x00] = CMD_GETAGC;
738 cmd.len = 0x01;
739 ret = cx24116_cmd_execute(fe, &cmd);
740 if (ret != 0)
741 return ret;
742
743 sig_reading =
744 (cx24116_readreg(state,
745 CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
746 (cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
747 *signal_strength = 0 - sig_reading;
748
749 dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
750 __func__, sig_reading, *signal_strength);
751
752 return 0;
753}
754
755
756static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
757{
758 struct cx24116_state *state = fe->demodulator_priv;
759 u8 snr_reading;
760 static const u32 snr_tab[] = {
761 0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
762 0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
763 0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
764 0x18000 };
765
766 dprintk("%s()\n", __func__);
767
768 snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
769
770 if (snr_reading >= 0xa0 )
771 *snr = 0xffff;
772 else
773 *snr = snr_tab[(snr_reading & 0xf0) >> 4] +
774 (snr_tab[(snr_reading & 0x0f)] >> 4);
775
776 dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
777 snr_reading, *snr);
778
779 return 0;
780}
781
782
783
784
785
786static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
787{
788 struct cx24116_state *state = fe->demodulator_priv;
789
790 dprintk("%s()\n", __func__);
791
792 *snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
793 cx24116_readreg(state, CX24116_REG_QUALITY0);
794
795 dprintk("%s: raw 0x%04x\n", __func__, *snr);
796
797 return 0;
798}
799
800static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
801{
802 if (esno_snr == 1)
803 return cx24116_read_snr_esno(fe, snr);
804 else
805 return cx24116_read_snr_pct(fe, snr);
806}
807
808static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
809{
810 struct cx24116_state *state = fe->demodulator_priv;
811
812 dprintk("%s()\n", __func__);
813
814 *ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
815 cx24116_readreg(state, CX24116_REG_UCB0);
816
817 return 0;
818}
819
820
821static void cx24116_clone_params(struct dvb_frontend *fe)
822{
823 struct cx24116_state *state = fe->demodulator_priv;
824 state->dcur = state->dnxt;
825}
826
827
828static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
829{
830 struct cx24116_state *state = fe->demodulator_priv;
831 int i;
832
833 dprintk("%s() qstatus = 0x%02x\n", __func__,
834 cx24116_readreg(state, CX24116_REG_QSTATUS));
835
836
837 for (i = 0; i < 30 ; i++) {
838 if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
839 return 0;
840 msleep(10);
841 }
842
843 dprintk("%s(): LNB not ready\n", __func__);
844
845 return -ETIMEDOUT;
846}
847
848static int cx24116_set_voltage(struct dvb_frontend *fe,
849 enum fe_sec_voltage voltage)
850{
851 struct cx24116_cmd cmd;
852 int ret;
853
854 dprintk("%s: %s\n", __func__,
855 voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
856 voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
857
858
859 ret = cx24116_wait_for_lnb(fe);
860 if (ret != 0)
861 return ret;
862
863
864 msleep(100);
865
866 cmd.args[0x00] = CMD_LNBDCLEVEL;
867 cmd.args[0x01] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);
868 cmd.len = 0x02;
869
870
871 msleep(15);
872
873 return cx24116_cmd_execute(fe, &cmd);
874}
875
876static int cx24116_set_tone(struct dvb_frontend *fe,
877 enum fe_sec_tone_mode tone)
878{
879 struct cx24116_cmd cmd;
880 int ret;
881
882 dprintk("%s(%d)\n", __func__, tone);
883 if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
884 printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
885 return -EINVAL;
886 }
887
888
889 ret = cx24116_wait_for_lnb(fe);
890 if (ret != 0)
891 return ret;
892
893
894 msleep(15);
895
896
897 cmd.args[0x00] = CMD_SET_TONE;
898 cmd.args[0x01] = 0x00;
899 cmd.args[0x02] = 0x00;
900
901 switch (tone) {
902 case SEC_TONE_ON:
903 dprintk("%s: setting tone on\n", __func__);
904 cmd.args[0x03] = 0x01;
905 break;
906 case SEC_TONE_OFF:
907 dprintk("%s: setting tone off\n", __func__);
908 cmd.args[0x03] = 0x00;
909 break;
910 }
911 cmd.len = 0x04;
912
913
914 msleep(15);
915
916 return cx24116_cmd_execute(fe, &cmd);
917}
918
919
920static int cx24116_diseqc_init(struct dvb_frontend *fe)
921{
922 struct cx24116_state *state = fe->demodulator_priv;
923 struct cx24116_cmd cmd;
924 int ret;
925
926
927 cmd.args[0x00] = CMD_LNBCONFIG;
928 cmd.args[0x01] = 0x00;
929 cmd.args[0x02] = 0x10;
930 cmd.args[0x03] = 0x00;
931 cmd.args[0x04] = 0x8f;
932 cmd.args[0x05] = 0x28;
933 cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
934 cmd.args[0x07] = 0x01;
935 cmd.len = 0x08;
936 ret = cx24116_cmd_execute(fe, &cmd);
937 if (ret != 0)
938 return ret;
939
940
941 state->dsec_cmd.args[0x00] = CMD_LNBSEND;
942
943
944 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
945
946
947 state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
948 state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
949
950 state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
951
952
953 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
954
955
956 state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
957
958 return 0;
959}
960
961
962static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
963 struct dvb_diseqc_master_cmd *d)
964{
965 struct cx24116_state *state = fe->demodulator_priv;
966 int i, ret;
967
968
969 if (d->msg_len > sizeof(d->msg))
970 return -EINVAL;
971
972
973 if (debug) {
974 printk(KERN_INFO "cx24116: %s(", __func__);
975 for (i = 0 ; i < d->msg_len ;) {
976 printk(KERN_INFO "0x%02x", d->msg[i]);
977 if (++i < d->msg_len)
978 printk(KERN_INFO ", ");
979 }
980 printk(") toneburst=%d\n", toneburst);
981 }
982
983
984 for (i = 0; i < d->msg_len; i++)
985 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
986
987
988 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
989
990
991 state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
992 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
993
994
995 if (toneburst == CX24116_DISEQC_MESGCACHE)
996
997 return 0;
998
999 else if (toneburst == CX24116_DISEQC_TONEOFF)
1000
1001 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
1002
1003 else if (toneburst == CX24116_DISEQC_TONECACHE) {
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022 if (d->msg_len >= 4 && d->msg[2] == 0x38)
1023 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1024 ((d->msg[3] & 4) >> 2);
1025 if (debug)
1026 dprintk("%s burst=%d\n", __func__,
1027 state->dsec_cmd.args[CX24116_DISEQC_BURST]);
1028 }
1029
1030
1031 ret = cx24116_wait_for_lnb(fe);
1032 if (ret != 0)
1033 return ret;
1034
1035
1036 msleep(100);
1037
1038
1039 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1040 if (ret != 0)
1041 return ret;
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052 msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
1053 ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
1054
1055 return 0;
1056}
1057
1058
1059static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
1060 enum fe_sec_mini_cmd burst)
1061{
1062 struct cx24116_state *state = fe->demodulator_priv;
1063 int ret;
1064
1065 dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
1066
1067
1068 if (burst == SEC_MINI_A)
1069 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1070 CX24116_DISEQC_MINI_A;
1071 else if (burst == SEC_MINI_B)
1072 state->dsec_cmd.args[CX24116_DISEQC_BURST] =
1073 CX24116_DISEQC_MINI_B;
1074 else
1075 return -EINVAL;
1076
1077
1078 if (toneburst != CX24116_DISEQC_MESGCACHE)
1079
1080 return 0;
1081
1082
1083
1084
1085 ret = cx24116_wait_for_lnb(fe);
1086 if (ret != 0)
1087 return ret;
1088
1089
1090 msleep(100);
1091
1092
1093 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1094 if (ret != 0)
1095 return ret;
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107 msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
1108
1109 return 0;
1110}
1111
1112static void cx24116_release(struct dvb_frontend *fe)
1113{
1114 struct cx24116_state *state = fe->demodulator_priv;
1115 dprintk("%s\n", __func__);
1116 kfree(state);
1117}
1118
1119static const struct dvb_frontend_ops cx24116_ops;
1120
1121struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
1122 struct i2c_adapter *i2c)
1123{
1124 struct cx24116_state *state = NULL;
1125 int ret;
1126
1127 dprintk("%s\n", __func__);
1128
1129
1130 state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL);
1131 if (state == NULL)
1132 goto error1;
1133
1134 state->config = config;
1135 state->i2c = i2c;
1136
1137
1138 ret = (cx24116_readreg(state, 0xFF) << 8) |
1139 cx24116_readreg(state, 0xFE);
1140 if (ret != 0x0501) {
1141 printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
1142 goto error2;
1143 }
1144
1145
1146 memcpy(&state->frontend.ops, &cx24116_ops,
1147 sizeof(struct dvb_frontend_ops));
1148 state->frontend.demodulator_priv = state;
1149 return &state->frontend;
1150
1151error2: kfree(state);
1152error1: return NULL;
1153}
1154EXPORT_SYMBOL(cx24116_attach);
1155
1156
1157
1158
1159
1160
1161static int cx24116_initfe(struct dvb_frontend *fe)
1162{
1163 struct cx24116_state *state = fe->demodulator_priv;
1164 struct cx24116_cmd cmd;
1165 int ret;
1166
1167 dprintk("%s()\n", __func__);
1168
1169
1170 cx24116_writereg(state, 0xe0, 0);
1171 cx24116_writereg(state, 0xe1, 0);
1172 cx24116_writereg(state, 0xea, 0);
1173
1174
1175 cmd.args[0x00] = CMD_TUNERSLEEP;
1176 cmd.args[0x01] = 0;
1177 cmd.len = 0x02;
1178 ret = cx24116_cmd_execute(fe, &cmd);
1179 if (ret != 0)
1180 return ret;
1181
1182 ret = cx24116_diseqc_init(fe);
1183 if (ret != 0)
1184 return ret;
1185
1186
1187 return cx24116_set_voltage(fe, SEC_VOLTAGE_13);
1188}
1189
1190
1191
1192
1193static int cx24116_sleep(struct dvb_frontend *fe)
1194{
1195 struct cx24116_state *state = fe->demodulator_priv;
1196 struct cx24116_cmd cmd;
1197 int ret;
1198
1199 dprintk("%s()\n", __func__);
1200
1201
1202 cmd.args[0x00] = CMD_TUNERSLEEP;
1203 cmd.args[0x01] = 1;
1204 cmd.len = 0x02;
1205 ret = cx24116_cmd_execute(fe, &cmd);
1206 if (ret != 0)
1207 return ret;
1208
1209
1210 cx24116_writereg(state, 0xea, 0xff);
1211 cx24116_writereg(state, 0xe1, 1);
1212 cx24116_writereg(state, 0xe0, 1);
1213
1214 return 0;
1215}
1216
1217
1218
1219
1220static int cx24116_set_frontend(struct dvb_frontend *fe)
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 enum fe_status 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 return cx24116_cmd_execute(fe, &cmd);
1443}
1444
1445static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,
1446 unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
1447{
1448
1449
1450
1451
1452
1453
1454
1455
1456 *delay = HZ / 5;
1457 if (re_tune) {
1458 int ret = cx24116_set_frontend(fe);
1459 if (ret)
1460 return ret;
1461 }
1462 return cx24116_read_status(fe, status);
1463}
1464
1465static int cx24116_get_algo(struct dvb_frontend *fe)
1466{
1467 return DVBFE_ALGO_HW;
1468}
1469
1470static const struct dvb_frontend_ops cx24116_ops = {
1471 .delsys = { SYS_DVBS, SYS_DVBS2 },
1472 .info = {
1473 .name = "Conexant CX24116/CX24118",
1474 .frequency_min = 950000,
1475 .frequency_max = 2150000,
1476 .frequency_stepsize = 1011,
1477 .frequency_tolerance = 5000,
1478 .symbol_rate_min = 1000000,
1479 .symbol_rate_max = 45000000,
1480 .caps = FE_CAN_INVERSION_AUTO |
1481 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1482 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
1483 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1484 FE_CAN_2G_MODULATION |
1485 FE_CAN_QPSK | FE_CAN_RECOVER
1486 },
1487
1488 .release = cx24116_release,
1489
1490 .init = cx24116_initfe,
1491 .sleep = cx24116_sleep,
1492 .read_status = cx24116_read_status,
1493 .read_ber = cx24116_read_ber,
1494 .read_signal_strength = cx24116_read_signal_strength,
1495 .read_snr = cx24116_read_snr,
1496 .read_ucblocks = cx24116_read_ucblocks,
1497 .set_tone = cx24116_set_tone,
1498 .set_voltage = cx24116_set_voltage,
1499 .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
1500 .diseqc_send_burst = cx24116_diseqc_send_burst,
1501 .get_frontend_algo = cx24116_get_algo,
1502 .tune = cx24116_tune,
1503
1504 .set_frontend = cx24116_set_frontend,
1505};
1506
1507MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
1508MODULE_AUTHOR("Steven Toth");
1509MODULE_LICENSE("GPL");
1510
1511