aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/cx24116.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/cx24116.c')
-rw-r--r--drivers/media/dvb/frontends/cx24116.c1423
1 files changed, 1423 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
new file mode 100644
index 000000000000..deb36f469ada
--- /dev/null
+++ b/drivers/media/dvb/frontends/cx24116.c
@@ -0,0 +1,1423 @@
1/*
2 Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
3
4 Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com>
5 Copyright (C) 2006-2007 Georg Acher
6 Copyright (C) 2007-2008 Darron Broad
7 March 2007
8 Fixed some bugs.
9 Added diseqc support.
10 Added corrected signal strength support.
11 August 2007
12 Sync with legacy version.
13 Some clean ups.
14 Copyright (C) 2008 Igor Liplianin
15 September, 9th 2008
16 Fixed locking on high symbol rates (>30000).
17 Implement MPEG initialization parameter.
18
19 This program is free software; you can redistribute it and/or modify
20 it under the terms of the GNU General Public License as published by
21 the Free Software Foundation; either version 2 of the License, or
22 (at your option) any later version.
23
24 This program is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 GNU General Public License for more details.
28
29 You should have received a copy of the GNU General Public License
30 along with this program; if not, write to the Free Software
31 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32*/
33
34#include <linux/slab.h>
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/moduleparam.h>
38#include <linux/init.h>
39#include <linux/firmware.h>
40
41#include "dvb_frontend.h"
42#include "cx24116.h"
43
44static int debug = 0;
45#define dprintk(args...) \
46 do { \
47 if (debug) printk ("cx24116: " args); \
48 } while (0)
49
50#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
51#define CX24116_SEARCH_RANGE_KHZ 5000
52
53/* known registers */
54#define CX24116_REG_COMMAND (0x00) /* command args 0x00..0x1e */
55#define CX24116_REG_EXECUTE (0x1f) /* execute command */
56#define CX24116_REG_MAILBOX (0x96) /* FW or multipurpose mailbox? */
57#define CX24116_REG_RESET (0x20) /* reset status > 0 */
58#define CX24116_REG_SIGNAL (0x9e) /* signal low */
59#define CX24116_REG_SSTATUS (0x9d) /* signal high / status */
60#define CX24116_REG_QUALITY8 (0xa3)
61#define CX24116_REG_QSTATUS (0xbc)
62#define CX24116_REG_QUALITY0 (0xd5)
63#define CX24116_REG_BER0 (0xc9)
64#define CX24116_REG_BER8 (0xc8)
65#define CX24116_REG_BER16 (0xc7)
66#define CX24116_REG_BER24 (0xc6)
67#define CX24116_REG_UCB0 (0xcb)
68#define CX24116_REG_UCB8 (0xca)
69#define CX24116_REG_CLKDIV (0xf3)
70#define CX24116_REG_RATEDIV (0xf9)
71#define CX24116_REG_FECSTATUS (0x9c) /* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
72
73/* FECSTATUS bits */
74#define CX24116_FEC_FECMASK (0x1f) /* mask to determine configured fec (not tuned) or actual fec (tuned) */
75#define CX24116_FEC_DVBS (0x20) /* Select DVB-S demodulator, else DVB-S2 */
76#define CX24116_FEC_UNKNOWN (0x40) /* Unknown/unused */
77#define CX24116_FEC_PILOT (0x80) /* Pilot mode requested when tuning else always reset when tuned */
78
79/* arg buffer size */
80#define CX24116_ARGLEN (0x1e)
81
82/* rolloff */
83#define CX24116_ROLLOFF_020 (0x00)
84#define CX24116_ROLLOFF_025 (0x01)
85#define CX24116_ROLLOFF_035 (0x02)
86
87/* pilot bit */
88#define CX24116_PILOT_OFF (0x00)
89#define CX24116_PILOT_ON (0x40)
90
91/* signal status */
92#define CX24116_HAS_SIGNAL (0x01)
93#define CX24116_HAS_CARRIER (0x02)
94#define CX24116_HAS_VITERBI (0x04)
95#define CX24116_HAS_SYNCLOCK (0x08)
96#define CX24116_HAS_UNKNOWN1 (0x10)
97#define CX24116_HAS_UNKNOWN2 (0x20)
98#define CX24116_STATUS_MASK (0x3f)
99#define CX24116_SIGNAL_MASK (0xc0)
100
101#define CX24116_DISEQC_TONEOFF (0) /* toneburst never sent */
102#define CX24116_DISEQC_TONECACHE (1) /* toneburst cached */
103#define CX24116_DISEQC_MESGCACHE (2) /* message cached */
104
105/* arg offset for DiSEqC */
106#define CX24116_DISEQC_BURST (1)
107#define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */
108#define CX24116_DISEQC_ARG3_0 (3) /* unknown value=0 */
109#define CX24116_DISEQC_ARG4_0 (4) /* unknown value=0 */
110#define CX24116_DISEQC_MSGLEN (5)
111#define CX24116_DISEQC_MSGOFS (6)
112
113/* DiSEqC burst */
114#define CX24116_DISEQC_MINI_A (0)
115#define CX24116_DISEQC_MINI_B (1)
116
117/* DiSEqC tone burst */
118static int toneburst = 1;
119
120/* SNR measurements */
121static int esno_snr = 0;
122
123enum cmds
124{
125 CMD_SET_VCO = 0x10,
126 CMD_TUNEREQUEST = 0x11,
127 CMD_MPEGCONFIG = 0x13,
128 CMD_TUNERINIT = 0x14,
129 CMD_BANDWIDTH = 0x15,
130 CMD_GETAGC = 0x19,
131 CMD_LNBCONFIG = 0x20,
132 CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */
133 CMD_SET_TONEPRE = 0x22,
134 CMD_SET_TONE = 0x23,
135 CMD_UPDFWVERS = 0x35,
136 CMD_TUNERSLEEP = 0x36,
137 CMD_AGCCONTROL = 0x3b, /* Unknown */
138};
139
140/* The Demod/Tuner can't easily provide these, we cache them */
141struct cx24116_tuning
142{
143 u32 frequency;
144 u32 symbol_rate;
145 fe_spectral_inversion_t inversion;
146 fe_code_rate_t fec;
147
148 fe_modulation_t modulation;
149 fe_pilot_t pilot;
150 fe_rolloff_t rolloff;
151
152 /* Demod values */
153 u8 fec_val;
154 u8 fec_mask;
155 u8 inversion_val;
156 u8 pilot_val;
157 u8 rolloff_val;
158};
159
160/* Basic commands that are sent to the firmware */
161struct cx24116_cmd
162{
163 u8 len;
164 u8 args[CX24116_ARGLEN];
165};
166
167struct cx24116_state
168{
169 struct i2c_adapter* i2c;
170 const struct cx24116_config* config;
171
172 struct dvb_frontend frontend;
173
174 struct cx24116_tuning dcur;
175 struct cx24116_tuning dnxt;
176
177 u8 skip_fw_load;
178 u8 burst;
179 struct cx24116_cmd dsec_cmd;
180};
181
182static int cx24116_writereg(struct cx24116_state* state, int reg, int data)
183{
184 u8 buf[] = { reg, data };
185 struct i2c_msg msg = { .addr = state->config->demod_address,
186 .flags = 0, .buf = buf, .len = 2 };
187 int err;
188
189 if (debug>1)
190 printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
191 __func__,reg, data);
192
193 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
194 printk("%s: writereg error(err == %i, reg == 0x%02x,"
195 " value == 0x%02x)\n", __func__, err, reg, data);
196 return -EREMOTEIO;
197 }
198
199 return 0;
200}
201
202/* Bulk byte writes to a single I2C address, for 32k firmware load */
203static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len)
204{
205 int ret = -EREMOTEIO;
206 struct i2c_msg msg;
207 u8 *buf;
208
209 buf = kmalloc(len + 1, GFP_KERNEL);
210 if (buf == NULL) {
211 printk("Unable to kmalloc\n");
212 ret = -ENOMEM;
213 goto error;
214 }
215
216 *(buf) = reg;
217 memcpy(buf + 1, data, len);
218
219 msg.addr = state->config->demod_address;
220 msg.flags = 0;
221 msg.buf = buf;
222 msg.len = len + 1;
223
224 if (debug>1)
225 printk("cx24116: %s: write regN 0x%02x, len = %d\n",
226 __func__,reg, len);
227
228 if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) {
229 printk("%s: writereg error(err == %i, reg == 0x%02x\n",
230 __func__, ret, reg);
231 ret = -EREMOTEIO;
232 }
233
234error:
235 kfree(buf);
236
237 return ret;
238}
239
240static int cx24116_readreg(struct cx24116_state* state, u8 reg)
241{
242 int ret;
243 u8 b0[] = { reg };
244 u8 b1[] = { 0 };
245 struct i2c_msg msg[] = {
246 { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
247 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
248 };
249
250 ret = i2c_transfer(state->i2c, msg, 2);
251
252 if (ret != 2) {
253 printk("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
254 return ret;
255 }
256
257 if (debug>1)
258 printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]);
259
260 return b1[0];
261}
262
263static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_inversion_t inversion)
264{
265 dprintk("%s(%d)\n", __func__, inversion);
266
267 switch (inversion) {
268 case INVERSION_OFF:
269 state->dnxt.inversion_val = 0x00;
270 break;
271 case INVERSION_ON:
272 state->dnxt.inversion_val = 0x04;
273 break;
274 case INVERSION_AUTO:
275 state->dnxt.inversion_val = 0x0C;
276 break;
277 default:
278 return -EINVAL;
279 }
280
281 state->dnxt.inversion = inversion;
282
283 return 0;
284}
285
286/*
287 * modfec (modulation and FEC)
288 * ===========================
289 *
290 * MOD FEC mask/val standard
291 * ---- -------- ----------- --------
292 * QPSK FEC_1_2 0x02 0x02+X DVB-S
293 * QPSK FEC_2_3 0x04 0x02+X DVB-S
294 * QPSK FEC_3_4 0x08 0x02+X DVB-S
295 * QPSK FEC_4_5 0x10 0x02+X DVB-S (?)
296 * QPSK FEC_5_6 0x20 0x02+X DVB-S
297 * QPSK FEC_6_7 0x40 0x02+X DVB-S
298 * QPSK FEC_7_8 0x80 0x02+X DVB-S
299 * QPSK FEC_8_9 0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
300 * QPSK AUTO 0xff 0x02+X DVB-S
301 *
302 * For DVB-S high byte probably represents FEC
303 * and low byte selects the modulator. The high
304 * byte is search range mask. Bit 5 may turn
305 * on DVB-S and remaining bits represent some
306 * kind of calibration (how/what i do not know).
307 *
308 * Eg.(2/3) szap "Zone Horror"
309 *
310 * mask/val = 0x04, 0x20
311 * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 00000000 | FE_HAS_LOCK
312 *
313 * mask/val = 0x04, 0x30
314 * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
315 *
316 * After tuning FECSTATUS contains actual FEC
317 * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
318 *
319 * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
320 *
321 * NBC-QPSK FEC_1_2 0x00, 0x04 DVB-S2
322 * NBC-QPSK FEC_3_5 0x00, 0x05 DVB-S2
323 * NBC-QPSK FEC_2_3 0x00, 0x06 DVB-S2
324 * NBC-QPSK FEC_3_4 0x00, 0x07 DVB-S2
325 * NBC-QPSK FEC_4_5 0x00, 0x08 DVB-S2
326 * NBC-QPSK FEC_5_6 0x00, 0x09 DVB-S2
327 * NBC-QPSK FEC_8_9 0x00, 0x0a DVB-S2
328 * NBC-QPSK FEC_9_10 0x00, 0x0b DVB-S2
329 *
330 * NBC-8PSK FEC_3_5 0x00, 0x0c DVB-S2
331 * NBC-8PSK FEC_2_3 0x00, 0x0d DVB-S2
332 * NBC-8PSK FEC_3_4 0x00, 0x0e DVB-S2
333 * NBC-8PSK FEC_5_6 0x00, 0x0f DVB-S2
334 * NBC-8PSK FEC_8_9 0x00, 0x10 DVB-S2
335 * NBC-8PSK FEC_9_10 0x00, 0x11 DVB-S2
336 *
337 * For DVB-S2 low bytes selects both modulator
338 * and FEC. High byte is meaningless here. To
339 * set pilot, bit 6 (0x40) is set. When inspecting
340 * FECSTATUS bit 7 (0x80) represents the pilot
341 * selection whilst not tuned. When tuned, actual FEC
342 * in use is found in FECSTATUS as per above. Pilot
343 * value is reset.
344 */
345
346/* A table of modulation, fec and configuration bytes for the demod.
347 * Not all S2 mmodulation schemes are support and not all rates with
348 * a scheme are support. Especially, no auto detect when in S2 mode.
349 */
350struct cx24116_modfec {
351 fe_delivery_system_t delivery_system;
352 fe_modulation_t modulation;
353 fe_code_rate_t fec;
354 u8 mask; /* In DVBS mode this is used to autodetect */
355 u8 val; /* Passed to the firmware to indicate mode selection */
356} CX24116_MODFEC_MODES[] = {
357 /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
358
359 /*mod fec mask val */
360 { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
361 { SYS_DVBS, QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */
362 { SYS_DVBS, QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */
363 { SYS_DVBS, QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */
364 { SYS_DVBS, QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */
365 { SYS_DVBS, QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */
366 { SYS_DVBS, QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */
367 { SYS_DVBS, QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */
368 { SYS_DVBS, QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */
369 { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
370 /* NBC-QPSK */
371 { SYS_DVBS2, QPSK, FEC_1_2, 0x00, 0x04 },
372 { SYS_DVBS2, QPSK, FEC_3_5, 0x00, 0x05 },
373 { SYS_DVBS2, QPSK, FEC_2_3, 0x00, 0x06 },
374 { SYS_DVBS2, QPSK, FEC_3_4, 0x00, 0x07 },
375 { SYS_DVBS2, QPSK, FEC_4_5, 0x00, 0x08 },
376 { SYS_DVBS2, QPSK, FEC_5_6, 0x00, 0x09 },
377 { SYS_DVBS2, QPSK, FEC_8_9, 0x00, 0x0a },
378 { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
379 /* 8PSK */
380 { SYS_DVBS2, PSK_8, FEC_3_5, 0x00, 0x0c },
381 { SYS_DVBS2, PSK_8, FEC_2_3, 0x00, 0x0d },
382 { SYS_DVBS2, PSK_8, FEC_3_4, 0x00, 0x0e },
383 { SYS_DVBS2, PSK_8, FEC_5_6, 0x00, 0x0f },
384 { SYS_DVBS2, PSK_8, FEC_8_9, 0x00, 0x10 },
385 { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
386 /*
387 * `val' can be found in the FECSTATUS register when tuning.
388 * FECSTATUS will give the actual FEC in use if tuning was successful.
389 */
390};
391
392static int cx24116_lookup_fecmod(struct cx24116_state* state,
393 fe_modulation_t m, fe_code_rate_t f)
394{
395 int i, ret = -EOPNOTSUPP;
396
397 dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
398
399 for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++)
400 {
401 if( (m == CX24116_MODFEC_MODES[i].modulation) &&
402 (f == CX24116_MODFEC_MODES[i].fec) )
403 {
404 ret = i;
405 break;
406 }
407 }
408
409 return ret;
410}
411
412static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec)
413{
414 int ret = 0;
415
416 dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
417
418 ret = cx24116_lookup_fecmod(state, mod, fec);
419
420 if(ret < 0)
421 return ret;
422
423 state->dnxt.fec = fec;
424 state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
425 state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
426 dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
427 state->dnxt.fec_mask, state->dnxt.fec_val);
428
429 return 0;
430}
431
432static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate)
433{
434 dprintk("%s(%d)\n", __func__, rate);
435
436 /* check if symbol rate is within limits */
437 if ((rate > state->frontend.ops.info.symbol_rate_max) ||
438 (rate < state->frontend.ops.info.symbol_rate_min)) {
439 dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
440 return -EOPNOTSUPP;
441 }
442
443 state->dnxt.symbol_rate = rate;
444 dprintk("%s() symbol_rate = %d\n", __func__, rate);
445
446 return 0;
447}
448
449static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw);
450
451static int cx24116_firmware_ondemand(struct dvb_frontend* fe)
452{
453 struct cx24116_state *state = fe->demodulator_priv;
454 const struct firmware *fw;
455 int ret = 0;
456
457 dprintk("%s()\n",__func__);
458
459 if (cx24116_readreg(state, 0x20) > 0)
460 {
461
462 if (state->skip_fw_load)
463 return 0;
464
465 /* Load firmware */
466 /* request the firmware, this will block until someone uploads it */
467 printk("%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE);
468 ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, &state->i2c->dev);
469 printk("%s: Waiting for firmware upload(2)...\n", __func__);
470 if (ret) {
471 printk("%s: No firmware uploaded (timeout or file not found?)\n", __func__);
472 return ret;
473 }
474
475 /* Make sure we don't recurse back through here during loading */
476 state->skip_fw_load = 1;
477
478 ret = cx24116_load_firmware(fe, fw);
479 if (ret)
480 printk("%s: Writing firmware to device failed\n", __func__);
481
482 release_firmware(fw);
483
484 printk("%s: Firmware upload %s\n", __func__, ret == 0 ? "complete" : "failed");
485
486 /* Ensure firmware is always loaded if required */
487 state->skip_fw_load = 0;
488 }
489
490 return ret;
491}
492
493/* Take a basic firmware command structure, format it and forward it for processing */
494static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd)
495{
496 struct cx24116_state *state = fe->demodulator_priv;
497 int i, ret;
498
499 dprintk("%s()\n", __func__);
500
501 /* Load the firmware if required */
502 if ( (ret = cx24116_firmware_ondemand(fe)) != 0)
503 {
504 printk("%s(): Unable initialise the firmware\n", __func__);
505 return ret;
506 }
507
508 /* Write the command */
509 for(i = 0; i < cmd->len ; i++)
510 {
511 dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
512 cx24116_writereg(state, i, cmd->args[i]);
513 }
514
515 /* Start execution and wait for cmd to terminate */
516 cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
517 while( cx24116_readreg(state, CX24116_REG_EXECUTE) )
518 {
519 msleep(10);
520 if(i++ > 64)
521 {
522 /* Avoid looping forever if the firmware does no respond */
523 printk("%s() Firmware not responding\n", __func__);
524 return -EREMOTEIO;
525 }
526 }
527 return 0;
528}
529
530static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
531{
532 struct cx24116_state* state = fe->demodulator_priv;
533 struct cx24116_cmd cmd;
534 int i, ret;
535 unsigned char vers[4];
536
537 dprintk("%s\n", __func__);
538 dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n"
539 ,fw->size
540 ,fw->data[0]
541 ,fw->data[1]
542 ,fw->data[ fw->size-2 ]
543 ,fw->data[ fw->size-1 ]
544 );
545
546 /* Toggle 88x SRST pin to reset demod */
547 if (state->config->reset_device)
548 state->config->reset_device(fe);
549
550 /* Begin the firmware load process */
551 /* Prepare the demod, load the firmware, cleanup after load */
552
553 /* Init PLL */
554 cx24116_writereg(state, 0xE5, 0x00);
555 cx24116_writereg(state, 0xF1, 0x08);
556 cx24116_writereg(state, 0xF2, 0x13);
557
558 /* Start PLL */
559 cx24116_writereg(state, 0xe0, 0x03);
560 cx24116_writereg(state, 0xe0, 0x00);
561
562 /* Unknown */
563 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
564 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
565
566 /* Unknown */
567 cx24116_writereg(state, 0xF0, 0x03);
568 cx24116_writereg(state, 0xF4, 0x81);
569 cx24116_writereg(state, 0xF5, 0x00);
570 cx24116_writereg(state, 0xF6, 0x00);
571
572 /* write the entire firmware as one transaction */
573 cx24116_writeregN(state, 0xF7, fw->data, fw->size);
574
575 cx24116_writereg(state, 0xF4, 0x10);
576 cx24116_writereg(state, 0xF0, 0x00);
577 cx24116_writereg(state, 0xF8, 0x06);
578
579 /* Firmware CMD 10: VCO config */
580 cmd.args[0x00] = CMD_SET_VCO;
581 cmd.args[0x01] = 0x05;
582 cmd.args[0x02] = 0xdc;
583 cmd.args[0x03] = 0xda;
584 cmd.args[0x04] = 0xae;
585 cmd.args[0x05] = 0xaa;
586 cmd.args[0x06] = 0x04;
587 cmd.args[0x07] = 0x9d;
588 cmd.args[0x08] = 0xfc;
589 cmd.args[0x09] = 0x06;
590 cmd.len= 0x0a;
591 ret = cx24116_cmd_execute(fe, &cmd);
592 if (ret != 0)
593 return ret;
594
595 cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
596
597 /* Firmware CMD 14: Tuner config */
598 cmd.args[0x00] = CMD_TUNERINIT;
599 cmd.args[0x01] = 0x00;
600 cmd.args[0x02] = 0x00;
601 cmd.len= 0x03;
602 ret = cx24116_cmd_execute(fe, &cmd);
603 if (ret != 0)
604 return ret;
605
606 cx24116_writereg(state, 0xe5, 0x00);
607
608 /* Firmware CMD 13: MPEG config */
609 cmd.args[0x00] = CMD_MPEGCONFIG;
610 cmd.args[0x01] = 0x01;
611 cmd.args[0x02] = 0x75;
612 cmd.args[0x03] = 0x00;
613 if (state->config->mpg_clk_pos_pol)
614 cmd.args[0x04] = state->config->mpg_clk_pos_pol;
615 else
616 cmd.args[0x04] = 0x02;
617 cmd.args[0x05] = 0x00;
618 cmd.len= 0x06;
619 ret = cx24116_cmd_execute(fe, &cmd);
620 if (ret != 0)
621 return ret;
622
623 /* Firmware CMD 35: Get firmware version */
624 cmd.args[0x00] = CMD_UPDFWVERS;
625 cmd.len= 0x02;
626 for(i=0; i<4; i++) {
627 cmd.args[0x01] = i;
628 ret = cx24116_cmd_execute(fe, &cmd);
629 if (ret != 0)
630 return ret;
631 vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX);
632 }
633 printk("%s: FW version %i.%i.%i.%i\n", __func__,
634 vers[0], vers[1], vers[2], vers[3]);
635
636 return 0;
637}
638
639static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
640{
641 /* The isl6421 module will override this function in the fops. */
642 dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__);
643
644 return -EOPNOTSUPP;
645}
646
647static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status)
648{
649 struct cx24116_state *state = fe->demodulator_priv;
650
651 int lock = cx24116_readreg(state, CX24116_REG_SSTATUS);
652
653 dprintk("%s: status = 0x%02x\n", __func__, lock);
654
655 *status = 0;
656
657 if (lock & CX24116_HAS_SIGNAL)
658 *status |= FE_HAS_SIGNAL;
659 if (lock & CX24116_HAS_CARRIER)
660 *status |= FE_HAS_CARRIER;
661 if (lock & CX24116_HAS_VITERBI)
662 *status |= FE_HAS_VITERBI;
663 if (lock & CX24116_HAS_SYNCLOCK)
664 *status |= FE_HAS_SYNC | FE_HAS_LOCK;
665
666 return 0;
667}
668
669static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber)
670{
671 struct cx24116_state *state = fe->demodulator_priv;
672
673 dprintk("%s()\n", __func__);
674
675 *ber = ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) |
676 ( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) |
677 ( cx24116_readreg(state, CX24116_REG_BER8 ) << 8 ) |
678 cx24116_readreg(state, CX24116_REG_BER0 );
679
680 return 0;
681}
682
683/* TODO Determine function and scale appropriately */
684static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
685{
686 struct cx24116_state *state = fe->demodulator_priv;
687 struct cx24116_cmd cmd;
688 int ret;
689 u16 sig_reading;
690
691 dprintk("%s()\n", __func__);
692
693 /* Firmware CMD 19: Get AGC */
694 cmd.args[0x00] = CMD_GETAGC;
695 cmd.len= 0x01;
696 ret = cx24116_cmd_execute(fe, &cmd);
697 if (ret != 0)
698 return ret;
699
700 sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) |
701 ( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 );
702 *signal_strength= 0 - sig_reading;
703
704 dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength);
705
706 return 0;
707}
708
709/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
710static int cx24116_read_snr_pct(struct dvb_frontend* fe, u16* snr)
711{
712 struct cx24116_state *state = fe->demodulator_priv;
713 u8 snr_reading;
714 static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
715 0x00000,0x0199A,0x03333,0x04ccD,0x06667,
716 0x08000,0x0999A,0x0b333,0x0cccD,0x0e667,
717 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 };
718
719 dprintk("%s()\n", __func__);
720
721 snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
722
723 if(snr_reading >= 0xa0 /* 100% */)
724 *snr = 0xffff;
725 else
726 *snr = snr_tab [ ( snr_reading & 0xf0 ) >> 4 ] +
727 ( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 );
728
729 dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
730 snr_reading, *snr);
731
732 return 0;
733}
734
735/* The reelbox patches show the value in the registers represents
736 * ESNO, from 0->30db (values 0->300). We provide this value by
737 * default.
738 */
739static int cx24116_read_snr_esno(struct dvb_frontend* fe, u16* snr)
740{
741 struct cx24116_state *state = fe->demodulator_priv;
742
743 dprintk("%s()\n", __func__);
744
745 *snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
746 cx24116_readreg(state, CX24116_REG_QUALITY0);
747
748 dprintk("%s: raw 0x%04x\n", __func__, *snr);
749
750 return 0;
751}
752
753static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr)
754{
755 if (esno_snr == 1)
756 return cx24116_read_snr_esno(fe, snr);
757 else
758 return cx24116_read_snr_pct(fe, snr);
759}
760
761static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
762{
763 struct cx24116_state *state = fe->demodulator_priv;
764
765 dprintk("%s()\n", __func__);
766
767 *ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) |
768 cx24116_readreg(state, CX24116_REG_UCB0);
769
770 return 0;
771}
772
773/* Overwrite the current tuning params, we are about to tune */
774static void cx24116_clone_params(struct dvb_frontend* fe)
775{
776 struct cx24116_state *state = fe->demodulator_priv;
777 memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
778}
779
780/* Wait for LNB */
781static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
782{
783 struct cx24116_state *state = fe->demodulator_priv;
784 int i;
785
786 dprintk("%s() qstatus = 0x%02x\n", __func__,
787 cx24116_readreg(state, CX24116_REG_QSTATUS));
788
789 /* Wait for up to 300 ms */
790 for(i = 0; i < 30 ; i++) {
791 if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
792 return 0;
793 msleep(10);
794 }
795
796 dprintk("%s(): LNB not ready\n", __func__);
797
798 return -ETIMEDOUT; /* -EBUSY ? */
799}
800
801static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
802{
803 struct cx24116_cmd cmd;
804 int ret;
805
806 dprintk("%s(%d)\n", __func__, tone);
807 if ( (tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF) ) {
808 printk("%s: Invalid, tone=%d\n", __func__, tone);
809 return -EINVAL;
810 }
811
812 /* Wait for LNB ready */
813 ret = cx24116_wait_for_lnb(fe);
814 if(ret != 0)
815 return ret;
816
817 /* Min delay time after DiSEqC send */
818 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
819
820 /* This is always done before the tone is set */
821 cmd.args[0x00] = CMD_SET_TONEPRE;
822 cmd.args[0x01] = 0x00;
823 cmd.len= 0x02;
824 ret = cx24116_cmd_execute(fe, &cmd);
825 if (ret != 0)
826 return ret;
827
828 /* Now we set the tone */
829 cmd.args[0x00] = CMD_SET_TONE;
830 cmd.args[0x01] = 0x00;
831 cmd.args[0x02] = 0x00;
832
833 switch (tone) {
834 case SEC_TONE_ON:
835 dprintk("%s: setting tone on\n", __func__);
836 cmd.args[0x03] = 0x01;
837 break;
838 case SEC_TONE_OFF:
839 dprintk("%s: setting tone off\n",__func__);
840 cmd.args[0x03] = 0x00;
841 break;
842 }
843 cmd.len= 0x04;
844
845 /* Min delay time before DiSEqC send */
846 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
847
848 return cx24116_cmd_execute(fe, &cmd);
849}
850
851/* Initialise DiSEqC */
852static int cx24116_diseqc_init(struct dvb_frontend* fe)
853{
854 struct cx24116_state *state = fe->demodulator_priv;
855 struct cx24116_cmd cmd;
856 int ret;
857
858 /* Firmware CMD 20: LNB/DiSEqC config */
859 cmd.args[0x00] = CMD_LNBCONFIG;
860 cmd.args[0x01] = 0x00;
861 cmd.args[0x02] = 0x10;
862 cmd.args[0x03] = 0x00;
863 cmd.args[0x04] = 0x8f;
864 cmd.args[0x05] = 0x28;
865 cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
866 cmd.args[0x07] = 0x01;
867 cmd.len= 0x08;
868 ret = cx24116_cmd_execute(fe, &cmd);
869 if (ret != 0)
870 return ret;
871
872 /* Prepare a DiSEqC command */
873 state->dsec_cmd.args[0x00] = CMD_LNBSEND;
874
875 /* DiSEqC burst */
876 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
877
878 /* Unknown */
879 state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
880 state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
881 state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */
882
883 /* DiSEqC message length */
884 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
885
886 /* Command length */
887 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS;
888
889 return 0;
890}
891
892/* Send DiSEqC message with derived burst (hack) || previous burst */
893static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d)
894{
895 struct cx24116_state *state = fe->demodulator_priv;
896 int i, ret;
897
898 /* Dump DiSEqC message */
899 if (debug) {
900 printk("cx24116: %s(", __func__);
901 for(i = 0 ; i < d->msg_len ;) {
902 printk("0x%02x", d->msg[i]);
903 if(++i < d->msg_len)
904 printk(", ");
905 }
906 printk(") toneburst=%d\n", toneburst);
907 }
908
909 /* Validate length */
910 if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
911 return -EINVAL;
912
913 /* DiSEqC message */
914 for (i = 0; i < d->msg_len; i++)
915 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
916
917 /* DiSEqC message length */
918 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
919
920 /* Command length */
921 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
922
923 /* DiSEqC toneburst */
924 if(toneburst == CX24116_DISEQC_MESGCACHE)
925 /* Message is cached */
926 return 0;
927
928 else if(toneburst == CX24116_DISEQC_TONEOFF)
929 /* Message is sent without burst */
930 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
931
932 else if(toneburst == CX24116_DISEQC_TONECACHE) {
933 /*
934 * Message is sent with derived else cached burst
935 *
936 * WRITE PORT GROUP COMMAND 38
937 *
938 * 0/A/A: E0 10 38 F0..F3
939 * 1/B/B: E0 10 38 F4..F7
940 * 2/C/A: E0 10 38 F8..FB
941 * 3/D/B: E0 10 38 FC..FF
942 *
943 * databyte[3]= 8421:8421
944 * ABCD:WXYZ
945 * CLR :SET
946 *
947 * WX= PORT SELECT 0..3 (X=TONEBURST)
948 * Y = VOLTAGE (0=13V, 1=18V)
949 * Z = BAND (0=LOW, 1=HIGH(22K))
950 */
951 if(d->msg_len >= 4 && d->msg[2] == 0x38)
952 state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2);
953 if(debug)
954 dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]);
955 }
956
957 /* Wait for LNB ready */
958 ret = cx24116_wait_for_lnb(fe);
959 if(ret != 0)
960 return ret;
961
962 /* Wait for voltage/min repeat delay */
963 msleep(100);
964
965 /* Command */
966 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
967 if(ret != 0)
968 return ret;
969 /*
970 * Wait for send
971 *
972 * Eutelsat spec:
973 * >15ms delay + (XXX determine if FW does this, see set_tone)
974 * 13.5ms per byte +
975 * >15ms delay +
976 * 12.5ms burst +
977 * >15ms delay (XXX determine if FW does this, see set_tone)
978 */
979 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) );
980
981 return 0;
982}
983
984/* Send DiSEqC burst */
985static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
986{
987 struct cx24116_state *state = fe->demodulator_priv;
988 int ret;
989
990 dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst);
991
992 /* DiSEqC burst */
993 if (burst == SEC_MINI_A)
994 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
995 else if(burst == SEC_MINI_B)
996 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B;
997 else
998 return -EINVAL;
999
1000 /* DiSEqC toneburst */
1001 if(toneburst != CX24116_DISEQC_MESGCACHE)
1002 /* Burst is cached */
1003 return 0;
1004
1005 /* Burst is to be sent with cached message */
1006
1007 /* Wait for LNB ready */
1008 ret = cx24116_wait_for_lnb(fe);
1009 if(ret != 0)
1010 return ret;
1011
1012 /* Wait for voltage/min repeat delay */
1013 msleep(100);
1014
1015 /* Command */
1016 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1017 if(ret != 0)
1018 return ret;
1019
1020 /*
1021 * Wait for send
1022 *
1023 * Eutelsat spec:
1024 * >15ms delay + (XXX determine if FW does this, see set_tone)
1025 * 13.5ms per byte +
1026 * >15ms delay +
1027 * 12.5ms burst +
1028 * >15ms delay (XXX determine if FW does this, see set_tone)
1029 */
1030 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 );
1031
1032 return 0;
1033}
1034
1035static void cx24116_release(struct dvb_frontend* fe)
1036{
1037 struct cx24116_state* state = fe->demodulator_priv;
1038 dprintk("%s\n",__func__);
1039 kfree(state);
1040}
1041
1042static struct dvb_frontend_ops cx24116_ops;
1043
1044struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
1045 struct i2c_adapter* i2c)
1046{
1047 struct cx24116_state* state = NULL;
1048 int ret;
1049
1050 dprintk("%s\n",__func__);
1051
1052 /* allocate memory for the internal state */
1053 state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
1054 if (state == NULL) {
1055 printk("Unable to kmalloc\n");
1056 goto error1;
1057 }
1058
1059 /* setup the state */
1060 memset(state, 0, sizeof(struct cx24116_state));
1061
1062 state->config = config;
1063 state->i2c = i2c;
1064
1065 /* check if the demod is present */
1066 ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE);
1067 if (ret != 0x0501) {
1068 printk("Invalid probe, probably not a CX24116 device\n");
1069 goto error2;
1070 }
1071
1072 /* create dvb_frontend */
1073 memcpy(&state->frontend.ops, &cx24116_ops, sizeof(struct dvb_frontend_ops));
1074 state->frontend.demodulator_priv = state;
1075 return &state->frontend;
1076
1077error2: kfree(state);
1078error1: return NULL;
1079}
1080/*
1081 * Initialise or wake up device
1082 *
1083 * Power config will reset and load initial firmware if required
1084 */
1085static int cx24116_initfe(struct dvb_frontend* fe)
1086{
1087 struct cx24116_state* state = fe->demodulator_priv;
1088 struct cx24116_cmd cmd;
1089 int ret;
1090
1091 dprintk("%s()\n",__func__);
1092
1093 /* Power on */
1094 cx24116_writereg(state, 0xe0, 0);
1095 cx24116_writereg(state, 0xe1, 0);
1096 cx24116_writereg(state, 0xea, 0);
1097
1098 /* Firmware CMD 36: Power config */
1099 cmd.args[0x00] = CMD_TUNERSLEEP;
1100 cmd.args[0x01] = 0;
1101 cmd.len= 0x02;
1102 ret = cx24116_cmd_execute(fe, &cmd);
1103 if(ret != 0)
1104 return ret;
1105
1106 return cx24116_diseqc_init(fe);
1107}
1108
1109/*
1110 * Put device to sleep
1111 */
1112static int cx24116_sleep(struct dvb_frontend* fe)
1113{
1114 struct cx24116_state* state = fe->demodulator_priv;
1115 struct cx24116_cmd cmd;
1116 int ret;
1117
1118 dprintk("%s()\n",__func__);
1119
1120 /* Firmware CMD 36: Power config */
1121 cmd.args[0x00] = CMD_TUNERSLEEP;
1122 cmd.args[0x01] = 1;
1123 cmd.len= 0x02;
1124 ret = cx24116_cmd_execute(fe, &cmd);
1125 if(ret != 0)
1126 return ret;
1127
1128 /* Power off (Shutdown clocks) */
1129 cx24116_writereg(state, 0xea, 0xff);
1130 cx24116_writereg(state, 0xe1, 1);
1131 cx24116_writereg(state, 0xe0, 1);
1132
1133 return 0;
1134}
1135
1136static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp)
1137{
1138 dprintk("%s(..)\n", __func__);
1139 return 0;
1140}
1141
1142static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp)
1143{
1144 dprintk("%s(..)\n", __func__);
1145 return 0;
1146}
1147
1148/* dvb-core told us to tune, the tv property cache will be complete,
1149 * it's safe for is to pull values and use them for tuning purposes.
1150 */
1151static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
1152{
1153 struct cx24116_state *state = fe->demodulator_priv;
1154 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1155 struct cx24116_cmd cmd;
1156 fe_status_t tunerstat;
1157 int i, status, ret, retune;
1158
1159 dprintk("%s()\n",__func__);
1160
1161 switch(c->delivery_system) {
1162 case SYS_DVBS:
1163 dprintk("%s: DVB-S delivery system selected\n",__func__);
1164
1165 /* Only QPSK is supported for DVB-S */
1166 if(c->modulation != QPSK) {
1167 dprintk("%s: unsupported modulation selected (%d)\n",
1168 __func__, c->modulation);
1169 return -EOPNOTSUPP;
1170 }
1171
1172 /* Pilot doesn't exist in DVB-S, turn bit off */
1173 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1174 retune = 1;
1175
1176 /* DVB-S only supports 0.35 */
1177 if(c->rolloff != ROLLOFF_35) {
1178 dprintk("%s: unsupported rolloff selected (%d)\n",
1179 __func__, c->rolloff);
1180 return -EOPNOTSUPP;
1181 }
1182 state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
1183 break;
1184
1185 case SYS_DVBS2:
1186 dprintk("%s: DVB-S2 delivery system selected\n",__func__);
1187
1188 /*
1189 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
1190 * but not hardware auto detection
1191 */
1192 if(c->modulation != PSK_8 && c->modulation != QPSK) {
1193 dprintk("%s: unsupported modulation selected (%d)\n",
1194 __func__, c->modulation);
1195 return -EOPNOTSUPP;
1196 }
1197
1198 switch(c->pilot) {
1199 case PILOT_AUTO: /* Not supported but emulated */
1200 retune = 2; /* Fall-through */
1201 case PILOT_OFF:
1202 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1203 break;
1204 case PILOT_ON:
1205 state->dnxt.pilot_val = CX24116_PILOT_ON;
1206 break;
1207 default:
1208 dprintk("%s: unsupported pilot mode selected (%d)\n",
1209 __func__, c->pilot);
1210 return -EOPNOTSUPP;
1211 }
1212
1213 switch(c->rolloff) {
1214 case ROLLOFF_20:
1215 state->dnxt.rolloff_val= CX24116_ROLLOFF_020;
1216 break;
1217 case ROLLOFF_25:
1218 state->dnxt.rolloff_val= CX24116_ROLLOFF_025;
1219 break;
1220 case ROLLOFF_35:
1221 state->dnxt.rolloff_val= CX24116_ROLLOFF_035;
1222 break;
1223 case ROLLOFF_AUTO: /* Rolloff must be explicit */
1224 default:
1225 dprintk("%s: unsupported rolloff selected (%d)\n",
1226 __func__, c->rolloff);
1227 return -EOPNOTSUPP;
1228 }
1229 break;
1230
1231 default:
1232 dprintk("%s: unsupported delivery system selected (%d)\n",
1233 __func__, c->delivery_system);
1234 return -EOPNOTSUPP;
1235 }
1236 state->dnxt.modulation = c->modulation;
1237 state->dnxt.frequency = c->frequency;
1238 state->dnxt.pilot = c->pilot;
1239 state->dnxt.rolloff = c->rolloff;
1240
1241 if ((ret = cx24116_set_inversion(state, c->inversion)) != 0)
1242 return ret;
1243
1244 /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
1245 if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) != 0)
1246 return ret;
1247
1248 if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) != 0)
1249 return ret;
1250
1251 /* discard the 'current' tuning parameters and prepare to tune */
1252 cx24116_clone_params(fe);
1253
1254 dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation);
1255 dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency);
1256 dprintk("%s: pilot = %d (val = 0x%02x)\n", __func__,
1257 state->dcur.pilot, state->dcur.pilot_val);
1258 dprintk("%s: retune = %d\n", __func__, retune);
1259 dprintk("%s: rolloff = %d (val = 0x%02x)\n", __func__,
1260 state->dcur.rolloff, state->dcur.rolloff_val);
1261 dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
1262 dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
1263 state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
1264 dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__,
1265 state->dcur.inversion, state->dcur.inversion_val);
1266
1267 /* This is also done in advise/acquire on HVR4000 but not on LITE */
1268 if (state->config->set_ts_params)
1269 state->config->set_ts_params(fe, 0);
1270
1271 /* Set/Reset B/W */
1272 cmd.args[0x00] = CMD_BANDWIDTH;
1273 cmd.args[0x01] = 0x01;
1274 cmd.len= 0x02;
1275 ret = cx24116_cmd_execute(fe, &cmd);
1276 if (ret != 0)
1277 return ret;
1278
1279 /* Prepare a tune request */
1280 cmd.args[0x00] = CMD_TUNEREQUEST;
1281
1282 /* Frequency */
1283 cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
1284 cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
1285 cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
1286
1287 /* Symbol Rate */
1288 cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
1289 cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
1290
1291 /* Automatic Inversion */
1292 cmd.args[0x06] = state->dcur.inversion_val;
1293
1294 /* Modulation / FEC / Pilot */
1295 cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
1296
1297 cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
1298 cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
1299 cmd.args[0x0a] = 0x00;
1300 cmd.args[0x0b] = 0x00;
1301 cmd.args[0x0c] = state->dcur.rolloff_val;
1302 cmd.args[0x0d] = state->dcur.fec_mask;
1303
1304 if (state->dcur.symbol_rate > 30000000) {
1305 cmd.args[0x0e] = 0x04;
1306 cmd.args[0x0f] = 0x00;
1307 cmd.args[0x10] = 0x01;
1308 cmd.args[0x11] = 0x77;
1309 cmd.args[0x12] = 0x36;
1310 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
1311 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
1312 } else {
1313 cmd.args[0x0e] = 0x06;
1314 cmd.args[0x0f] = 0x00;
1315 cmd.args[0x10] = 0x00;
1316 cmd.args[0x11] = 0xFA;
1317 cmd.args[0x12] = 0x24;
1318 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
1319 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
1320 }
1321
1322 cmd.len= 0x13;
1323
1324 /* We need to support pilot and non-pilot tuning in the
1325 * driver automatically. This is a workaround for because
1326 * the demod does not support autodetect.
1327 */
1328 do {
1329 /* Reset status register */
1330 status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK;
1331 cx24116_writereg(state, CX24116_REG_SSTATUS, status);
1332
1333 /* Tune */
1334 ret = cx24116_cmd_execute(fe, &cmd);
1335 if( ret != 0 )
1336 break;
1337
1338 /*
1339 * Wait for up to 500 ms before retrying
1340 *
1341 * If we are able to tune then generally it occurs within 100ms.
1342 * If it takes longer, try a different toneburst setting.
1343 */
1344 for(i = 0; i < 50 ; i++) {
1345 cx24116_read_status(fe, &tunerstat);
1346 status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
1347 if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
1348 dprintk("%s: Tuned\n",__func__);
1349 goto tuned;
1350 }
1351 msleep(10);
1352 }
1353
1354 dprintk("%s: Not tuned\n",__func__);
1355
1356 /* Toggle pilot bit when in auto-pilot */
1357 if(state->dcur.pilot == PILOT_AUTO)
1358 cmd.args[0x07] ^= CX24116_PILOT_ON;
1359 }
1360 while(--retune);
1361
1362tuned: /* Set/Reset B/W */
1363 cmd.args[0x00] = CMD_BANDWIDTH;
1364 cmd.args[0x01] = 0x00;
1365 cmd.len= 0x02;
1366 ret = cx24116_cmd_execute(fe, &cmd);
1367 if (ret != 0)
1368 return ret;
1369
1370 return ret;
1371}
1372
1373static struct dvb_frontend_ops cx24116_ops = {
1374
1375 .info = {
1376 .name = "Conexant CX24116/CX24118",
1377 .type = FE_QPSK,
1378 .frequency_min = 950000,
1379 .frequency_max = 2150000,
1380 .frequency_stepsize = 1011, /* kHz for QPSK frontends */
1381 .frequency_tolerance = 5000,
1382 .symbol_rate_min = 1000000,
1383 .symbol_rate_max = 45000000,
1384 .caps = FE_CAN_INVERSION_AUTO |
1385 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1386 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
1387 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1388 FE_CAN_QPSK | FE_CAN_RECOVER
1389 },
1390
1391 .release = cx24116_release,
1392
1393 .init = cx24116_initfe,
1394 .sleep = cx24116_sleep,
1395 .read_status = cx24116_read_status,
1396 .read_ber = cx24116_read_ber,
1397 .read_signal_strength = cx24116_read_signal_strength,
1398 .read_snr = cx24116_read_snr,
1399 .read_ucblocks = cx24116_read_ucblocks,
1400 .set_tone = cx24116_set_tone,
1401 .set_voltage = cx24116_set_voltage,
1402 .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
1403 .diseqc_send_burst = cx24116_diseqc_send_burst,
1404
1405 .set_property = cx24116_set_property,
1406 .get_property = cx24116_get_property,
1407 .set_frontend = cx24116_set_frontend,
1408};
1409
1410module_param(debug, int, 0644);
1411MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
1412
1413module_param(toneburst, int, 0644);
1414MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)");
1415
1416module_param(esno_snr, int, 0644);
1417MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, 1=ESNO(db * 10) (default:0)");
1418
1419MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
1420MODULE_AUTHOR("Steven Toth");
1421MODULE_LICENSE("GPL");
1422
1423EXPORT_SYMBOL(cx24116_attach);