blob: 808ef2995d80cd5c813114cc4e6398fc4ea4ad94 [file] [log] [blame]
Steven Toth0d467482008-09-04 01:14:43 -03001/*
2 Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
3
4 Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com>
Darron Broad490c8682008-09-13 19:42:16 -03005 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
Igor M. Liplianinc063a482008-09-14 07:43:53 -030016 Fixed locking on high symbol rates (>30000).
17 Implement MPEG initialization parameter.
Steven Toth0d467482008-09-04 01:14:43 -030018
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
Steven Toth0d467482008-09-04 01:14:43 -030034#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
Darron Broad490c8682008-09-13 19:42:16 -030044static int debug = 0;
45#define dprintk(args...) \
46 do { \
47 if (debug) printk ("cx24116: " args); \
48 } while (0)
49
Steven Toth0d467482008-09-04 01:14:43 -030050#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
51#define CX24116_SEARCH_RANGE_KHZ 5000
52
Darron Broad490c8682008-09-13 19:42:16 -030053/* 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_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)
Darron Broad681faa02008-09-22 00:47:20 -030070#define CX24116_REG_FECSTATUS (0x9c) /* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
71
72/* FECSTATUS bits */
73#define CX24116_FEC_FECMASK (0x1f) /* mask to determine configured fec (not tuned) or actual fec (tuned) */
74#define CX24116_FEC_DVBS (0x20) /* Select DVB-S demodulator, else DVB-S2 */
75#define CX24116_FEC_UNKNOWN (0x40) /* Unknown/unused */
76#define CX24116_FEC_PILOT (0x80) /* Pilot mode requested when tuning else always reset when tuned */
Steven Toth0d467482008-09-04 01:14:43 -030077
78/* arg buffer size */
79#define CX24116_ARGLEN (0x1e)
80
Darron Broad490c8682008-09-13 19:42:16 -030081/* rolloff */
82#define CX24116_ROLLOFF_020 (0x00)
83#define CX24116_ROLLOFF_025 (0x01)
84#define CX24116_ROLLOFF_035 (0x02)
85
86/* pilot bit */
Darron Broad01a8f032008-10-03 11:47:46 -030087#define CX24116_PILOT_OFF (0x00)
88#define CX24116_PILOT_ON (0x40)
Darron Broad490c8682008-09-13 19:42:16 -030089
90/* signal status */
91#define CX24116_HAS_SIGNAL (0x01)
92#define CX24116_HAS_CARRIER (0x02)
93#define CX24116_HAS_VITERBI (0x04)
94#define CX24116_HAS_SYNCLOCK (0x08)
95#define CX24116_HAS_UNKNOWN1 (0x10)
96#define CX24116_HAS_UNKNOWN2 (0x20)
97#define CX24116_STATUS_MASK (0x3f)
98#define CX24116_SIGNAL_MASK (0xc0)
99
100#define CX24116_DISEQC_TONEOFF (0) /* toneburst never sent */
101#define CX24116_DISEQC_TONECACHE (1) /* toneburst cached */
102#define CX24116_DISEQC_MESGCACHE (2) /* message cached */
103
Steven Toth0d467482008-09-04 01:14:43 -0300104/* arg offset for DiSEqC */
105#define CX24116_DISEQC_BURST (1)
106#define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */
107#define CX24116_DISEQC_ARG3_0 (3) /* unknown value=0 */
108#define CX24116_DISEQC_ARG4_0 (4) /* unknown value=0 */
109#define CX24116_DISEQC_MSGLEN (5)
110#define CX24116_DISEQC_MSGOFS (6)
111
112/* DiSEqC burst */
113#define CX24116_DISEQC_MINI_A (0)
114#define CX24116_DISEQC_MINI_B (1)
115
Darron Broad490c8682008-09-13 19:42:16 -0300116/* DiSEqC tone burst */
117static int toneburst = 1;
118
Steven Toth0d467482008-09-04 01:14:43 -0300119enum cmds
120{
Darron Broad490c8682008-09-13 19:42:16 -0300121 CMD_SET_VCO = 0x10,
Steven Toth0d467482008-09-04 01:14:43 -0300122 CMD_TUNEREQUEST = 0x11,
Darron Broad490c8682008-09-13 19:42:16 -0300123 CMD_MPEGCONFIG = 0x13,
124 CMD_TUNERINIT = 0x14,
125 CMD_BANDWIDTH = 0x15,
126 CMD_GETAGC = 0x19,
127 CMD_LNBCONFIG = 0x20,
128 CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */
Steven Toth0d467482008-09-04 01:14:43 -0300129 CMD_SET_TONEPRE = 0x22,
130 CMD_SET_TONE = 0x23,
Darron Broad490c8682008-09-13 19:42:16 -0300131 CMD_UPDFWVERS = 0x35,
132 CMD_TUNERSLEEP = 0x36,
133 CMD_AGCCONTROL = 0x3b, /* Unknown */
Steven Toth0d467482008-09-04 01:14:43 -0300134};
135
136/* The Demod/Tuner can't easily provide these, we cache them */
137struct cx24116_tuning
138{
139 u32 frequency;
140 u32 symbol_rate;
141 fe_spectral_inversion_t inversion;
142 fe_code_rate_t fec;
143
144 fe_modulation_t modulation;
Darron Broad490c8682008-09-13 19:42:16 -0300145 fe_pilot_t pilot;
146 fe_rolloff_t rolloff;
Steven Toth0d467482008-09-04 01:14:43 -0300147
148 /* Demod values */
149 u8 fec_val;
150 u8 fec_mask;
151 u8 inversion_val;
Darron Broad01a8f032008-10-03 11:47:46 -0300152 u8 pilot_val;
Darron Broad490c8682008-09-13 19:42:16 -0300153 u8 rolloff_val;
Steven Toth0d467482008-09-04 01:14:43 -0300154};
155
156/* Basic commands that are sent to the firmware */
157struct cx24116_cmd
158{
159 u8 len;
160 u8 args[CX24116_ARGLEN];
161};
162
163struct cx24116_state
164{
165 struct i2c_adapter* i2c;
166 const struct cx24116_config* config;
167
168 struct dvb_frontend frontend;
169
170 struct cx24116_tuning dcur;
171 struct cx24116_tuning dnxt;
172
173 u8 skip_fw_load;
174 u8 burst;
Darron Broad490c8682008-09-13 19:42:16 -0300175 struct cx24116_cmd dsec_cmd;
Steven Toth0d467482008-09-04 01:14:43 -0300176};
177
178static int cx24116_writereg(struct cx24116_state* state, int reg, int data)
179{
180 u8 buf[] = { reg, data };
181 struct i2c_msg msg = { .addr = state->config->demod_address,
182 .flags = 0, .buf = buf, .len = 2 };
183 int err;
184
185 if (debug>1)
186 printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
187 __func__,reg, data);
188
189 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
190 printk("%s: writereg error(err == %i, reg == 0x%02x,"
191 " value == 0x%02x)\n", __func__, err, reg, data);
192 return -EREMOTEIO;
193 }
194
195 return 0;
196}
197
198/* Bulk byte writes to a single I2C address, for 32k firmware load */
199static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len)
200{
201 int ret = -EREMOTEIO;
202 struct i2c_msg msg;
203 u8 *buf;
204
205 buf = kmalloc(len + 1, GFP_KERNEL);
206 if (buf == NULL) {
207 printk("Unable to kmalloc\n");
208 ret = -ENOMEM;
209 goto error;
210 }
211
212 *(buf) = reg;
213 memcpy(buf + 1, data, len);
214
215 msg.addr = state->config->demod_address;
216 msg.flags = 0;
217 msg.buf = buf;
218 msg.len = len + 1;
219
220 if (debug>1)
221 printk("cx24116: %s: write regN 0x%02x, len = %d\n",
222 __func__,reg, len);
223
224 if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) {
225 printk("%s: writereg error(err == %i, reg == 0x%02x\n",
226 __func__, ret, reg);
227 ret = -EREMOTEIO;
228 }
229
230error:
231 kfree(buf);
232
233 return ret;
234}
235
236static int cx24116_readreg(struct cx24116_state* state, u8 reg)
237{
238 int ret;
239 u8 b0[] = { reg };
240 u8 b1[] = { 0 };
241 struct i2c_msg msg[] = {
242 { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
243 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
244 };
245
246 ret = i2c_transfer(state->i2c, msg, 2);
247
248 if (ret != 2) {
249 printk("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
250 return ret;
251 }
252
253 if (debug>1)
254 printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]);
255
256 return b1[0];
257}
258
259static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_inversion_t inversion)
260{
261 dprintk("%s(%d)\n", __func__, inversion);
262
263 switch (inversion) {
264 case INVERSION_OFF:
265 state->dnxt.inversion_val = 0x00;
266 break;
267 case INVERSION_ON:
268 state->dnxt.inversion_val = 0x04;
269 break;
270 case INVERSION_AUTO:
271 state->dnxt.inversion_val = 0x0C;
272 break;
273 default:
274 return -EINVAL;
275 }
276
277 state->dnxt.inversion = inversion;
278
279 return 0;
280}
281
Darron Broad490c8682008-09-13 19:42:16 -0300282/*
283 * modfec (modulation and FEC)
284 * ===========================
285 *
286 * MOD FEC mask/val standard
287 * ---- -------- ----------- --------
288 * QPSK FEC_1_2 0x02 0x02+X DVB-S
289 * QPSK FEC_2_3 0x04 0x02+X DVB-S
290 * QPSK FEC_3_4 0x08 0x02+X DVB-S
291 * QPSK FEC_4_5 0x10 0x02+X DVB-S (?)
292 * QPSK FEC_5_6 0x20 0x02+X DVB-S
293 * QPSK FEC_6_7 0x40 0x02+X DVB-S
294 * QPSK FEC_7_8 0x80 0x02+X DVB-S
295 * QPSK FEC_8_9 0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
296 * QPSK AUTO 0xff 0x02+X DVB-S
297 *
298 * For DVB-S high byte probably represents FEC
299 * and low byte selects the modulator. The high
300 * byte is search range mask. Bit 5 may turn
301 * on DVB-S and remaining bits represent some
302 * kind of calibration (how/what i do not know).
303 *
304 * Eg.(2/3) szap "Zone Horror"
305 *
306 * mask/val = 0x04, 0x20
307 * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 00000000 | FE_HAS_LOCK
308 *
309 * mask/val = 0x04, 0x30
310 * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
311 *
312 * After tuning FECSTATUS contains actual FEC
313 * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
314 *
315 * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
316 *
317 * NBC-QPSK FEC_1_2 0x00, 0x04 DVB-S2
318 * NBC-QPSK FEC_3_5 0x00, 0x05 DVB-S2
319 * NBC-QPSK FEC_2_3 0x00, 0x06 DVB-S2
320 * NBC-QPSK FEC_3_4 0x00, 0x07 DVB-S2
321 * NBC-QPSK FEC_4_5 0x00, 0x08 DVB-S2
322 * NBC-QPSK FEC_5_6 0x00, 0x09 DVB-S2
323 * NBC-QPSK FEC_8_9 0x00, 0x0a DVB-S2
324 * NBC-QPSK FEC_9_10 0x00, 0x0b DVB-S2
325 *
326 * NBC-8PSK FEC_3_5 0x00, 0x0c DVB-S2
327 * NBC-8PSK FEC_2_3 0x00, 0x0d DVB-S2
328 * NBC-8PSK FEC_3_4 0x00, 0x0e DVB-S2
329 * NBC-8PSK FEC_5_6 0x00, 0x0f DVB-S2
330 * NBC-8PSK FEC_8_9 0x00, 0x10 DVB-S2
331 * NBC-8PSK FEC_9_10 0x00, 0x11 DVB-S2
332 *
333 * For DVB-S2 low bytes selects both modulator
334 * and FEC. High byte is meaningless here. To
335 * set pilot, bit 6 (0x40) is set. When inspecting
336 * FECSTATUS bit 7 (0x80) represents the pilot
337 * selection whilst not tuned. When tuned, actual FEC
338 * in use is found in FECSTATUS as per above. Pilot
339 * value is reset.
340 */
341
Steven Toth0d467482008-09-04 01:14:43 -0300342/* A table of modulation, fec and configuration bytes for the demod.
343 * Not all S2 mmodulation schemes are support and not all rates with
344 * a scheme are support. Especially, no auto detect when in S2 mode.
345 */
346struct cx24116_modfec {
347 fe_modulation_t modulation;
348 fe_code_rate_t fec;
349 u8 mask; /* In DVBS mode this is used to autodetect */
350 u8 val; /* Passed to the firmware to indicate mode selection */
351} CX24116_MODFEC_MODES[] = {
352 /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
Darron Broad490c8682008-09-13 19:42:16 -0300353
354 /*mod fec mask val */
Steven Toth0d467482008-09-04 01:14:43 -0300355 { QPSK, FEC_NONE, 0xfe, 0x30 },
Darron Broad490c8682008-09-13 19:42:16 -0300356 { QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */
357 { QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */
358 { QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */
359 { QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */
360 { QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */
361 { QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */
362 { QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */
363 { QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */
Steven Toth0d467482008-09-04 01:14:43 -0300364 { QPSK, FEC_AUTO, 0xfe, 0x30 },
365 /* NBC-QPSK */
366 { NBC_QPSK, FEC_1_2, 0x00, 0x04 },
367 { NBC_QPSK, FEC_3_5, 0x00, 0x05 },
368 { NBC_QPSK, FEC_2_3, 0x00, 0x06 },
369 { NBC_QPSK, FEC_3_4, 0x00, 0x07 },
370 { NBC_QPSK, FEC_4_5, 0x00, 0x08 },
371 { NBC_QPSK, FEC_5_6, 0x00, 0x09 },
372 { NBC_QPSK, FEC_8_9, 0x00, 0x0a },
373 { NBC_QPSK, FEC_9_10, 0x00, 0x0b },
374 /* 8PSK */
375 { _8PSK, FEC_3_5, 0x00, 0x0c },
376 { _8PSK, FEC_2_3, 0x00, 0x0d },
377 { _8PSK, FEC_3_4, 0x00, 0x0e },
378 { _8PSK, FEC_5_6, 0x00, 0x0f },
Darron Broad490c8682008-09-13 19:42:16 -0300379 { _8PSK, FEC_8_9, 0x00, 0x10 },
Steven Toth0d467482008-09-04 01:14:43 -0300380 { _8PSK, FEC_9_10, 0x00, 0x11 },
Darron Broad490c8682008-09-13 19:42:16 -0300381 /*
382 * `val' can be found in the FECSTATUS register when tuning.
383 * FECSTATUS will give the actual FEC in use if tuning was successful.
384 */
Steven Toth0d467482008-09-04 01:14:43 -0300385};
386
387static int cx24116_lookup_fecmod(struct cx24116_state* state,
388 fe_modulation_t m, fe_code_rate_t f)
389{
390 int i, ret = -EOPNOTSUPP;
391
Darron Broad490c8682008-09-13 19:42:16 -0300392 dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
393
Steven Toth0d467482008-09-04 01:14:43 -0300394 for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++)
395 {
396 if( (m == CX24116_MODFEC_MODES[i].modulation) &&
397 (f == CX24116_MODFEC_MODES[i].fec) )
398 {
399 ret = i;
400 break;
401 }
402 }
403
404 return ret;
405}
406
407static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec)
408{
409 int ret = 0;
Darron Broad490c8682008-09-13 19:42:16 -0300410
411 dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
Steven Toth0d467482008-09-04 01:14:43 -0300412
413 ret = cx24116_lookup_fecmod(state, mod, fec);
414
415 if(ret < 0)
416 return ret;
417
Darron Broad490c8682008-09-13 19:42:16 -0300418 state->dnxt.fec = fec;
Steven Toth0d467482008-09-04 01:14:43 -0300419 state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
420 state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
Darron Broad490c8682008-09-13 19:42:16 -0300421 dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
422 state->dnxt.fec_mask, state->dnxt.fec_val);
Steven Toth0d467482008-09-04 01:14:43 -0300423
424 return 0;
425}
426
427static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate)
428{
Darron Broad490c8682008-09-13 19:42:16 -0300429 dprintk("%s(%d)\n", __func__, rate);
Steven Toth0d467482008-09-04 01:14:43 -0300430
431 /* check if symbol rate is within limits */
Darron Broad490c8682008-09-13 19:42:16 -0300432 if ((rate > state->frontend.ops.info.symbol_rate_max) ||
433 (rate < state->frontend.ops.info.symbol_rate_min)) {
434 dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
435 return -EOPNOTSUPP;
436 }
Steven Toth0d467482008-09-04 01:14:43 -0300437
Darron Broad490c8682008-09-13 19:42:16 -0300438 state->dnxt.symbol_rate = rate;
439 dprintk("%s() symbol_rate = %d\n", __func__, rate);
440
441 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300442}
443
444static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw);
445
446static int cx24116_firmware_ondemand(struct dvb_frontend* fe)
447{
448 struct cx24116_state *state = fe->demodulator_priv;
449 const struct firmware *fw;
450 int ret = 0;
451
452 dprintk("%s()\n",__func__);
453
454 if (cx24116_readreg(state, 0x20) > 0)
455 {
456
457 if (state->skip_fw_load)
458 return 0;
459
460 /* Load firmware */
461 /* request the firmware, this will block until someone uploads it */
462 printk("%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE);
463 ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, &state->i2c->dev);
464 printk("%s: Waiting for firmware upload(2)...\n", __func__);
465 if (ret) {
466 printk("%s: No firmware uploaded (timeout or file not found?)\n", __func__);
467 return ret;
468 }
469
470 /* Make sure we don't recurse back through here during loading */
471 state->skip_fw_load = 1;
472
473 ret = cx24116_load_firmware(fe, fw);
474 if (ret)
475 printk("%s: Writing firmware to device failed\n", __func__);
476
477 release_firmware(fw);
478
479 printk("%s: Firmware upload %s\n", __func__, ret == 0 ? "complete" : "failed");
480
481 /* Ensure firmware is always loaded if required */
482 state->skip_fw_load = 0;
483 }
484
485 return ret;
486}
487
488/* Take a basic firmware command structure, format it and forward it for processing */
489static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd)
490{
491 struct cx24116_state *state = fe->demodulator_priv;
492 int i, ret;
493
494 dprintk("%s()\n", __func__);
495
496 /* Load the firmware if required */
497 if ( (ret = cx24116_firmware_ondemand(fe)) != 0)
498 {
499 printk("%s(): Unable initialise the firmware\n", __func__);
500 return ret;
501 }
502
503 /* Write the command */
504 for(i = 0; i < cmd->len ; i++)
505 {
506 dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
507 cx24116_writereg(state, i, cmd->args[i]);
508 }
509
510 /* Start execution and wait for cmd to terminate */
Darron Broad490c8682008-09-13 19:42:16 -0300511 cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
512 while( cx24116_readreg(state, CX24116_REG_EXECUTE) )
Steven Toth0d467482008-09-04 01:14:43 -0300513 {
514 msleep(10);
515 if(i++ > 64)
516 {
517 /* Avoid looping forever if the firmware does no respond */
518 printk("%s() Firmware not responding\n", __func__);
519 return -EREMOTEIO;
520 }
521 }
522 return 0;
523}
524
525static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
526{
527 struct cx24116_state* state = fe->demodulator_priv;
528 struct cx24116_cmd cmd;
Darron Broad490c8682008-09-13 19:42:16 -0300529 int i, ret;
530 unsigned char vers[4];
Steven Toth0d467482008-09-04 01:14:43 -0300531
532 dprintk("%s\n", __func__);
533 dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n"
534 ,fw->size
535 ,fw->data[0]
536 ,fw->data[1]
537 ,fw->data[ fw->size-2 ]
538 ,fw->data[ fw->size-1 ]
539 );
540
541 /* Toggle 88x SRST pin to reset demod */
542 if (state->config->reset_device)
543 state->config->reset_device(fe);
544
545 /* Begin the firmware load process */
546 /* Prepare the demod, load the firmware, cleanup after load */
Steven Toth0d467482008-09-04 01:14:43 -0300547
Darron Broad490c8682008-09-13 19:42:16 -0300548 /* Init PLL */
549 cx24116_writereg(state, 0xE5, 0x00);
550 cx24116_writereg(state, 0xF1, 0x08);
551 cx24116_writereg(state, 0xF2, 0x13);
552
553 /* Start PLL */
554 cx24116_writereg(state, 0xe0, 0x03);
555 cx24116_writereg(state, 0xe0, 0x00);
556
557 /* Unknown */
558 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
559 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
560
561 /* Unknown */
Steven Toth0d467482008-09-04 01:14:43 -0300562 cx24116_writereg(state, 0xF0, 0x03);
563 cx24116_writereg(state, 0xF4, 0x81);
564 cx24116_writereg(state, 0xF5, 0x00);
565 cx24116_writereg(state, 0xF6, 0x00);
566
567 /* write the entire firmware as one transaction */
568 cx24116_writeregN(state, 0xF7, fw->data, fw->size);
569
570 cx24116_writereg(state, 0xF4, 0x10);
571 cx24116_writereg(state, 0xF0, 0x00);
572 cx24116_writereg(state, 0xF8, 0x06);
573
Darron Broad490c8682008-09-13 19:42:16 -0300574 /* Firmware CMD 10: VCO config */
575 cmd.args[0x00] = CMD_SET_VCO;
Steven Toth0d467482008-09-04 01:14:43 -0300576 cmd.args[0x01] = 0x05;
577 cmd.args[0x02] = 0xdc;
578 cmd.args[0x03] = 0xda;
579 cmd.args[0x04] = 0xae;
580 cmd.args[0x05] = 0xaa;
581 cmd.args[0x06] = 0x04;
582 cmd.args[0x07] = 0x9d;
583 cmd.args[0x08] = 0xfc;
584 cmd.args[0x09] = 0x06;
585 cmd.len= 0x0a;
586 ret = cx24116_cmd_execute(fe, &cmd);
587 if (ret != 0)
588 return ret;
589
Darron Broad490c8682008-09-13 19:42:16 -0300590 cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
Steven Toth0d467482008-09-04 01:14:43 -0300591
Darron Broad490c8682008-09-13 19:42:16 -0300592 /* Firmware CMD 14: Tuner config */
593 cmd.args[0x00] = CMD_TUNERINIT;
Steven Toth0d467482008-09-04 01:14:43 -0300594 cmd.args[0x01] = 0x00;
595 cmd.args[0x02] = 0x00;
596 cmd.len= 0x03;
597 ret = cx24116_cmd_execute(fe, &cmd);
598 if (ret != 0)
599 return ret;
600
601 cx24116_writereg(state, 0xe5, 0x00);
602
Darron Broad490c8682008-09-13 19:42:16 -0300603 /* Firmware CMD 13: MPEG config */
604 cmd.args[0x00] = CMD_MPEGCONFIG;
Steven Toth0d467482008-09-04 01:14:43 -0300605 cmd.args[0x01] = 0x01;
606 cmd.args[0x02] = 0x75;
607 cmd.args[0x03] = 0x00;
Igor M. Liplianincc8c4f32008-09-09 13:57:47 -0300608 if (state->config->mpg_clk_pos_pol)
609 cmd.args[0x04] = state->config->mpg_clk_pos_pol;
610 else
611 cmd.args[0x04] = 0x02;
Steven Toth0d467482008-09-04 01:14:43 -0300612 cmd.args[0x05] = 0x00;
613 cmd.len= 0x06;
614 ret = cx24116_cmd_execute(fe, &cmd);
615 if (ret != 0)
616 return ret;
617
Darron Broad490c8682008-09-13 19:42:16 -0300618 /* Firmware CMD 35: Get firmware version */
619 cmd.args[0x00] = CMD_UPDFWVERS;
620 cmd.len= 0x02;
621 for(i=0; i<4; i++) {
622 cmd.args[0x01] = i;
623 ret = cx24116_cmd_execute(fe, &cmd);
624 if (ret != 0)
625 return ret;
626 vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX);
627 }
628 printk("%s: FW version %i.%i.%i.%i\n", __func__,
629 vers[0], vers[1], vers[2], vers[3]);
630
Steven Toth0d467482008-09-04 01:14:43 -0300631 return 0;
632}
633
634static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
635{
636 /* The isl6421 module will override this function in the fops. */
637 dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__);
638
639 return -EOPNOTSUPP;
640}
641
642static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status)
643{
644 struct cx24116_state *state = fe->demodulator_priv;
645
Darron Broad490c8682008-09-13 19:42:16 -0300646 int lock = cx24116_readreg(state, CX24116_REG_SSTATUS);
Steven Toth0d467482008-09-04 01:14:43 -0300647
648 dprintk("%s: status = 0x%02x\n", __func__, lock);
649
650 *status = 0;
651
Darron Broad490c8682008-09-13 19:42:16 -0300652 if (lock & CX24116_HAS_SIGNAL)
Steven Toth0d467482008-09-04 01:14:43 -0300653 *status |= FE_HAS_SIGNAL;
Darron Broad490c8682008-09-13 19:42:16 -0300654 if (lock & CX24116_HAS_CARRIER)
Steven Toth0d467482008-09-04 01:14:43 -0300655 *status |= FE_HAS_CARRIER;
Darron Broad490c8682008-09-13 19:42:16 -0300656 if (lock & CX24116_HAS_VITERBI)
Steven Toth0d467482008-09-04 01:14:43 -0300657 *status |= FE_HAS_VITERBI;
Darron Broad490c8682008-09-13 19:42:16 -0300658 if (lock & CX24116_HAS_SYNCLOCK)
Steven Toth0d467482008-09-04 01:14:43 -0300659 *status |= FE_HAS_SYNC | FE_HAS_LOCK;
660
661 return 0;
662}
663
Steven Toth0d467482008-09-04 01:14:43 -0300664static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber)
665{
Darron Broad490c8682008-09-13 19:42:16 -0300666 struct cx24116_state *state = fe->demodulator_priv;
667
Steven Toth0d467482008-09-04 01:14:43 -0300668 dprintk("%s()\n", __func__);
Darron Broad490c8682008-09-13 19:42:16 -0300669
670 *ber = ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) |
671 ( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) |
672 ( cx24116_readreg(state, CX24116_REG_BER8 ) << 8 ) |
673 cx24116_readreg(state, CX24116_REG_BER0 );
Steven Toth0d467482008-09-04 01:14:43 -0300674
675 return 0;
676}
677
Darron Broad490c8682008-09-13 19:42:16 -0300678/* TODO Determine function and scale appropriately */
Steven Toth0d467482008-09-04 01:14:43 -0300679static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
680{
681 struct cx24116_state *state = fe->demodulator_priv;
Darron Broad490c8682008-09-13 19:42:16 -0300682 struct cx24116_cmd cmd;
683 int ret;
684 u16 sig_reading;
685
686 dprintk("%s()\n", __func__);
687
688 /* Firmware CMD 19: Get AGC */
689 cmd.args[0x00] = CMD_GETAGC;
690 cmd.len= 0x01;
691 ret = cx24116_cmd_execute(fe, &cmd);
692 if (ret != 0)
693 return ret;
694
695 sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) |
696 ( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 );
697 *signal_strength= 0 - sig_reading;
698
699 dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength);
700
701 return 0;
702}
703
704/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
705static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr)
706{
707 struct cx24116_state *state = fe->demodulator_priv;
708 u8 snr_reading;
709 static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
710 0x00000,0x0199A,0x03333,0x04ccD,0x06667,
711 0x08000,0x0999A,0x0b333,0x0cccD,0x0e667,
Steven Toth0d467482008-09-04 01:14:43 -0300712 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 };
713
714 dprintk("%s()\n", __func__);
715
Darron Broad490c8682008-09-13 19:42:16 -0300716 snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY);
Steven Toth0d467482008-09-04 01:14:43 -0300717
Darron Broad490c8682008-09-13 19:42:16 -0300718 if(snr_reading >= 0xa0 /* 100% */)
719 *snr = 0xffff;
Steven Toth0d467482008-09-04 01:14:43 -0300720 else
Darron Broad490c8682008-09-13 19:42:16 -0300721 *snr = snr_tab [ ( snr_reading & 0xf0 ) >> 4 ] +
722 ( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 );
Steven Toth0d467482008-09-04 01:14:43 -0300723
Darron Broad490c8682008-09-13 19:42:16 -0300724 dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
725 snr_reading, *snr);
Steven Toth0d467482008-09-04 01:14:43 -0300726
727 return 0;
728}
729
Steven Toth0d467482008-09-04 01:14:43 -0300730static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
731{
Darron Broad490c8682008-09-13 19:42:16 -0300732 struct cx24116_state *state = fe->demodulator_priv;
733
Steven Toth0d467482008-09-04 01:14:43 -0300734 dprintk("%s()\n", __func__);
Darron Broad490c8682008-09-13 19:42:16 -0300735
736 *ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) |
737 cx24116_readreg(state, CX24116_REG_UCB0);
Steven Toth0d467482008-09-04 01:14:43 -0300738
739 return 0;
740}
741
742/* Overwrite the current tuning params, we are about to tune */
743static void cx24116_clone_params(struct dvb_frontend* fe)
744{
745 struct cx24116_state *state = fe->demodulator_priv;
746 memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
747}
748
Darron Broad490c8682008-09-13 19:42:16 -0300749/* Wait for LNB */
750static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
751{
752 struct cx24116_state *state = fe->demodulator_priv;
753 int i;
754
755 dprintk("%s() qstatus = 0x%02x\n", __func__,
756 cx24116_readreg(state, CX24116_REG_QSTATUS));
757
758 /* Wait for up to 300 ms */
759 for(i = 0; i < 30 ; i++) {
760 if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
761 return 0;
762 msleep(10);
763 }
764
765 dprintk("%s(): LNB not ready\n", __func__);
766
767 return -ETIMEDOUT; /* -EBUSY ? */
768}
769
Steven Toth0d467482008-09-04 01:14:43 -0300770static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
771{
772 struct cx24116_cmd cmd;
773 int ret;
774
775 dprintk("%s(%d)\n", __func__, tone);
776 if ( (tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF) ) {
777 printk("%s: Invalid, tone=%d\n", __func__, tone);
778 return -EINVAL;
779 }
780
Darron Broad490c8682008-09-13 19:42:16 -0300781 /* Wait for LNB ready */
782 ret = cx24116_wait_for_lnb(fe);
783 if(ret != 0)
784 return ret;
785
786 /* Min delay time after DiSEqC send */
787 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
788
Steven Toth0d467482008-09-04 01:14:43 -0300789 /* This is always done before the tone is set */
790 cmd.args[0x00] = CMD_SET_TONEPRE;
791 cmd.args[0x01] = 0x00;
792 cmd.len= 0x02;
793 ret = cx24116_cmd_execute(fe, &cmd);
794 if (ret != 0)
795 return ret;
796
797 /* Now we set the tone */
798 cmd.args[0x00] = CMD_SET_TONE;
799 cmd.args[0x01] = 0x00;
800 cmd.args[0x02] = 0x00;
801
802 switch (tone) {
803 case SEC_TONE_ON:
804 dprintk("%s: setting tone on\n", __func__);
805 cmd.args[0x03] = 0x01;
806 break;
807 case SEC_TONE_OFF:
808 dprintk("%s: setting tone off\n",__func__);
809 cmd.args[0x03] = 0x00;
810 break;
811 }
812 cmd.len= 0x04;
813
Darron Broad490c8682008-09-13 19:42:16 -0300814 /* Min delay time before DiSEqC send */
815 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
816
Steven Toth0d467482008-09-04 01:14:43 -0300817 return cx24116_cmd_execute(fe, &cmd);
818}
819
820/* Initialise DiSEqC */
821static int cx24116_diseqc_init(struct dvb_frontend* fe)
822{
823 struct cx24116_state *state = fe->demodulator_priv;
Darron Broad490c8682008-09-13 19:42:16 -0300824 struct cx24116_cmd cmd;
825 int ret;
Steven Toth0d467482008-09-04 01:14:43 -0300826
Darron Broad490c8682008-09-13 19:42:16 -0300827 /* Firmware CMD 20: LNB/DiSEqC config */
828 cmd.args[0x00] = CMD_LNBCONFIG;
829 cmd.args[0x01] = 0x00;
830 cmd.args[0x02] = 0x10;
831 cmd.args[0x03] = 0x00;
832 cmd.args[0x04] = 0x8f;
833 cmd.args[0x05] = 0x28;
834 cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
835 cmd.args[0x07] = 0x01;
836 cmd.len= 0x08;
837 ret = cx24116_cmd_execute(fe, &cmd);
838 if (ret != 0)
839 return ret;
840
841 /* Prepare a DiSEqC command */
842 state->dsec_cmd.args[0x00] = CMD_LNBSEND;
843
844 /* DiSEqC burst */
845 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
846
847 /* Unknown */
848 state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
849 state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
850 state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */
851
852 /* DiSEqC message length */
853 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
854
855 /* Command length */
856 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS;
Steven Toth0d467482008-09-04 01:14:43 -0300857
858 return 0;
859}
860
861/* Send DiSEqC message with derived burst (hack) || previous burst */
862static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d)
863{
864 struct cx24116_state *state = fe->demodulator_priv;
Steven Toth0d467482008-09-04 01:14:43 -0300865 int i, ret;
866
867 /* Dump DiSEqC message */
868 if (debug) {
869 printk("cx24116: %s(", __func__);
870 for(i = 0 ; i < d->msg_len ;) {
871 printk("0x%02x", d->msg[i]);
872 if(++i < d->msg_len)
873 printk(", ");
Darron Broad490c8682008-09-13 19:42:16 -0300874 }
875 printk(") toneburst=%d\n", toneburst);
Steven Toth0d467482008-09-04 01:14:43 -0300876 }
877
Darron Broad490c8682008-09-13 19:42:16 -0300878 /* Validate length */
Steven Toth0d467482008-09-04 01:14:43 -0300879 if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
880 return -EINVAL;
881
Steven Toth0d467482008-09-04 01:14:43 -0300882 /* DiSEqC message */
883 for (i = 0; i < d->msg_len; i++)
Darron Broad490c8682008-09-13 19:42:16 -0300884 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
Steven Toth0d467482008-09-04 01:14:43 -0300885
Darron Broad490c8682008-09-13 19:42:16 -0300886 /* DiSEqC message length */
887 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
Steven Toth0d467482008-09-04 01:14:43 -0300888
Darron Broad490c8682008-09-13 19:42:16 -0300889 /* Command length */
890 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
Steven Toth0d467482008-09-04 01:14:43 -0300891
Darron Broad490c8682008-09-13 19:42:16 -0300892 /* DiSEqC toneburst */
893 if(toneburst == CX24116_DISEQC_MESGCACHE)
894 /* Message is cached */
895 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300896
Darron Broad490c8682008-09-13 19:42:16 -0300897 else if(toneburst == CX24116_DISEQC_TONEOFF)
898 /* Message is sent without burst */
899 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
900
901 else if(toneburst == CX24116_DISEQC_TONECACHE) {
902 /*
903 * Message is sent with derived else cached burst
904 *
905 * WRITE PORT GROUP COMMAND 38
906 *
907 * 0/A/A: E0 10 38 F0..F3
908 * 1/B/B: E0 10 38 F4..F7
909 * 2/C/A: E0 10 38 F8..FB
910 * 3/D/B: E0 10 38 FC..FF
911 *
Darron Broad7396d3e2008-09-14 10:45:58 -0300912 * databyte[3]= 8421:8421
Darron Broad490c8682008-09-13 19:42:16 -0300913 * ABCD:WXYZ
914 * CLR :SET
915 *
916 * WX= PORT SELECT 0..3 (X=TONEBURST)
917 * Y = VOLTAGE (0=13V, 1=18V)
918 * Z = BAND (0=LOW, 1=HIGH(22K))
919 */
920 if(d->msg_len >= 4 && d->msg[2] == 0x38)
921 state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2);
922 if(debug)
923 dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]);
924 }
925
926 /* Wait for LNB ready */
927 ret = cx24116_wait_for_lnb(fe);
928 if(ret != 0)
929 return ret;
930
931 /* Wait for voltage/min repeat delay */
932 msleep(100);
933
934 /* Command */
935 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
936 if(ret != 0)
937 return ret;
938 /*
939 * Wait for send
Steven Toth0d467482008-09-04 01:14:43 -0300940 *
941 * Eutelsat spec:
Darron Broad490c8682008-09-13 19:42:16 -0300942 * >15ms delay + (XXX determine if FW does this, see set_tone)
943 * 13.5ms per byte +
944 * >15ms delay +
945 * 12.5ms burst +
946 * >15ms delay (XXX determine if FW does this, see set_tone)
Steven Toth0d467482008-09-04 01:14:43 -0300947 */
Darron Broad490c8682008-09-13 19:42:16 -0300948 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) );
Steven Toth0d467482008-09-04 01:14:43 -0300949
Darron Broad490c8682008-09-13 19:42:16 -0300950 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300951}
952
953/* Send DiSEqC burst */
954static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
955{
956 struct cx24116_state *state = fe->demodulator_priv;
Steven Toth0d467482008-09-04 01:14:43 -0300957 int ret;
958
Darron Broad490c8682008-09-13 19:42:16 -0300959 dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst);
Steven Toth0d467482008-09-04 01:14:43 -0300960
Darron Broad490c8682008-09-13 19:42:16 -0300961 /* DiSEqC burst */
Steven Toth0d467482008-09-04 01:14:43 -0300962 if (burst == SEC_MINI_A)
Darron Broad490c8682008-09-13 19:42:16 -0300963 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
Steven Toth0d467482008-09-04 01:14:43 -0300964 else if(burst == SEC_MINI_B)
Darron Broad490c8682008-09-13 19:42:16 -0300965 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B;
Steven Toth0d467482008-09-04 01:14:43 -0300966 else
967 return -EINVAL;
968
Darron Broad490c8682008-09-13 19:42:16 -0300969 /* DiSEqC toneburst */
970 if(toneburst != CX24116_DISEQC_MESGCACHE)
971 /* Burst is cached */
972 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300973
Darron Broad490c8682008-09-13 19:42:16 -0300974 /* Burst is to be sent with cached message */
Steven Toth0d467482008-09-04 01:14:43 -0300975
Darron Broad490c8682008-09-13 19:42:16 -0300976 /* Wait for LNB ready */
977 ret = cx24116_wait_for_lnb(fe);
978 if(ret != 0)
979 return ret;
Steven Toth0d467482008-09-04 01:14:43 -0300980
Darron Broad490c8682008-09-13 19:42:16 -0300981 /* Wait for voltage/min repeat delay */
982 msleep(100);
Steven Toth0d467482008-09-04 01:14:43 -0300983
Darron Broad490c8682008-09-13 19:42:16 -0300984 /* Command */
985 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
986 if(ret != 0)
987 return ret;
988
989 /*
990 * Wait for send
991 *
992 * Eutelsat spec:
993 * >15ms delay + (XXX determine if FW does this, see set_tone)
994 * 13.5ms per byte +
995 * >15ms delay +
996 * 12.5ms burst +
997 * >15ms delay (XXX determine if FW does this, see set_tone)
998 */
999 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 );
1000
1001 return 0;
Steven Toth0d467482008-09-04 01:14:43 -03001002}
1003
1004static void cx24116_release(struct dvb_frontend* fe)
1005{
1006 struct cx24116_state* state = fe->demodulator_priv;
1007 dprintk("%s\n",__func__);
1008 kfree(state);
1009}
1010
1011static struct dvb_frontend_ops cx24116_ops;
1012
1013struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
1014 struct i2c_adapter* i2c)
1015{
1016 struct cx24116_state* state = NULL;
1017 int ret;
1018
1019 dprintk("%s\n",__func__);
1020
1021 /* allocate memory for the internal state */
1022 state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
1023 if (state == NULL) {
1024 printk("Unable to kmalloc\n");
Darron Broad7396d3e2008-09-14 10:45:58 -03001025 goto error1;
Steven Toth0d467482008-09-04 01:14:43 -03001026 }
1027
1028 /* setup the state */
1029 memset(state, 0, sizeof(struct cx24116_state));
1030
1031 state->config = config;
1032 state->i2c = i2c;
1033
1034 /* check if the demod is present */
1035 ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE);
1036 if (ret != 0x0501) {
1037 printk("Invalid probe, probably not a CX24116 device\n");
Darron Broad7396d3e2008-09-14 10:45:58 -03001038 goto error2;
Steven Toth0d467482008-09-04 01:14:43 -03001039 }
1040
1041 /* create dvb_frontend */
1042 memcpy(&state->frontend.ops, &cx24116_ops, sizeof(struct dvb_frontend_ops));
1043 state->frontend.demodulator_priv = state;
1044 return &state->frontend;
1045
Darron Broad7396d3e2008-09-14 10:45:58 -03001046error2: kfree(state);
Darron Broad490c8682008-09-13 19:42:16 -03001047error1: return NULL;
Steven Toth0d467482008-09-04 01:14:43 -03001048}
Darron Broad490c8682008-09-13 19:42:16 -03001049/*
1050 * Initialise or wake up device
1051 *
1052 * Power config will reset and load initial firmware if required
1053 */
Steven Toth0d467482008-09-04 01:14:43 -03001054static int cx24116_initfe(struct dvb_frontend* fe)
1055{
Darron Broad490c8682008-09-13 19:42:16 -03001056 struct cx24116_state* state = fe->demodulator_priv;
1057 struct cx24116_cmd cmd;
1058 int ret;
1059
Steven Toth0d467482008-09-04 01:14:43 -03001060 dprintk("%s()\n",__func__);
1061
Darron Broad490c8682008-09-13 19:42:16 -03001062 /* Power on */
1063 cx24116_writereg(state, 0xe0, 0);
1064 cx24116_writereg(state, 0xe1, 0);
1065 cx24116_writereg(state, 0xea, 0);
1066
1067 /* Firmware CMD 36: Power config */
1068 cmd.args[0x00] = CMD_TUNERSLEEP;
1069 cmd.args[0x01] = 0;
1070 cmd.len= 0x02;
1071 ret = cx24116_cmd_execute(fe, &cmd);
1072 if(ret != 0)
1073 return ret;
1074
Steven Toth0d467482008-09-04 01:14:43 -03001075 return cx24116_diseqc_init(fe);
1076}
1077
Darron Broad490c8682008-09-13 19:42:16 -03001078/*
1079 * Put device to sleep
1080 */
1081static int cx24116_sleep(struct dvb_frontend* fe)
1082{
1083 struct cx24116_state* state = fe->demodulator_priv;
1084 struct cx24116_cmd cmd;
1085 int ret;
1086
1087 dprintk("%s()\n",__func__);
1088
1089 /* Firmware CMD 36: Power config */
1090 cmd.args[0x00] = CMD_TUNERSLEEP;
1091 cmd.args[0x01] = 1;
1092 cmd.len= 0x02;
1093 ret = cx24116_cmd_execute(fe, &cmd);
1094 if(ret != 0)
1095 return ret;
1096
1097 /* Power off (Shutdown clocks) */
1098 cx24116_writereg(state, 0xea, 0xff);
1099 cx24116_writereg(state, 0xe1, 1);
1100 cx24116_writereg(state, 0xe0, 1);
1101
1102 return 0;
1103}
1104
Steven Tothe7fee0f32008-09-11 10:23:01 -03001105static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp)
Steven Toth0d467482008-09-04 01:14:43 -03001106{
1107 dprintk("%s(..)\n", __func__);
1108 return 0;
1109}
1110
Steven Tothbfbf2da2008-09-12 01:37:37 -03001111static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp)
Steven Toth0d467482008-09-04 01:14:43 -03001112{
Steven Tothbfbf2da2008-09-12 01:37:37 -03001113 dprintk("%s(..)\n", __func__);
Steven Toth0d467482008-09-04 01:14:43 -03001114 return 0;
1115}
1116
1117/* dvb-core told us to tune, the tv property cache will be complete,
1118 * it's safe for is to pull values and use them for tuning purposes.
1119 */
1120static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
1121{
1122 struct cx24116_state *state = fe->demodulator_priv;
Steven Toth56f06802008-09-11 10:19:27 -03001123 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Steven Toth0d467482008-09-04 01:14:43 -03001124 struct cx24116_cmd cmd;
1125 fe_status_t tunerstat;
Darron Broad01a8f032008-10-03 11:47:46 -03001126 int i, status, ret, retune;
Steven Toth0d467482008-09-04 01:14:43 -03001127
1128 dprintk("%s()\n",__func__);
1129
Darron Broad490c8682008-09-13 19:42:16 -03001130 switch(c->delivery_system) {
1131 case SYS_DVBS:
1132 dprintk("%s: DVB-S delivery system selected\n",__func__);
Darron Broad01a8f032008-10-03 11:47:46 -03001133
1134 /* Only QPSK is supported for DVB-S */
1135 if(c->modulation != QPSK) {
1136 dprintk("%s: unsupported modulation selected (%d)\n",
1137 __func__, c->modulation);
1138 return -EOPNOTSUPP;
1139 }
1140
1141 /* Pilot doesn't exist in DVB-S, turn bit off */
1142 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1143 retune = 1;
1144
1145 /* DVB-S only supports 0.35 */
1146 if(c->rolloff != ROLLOFF_35) {
1147 dprintk("%s: unsupported rolloff selected (%d)\n",
1148 __func__, c->rolloff);
1149 return -EOPNOTSUPP;
1150 }
Darron Broad7396d3e2008-09-14 10:45:58 -03001151 state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
Darron Broad490c8682008-09-13 19:42:16 -03001152 break;
Darron Broad01a8f032008-10-03 11:47:46 -03001153
Darron Broad490c8682008-09-13 19:42:16 -03001154 case SYS_DVBS2:
1155 dprintk("%s: DVB-S2 delivery system selected\n",__func__);
Darron Broad01a8f032008-10-03 11:47:46 -03001156
1157 /*
1158 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
1159 * but not hardware auto detection
1160 */
1161 if(c->modulation != _8PSK && c->modulation != NBC_QPSK) {
1162 dprintk("%s: unsupported modulation selected (%d)\n",
1163 __func__, c->modulation);
1164 return -EOPNOTSUPP;
1165 }
1166
1167 switch(c->pilot) {
1168 case PILOT_AUTO: /* Not supported but emulated */
1169 retune = 2; /* Fall-through */
1170 case PILOT_OFF:
1171 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1172 break;
1173 case PILOT_ON:
1174 state->dnxt.pilot_val = CX24116_PILOT_ON;
1175 break;
1176 default:
1177 dprintk("%s: unsupported pilot mode selected (%d)\n",
1178 __func__, c->pilot);
1179 return -EOPNOTSUPP;
1180 }
1181
Darron Broad490c8682008-09-13 19:42:16 -03001182 switch(c->rolloff) {
1183 case ROLLOFF_20:
1184 state->dnxt.rolloff_val= CX24116_ROLLOFF_020;
1185 break;
1186 case ROLLOFF_25:
1187 state->dnxt.rolloff_val= CX24116_ROLLOFF_025;
1188 break;
1189 case ROLLOFF_35:
1190 state->dnxt.rolloff_val= CX24116_ROLLOFF_035;
1191 break;
Darron Broad01a8f032008-10-03 11:47:46 -03001192 case ROLLOFF_AUTO: /* Rolloff must be explicit */
1193 default:
1194 dprintk("%s: unsupported rolloff selected (%d)\n",
1195 __func__, c->rolloff);
Darron Broad490c8682008-09-13 19:42:16 -03001196 return -EOPNOTSUPP;
1197 }
Darron Broad490c8682008-09-13 19:42:16 -03001198 break;
Darron Broad01a8f032008-10-03 11:47:46 -03001199
Darron Broad490c8682008-09-13 19:42:16 -03001200 default:
1201 dprintk("%s: unsupported delivery system selected (%d)\n",
1202 __func__, c->delivery_system);
1203 return -EOPNOTSUPP;
1204 }
Darron Broad01a8f032008-10-03 11:47:46 -03001205 state->dnxt.modulation = c->modulation;
1206 state->dnxt.frequency = c->frequency;
1207 state->dnxt.pilot = c->pilot;
1208 state->dnxt.rolloff = c->rolloff;
Darron Broad490c8682008-09-13 19:42:16 -03001209
Steven Toth0d467482008-09-04 01:14:43 -03001210 if ((ret = cx24116_set_inversion(state, c->inversion)) != 0)
1211 return ret;
1212
Darron Broad01a8f032008-10-03 11:47:46 -03001213 /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
Steven Toth0d467482008-09-04 01:14:43 -03001214 if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) != 0)
1215 return ret;
1216
1217 if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) != 0)
1218 return ret;
1219
1220 /* discard the 'current' tuning parameters and prepare to tune */
1221 cx24116_clone_params(fe);
1222
Darron Broad01a8f032008-10-03 11:47:46 -03001223 dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation);
Steven Toth0d467482008-09-04 01:14:43 -03001224 dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency);
Darron Broad01a8f032008-10-03 11:47:46 -03001225 dprintk("%s: pilot = %d (val = 0x%02x)\n", __func__,
1226 state->dcur.pilot, state->dcur.pilot_val);
1227 dprintk("%s: retune = %d\n", __func__, retune);
1228 dprintk("%s: rolloff = %d (val = 0x%02x)\n", __func__,
1229 state->dcur.rolloff, state->dcur.rolloff_val);
Steven Toth0d467482008-09-04 01:14:43 -03001230 dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
1231 dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
1232 state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
1233 dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__,
1234 state->dcur.inversion, state->dcur.inversion_val);
1235
Darron Broad490c8682008-09-13 19:42:16 -03001236 /* This is also done in advise/acquire on HVR4000 but not on LITE */
Steven Toth0d467482008-09-04 01:14:43 -03001237 if (state->config->set_ts_params)
1238 state->config->set_ts_params(fe, 0);
1239
Darron Broad490c8682008-09-13 19:42:16 -03001240 /* Set/Reset B/W */
1241 cmd.args[0x00] = CMD_BANDWIDTH;
1242 cmd.args[0x01] = 0x01;
1243 cmd.len= 0x02;
1244 ret = cx24116_cmd_execute(fe, &cmd);
1245 if (ret != 0)
1246 return ret;
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001247
Steven Toth0d467482008-09-04 01:14:43 -03001248 /* Prepare a tune request */
1249 cmd.args[0x00] = CMD_TUNEREQUEST;
1250
1251 /* Frequency */
1252 cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
1253 cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
1254 cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
1255
1256 /* Symbol Rate */
1257 cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
1258 cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
1259
1260 /* Automatic Inversion */
1261 cmd.args[0x06] = state->dcur.inversion_val;
1262
Darron Broad01a8f032008-10-03 11:47:46 -03001263 /* Modulation / FEC / Pilot */
1264 cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
Steven Toth0d467482008-09-04 01:14:43 -03001265
1266 cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
1267 cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
1268 cmd.args[0x0a] = 0x00;
1269 cmd.args[0x0b] = 0x00;
Darron Broad490c8682008-09-13 19:42:16 -03001270 cmd.args[0x0c] = state->dcur.rolloff_val;
Steven Toth0d467482008-09-04 01:14:43 -03001271 cmd.args[0x0d] = state->dcur.fec_mask;
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001272
Darron Broad490c8682008-09-13 19:42:16 -03001273 if (state->dcur.symbol_rate > 30000000) {
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001274 cmd.args[0x0e] = 0x04;
1275 cmd.args[0x0f] = 0x00;
1276 cmd.args[0x10] = 0x01;
1277 cmd.args[0x11] = 0x77;
1278 cmd.args[0x12] = 0x36;
Darron Broad490c8682008-09-13 19:42:16 -03001279 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
1280 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001281 } else {
1282 cmd.args[0x0e] = 0x06;
1283 cmd.args[0x0f] = 0x00;
1284 cmd.args[0x10] = 0x00;
1285 cmd.args[0x11] = 0xFA;
1286 cmd.args[0x12] = 0x24;
Darron Broad490c8682008-09-13 19:42:16 -03001287 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
1288 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001289 }
1290
Steven Toth0d467482008-09-04 01:14:43 -03001291 cmd.len= 0x13;
1292
1293 /* We need to support pilot and non-pilot tuning in the
1294 * driver automatically. This is a workaround for because
1295 * the demod does not support autodetect.
1296 */
1297 do {
Darron Broad490c8682008-09-13 19:42:16 -03001298 /* Reset status register */
1299 status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK;
1300 cx24116_writereg(state, CX24116_REG_SSTATUS, status);
Steven Toth0d467482008-09-04 01:14:43 -03001301
1302 /* Tune */
1303 ret = cx24116_cmd_execute(fe, &cmd);
1304 if( ret != 0 )
1305 break;
1306
Darron Broad490c8682008-09-13 19:42:16 -03001307 /*
1308 * Wait for up to 500 ms before retrying
1309 *
1310 * If we are able to tune then generally it occurs within 100ms.
1311 * If it takes longer, try a different toneburst setting.
1312 */
1313 for(i = 0; i < 50 ; i++) {
1314 cx24116_read_status(fe, &tunerstat);
1315 status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
1316 if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
1317 dprintk("%s: Tuned\n",__func__);
1318 goto tuned;
1319 }
1320 msleep(10);
Steven Toth0d467482008-09-04 01:14:43 -03001321 }
Darron Broad490c8682008-09-13 19:42:16 -03001322
1323 dprintk("%s: Not tuned\n",__func__);
1324
1325 /* Toggle pilot bit when in auto-pilot */
1326 if(state->dcur.pilot == PILOT_AUTO)
Darron Broad01a8f032008-10-03 11:47:46 -03001327 cmd.args[0x07] ^= CX24116_PILOT_ON;
Steven Toth0d467482008-09-04 01:14:43 -03001328 }
1329 while(--retune);
1330
Darron Broad490c8682008-09-13 19:42:16 -03001331tuned: /* Set/Reset B/W */
1332 cmd.args[0x00] = CMD_BANDWIDTH;
1333 cmd.args[0x01] = 0x00;
1334 cmd.len= 0x02;
1335 ret = cx24116_cmd_execute(fe, &cmd);
1336 if (ret != 0)
1337 return ret;
1338
Steven Toth0d467482008-09-04 01:14:43 -03001339 return ret;
1340}
1341
1342static struct dvb_frontend_ops cx24116_ops = {
1343
1344 .info = {
1345 .name = "Conexant CX24116/CX24118",
1346 .type = FE_QPSK,
1347 .frequency_min = 950000,
1348 .frequency_max = 2150000,
1349 .frequency_stepsize = 1011, /* kHz for QPSK frontends */
1350 .frequency_tolerance = 5000,
1351 .symbol_rate_min = 1000000,
1352 .symbol_rate_max = 45000000,
1353 .caps = FE_CAN_INVERSION_AUTO |
1354 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1355 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
1356 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1357 FE_CAN_QPSK | FE_CAN_RECOVER
1358 },
1359
1360 .release = cx24116_release,
1361
1362 .init = cx24116_initfe,
Darron Broad490c8682008-09-13 19:42:16 -03001363 .sleep = cx24116_sleep,
Steven Toth0d467482008-09-04 01:14:43 -03001364 .read_status = cx24116_read_status,
1365 .read_ber = cx24116_read_ber,
1366 .read_signal_strength = cx24116_read_signal_strength,
1367 .read_snr = cx24116_read_snr,
1368 .read_ucblocks = cx24116_read_ucblocks,
1369 .set_tone = cx24116_set_tone,
1370 .set_voltage = cx24116_set_voltage,
1371 .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
1372 .diseqc_send_burst = cx24116_diseqc_send_burst,
1373
1374 .set_property = cx24116_set_property,
Steven Tothbfbf2da2008-09-12 01:37:37 -03001375 .get_property = cx24116_get_property,
Steven Toth0d467482008-09-04 01:14:43 -03001376 .set_frontend = cx24116_set_frontend,
1377};
1378
1379module_param(debug, int, 0644);
1380MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
1381
Darron Broad490c8682008-09-13 19:42:16 -03001382module_param(toneburst, int, 0644);
1383MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)");
1384
Steven Toth0d467482008-09-04 01:14:43 -03001385MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
1386MODULE_AUTHOR("Steven Toth");
1387MODULE_LICENSE("GPL");
1388
1389EXPORT_SYMBOL(cx24116_attach);