aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorDarron Broad <darron@kewl.org>2008-09-13 18:42:16 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:37:06 -0400
commit490c868408bc57a756550148313ac8582fe501ef (patch)
tree09d9b378c9d79aab84fb5bdc43fcf41454e522e3 /drivers/media/dvb
parenta611d0ca006fe76d88b8dd5ac44f4468293b6760 (diff)
V4L/DVB (9011): S2API: A number of cleanusp from the last 24 months.
I was given these changes by Darron Broad and Igor Liplianin and represent a series of patches they've been making to the cx24116 driver over the last two years. Changes for handling symbolrates >30Ksps Tone handling changes. Diseqc support. Sleep support, shutting down the clocks correctly. Cleanup on ROLL_OFF and PILOT support. *** ST - We need to cleanup the sysclt control, this is abnormal in a demod driver. We should work towards understanding the missing API's and ensure we have them in S2API. *** Signed-off-by: Steven Toth <stoth@linuxtv.org> Signed-off-by: Darron Broad <darron@kewl.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/frontends/cx24116.c808
1 files changed, 617 insertions, 191 deletions
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
index 0ac2c5493087..cfb265de5229 100644
--- a/drivers/media/dvb/frontends/cx24116.c
+++ b/drivers/media/dvb/frontends/cx24116.c
@@ -2,6 +2,18 @@
2 Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver 2 Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
3 3
4 Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com> 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).
5 17
6 This program is free software; you can redistribute it and/or modify 18 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 19 it under the terms of the GNU General Public License as published by
@@ -18,51 +30,69 @@
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 30 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/ 31*/
20 32
21/*
22 * Updates by Darron Broad 2007.
23 *
24 * March
25 * Fixed some bugs.
26 * Added diseqc support.
27 * Added corrected signal strength support.
28 *
29 * August
30 * Sync with legacy version.
31 * Some clean ups.
32 */
33/* Updates by Igor Liplianin
34 *
35 * September, 9th 2008
36 * Fixed locking on high symbol rates (>30000).
37 */
38
39#include <linux/slab.h> 33#include <linux/slab.h>
40#include <linux/kernel.h> 34#include <linux/kernel.h>
41#include <linux/module.h> 35#include <linux/module.h>
42#include <linux/moduleparam.h> 36#include <linux/moduleparam.h>
43#include <linux/init.h> 37#include <linux/init.h>
44#include <linux/firmware.h> 38#include <linux/firmware.h>
39#include <linux/sysctl.h>
45 40
46#include "dvb_frontend.h" 41#include "dvb_frontend.h"
47#include "cx24116.h" 42#include "cx24116.h"
48 43
49/* 44static int debug = 0;
50 * Fetch firmware in the following manner. 45#define dprintk(args...) \
51 * 46 do { \
52 * #!/bin/sh 47 if (debug) printk ("cx24116: " args); \
53 * wget ftp://167.206.143.11/outgoing/Oxford/88x_2_117_24275_1_INF.zip 48 } while (0)
54 * unzip 88x_2_117_24275_1_INF.zip 49
55 * dd if=Driver88/hcw88bda.sys of=dvb-fe-cx24116.fw skip=81768 bs=1 count=32522
56 */
57#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw" 50#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
58#define CX24116_SEARCH_RANGE_KHZ 5000 51#define CX24116_SEARCH_RANGE_KHZ 5000
59 52
60/* registers (TO BE COMPLETED) */ 53/* known registers */
61#define CX24116_REG_SIGNAL (0xd5) 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_QSTATUS (0xbc)
61#define CX24116_REG_QUALITY (0xd5)
62#define CX24116_REG_BER0 (0xc9)
63#define CX24116_REG_BER8 (0xc8)
64#define CX24116_REG_BER16 (0xc7)
65#define CX24116_REG_BER24 (0xc6)
66#define CX24116_REG_UCB0 (0xcb)
67#define CX24116_REG_UCB8 (0xca)
68#define CX24116_REG_CLKDIV (0xf3)
69#define CX24116_REG_RATEDIV (0xf9)
62 70
63/* arg buffer size */ 71/* arg buffer size */
64#define CX24116_ARGLEN (0x1e) 72#define CX24116_ARGLEN (0x1e)
65 73
74/* rolloff */
75#define CX24116_ROLLOFF_020 (0x00)
76#define CX24116_ROLLOFF_025 (0x01)
77#define CX24116_ROLLOFF_035 (0x02)
78
79/* pilot bit */
80#define CX24116_PILOT (0x40)
81
82/* signal status */
83#define CX24116_HAS_SIGNAL (0x01)
84#define CX24116_HAS_CARRIER (0x02)
85#define CX24116_HAS_VITERBI (0x04)
86#define CX24116_HAS_SYNCLOCK (0x08)
87#define CX24116_HAS_UNKNOWN1 (0x10)
88#define CX24116_HAS_UNKNOWN2 (0x20)
89#define CX24116_STATUS_MASK (0x3f)
90#define CX24116_SIGNAL_MASK (0xc0)
91
92#define CX24116_DISEQC_TONEOFF (0) /* toneburst never sent */
93#define CX24116_DISEQC_TONECACHE (1) /* toneburst cached */
94#define CX24116_DISEQC_MESGCACHE (2) /* message cached */
95
66/* arg offset for DiSEqC */ 96/* arg offset for DiSEqC */
67#define CX24116_DISEQC_BURST (1) 97#define CX24116_DISEQC_BURST (1)
68#define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */ 98#define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */
@@ -75,21 +105,88 @@
75#define CX24116_DISEQC_MINI_A (0) 105#define CX24116_DISEQC_MINI_A (0)
76#define CX24116_DISEQC_MINI_B (1) 106#define CX24116_DISEQC_MINI_B (1)
77 107
78static int debug = 0; 108/* DiSEqC tone burst */
79#define dprintk(args...) \ 109static int toneburst = 1;
80 do { \ 110
81 if (debug) printk ("cx24116: " args); \ 111/* debug & toneburst sysctl */
82 } while (0) 112static struct ctl_table_header *kernel_table_header;
113static ctl_table toneburst_table[] = {
114{
115 .ctl_name = 0,
116 .procname = "toneburst",
117 .data = &toneburst,
118 .maxlen = sizeof(int),
119 .mode = 0666,
120 .child = NULL,
121 .parent = NULL,
122 .proc_handler = &proc_dointvec,
123 .strategy = NULL,
124 .extra1 = NULL,
125 .extra2 = NULL,
126},
127{
128 .ctl_name = 0,
129 .procname = "debug",
130 .data = &debug,
131 .maxlen = sizeof(int),
132 .mode = 0666,
133 .child = NULL,
134 .parent = NULL,
135 .proc_handler = &proc_dointvec,
136 .strategy = NULL,
137 .extra1 = NULL,
138 .extra2 = NULL,
139 },
140 {0},
141};
142static ctl_table cx24116_table[] = {
143{
144 .ctl_name = 0,
145 .procname = "cx24116",
146 .data = NULL,
147 .maxlen = 0,
148 .mode = 0555,
149 .child = toneburst_table,
150 .parent = NULL,
151 .proc_handler = NULL,
152 .strategy = NULL,
153 .extra1 = NULL,
154 .extra2 = NULL,
155 },
156 {0},
157};
158static ctl_table kernel_table[] = {
159{
160 .ctl_name = CTL_DEV,
161 .procname = "dev",
162 .data = NULL,
163 .maxlen = 0,
164 .mode = 0555,
165 .child = cx24116_table,
166 .parent = NULL,
167 .proc_handler = NULL,
168 .strategy = NULL,
169 .extra1 = NULL,
170 .extra2 = NULL,
171 },
172 {0},
173};
83 174
84enum cmds 175enum cmds
85{ 176{
86 CMD_INIT_CMD10 = 0x10, 177 CMD_SET_VCO = 0x10,
87 CMD_TUNEREQUEST = 0x11, 178 CMD_TUNEREQUEST = 0x11,
88 CMD_INIT_CMD13 = 0x13, 179 CMD_MPEGCONFIG = 0x13,
89 CMD_INIT_CMD14 = 0x14, 180 CMD_TUNERINIT = 0x14,
90 CMD_SEND_DISEQC = 0x21, 181 CMD_BANDWIDTH = 0x15,
182 CMD_GETAGC = 0x19,
183 CMD_LNBCONFIG = 0x20,
184 CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */
91 CMD_SET_TONEPRE = 0x22, 185 CMD_SET_TONEPRE = 0x22,
92 CMD_SET_TONE = 0x23, 186 CMD_SET_TONE = 0x23,
187 CMD_UPDFWVERS = 0x35,
188 CMD_TUNERSLEEP = 0x36,
189 CMD_AGCCONTROL = 0x3b, /* Unknown */
93}; 190};
94 191
95/* The Demod/Tuner can't easily provide these, we cache them */ 192/* The Demod/Tuner can't easily provide these, we cache them */
@@ -101,11 +198,14 @@ struct cx24116_tuning
101 fe_code_rate_t fec; 198 fe_code_rate_t fec;
102 199
103 fe_modulation_t modulation; 200 fe_modulation_t modulation;
201 fe_pilot_t pilot;
202 fe_rolloff_t rolloff;
104 203
105 /* Demod values */ 204 /* Demod values */
106 u8 fec_val; 205 u8 fec_val;
107 u8 fec_mask; 206 u8 fec_mask;
108 u8 inversion_val; 207 u8 inversion_val;
208 u8 rolloff_val;
109}; 209};
110 210
111/* Basic commands that are sent to the firmware */ 211/* Basic commands that are sent to the firmware */
@@ -127,6 +227,7 @@ struct cx24116_state
127 227
128 u8 skip_fw_load; 228 u8 skip_fw_load;
129 u8 burst; 229 u8 burst;
230 struct cx24116_cmd dsec_cmd;
130}; 231};
131 232
132static int cx24116_writereg(struct cx24116_state* state, int reg, int data) 233static int cx24116_writereg(struct cx24116_state* state, int reg, int data)
@@ -233,6 +334,66 @@ static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_invers
233 return 0; 334 return 0;
234} 335}
235 336
337/*
338 * modfec (modulation and FEC)
339 * ===========================
340 *
341 * MOD FEC mask/val standard
342 * ---- -------- ----------- --------
343 * QPSK FEC_1_2 0x02 0x02+X DVB-S
344 * QPSK FEC_2_3 0x04 0x02+X DVB-S
345 * QPSK FEC_3_4 0x08 0x02+X DVB-S
346 * QPSK FEC_4_5 0x10 0x02+X DVB-S (?)
347 * QPSK FEC_5_6 0x20 0x02+X DVB-S
348 * QPSK FEC_6_7 0x40 0x02+X DVB-S
349 * QPSK FEC_7_8 0x80 0x02+X DVB-S
350 * QPSK FEC_8_9 0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
351 * QPSK AUTO 0xff 0x02+X DVB-S
352 *
353 * For DVB-S high byte probably represents FEC
354 * and low byte selects the modulator. The high
355 * byte is search range mask. Bit 5 may turn
356 * on DVB-S and remaining bits represent some
357 * kind of calibration (how/what i do not know).
358 *
359 * Eg.(2/3) szap "Zone Horror"
360 *
361 * mask/val = 0x04, 0x20
362 * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 00000000 | FE_HAS_LOCK
363 *
364 * mask/val = 0x04, 0x30
365 * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
366 *
367 * After tuning FECSTATUS contains actual FEC
368 * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
369 *
370 * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
371 *
372 * NBC-QPSK FEC_1_2 0x00, 0x04 DVB-S2
373 * NBC-QPSK FEC_3_5 0x00, 0x05 DVB-S2
374 * NBC-QPSK FEC_2_3 0x00, 0x06 DVB-S2
375 * NBC-QPSK FEC_3_4 0x00, 0x07 DVB-S2
376 * NBC-QPSK FEC_4_5 0x00, 0x08 DVB-S2
377 * NBC-QPSK FEC_5_6 0x00, 0x09 DVB-S2
378 * NBC-QPSK FEC_8_9 0x00, 0x0a DVB-S2
379 * NBC-QPSK FEC_9_10 0x00, 0x0b DVB-S2
380 *
381 * NBC-8PSK FEC_3_5 0x00, 0x0c DVB-S2
382 * NBC-8PSK FEC_2_3 0x00, 0x0d DVB-S2
383 * NBC-8PSK FEC_3_4 0x00, 0x0e DVB-S2
384 * NBC-8PSK FEC_5_6 0x00, 0x0f DVB-S2
385 * NBC-8PSK FEC_8_9 0x00, 0x10 DVB-S2
386 * NBC-8PSK FEC_9_10 0x00, 0x11 DVB-S2
387 *
388 * For DVB-S2 low bytes selects both modulator
389 * and FEC. High byte is meaningless here. To
390 * set pilot, bit 6 (0x40) is set. When inspecting
391 * FECSTATUS bit 7 (0x80) represents the pilot
392 * selection whilst not tuned. When tuned, actual FEC
393 * in use is found in FECSTATUS as per above. Pilot
394 * value is reset.
395 */
396
236/* A table of modulation, fec and configuration bytes for the demod. 397/* A table of modulation, fec and configuration bytes for the demod.
237 * Not all S2 mmodulation schemes are support and not all rates with 398 * Not all S2 mmodulation schemes are support and not all rates with
238 * a scheme are support. Especially, no auto detect when in S2 mode. 399 * a scheme are support. Especially, no auto detect when in S2 mode.
@@ -244,15 +405,17 @@ struct cx24116_modfec {
244 u8 val; /* Passed to the firmware to indicate mode selection */ 405 u8 val; /* Passed to the firmware to indicate mode selection */
245} CX24116_MODFEC_MODES[] = { 406} CX24116_MODFEC_MODES[] = {
246 /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */ 407 /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
408
409 /*mod fec mask val */
247 { QPSK, FEC_NONE, 0xfe, 0x30 }, 410 { QPSK, FEC_NONE, 0xfe, 0x30 },
248 { QPSK, FEC_1_2, 0x02, 0x2e }, 411 { QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */
249 { QPSK, FEC_2_3, 0x04, 0x2f }, 412 { QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */
250 { QPSK, FEC_3_4, 0x08, 0x30 }, 413 { QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */
251 { QPSK, FEC_4_5, 0xfe, 0x30 }, 414 { QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */
252 { QPSK, FEC_5_6, 0x20, 0x31 }, 415 { QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */
253 { QPSK, FEC_6_7, 0xfe, 0x30 }, 416 { QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */
254 { QPSK, FEC_7_8, 0x80, 0x32 }, 417 { QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */
255 { QPSK, FEC_8_9, 0xfe, 0x30 }, 418 { QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */
256 { QPSK, FEC_AUTO, 0xfe, 0x30 }, 419 { QPSK, FEC_AUTO, 0xfe, 0x30 },
257 /* NBC-QPSK */ 420 /* NBC-QPSK */
258 { NBC_QPSK, FEC_1_2, 0x00, 0x04 }, 421 { NBC_QPSK, FEC_1_2, 0x00, 0x04 },
@@ -268,7 +431,12 @@ struct cx24116_modfec {
268 { _8PSK, FEC_2_3, 0x00, 0x0d }, 431 { _8PSK, FEC_2_3, 0x00, 0x0d },
269 { _8PSK, FEC_3_4, 0x00, 0x0e }, 432 { _8PSK, FEC_3_4, 0x00, 0x0e },
270 { _8PSK, FEC_5_6, 0x00, 0x0f }, 433 { _8PSK, FEC_5_6, 0x00, 0x0f },
434 { _8PSK, FEC_8_9, 0x00, 0x10 },
271 { _8PSK, FEC_9_10, 0x00, 0x11 }, 435 { _8PSK, FEC_9_10, 0x00, 0x11 },
436 /*
437 * `val' can be found in the FECSTATUS register when tuning.
438 * FECSTATUS will give the actual FEC in use if tuning was successful.
439 */
272}; 440};
273 441
274static int cx24116_lookup_fecmod(struct cx24116_state* state, 442static int cx24116_lookup_fecmod(struct cx24116_state* state,
@@ -276,6 +444,8 @@ static int cx24116_lookup_fecmod(struct cx24116_state* state,
276{ 444{
277 int i, ret = -EOPNOTSUPP; 445 int i, ret = -EOPNOTSUPP;
278 446
447 dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
448
279 for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++) 449 for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++)
280 { 450 {
281 if( (m == CX24116_MODFEC_MODES[i].modulation) && 451 if( (m == CX24116_MODFEC_MODES[i].modulation) &&
@@ -292,37 +462,38 @@ static int cx24116_lookup_fecmod(struct cx24116_state* state,
292static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec) 462static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec)
293{ 463{
294 int ret = 0; 464 int ret = 0;
295 dprintk("%s()\n", __func__); 465
466 dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
296 467
297 ret = cx24116_lookup_fecmod(state, mod, fec); 468 ret = cx24116_lookup_fecmod(state, mod, fec);
298 469
299 if(ret < 0) 470 if(ret < 0)
300 return ret; 471 return ret;
301 472
473 state->dnxt.fec = fec;
302 state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val; 474 state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
303 state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask; 475 state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
304 dprintk("%s() fec_val/mask = 0x%02x/0x%02x\n", __func__, 476 dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
305 state->dnxt.fec_val, state->dnxt.fec_mask); 477 state->dnxt.fec_mask, state->dnxt.fec_val);
306 478
307 return 0; 479 return 0;
308} 480}
309 481
310static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate) 482static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate)
311{ 483{
312 int ret = 0; 484 dprintk("%s(%d)\n", __func__, rate);
313 485
314 dprintk("%s()\n", __func__); 486 /* check if symbol rate is within limits */
487 if ((rate > state->frontend.ops.info.symbol_rate_max) ||
488 (rate < state->frontend.ops.info.symbol_rate_min)) {
489 dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
490 return -EOPNOTSUPP;
491 }
315 492
316 state->dnxt.symbol_rate = rate; 493 state->dnxt.symbol_rate = rate;
494 dprintk("%s() symbol_rate = %d\n", __func__, rate);
317 495
318 dprintk("%s() symbol_rate = %d\n", __func__, state->dnxt.symbol_rate); 496 return 0;
319
320 /* check if symbol rate is within limits */
321 if ((state->dnxt.symbol_rate > state->frontend.ops.info.symbol_rate_max) ||
322 (state->dnxt.symbol_rate < state->frontend.ops.info.symbol_rate_min))
323 ret = -EOPNOTSUPP;
324
325 return ret;
326} 497}
327 498
328static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw); 499static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw);
@@ -392,8 +563,8 @@ static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd)
392 } 563 }
393 564
394 /* Start execution and wait for cmd to terminate */ 565 /* Start execution and wait for cmd to terminate */
395 cx24116_writereg(state, 0x1f, 0x01); 566 cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
396 while( cx24116_readreg(state, 0x1f) ) 567 while( cx24116_readreg(state, CX24116_REG_EXECUTE) )
397 { 568 {
398 msleep(10); 569 msleep(10);
399 if(i++ > 64) 570 if(i++ > 64)
@@ -410,7 +581,8 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware
410{ 581{
411 struct cx24116_state* state = fe->demodulator_priv; 582 struct cx24116_state* state = fe->demodulator_priv;
412 struct cx24116_cmd cmd; 583 struct cx24116_cmd cmd;
413 int ret; 584 int i, ret;
585 unsigned char vers[4];
414 586
415 dprintk("%s\n", __func__); 587 dprintk("%s\n", __func__);
416 dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n" 588 dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n"
@@ -427,11 +599,21 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware
427 599
428 /* Begin the firmware load process */ 600 /* Begin the firmware load process */
429 /* Prepare the demod, load the firmware, cleanup after load */ 601 /* Prepare the demod, load the firmware, cleanup after load */
602
603 /* Init PLL */
604 cx24116_writereg(state, 0xE5, 0x00);
430 cx24116_writereg(state, 0xF1, 0x08); 605 cx24116_writereg(state, 0xF1, 0x08);
431 cx24116_writereg(state, 0xF2, cx24116_readreg(state, 0xF2) | 0x03); 606 cx24116_writereg(state, 0xF2, 0x13);
432 cx24116_writereg(state, 0xF3, 0x46); 607
433 cx24116_writereg(state, 0xF9, 0x00); 608 /* Start PLL */
609 cx24116_writereg(state, 0xe0, 0x03);
610 cx24116_writereg(state, 0xe0, 0x00);
611
612 /* Unknown */
613 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
614 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
434 615
616 /* Unknown */
435 cx24116_writereg(state, 0xF0, 0x03); 617 cx24116_writereg(state, 0xF0, 0x03);
436 cx24116_writereg(state, 0xF4, 0x81); 618 cx24116_writereg(state, 0xF4, 0x81);
437 cx24116_writereg(state, 0xF5, 0x00); 619 cx24116_writereg(state, 0xF5, 0x00);
@@ -444,8 +626,8 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware
444 cx24116_writereg(state, 0xF0, 0x00); 626 cx24116_writereg(state, 0xF0, 0x00);
445 cx24116_writereg(state, 0xF8, 0x06); 627 cx24116_writereg(state, 0xF8, 0x06);
446 628
447 /* Firmware CMD 10: Chip config? */ 629 /* Firmware CMD 10: VCO config */
448 cmd.args[0x00] = CMD_INIT_CMD10; 630 cmd.args[0x00] = CMD_SET_VCO;
449 cmd.args[0x01] = 0x05; 631 cmd.args[0x01] = 0x05;
450 cmd.args[0x02] = 0xdc; 632 cmd.args[0x02] = 0xdc;
451 cmd.args[0x03] = 0xda; 633 cmd.args[0x03] = 0xda;
@@ -460,10 +642,10 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware
460 if (ret != 0) 642 if (ret != 0)
461 return ret; 643 return ret;
462 644
463 cx24116_writereg(state, 0x9d, 0x00); 645 cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
464 646
465 /* Firmware CMD 14: Unknown */ 647 /* Firmware CMD 14: Tuner config */
466 cmd.args[0x00] = CMD_INIT_CMD14; 648 cmd.args[0x00] = CMD_TUNERINIT;
467 cmd.args[0x01] = 0x00; 649 cmd.args[0x01] = 0x00;
468 cmd.args[0x02] = 0x00; 650 cmd.args[0x02] = 0x00;
469 cmd.len= 0x03; 651 cmd.len= 0x03;
@@ -473,8 +655,8 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware
473 655
474 cx24116_writereg(state, 0xe5, 0x00); 656 cx24116_writereg(state, 0xe5, 0x00);
475 657
476 /* Firmware CMD 13: Unknown - Firmware config? */ 658 /* Firmware CMD 13: MPEG config */
477 cmd.args[0x00] = CMD_INIT_CMD13; 659 cmd.args[0x00] = CMD_MPEGCONFIG;
478 cmd.args[0x01] = 0x01; 660 cmd.args[0x01] = 0x01;
479 cmd.args[0x02] = 0x75; 661 cmd.args[0x02] = 0x75;
480 cmd.args[0x03] = 0x00; 662 cmd.args[0x03] = 0x00;
@@ -488,6 +670,19 @@ static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware
488 if (ret != 0) 670 if (ret != 0)
489 return ret; 671 return ret;
490 672
673 /* Firmware CMD 35: Get firmware version */
674 cmd.args[0x00] = CMD_UPDFWVERS;
675 cmd.len= 0x02;
676 for(i=0; i<4; i++) {
677 cmd.args[0x01] = i;
678 ret = cx24116_cmd_execute(fe, &cmd);
679 if (ret != 0)
680 return ret;
681 vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX);
682 }
683 printk("%s: FW version %i.%i.%i.%i\n", __func__,
684 vers[0], vers[1], vers[2], vers[3]);
685
491 return 0; 686 return 0;
492} 687}
493 688
@@ -503,75 +698,98 @@ static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status)
503{ 698{
504 struct cx24116_state *state = fe->demodulator_priv; 699 struct cx24116_state *state = fe->demodulator_priv;
505 700
506 int lock = cx24116_readreg(state, 0x9d); 701 int lock = cx24116_readreg(state, CX24116_REG_SSTATUS);
507 702
508 dprintk("%s: status = 0x%02x\n", __func__, lock); 703 dprintk("%s: status = 0x%02x\n", __func__, lock);
509 704
510 *status = 0; 705 *status = 0;
511 706
512 if (lock & 0x01) 707 if (lock & CX24116_HAS_SIGNAL)
513 *status |= FE_HAS_SIGNAL; 708 *status |= FE_HAS_SIGNAL;
514 if (lock & 0x02) 709 if (lock & CX24116_HAS_CARRIER)
515 *status |= FE_HAS_CARRIER; 710 *status |= FE_HAS_CARRIER;
516 if (lock & 0x04) 711 if (lock & CX24116_HAS_VITERBI)
517 *status |= FE_HAS_VITERBI; 712 *status |= FE_HAS_VITERBI;
518 if (lock & 0x08) 713 if (lock & CX24116_HAS_SYNCLOCK)
519 *status |= FE_HAS_SYNC | FE_HAS_LOCK; 714 *status |= FE_HAS_SYNC | FE_HAS_LOCK;
520 715
521 return 0; 716 return 0;
522} 717}
523 718
524/* TODO: Not clear how we do this */
525static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber) 719static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber)
526{ 720{
527 //struct cx24116_state *state = fe->demodulator_priv; 721 struct cx24116_state *state = fe->demodulator_priv;
722
528 dprintk("%s()\n", __func__); 723 dprintk("%s()\n", __func__);
529 *ber = 0; 724
725 *ber = ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) |
726 ( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) |
727 ( cx24116_readreg(state, CX24116_REG_BER8 ) << 8 ) |
728 cx24116_readreg(state, CX24116_REG_BER0 );
530 729
531 return 0; 730 return 0;
532} 731}
533 732
534/* Signal strength (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */ 733/* TODO Determine function and scale appropriately */
535static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) 734static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
536{ 735{
537 struct cx24116_state *state = fe->demodulator_priv; 736 struct cx24116_state *state = fe->demodulator_priv;
538 u8 strength_reg; 737 struct cx24116_cmd cmd;
539 static const u32 strength_tab[] = { /* 10 x Table (rounded up) */ 738 int ret;
540 0x00000,0x0199A,0x03333,0x04ccD,0x06667,0x08000,0x0999A,0x0b333,0x0cccD,0x0e667, 739 u16 sig_reading;
541 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 };
542 740
543 dprintk("%s()\n", __func__); 741 dprintk("%s()\n", __func__);
544 742
545 strength_reg = cx24116_readreg(state, CX24116_REG_SIGNAL); 743 /* Firmware CMD 19: Get AGC */
744 cmd.args[0x00] = CMD_GETAGC;
745 cmd.len= 0x01;
746 ret = cx24116_cmd_execute(fe, &cmd);
747 if (ret != 0)
748 return ret;
546 749
547 if(strength_reg < 0xa0) 750 sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) |
548 *signal_strength = strength_tab [ ( strength_reg & 0xf0 ) >> 4 ] + 751 ( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 );
549 ( strength_tab [ ( strength_reg & 0x0f ) ] >> 4 ); 752 *signal_strength= 0 - sig_reading;
550 else
551 *signal_strength = 0xffff;
552 753
553 dprintk("%s: Signal strength (raw / cooked) = (0x%02x / 0x%04x)\n", 754 dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength);
554 __func__,strength_reg,*signal_strength);
555 755
556 return 0; 756 return 0;
557} 757}
558 758
559/* TODO: Not clear how we do this */ 759/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
560static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr) 760static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr)
561{ 761{
562 //struct cx24116_state *state = fe->demodulator_priv; 762 struct cx24116_state *state = fe->demodulator_priv;
763 u8 snr_reading;
764 static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
765 0x00000,0x0199A,0x03333,0x04ccD,0x06667,
766 0x08000,0x0999A,0x0b333,0x0cccD,0x0e667,
767 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 };
768
563 dprintk("%s()\n", __func__); 769 dprintk("%s()\n", __func__);
564 *snr = 0; 770
771 snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY);
772
773 if(snr_reading >= 0xa0 /* 100% */)
774 *snr = 0xffff;
775 else
776 *snr = snr_tab [ ( snr_reading & 0xf0 ) >> 4 ] +
777 ( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 );
778
779 dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
780 snr_reading, *snr);
565 781
566 return 0; 782 return 0;
567} 783}
568 784
569/* TODO: Not clear how we do this */
570static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) 785static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
571{ 786{
572 //struct cx24116_state *state = fe->demodulator_priv; 787 struct cx24116_state *state = fe->demodulator_priv;
788
573 dprintk("%s()\n", __func__); 789 dprintk("%s()\n", __func__);
574 *ucblocks = 0; 790
791 *ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) |
792 cx24116_readreg(state, CX24116_REG_UCB0);
575 793
576 return 0; 794 return 0;
577} 795}
@@ -583,6 +801,27 @@ static void cx24116_clone_params(struct dvb_frontend* fe)
583 memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur)); 801 memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
584} 802}
585 803
804/* Wait for LNB */
805static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
806{
807 struct cx24116_state *state = fe->demodulator_priv;
808 int i;
809
810 dprintk("%s() qstatus = 0x%02x\n", __func__,
811 cx24116_readreg(state, CX24116_REG_QSTATUS));
812
813 /* Wait for up to 300 ms */
814 for(i = 0; i < 30 ; i++) {
815 if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
816 return 0;
817 msleep(10);
818 }
819
820 dprintk("%s(): LNB not ready\n", __func__);
821
822 return -ETIMEDOUT; /* -EBUSY ? */
823}
824
586static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) 825static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
587{ 826{
588 struct cx24116_cmd cmd; 827 struct cx24116_cmd cmd;
@@ -594,6 +833,14 @@ static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
594 return -EINVAL; 833 return -EINVAL;
595 } 834 }
596 835
836 /* Wait for LNB ready */
837 ret = cx24116_wait_for_lnb(fe);
838 if(ret != 0)
839 return ret;
840
841 /* Min delay time after DiSEqC send */
842 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
843
597 /* This is always done before the tone is set */ 844 /* This is always done before the tone is set */
598 cmd.args[0x00] = CMD_SET_TONEPRE; 845 cmd.args[0x00] = CMD_SET_TONEPRE;
599 cmd.args[0x01] = 0x00; 846 cmd.args[0x01] = 0x00;
@@ -619,6 +866,9 @@ static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
619 } 866 }
620 cmd.len= 0x04; 867 cmd.len= 0x04;
621 868
869 /* Min delay time before DiSEqC send */
870 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
871
622 return cx24116_cmd_execute(fe, &cmd); 872 return cx24116_cmd_execute(fe, &cmd);
623} 873}
624 874
@@ -626,9 +876,39 @@ static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
626static int cx24116_diseqc_init(struct dvb_frontend* fe) 876static int cx24116_diseqc_init(struct dvb_frontend* fe)
627{ 877{
628 struct cx24116_state *state = fe->demodulator_priv; 878 struct cx24116_state *state = fe->demodulator_priv;
879 struct cx24116_cmd cmd;
880 int ret;
881
882 /* Firmware CMD 20: LNB/DiSEqC config */
883 cmd.args[0x00] = CMD_LNBCONFIG;
884 cmd.args[0x01] = 0x00;
885 cmd.args[0x02] = 0x10;
886 cmd.args[0x03] = 0x00;
887 cmd.args[0x04] = 0x8f;
888 cmd.args[0x05] = 0x28;
889 cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
890 cmd.args[0x07] = 0x01;
891 cmd.len= 0x08;
892 ret = cx24116_cmd_execute(fe, &cmd);
893 if (ret != 0)
894 return ret;
895
896 /* Prepare a DiSEqC command */
897 state->dsec_cmd.args[0x00] = CMD_LNBSEND;
898
899 /* DiSEqC burst */
900 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
901
902 /* Unknown */
903 state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
904 state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
905 state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */
629 906
630 /* Default DiSEqC burst state */ 907 /* DiSEqC message length */
631 state->burst = CX24116_DISEQC_MINI_A; 908 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
909
910 /* Command length */
911 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS;
632 912
633 return 0; 913 return 0;
634} 914}
@@ -637,7 +917,6 @@ static int cx24116_diseqc_init(struct dvb_frontend* fe)
637static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d) 917static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d)
638{ 918{
639 struct cx24116_state *state = fe->demodulator_priv; 919 struct cx24116_state *state = fe->demodulator_priv;
640 struct cx24116_cmd cmd;
641 int i, ret; 920 int i, ret;
642 921
643 /* Dump DiSEqC message */ 922 /* Dump DiSEqC message */
@@ -647,82 +926,134 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
647 printk("0x%02x", d->msg[i]); 926 printk("0x%02x", d->msg[i]);
648 if(++i < d->msg_len) 927 if(++i < d->msg_len)
649 printk(", "); 928 printk(", ");
650 } 929 }
651 printk(")\n"); 930 printk(") toneburst=%d\n", toneburst);
652 } 931 }
653 932
933 /* Validate length */
654 if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS)) 934 if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
655 return -EINVAL; 935 return -EINVAL;
656 936
657 cmd.args[0x00] = CMD_SEND_DISEQC;
658 cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
659 cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
660 cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
661
662 /* DiSEqC message */ 937 /* DiSEqC message */
663 for (i = 0; i < d->msg_len; i++) 938 for (i = 0; i < d->msg_len; i++)
664 cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i]; 939 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
940
941 /* DiSEqC message length */
942 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
943
944 /* Command length */
945 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
946
947 /* DiSEqC toneburst */
948 if(toneburst == CX24116_DISEQC_MESGCACHE)
949 /* Message is cached */
950 return 0;
951
952 else if(toneburst == CX24116_DISEQC_TONEOFF)
953 /* Message is sent without burst */
954 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
955
956 else if(toneburst == CX24116_DISEQC_TONECACHE) {
957 /*
958 * Message is sent with derived else cached burst
959 *
960 * WRITE PORT GROUP COMMAND 38
961 *
962 * 0/A/A: E0 10 38 F0..F3
963 * 1/B/B: E0 10 38 F4..F7
964 * 2/C/A: E0 10 38 F8..FB
965 * 3/D/B: E0 10 38 FC..FF
966 *
967 * datebyte[3]= 8421:8421
968 * ABCD:WXYZ
969 * CLR :SET
970 *
971 * WX= PORT SELECT 0..3 (X=TONEBURST)
972 * Y = VOLTAGE (0=13V, 1=18V)
973 * Z = BAND (0=LOW, 1=HIGH(22K))
974 */
975 if(d->msg_len >= 4 && d->msg[2] == 0x38)
976 state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2);
977 if(debug)
978 dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]);
979 }
665 980
666 /* Hack: Derive burst from command else use previous burst */ 981 /* Wait for LNB ready */
667 if(d->msg_len >= 4 && d->msg[2] == 0x38) 982 ret = cx24116_wait_for_lnb(fe);
668 cmd.args[CX24116_DISEQC_BURST] = (d->msg[3] >> 2) & 1; 983 if(ret != 0)
669 else 984 return ret;
670 cmd.args[CX24116_DISEQC_BURST] = state->burst;
671 985
672 cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len; 986 /* Wait for voltage/min repeat delay */
673 cmd.len = CX24116_DISEQC_MSGOFS + d->msg_len; 987 msleep(100);
674 988
675 ret = cx24116_cmd_execute(fe, &cmd); 989 /* Command */
676 990 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
677 /* Firmware command duration is unknown, so guess... 991 if(ret != 0)
992 return ret;
993 /*
994 * Wait for send
678 * 995 *
679 * Eutelsat spec: 996 * Eutelsat spec:
680 * >15ms delay + 997 * >15ms delay + (XXX determine if FW does this, see set_tone)
681 * 13.5ms per byte + 998 * 13.5ms per byte +
682 * >15ms delay + 999 * >15ms delay +
683 * 12.5ms burst + 1000 * 12.5ms burst +
684 * >15ms delay 1001 * >15ms delay (XXX determine if FW does this, see set_tone)
685 */ 1002 */
686 if(ret == 0) 1003 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) );
687 msleep( (cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 );
688 1004
689 return ret; 1005 return 0;
690} 1006}
691 1007
692/* Send DiSEqC burst */ 1008/* Send DiSEqC burst */
693static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) 1009static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
694{ 1010{
695 struct cx24116_state *state = fe->demodulator_priv; 1011 struct cx24116_state *state = fe->demodulator_priv;
696 struct cx24116_cmd cmd;
697 int ret; 1012 int ret;
698 1013
699 dprintk("%s(%d)\n",__func__,(int)burst); 1014 dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst);
700
701 cmd.args[0x00] = CMD_SEND_DISEQC;
702 cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
703 cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
704 cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
705 1015
1016 /* DiSEqC burst */
706 if (burst == SEC_MINI_A) 1017 if (burst == SEC_MINI_A)
707 cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; 1018 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
708 else if(burst == SEC_MINI_B) 1019 else if(burst == SEC_MINI_B)
709 cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B; 1020 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B;
710 else 1021 else
711 return -EINVAL; 1022 return -EINVAL;
712 1023
713 /* Cache as previous burst state */ 1024 /* DiSEqC toneburst */
714 state->burst= cmd.args[CX24116_DISEQC_BURST]; 1025 if(toneburst != CX24116_DISEQC_MESGCACHE)
1026 /* Burst is cached */
1027 return 0;
715 1028
716 cmd.args[CX24116_DISEQC_MSGLEN] = 0x00; 1029 /* Burst is to be sent with cached message */
717 cmd.len= CX24116_DISEQC_MSGOFS;
718 1030
719 ret= cx24116_cmd_execute(fe, &cmd); 1031 /* Wait for LNB ready */
1032 ret = cx24116_wait_for_lnb(fe);
1033 if(ret != 0)
1034 return ret;
720 1035
721 /* Firmware command duration is unknown, so guess... */ 1036 /* Wait for voltage/min repeat delay */
722 if(ret == 0) 1037 msleep(100);
723 msleep(60);
724 1038
725 return ret; 1039 /* Command */
1040 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
1041 if(ret != 0)
1042 return ret;
1043
1044 /*
1045 * Wait for send
1046 *
1047 * Eutelsat spec:
1048 * >15ms delay + (XXX determine if FW does this, see set_tone)
1049 * 13.5ms per byte +
1050 * >15ms delay +
1051 * 12.5ms burst +
1052 * >15ms delay (XXX determine if FW does this, see set_tone)
1053 */
1054 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 );
1055
1056 return 0;
726} 1057}
727 1058
728static void cx24116_release(struct dvb_frontend* fe) 1059static void cx24116_release(struct dvb_frontend* fe)
@@ -730,6 +1061,7 @@ static void cx24116_release(struct dvb_frontend* fe)
730 struct cx24116_state* state = fe->demodulator_priv; 1061 struct cx24116_state* state = fe->demodulator_priv;
731 dprintk("%s\n",__func__); 1062 dprintk("%s\n",__func__);
732 kfree(state); 1063 kfree(state);
1064 unregister_sysctl_table(kernel_table_header);
733} 1065}
734 1066
735static struct dvb_frontend_ops cx24116_ops; 1067static struct dvb_frontend_ops cx24116_ops;
@@ -742,11 +1074,15 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
742 1074
743 dprintk("%s\n",__func__); 1075 dprintk("%s\n",__func__);
744 1076
1077 kernel_table_header = register_sysctl_table(kernel_table);
1078 if(!kernel_table_header)
1079 goto error1;
1080
745 /* allocate memory for the internal state */ 1081 /* allocate memory for the internal state */
746 state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL); 1082 state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
747 if (state == NULL) { 1083 if (state == NULL) {
748 printk("Unable to kmalloc\n"); 1084 printk("Unable to kmalloc\n");
749 goto error; 1085 goto error2;
750 } 1086 }
751 1087
752 /* setup the state */ 1088 /* setup the state */
@@ -759,7 +1095,7 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
759 ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE); 1095 ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE);
760 if (ret != 0x0501) { 1096 if (ret != 0x0501) {
761 printk("Invalid probe, probably not a CX24116 device\n"); 1097 printk("Invalid probe, probably not a CX24116 device\n");
762 goto error; 1098 goto error3;
763 } 1099 }
764 1100
765 /* create dvb_frontend */ 1101 /* create dvb_frontend */
@@ -767,33 +1103,64 @@ struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
767 state->frontend.demodulator_priv = state; 1103 state->frontend.demodulator_priv = state;
768 return &state->frontend; 1104 return &state->frontend;
769 1105
770error: 1106error3: kfree(state);
771 kfree(state); 1107error2: unregister_sysctl_table(kernel_table_header);
772 1108error1: return NULL;
773 return NULL;
774} 1109}
775 1110/*
776static int cx24116_get_params(struct dvb_frontend* fe) 1111 * Initialise or wake up device
1112 *
1113 * Power config will reset and load initial firmware if required
1114 */
1115static int cx24116_initfe(struct dvb_frontend* fe)
777{ 1116{
778 struct cx24116_state *state = fe->demodulator_priv; 1117 struct cx24116_state* state = fe->demodulator_priv;
779 struct dtv_frontend_properties *cache = &fe->dtv_property_cache; 1118 struct cx24116_cmd cmd;
1119 int ret;
780 1120
781 dprintk("%s()\n",__func__); 1121 dprintk("%s()\n",__func__);
782 1122
783 cache->frequency = state->dcur.frequency; 1123 /* Power on */
784 cache->inversion = state->dcur.inversion; 1124 cx24116_writereg(state, 0xe0, 0);
785 cache->modulation = state->dcur.modulation; 1125 cx24116_writereg(state, 0xe1, 0);
786 cache->fec_inner = state->dcur.fec; 1126 cx24116_writereg(state, 0xea, 0);
787 cache->symbol_rate = state->dcur.symbol_rate;
788 1127
789 return 0; 1128 /* Firmware CMD 36: Power config */
1129 cmd.args[0x00] = CMD_TUNERSLEEP;
1130 cmd.args[0x01] = 0;
1131 cmd.len= 0x02;
1132 ret = cx24116_cmd_execute(fe, &cmd);
1133 if(ret != 0)
1134 return ret;
1135
1136 return cx24116_diseqc_init(fe);
790} 1137}
791 1138
792static int cx24116_initfe(struct dvb_frontend* fe) 1139/*
1140 * Put device to sleep
1141 */
1142static int cx24116_sleep(struct dvb_frontend* fe)
793{ 1143{
1144 struct cx24116_state* state = fe->demodulator_priv;
1145 struct cx24116_cmd cmd;
1146 int ret;
1147
794 dprintk("%s()\n",__func__); 1148 dprintk("%s()\n",__func__);
795 1149
796 return cx24116_diseqc_init(fe); 1150 /* Firmware CMD 36: Power config */
1151 cmd.args[0x00] = CMD_TUNERSLEEP;
1152 cmd.args[0x01] = 1;
1153 cmd.len= 0x02;
1154 ret = cx24116_cmd_execute(fe, &cmd);
1155 if(ret != 0)
1156 return ret;
1157
1158 /* Power off (Shutdown clocks) */
1159 cx24116_writereg(state, 0xea, 0xff);
1160 cx24116_writereg(state, 0xe1, 1);
1161 cx24116_writereg(state, 0xe0, 1);
1162
1163 return 0;
797} 1164}
798 1165
799static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp) 1166static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp)
@@ -817,14 +1184,45 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
817 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 1184 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
818 struct cx24116_cmd cmd; 1185 struct cx24116_cmd cmd;
819 fe_status_t tunerstat; 1186 fe_status_t tunerstat;
820 int ret, above30msps; 1187 int i, status, ret, retune = 1;
821 u8 retune=4;
822 1188
823 dprintk("%s()\n",__func__); 1189 dprintk("%s()\n",__func__);
824 1190
825 state->dnxt.modulation = c->modulation; 1191 state->dnxt.modulation = c->modulation;
826 state->dnxt.frequency = c->frequency; 1192 state->dnxt.frequency = c->frequency;
827 1193
1194 switch(c->delivery_system) {
1195 case SYS_DVBS:
1196 dprintk("%s: DVB-S delivery system selected\n",__func__);
1197 state->dnxt.pilot = PILOT_OFF;
1198 state->dnxt.rolloff = CX24116_ROLLOFF_035;
1199 break;
1200 case SYS_DVBS2:
1201 dprintk("%s: DVB-S2 delivery system selected\n",__func__);
1202 if(c->pilot == PILOT_AUTO)
1203 retune++;
1204 state->dnxt.pilot = c->pilot;
1205 switch(c->rolloff) {
1206 case ROLLOFF_20:
1207 state->dnxt.rolloff_val= CX24116_ROLLOFF_020;
1208 break;
1209 case ROLLOFF_25:
1210 state->dnxt.rolloff_val= CX24116_ROLLOFF_025;
1211 break;
1212 case ROLLOFF_35:
1213 state->dnxt.rolloff_val= CX24116_ROLLOFF_035;
1214 break;
1215 case ROLLOFF_AUTO:
1216 return -EOPNOTSUPP;
1217 }
1218 state->dnxt.rolloff = c->rolloff;
1219 break;
1220 default:
1221 dprintk("%s: unsupported delivery system selected (%d)\n",
1222 __func__, c->delivery_system);
1223 return -EOPNOTSUPP;
1224 }
1225
828 if ((ret = cx24116_set_inversion(state, c->inversion)) != 0) 1226 if ((ret = cx24116_set_inversion(state, c->inversion)) != 0)
829 return ret; 1227 return ret;
830 1228
@@ -837,6 +1235,9 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
837 /* discard the 'current' tuning parameters and prepare to tune */ 1235 /* discard the 'current' tuning parameters and prepare to tune */
838 cx24116_clone_params(fe); 1236 cx24116_clone_params(fe);
839 1237
1238 dprintk("%s: retune = %d\n", __func__, retune);
1239 dprintk("%s: rolloff = %d\n", __func__, state->dcur.rolloff);
1240 dprintk("%s: pilot = %d\n", __func__, state->dcur.pilot);
840 dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency); 1241 dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency);
841 dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate); 1242 dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
842 dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__, 1243 dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
@@ -844,18 +1245,17 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
844 dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__, 1245 dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__,
845 state->dcur.inversion, state->dcur.inversion_val); 1246 state->dcur.inversion, state->dcur.inversion_val);
846 1247
1248 /* This is also done in advise/acquire on HVR4000 but not on LITE */
847 if (state->config->set_ts_params) 1249 if (state->config->set_ts_params)
848 state->config->set_ts_params(fe, 0); 1250 state->config->set_ts_params(fe, 0);
849 1251
850 above30msps = (state->dcur.symbol_rate > 30000000); 1252 /* Set/Reset B/W */
851 1253 cmd.args[0x00] = CMD_BANDWIDTH;
852 if (above30msps){ 1254 cmd.args[0x01] = 0x01;
853 cx24116_writereg(state, 0xF9, 0x01); 1255 cmd.len= 0x02;
854 cx24116_writereg(state, 0xF3, 0x44); 1256 ret = cx24116_cmd_execute(fe, &cmd);
855 } else { 1257 if (ret != 0)
856 cx24116_writereg(state, 0xF9, 0x00); 1258 return ret;
857 cx24116_writereg(state, 0xF3, 0x46);
858 }
859 1259
860 /* Prepare a tune request */ 1260 /* Prepare a tune request */
861 cmd.args[0x00] = CMD_TUNEREQUEST; 1261 cmd.args[0x00] = CMD_TUNEREQUEST;
@@ -875,28 +1275,32 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
875 /* Modulation / FEC & Pilot Off */ 1275 /* Modulation / FEC & Pilot Off */
876 cmd.args[0x07] = state->dcur.fec_val; 1276 cmd.args[0x07] = state->dcur.fec_val;
877 1277
878 if (c->pilot == PILOT_ON) 1278 if (state->dcur.pilot == PILOT_ON)
879 cmd.args[0x07] |= 0x40; 1279 cmd.args[0x07] |= CX24116_PILOT;
880 1280
881 cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8; 1281 cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
882 cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff; 1282 cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
883 cmd.args[0x0a] = 0x00; 1283 cmd.args[0x0a] = 0x00;
884 cmd.args[0x0b] = 0x00; 1284 cmd.args[0x0b] = 0x00;
885 cmd.args[0x0c] = 0x02; 1285 cmd.args[0x0c] = state->dcur.rolloff_val;
886 cmd.args[0x0d] = state->dcur.fec_mask; 1286 cmd.args[0x0d] = state->dcur.fec_mask;
887 1287
888 if (above30msps){ 1288 if (state->dcur.symbol_rate > 30000000) {
889 cmd.args[0x0e] = 0x04; 1289 cmd.args[0x0e] = 0x04;
890 cmd.args[0x0f] = 0x00; 1290 cmd.args[0x0f] = 0x00;
891 cmd.args[0x10] = 0x01; 1291 cmd.args[0x10] = 0x01;
892 cmd.args[0x11] = 0x77; 1292 cmd.args[0x11] = 0x77;
893 cmd.args[0x12] = 0x36; 1293 cmd.args[0x12] = 0x36;
1294 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
1295 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
894 } else { 1296 } else {
895 cmd.args[0x0e] = 0x06; 1297 cmd.args[0x0e] = 0x06;
896 cmd.args[0x0f] = 0x00; 1298 cmd.args[0x0f] = 0x00;
897 cmd.args[0x10] = 0x00; 1299 cmd.args[0x10] = 0x00;
898 cmd.args[0x11] = 0xFA; 1300 cmd.args[0x11] = 0xFA;
899 cmd.args[0x12] = 0x24; 1301 cmd.args[0x12] = 0x24;
1302 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
1303 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
900 } 1304 }
901 1305
902 cmd.len= 0x13; 1306 cmd.len= 0x13;
@@ -906,29 +1310,47 @@ static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
906 * the demod does not support autodetect. 1310 * the demod does not support autodetect.
907 */ 1311 */
908 do { 1312 do {
909 /* Reset status register? */ 1313 /* Reset status register */
910 cx24116_writereg(state, 0x9d, 0xc1); 1314 status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK;
1315 cx24116_writereg(state, CX24116_REG_SSTATUS, status);
911 1316
912 /* Tune */ 1317 /* Tune */
913 ret = cx24116_cmd_execute(fe, &cmd); 1318 ret = cx24116_cmd_execute(fe, &cmd);
914 if( ret != 0 ) 1319 if( ret != 0 )
915 break; 1320 break;
916 1321
917 /* The hardware can take time to lock, wait a while */ 1322 /*
918 msleep(500); 1323 * Wait for up to 500 ms before retrying
919 1324 *
920 cx24116_read_status(fe, &tunerstat); 1325 * If we are able to tune then generally it occurs within 100ms.
921 if(tunerstat & FE_HAS_SIGNAL) { 1326 * If it takes longer, try a different toneburst setting.
922 if(tunerstat & FE_HAS_SYNC) 1327 */
923 /* Tuned */ 1328 for(i = 0; i < 50 ; i++) {
924 break; 1329 cx24116_read_status(fe, &tunerstat);
925 else if(c->pilot == PILOT_AUTO) 1330 status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
926 /* Toggle pilot bit */ 1331 if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
927 cmd.args[0x07] ^= 0x40; 1332 dprintk("%s: Tuned\n",__func__);
1333 goto tuned;
1334 }
1335 msleep(10);
928 } 1336 }
1337
1338 dprintk("%s: Not tuned\n",__func__);
1339
1340 /* Toggle pilot bit when in auto-pilot */
1341 if(state->dcur.pilot == PILOT_AUTO)
1342 cmd.args[0x07] ^= CX24116_PILOT;
929 } 1343 }
930 while(--retune); 1344 while(--retune);
931 1345
1346tuned: /* Set/Reset B/W */
1347 cmd.args[0x00] = CMD_BANDWIDTH;
1348 cmd.args[0x01] = 0x00;
1349 cmd.len= 0x02;
1350 ret = cx24116_cmd_execute(fe, &cmd);
1351 if (ret != 0)
1352 return ret;
1353
932 return ret; 1354 return ret;
933} 1355}
934 1356
@@ -953,6 +1375,7 @@ static struct dvb_frontend_ops cx24116_ops = {
953 .release = cx24116_release, 1375 .release = cx24116_release,
954 1376
955 .init = cx24116_initfe, 1377 .init = cx24116_initfe,
1378 .sleep = cx24116_sleep,
956 .read_status = cx24116_read_status, 1379 .read_status = cx24116_read_status,
957 .read_ber = cx24116_read_ber, 1380 .read_ber = cx24116_read_ber,
958 .read_signal_strength = cx24116_read_signal_strength, 1381 .read_signal_strength = cx24116_read_signal_strength,
@@ -971,6 +1394,9 @@ static struct dvb_frontend_ops cx24116_ops = {
971module_param(debug, int, 0644); 1394module_param(debug, int, 0644);
972MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); 1395MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
973 1396
1397module_param(toneburst, int, 0644);
1398MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)");
1399
974MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware"); 1400MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
975MODULE_AUTHOR("Steven Toth"); 1401MODULE_AUTHOR("Steven Toth");
976MODULE_LICENSE("GPL"); 1402MODULE_LICENSE("GPL");