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