blob: 4ad86d84875f781ae4729ee721861126fe520914 [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)
Steven Toth0d467482008-09-04 01:14:43 -030070
71/* arg buffer size */
72#define CX24116_ARGLEN (0x1e)
73
Darron Broad490c8682008-09-13 19:42:16 -030074/* 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
Steven Toth0d467482008-09-04 01:14:43 -030096/* arg offset for DiSEqC */
97#define CX24116_DISEQC_BURST (1)
98#define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */
99#define CX24116_DISEQC_ARG3_0 (3) /* unknown value=0 */
100#define CX24116_DISEQC_ARG4_0 (4) /* unknown value=0 */
101#define CX24116_DISEQC_MSGLEN (5)
102#define CX24116_DISEQC_MSGOFS (6)
103
104/* DiSEqC burst */
105#define CX24116_DISEQC_MINI_A (0)
106#define CX24116_DISEQC_MINI_B (1)
107
Darron Broad490c8682008-09-13 19:42:16 -0300108/* DiSEqC tone burst */
109static int toneburst = 1;
110
Steven Toth0d467482008-09-04 01:14:43 -0300111enum cmds
112{
Darron Broad490c8682008-09-13 19:42:16 -0300113 CMD_SET_VCO = 0x10,
Steven Toth0d467482008-09-04 01:14:43 -0300114 CMD_TUNEREQUEST = 0x11,
Darron Broad490c8682008-09-13 19:42:16 -0300115 CMD_MPEGCONFIG = 0x13,
116 CMD_TUNERINIT = 0x14,
117 CMD_BANDWIDTH = 0x15,
118 CMD_GETAGC = 0x19,
119 CMD_LNBCONFIG = 0x20,
120 CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */
Steven Toth0d467482008-09-04 01:14:43 -0300121 CMD_SET_TONEPRE = 0x22,
122 CMD_SET_TONE = 0x23,
Darron Broad490c8682008-09-13 19:42:16 -0300123 CMD_UPDFWVERS = 0x35,
124 CMD_TUNERSLEEP = 0x36,
125 CMD_AGCCONTROL = 0x3b, /* Unknown */
Steven Toth0d467482008-09-04 01:14:43 -0300126};
127
128/* The Demod/Tuner can't easily provide these, we cache them */
129struct cx24116_tuning
130{
131 u32 frequency;
132 u32 symbol_rate;
133 fe_spectral_inversion_t inversion;
134 fe_code_rate_t fec;
135
136 fe_modulation_t modulation;
Darron Broad490c8682008-09-13 19:42:16 -0300137 fe_pilot_t pilot;
138 fe_rolloff_t rolloff;
Steven Toth0d467482008-09-04 01:14:43 -0300139
140 /* Demod values */
141 u8 fec_val;
142 u8 fec_mask;
143 u8 inversion_val;
Darron Broad490c8682008-09-13 19:42:16 -0300144 u8 rolloff_val;
Steven Toth0d467482008-09-04 01:14:43 -0300145};
146
147/* Basic commands that are sent to the firmware */
148struct cx24116_cmd
149{
150 u8 len;
151 u8 args[CX24116_ARGLEN];
152};
153
154struct cx24116_state
155{
156 struct i2c_adapter* i2c;
157 const struct cx24116_config* config;
158
159 struct dvb_frontend frontend;
160
161 struct cx24116_tuning dcur;
162 struct cx24116_tuning dnxt;
163
164 u8 skip_fw_load;
165 u8 burst;
Darron Broad490c8682008-09-13 19:42:16 -0300166 struct cx24116_cmd dsec_cmd;
Steven Toth0d467482008-09-04 01:14:43 -0300167};
168
169static int cx24116_writereg(struct cx24116_state* state, int reg, int data)
170{
171 u8 buf[] = { reg, data };
172 struct i2c_msg msg = { .addr = state->config->demod_address,
173 .flags = 0, .buf = buf, .len = 2 };
174 int err;
175
176 if (debug>1)
177 printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
178 __func__,reg, data);
179
180 if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
181 printk("%s: writereg error(err == %i, reg == 0x%02x,"
182 " value == 0x%02x)\n", __func__, err, reg, data);
183 return -EREMOTEIO;
184 }
185
186 return 0;
187}
188
189/* Bulk byte writes to a single I2C address, for 32k firmware load */
190static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len)
191{
192 int ret = -EREMOTEIO;
193 struct i2c_msg msg;
194 u8 *buf;
195
196 buf = kmalloc(len + 1, GFP_KERNEL);
197 if (buf == NULL) {
198 printk("Unable to kmalloc\n");
199 ret = -ENOMEM;
200 goto error;
201 }
202
203 *(buf) = reg;
204 memcpy(buf + 1, data, len);
205
206 msg.addr = state->config->demod_address;
207 msg.flags = 0;
208 msg.buf = buf;
209 msg.len = len + 1;
210
211 if (debug>1)
212 printk("cx24116: %s: write regN 0x%02x, len = %d\n",
213 __func__,reg, len);
214
215 if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) {
216 printk("%s: writereg error(err == %i, reg == 0x%02x\n",
217 __func__, ret, reg);
218 ret = -EREMOTEIO;
219 }
220
221error:
222 kfree(buf);
223
224 return ret;
225}
226
227static int cx24116_readreg(struct cx24116_state* state, u8 reg)
228{
229 int ret;
230 u8 b0[] = { reg };
231 u8 b1[] = { 0 };
232 struct i2c_msg msg[] = {
233 { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
234 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
235 };
236
237 ret = i2c_transfer(state->i2c, msg, 2);
238
239 if (ret != 2) {
240 printk("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
241 return ret;
242 }
243
244 if (debug>1)
245 printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]);
246
247 return b1[0];
248}
249
250static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_inversion_t inversion)
251{
252 dprintk("%s(%d)\n", __func__, inversion);
253
254 switch (inversion) {
255 case INVERSION_OFF:
256 state->dnxt.inversion_val = 0x00;
257 break;
258 case INVERSION_ON:
259 state->dnxt.inversion_val = 0x04;
260 break;
261 case INVERSION_AUTO:
262 state->dnxt.inversion_val = 0x0C;
263 break;
264 default:
265 return -EINVAL;
266 }
267
268 state->dnxt.inversion = inversion;
269
270 return 0;
271}
272
Darron Broad490c8682008-09-13 19:42:16 -0300273/*
274 * modfec (modulation and FEC)
275 * ===========================
276 *
277 * MOD FEC mask/val standard
278 * ---- -------- ----------- --------
279 * QPSK FEC_1_2 0x02 0x02+X DVB-S
280 * QPSK FEC_2_3 0x04 0x02+X DVB-S
281 * QPSK FEC_3_4 0x08 0x02+X DVB-S
282 * QPSK FEC_4_5 0x10 0x02+X DVB-S (?)
283 * QPSK FEC_5_6 0x20 0x02+X DVB-S
284 * QPSK FEC_6_7 0x40 0x02+X DVB-S
285 * QPSK FEC_7_8 0x80 0x02+X DVB-S
286 * QPSK FEC_8_9 0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
287 * QPSK AUTO 0xff 0x02+X DVB-S
288 *
289 * For DVB-S high byte probably represents FEC
290 * and low byte selects the modulator. The high
291 * byte is search range mask. Bit 5 may turn
292 * on DVB-S and remaining bits represent some
293 * kind of calibration (how/what i do not know).
294 *
295 * Eg.(2/3) szap "Zone Horror"
296 *
297 * mask/val = 0x04, 0x20
298 * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 00000000 | FE_HAS_LOCK
299 *
300 * mask/val = 0x04, 0x30
301 * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
302 *
303 * After tuning FECSTATUS contains actual FEC
304 * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
305 *
306 * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
307 *
308 * NBC-QPSK FEC_1_2 0x00, 0x04 DVB-S2
309 * NBC-QPSK FEC_3_5 0x00, 0x05 DVB-S2
310 * NBC-QPSK FEC_2_3 0x00, 0x06 DVB-S2
311 * NBC-QPSK FEC_3_4 0x00, 0x07 DVB-S2
312 * NBC-QPSK FEC_4_5 0x00, 0x08 DVB-S2
313 * NBC-QPSK FEC_5_6 0x00, 0x09 DVB-S2
314 * NBC-QPSK FEC_8_9 0x00, 0x0a DVB-S2
315 * NBC-QPSK FEC_9_10 0x00, 0x0b DVB-S2
316 *
317 * NBC-8PSK FEC_3_5 0x00, 0x0c DVB-S2
318 * NBC-8PSK FEC_2_3 0x00, 0x0d DVB-S2
319 * NBC-8PSK FEC_3_4 0x00, 0x0e DVB-S2
320 * NBC-8PSK FEC_5_6 0x00, 0x0f DVB-S2
321 * NBC-8PSK FEC_8_9 0x00, 0x10 DVB-S2
322 * NBC-8PSK FEC_9_10 0x00, 0x11 DVB-S2
323 *
324 * For DVB-S2 low bytes selects both modulator
325 * and FEC. High byte is meaningless here. To
326 * set pilot, bit 6 (0x40) is set. When inspecting
327 * FECSTATUS bit 7 (0x80) represents the pilot
328 * selection whilst not tuned. When tuned, actual FEC
329 * in use is found in FECSTATUS as per above. Pilot
330 * value is reset.
331 */
332
Steven Toth0d467482008-09-04 01:14:43 -0300333/* A table of modulation, fec and configuration bytes for the demod.
334 * Not all S2 mmodulation schemes are support and not all rates with
335 * a scheme are support. Especially, no auto detect when in S2 mode.
336 */
337struct cx24116_modfec {
338 fe_modulation_t modulation;
339 fe_code_rate_t fec;
340 u8 mask; /* In DVBS mode this is used to autodetect */
341 u8 val; /* Passed to the firmware to indicate mode selection */
342} CX24116_MODFEC_MODES[] = {
343 /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
Darron Broad490c8682008-09-13 19:42:16 -0300344
345 /*mod fec mask val */
Steven Toth0d467482008-09-04 01:14:43 -0300346 { QPSK, FEC_NONE, 0xfe, 0x30 },
Darron Broad490c8682008-09-13 19:42:16 -0300347 { QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */
348 { QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */
349 { QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */
350 { QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */
351 { QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */
352 { QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */
353 { QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */
354 { QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */
Steven Toth0d467482008-09-04 01:14:43 -0300355 { QPSK, FEC_AUTO, 0xfe, 0x30 },
356 /* NBC-QPSK */
357 { NBC_QPSK, FEC_1_2, 0x00, 0x04 },
358 { NBC_QPSK, FEC_3_5, 0x00, 0x05 },
359 { NBC_QPSK, FEC_2_3, 0x00, 0x06 },
360 { NBC_QPSK, FEC_3_4, 0x00, 0x07 },
361 { NBC_QPSK, FEC_4_5, 0x00, 0x08 },
362 { NBC_QPSK, FEC_5_6, 0x00, 0x09 },
363 { NBC_QPSK, FEC_8_9, 0x00, 0x0a },
364 { NBC_QPSK, FEC_9_10, 0x00, 0x0b },
365 /* 8PSK */
366 { _8PSK, FEC_3_5, 0x00, 0x0c },
367 { _8PSK, FEC_2_3, 0x00, 0x0d },
368 { _8PSK, FEC_3_4, 0x00, 0x0e },
369 { _8PSK, FEC_5_6, 0x00, 0x0f },
Darron Broad490c8682008-09-13 19:42:16 -0300370 { _8PSK, FEC_8_9, 0x00, 0x10 },
Steven Toth0d467482008-09-04 01:14:43 -0300371 { _8PSK, FEC_9_10, 0x00, 0x11 },
Darron Broad490c8682008-09-13 19:42:16 -0300372 /*
373 * `val' can be found in the FECSTATUS register when tuning.
374 * FECSTATUS will give the actual FEC in use if tuning was successful.
375 */
Steven Toth0d467482008-09-04 01:14:43 -0300376};
377
378static int cx24116_lookup_fecmod(struct cx24116_state* state,
379 fe_modulation_t m, fe_code_rate_t f)
380{
381 int i, ret = -EOPNOTSUPP;
382
Darron Broad490c8682008-09-13 19:42:16 -0300383 dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
384
Steven Toth0d467482008-09-04 01:14:43 -0300385 for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++)
386 {
387 if( (m == CX24116_MODFEC_MODES[i].modulation) &&
388 (f == CX24116_MODFEC_MODES[i].fec) )
389 {
390 ret = i;
391 break;
392 }
393 }
394
395 return ret;
396}
397
398static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec)
399{
400 int ret = 0;
Darron Broad490c8682008-09-13 19:42:16 -0300401
402 dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
Steven Toth0d467482008-09-04 01:14:43 -0300403
404 ret = cx24116_lookup_fecmod(state, mod, fec);
405
406 if(ret < 0)
407 return ret;
408
Darron Broad490c8682008-09-13 19:42:16 -0300409 state->dnxt.fec = fec;
Steven Toth0d467482008-09-04 01:14:43 -0300410 state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
411 state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
Darron Broad490c8682008-09-13 19:42:16 -0300412 dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
413 state->dnxt.fec_mask, state->dnxt.fec_val);
Steven Toth0d467482008-09-04 01:14:43 -0300414
415 return 0;
416}
417
418static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate)
419{
Darron Broad490c8682008-09-13 19:42:16 -0300420 dprintk("%s(%d)\n", __func__, rate);
Steven Toth0d467482008-09-04 01:14:43 -0300421
422 /* check if symbol rate is within limits */
Darron Broad490c8682008-09-13 19:42:16 -0300423 if ((rate > state->frontend.ops.info.symbol_rate_max) ||
424 (rate < state->frontend.ops.info.symbol_rate_min)) {
425 dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
426 return -EOPNOTSUPP;
427 }
Steven Toth0d467482008-09-04 01:14:43 -0300428
Darron Broad490c8682008-09-13 19:42:16 -0300429 state->dnxt.symbol_rate = rate;
430 dprintk("%s() symbol_rate = %d\n", __func__, rate);
431
432 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300433}
434
435static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw);
436
437static int cx24116_firmware_ondemand(struct dvb_frontend* fe)
438{
439 struct cx24116_state *state = fe->demodulator_priv;
440 const struct firmware *fw;
441 int ret = 0;
442
443 dprintk("%s()\n",__func__);
444
445 if (cx24116_readreg(state, 0x20) > 0)
446 {
447
448 if (state->skip_fw_load)
449 return 0;
450
451 /* Load firmware */
452 /* request the firmware, this will block until someone uploads it */
453 printk("%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE);
454 ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, &state->i2c->dev);
455 printk("%s: Waiting for firmware upload(2)...\n", __func__);
456 if (ret) {
457 printk("%s: No firmware uploaded (timeout or file not found?)\n", __func__);
458 return ret;
459 }
460
461 /* Make sure we don't recurse back through here during loading */
462 state->skip_fw_load = 1;
463
464 ret = cx24116_load_firmware(fe, fw);
465 if (ret)
466 printk("%s: Writing firmware to device failed\n", __func__);
467
468 release_firmware(fw);
469
470 printk("%s: Firmware upload %s\n", __func__, ret == 0 ? "complete" : "failed");
471
472 /* Ensure firmware is always loaded if required */
473 state->skip_fw_load = 0;
474 }
475
476 return ret;
477}
478
479/* Take a basic firmware command structure, format it and forward it for processing */
480static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd)
481{
482 struct cx24116_state *state = fe->demodulator_priv;
483 int i, ret;
484
485 dprintk("%s()\n", __func__);
486
487 /* Load the firmware if required */
488 if ( (ret = cx24116_firmware_ondemand(fe)) != 0)
489 {
490 printk("%s(): Unable initialise the firmware\n", __func__);
491 return ret;
492 }
493
494 /* Write the command */
495 for(i = 0; i < cmd->len ; i++)
496 {
497 dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
498 cx24116_writereg(state, i, cmd->args[i]);
499 }
500
501 /* Start execution and wait for cmd to terminate */
Darron Broad490c8682008-09-13 19:42:16 -0300502 cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
503 while( cx24116_readreg(state, CX24116_REG_EXECUTE) )
Steven Toth0d467482008-09-04 01:14:43 -0300504 {
505 msleep(10);
506 if(i++ > 64)
507 {
508 /* Avoid looping forever if the firmware does no respond */
509 printk("%s() Firmware not responding\n", __func__);
510 return -EREMOTEIO;
511 }
512 }
513 return 0;
514}
515
516static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
517{
518 struct cx24116_state* state = fe->demodulator_priv;
519 struct cx24116_cmd cmd;
Darron Broad490c8682008-09-13 19:42:16 -0300520 int i, ret;
521 unsigned char vers[4];
Steven Toth0d467482008-09-04 01:14:43 -0300522
523 dprintk("%s\n", __func__);
524 dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n"
525 ,fw->size
526 ,fw->data[0]
527 ,fw->data[1]
528 ,fw->data[ fw->size-2 ]
529 ,fw->data[ fw->size-1 ]
530 );
531
532 /* Toggle 88x SRST pin to reset demod */
533 if (state->config->reset_device)
534 state->config->reset_device(fe);
535
536 /* Begin the firmware load process */
537 /* Prepare the demod, load the firmware, cleanup after load */
Steven Toth0d467482008-09-04 01:14:43 -0300538
Darron Broad490c8682008-09-13 19:42:16 -0300539 /* Init PLL */
540 cx24116_writereg(state, 0xE5, 0x00);
541 cx24116_writereg(state, 0xF1, 0x08);
542 cx24116_writereg(state, 0xF2, 0x13);
543
544 /* Start PLL */
545 cx24116_writereg(state, 0xe0, 0x03);
546 cx24116_writereg(state, 0xe0, 0x00);
547
548 /* Unknown */
549 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
550 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
551
552 /* Unknown */
Steven Toth0d467482008-09-04 01:14:43 -0300553 cx24116_writereg(state, 0xF0, 0x03);
554 cx24116_writereg(state, 0xF4, 0x81);
555 cx24116_writereg(state, 0xF5, 0x00);
556 cx24116_writereg(state, 0xF6, 0x00);
557
558 /* write the entire firmware as one transaction */
559 cx24116_writeregN(state, 0xF7, fw->data, fw->size);
560
561 cx24116_writereg(state, 0xF4, 0x10);
562 cx24116_writereg(state, 0xF0, 0x00);
563 cx24116_writereg(state, 0xF8, 0x06);
564
Darron Broad490c8682008-09-13 19:42:16 -0300565 /* Firmware CMD 10: VCO config */
566 cmd.args[0x00] = CMD_SET_VCO;
Steven Toth0d467482008-09-04 01:14:43 -0300567 cmd.args[0x01] = 0x05;
568 cmd.args[0x02] = 0xdc;
569 cmd.args[0x03] = 0xda;
570 cmd.args[0x04] = 0xae;
571 cmd.args[0x05] = 0xaa;
572 cmd.args[0x06] = 0x04;
573 cmd.args[0x07] = 0x9d;
574 cmd.args[0x08] = 0xfc;
575 cmd.args[0x09] = 0x06;
576 cmd.len= 0x0a;
577 ret = cx24116_cmd_execute(fe, &cmd);
578 if (ret != 0)
579 return ret;
580
Darron Broad490c8682008-09-13 19:42:16 -0300581 cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
Steven Toth0d467482008-09-04 01:14:43 -0300582
Darron Broad490c8682008-09-13 19:42:16 -0300583 /* Firmware CMD 14: Tuner config */
584 cmd.args[0x00] = CMD_TUNERINIT;
Steven Toth0d467482008-09-04 01:14:43 -0300585 cmd.args[0x01] = 0x00;
586 cmd.args[0x02] = 0x00;
587 cmd.len= 0x03;
588 ret = cx24116_cmd_execute(fe, &cmd);
589 if (ret != 0)
590 return ret;
591
592 cx24116_writereg(state, 0xe5, 0x00);
593
Darron Broad490c8682008-09-13 19:42:16 -0300594 /* Firmware CMD 13: MPEG config */
595 cmd.args[0x00] = CMD_MPEGCONFIG;
Steven Toth0d467482008-09-04 01:14:43 -0300596 cmd.args[0x01] = 0x01;
597 cmd.args[0x02] = 0x75;
598 cmd.args[0x03] = 0x00;
Igor M. Liplianincc8c4f32008-09-09 13:57:47 -0300599 if (state->config->mpg_clk_pos_pol)
600 cmd.args[0x04] = state->config->mpg_clk_pos_pol;
601 else
602 cmd.args[0x04] = 0x02;
Steven Toth0d467482008-09-04 01:14:43 -0300603 cmd.args[0x05] = 0x00;
604 cmd.len= 0x06;
605 ret = cx24116_cmd_execute(fe, &cmd);
606 if (ret != 0)
607 return ret;
608
Darron Broad490c8682008-09-13 19:42:16 -0300609 /* Firmware CMD 35: Get firmware version */
610 cmd.args[0x00] = CMD_UPDFWVERS;
611 cmd.len= 0x02;
612 for(i=0; i<4; i++) {
613 cmd.args[0x01] = i;
614 ret = cx24116_cmd_execute(fe, &cmd);
615 if (ret != 0)
616 return ret;
617 vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX);
618 }
619 printk("%s: FW version %i.%i.%i.%i\n", __func__,
620 vers[0], vers[1], vers[2], vers[3]);
621
Steven Toth0d467482008-09-04 01:14:43 -0300622 return 0;
623}
624
625static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
626{
627 /* The isl6421 module will override this function in the fops. */
628 dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__);
629
630 return -EOPNOTSUPP;
631}
632
633static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status)
634{
635 struct cx24116_state *state = fe->demodulator_priv;
636
Darron Broad490c8682008-09-13 19:42:16 -0300637 int lock = cx24116_readreg(state, CX24116_REG_SSTATUS);
Steven Toth0d467482008-09-04 01:14:43 -0300638
639 dprintk("%s: status = 0x%02x\n", __func__, lock);
640
641 *status = 0;
642
Darron Broad490c8682008-09-13 19:42:16 -0300643 if (lock & CX24116_HAS_SIGNAL)
Steven Toth0d467482008-09-04 01:14:43 -0300644 *status |= FE_HAS_SIGNAL;
Darron Broad490c8682008-09-13 19:42:16 -0300645 if (lock & CX24116_HAS_CARRIER)
Steven Toth0d467482008-09-04 01:14:43 -0300646 *status |= FE_HAS_CARRIER;
Darron Broad490c8682008-09-13 19:42:16 -0300647 if (lock & CX24116_HAS_VITERBI)
Steven Toth0d467482008-09-04 01:14:43 -0300648 *status |= FE_HAS_VITERBI;
Darron Broad490c8682008-09-13 19:42:16 -0300649 if (lock & CX24116_HAS_SYNCLOCK)
Steven Toth0d467482008-09-04 01:14:43 -0300650 *status |= FE_HAS_SYNC | FE_HAS_LOCK;
651
652 return 0;
653}
654
Steven Toth0d467482008-09-04 01:14:43 -0300655static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber)
656{
Darron Broad490c8682008-09-13 19:42:16 -0300657 struct cx24116_state *state = fe->demodulator_priv;
658
Steven Toth0d467482008-09-04 01:14:43 -0300659 dprintk("%s()\n", __func__);
Darron Broad490c8682008-09-13 19:42:16 -0300660
661 *ber = ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) |
662 ( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) |
663 ( cx24116_readreg(state, CX24116_REG_BER8 ) << 8 ) |
664 cx24116_readreg(state, CX24116_REG_BER0 );
Steven Toth0d467482008-09-04 01:14:43 -0300665
666 return 0;
667}
668
Darron Broad490c8682008-09-13 19:42:16 -0300669/* TODO Determine function and scale appropriately */
Steven Toth0d467482008-09-04 01:14:43 -0300670static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
671{
672 struct cx24116_state *state = fe->demodulator_priv;
Darron Broad490c8682008-09-13 19:42:16 -0300673 struct cx24116_cmd cmd;
674 int ret;
675 u16 sig_reading;
676
677 dprintk("%s()\n", __func__);
678
679 /* Firmware CMD 19: Get AGC */
680 cmd.args[0x00] = CMD_GETAGC;
681 cmd.len= 0x01;
682 ret = cx24116_cmd_execute(fe, &cmd);
683 if (ret != 0)
684 return ret;
685
686 sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) |
687 ( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 );
688 *signal_strength= 0 - sig_reading;
689
690 dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength);
691
692 return 0;
693}
694
695/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
696static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr)
697{
698 struct cx24116_state *state = fe->demodulator_priv;
699 u8 snr_reading;
700 static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
701 0x00000,0x0199A,0x03333,0x04ccD,0x06667,
702 0x08000,0x0999A,0x0b333,0x0cccD,0x0e667,
Steven Toth0d467482008-09-04 01:14:43 -0300703 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 };
704
705 dprintk("%s()\n", __func__);
706
Darron Broad490c8682008-09-13 19:42:16 -0300707 snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY);
Steven Toth0d467482008-09-04 01:14:43 -0300708
Darron Broad490c8682008-09-13 19:42:16 -0300709 if(snr_reading >= 0xa0 /* 100% */)
710 *snr = 0xffff;
Steven Toth0d467482008-09-04 01:14:43 -0300711 else
Darron Broad490c8682008-09-13 19:42:16 -0300712 *snr = snr_tab [ ( snr_reading & 0xf0 ) >> 4 ] +
713 ( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 );
Steven Toth0d467482008-09-04 01:14:43 -0300714
Darron Broad490c8682008-09-13 19:42:16 -0300715 dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
716 snr_reading, *snr);
Steven Toth0d467482008-09-04 01:14:43 -0300717
718 return 0;
719}
720
Steven Toth0d467482008-09-04 01:14:43 -0300721static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
722{
Darron Broad490c8682008-09-13 19:42:16 -0300723 struct cx24116_state *state = fe->demodulator_priv;
724
Steven Toth0d467482008-09-04 01:14:43 -0300725 dprintk("%s()\n", __func__);
Darron Broad490c8682008-09-13 19:42:16 -0300726
727 *ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) |
728 cx24116_readreg(state, CX24116_REG_UCB0);
Steven Toth0d467482008-09-04 01:14:43 -0300729
730 return 0;
731}
732
733/* Overwrite the current tuning params, we are about to tune */
734static void cx24116_clone_params(struct dvb_frontend* fe)
735{
736 struct cx24116_state *state = fe->demodulator_priv;
737 memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
738}
739
Darron Broad490c8682008-09-13 19:42:16 -0300740/* Wait for LNB */
741static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
742{
743 struct cx24116_state *state = fe->demodulator_priv;
744 int i;
745
746 dprintk("%s() qstatus = 0x%02x\n", __func__,
747 cx24116_readreg(state, CX24116_REG_QSTATUS));
748
749 /* Wait for up to 300 ms */
750 for(i = 0; i < 30 ; i++) {
751 if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
752 return 0;
753 msleep(10);
754 }
755
756 dprintk("%s(): LNB not ready\n", __func__);
757
758 return -ETIMEDOUT; /* -EBUSY ? */
759}
760
Steven Toth0d467482008-09-04 01:14:43 -0300761static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
762{
763 struct cx24116_cmd cmd;
764 int ret;
765
766 dprintk("%s(%d)\n", __func__, tone);
767 if ( (tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF) ) {
768 printk("%s: Invalid, tone=%d\n", __func__, tone);
769 return -EINVAL;
770 }
771
Darron Broad490c8682008-09-13 19:42:16 -0300772 /* Wait for LNB ready */
773 ret = cx24116_wait_for_lnb(fe);
774 if(ret != 0)
775 return ret;
776
777 /* Min delay time after DiSEqC send */
778 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
779
Steven Toth0d467482008-09-04 01:14:43 -0300780 /* This is always done before the tone is set */
781 cmd.args[0x00] = CMD_SET_TONEPRE;
782 cmd.args[0x01] = 0x00;
783 cmd.len= 0x02;
784 ret = cx24116_cmd_execute(fe, &cmd);
785 if (ret != 0)
786 return ret;
787
788 /* Now we set the tone */
789 cmd.args[0x00] = CMD_SET_TONE;
790 cmd.args[0x01] = 0x00;
791 cmd.args[0x02] = 0x00;
792
793 switch (tone) {
794 case SEC_TONE_ON:
795 dprintk("%s: setting tone on\n", __func__);
796 cmd.args[0x03] = 0x01;
797 break;
798 case SEC_TONE_OFF:
799 dprintk("%s: setting tone off\n",__func__);
800 cmd.args[0x03] = 0x00;
801 break;
802 }
803 cmd.len= 0x04;
804
Darron Broad490c8682008-09-13 19:42:16 -0300805 /* Min delay time before DiSEqC send */
806 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
807
Steven Toth0d467482008-09-04 01:14:43 -0300808 return cx24116_cmd_execute(fe, &cmd);
809}
810
811/* Initialise DiSEqC */
812static int cx24116_diseqc_init(struct dvb_frontend* fe)
813{
814 struct cx24116_state *state = fe->demodulator_priv;
Darron Broad490c8682008-09-13 19:42:16 -0300815 struct cx24116_cmd cmd;
816 int ret;
Steven Toth0d467482008-09-04 01:14:43 -0300817
Darron Broad490c8682008-09-13 19:42:16 -0300818 /* Firmware CMD 20: LNB/DiSEqC config */
819 cmd.args[0x00] = CMD_LNBCONFIG;
820 cmd.args[0x01] = 0x00;
821 cmd.args[0x02] = 0x10;
822 cmd.args[0x03] = 0x00;
823 cmd.args[0x04] = 0x8f;
824 cmd.args[0x05] = 0x28;
825 cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
826 cmd.args[0x07] = 0x01;
827 cmd.len= 0x08;
828 ret = cx24116_cmd_execute(fe, &cmd);
829 if (ret != 0)
830 return ret;
831
832 /* Prepare a DiSEqC command */
833 state->dsec_cmd.args[0x00] = CMD_LNBSEND;
834
835 /* DiSEqC burst */
836 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
837
838 /* Unknown */
839 state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
840 state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
841 state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */
842
843 /* DiSEqC message length */
844 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
845
846 /* Command length */
847 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS;
Steven Toth0d467482008-09-04 01:14:43 -0300848
849 return 0;
850}
851
852/* Send DiSEqC message with derived burst (hack) || previous burst */
853static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d)
854{
855 struct cx24116_state *state = fe->demodulator_priv;
Steven Toth0d467482008-09-04 01:14:43 -0300856 int i, ret;
857
858 /* Dump DiSEqC message */
859 if (debug) {
860 printk("cx24116: %s(", __func__);
861 for(i = 0 ; i < d->msg_len ;) {
862 printk("0x%02x", d->msg[i]);
863 if(++i < d->msg_len)
864 printk(", ");
Darron Broad490c8682008-09-13 19:42:16 -0300865 }
866 printk(") toneburst=%d\n", toneburst);
Steven Toth0d467482008-09-04 01:14:43 -0300867 }
868
Darron Broad490c8682008-09-13 19:42:16 -0300869 /* Validate length */
Steven Toth0d467482008-09-04 01:14:43 -0300870 if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
871 return -EINVAL;
872
Steven Toth0d467482008-09-04 01:14:43 -0300873 /* DiSEqC message */
874 for (i = 0; i < d->msg_len; i++)
Darron Broad490c8682008-09-13 19:42:16 -0300875 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
Steven Toth0d467482008-09-04 01:14:43 -0300876
Darron Broad490c8682008-09-13 19:42:16 -0300877 /* DiSEqC message length */
878 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
Steven Toth0d467482008-09-04 01:14:43 -0300879
Darron Broad490c8682008-09-13 19:42:16 -0300880 /* Command length */
881 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
Steven Toth0d467482008-09-04 01:14:43 -0300882
Darron Broad490c8682008-09-13 19:42:16 -0300883 /* DiSEqC toneburst */
884 if(toneburst == CX24116_DISEQC_MESGCACHE)
885 /* Message is cached */
886 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300887
Darron Broad490c8682008-09-13 19:42:16 -0300888 else if(toneburst == CX24116_DISEQC_TONEOFF)
889 /* Message is sent without burst */
890 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
891
892 else if(toneburst == CX24116_DISEQC_TONECACHE) {
893 /*
894 * Message is sent with derived else cached burst
895 *
896 * WRITE PORT GROUP COMMAND 38
897 *
898 * 0/A/A: E0 10 38 F0..F3
899 * 1/B/B: E0 10 38 F4..F7
900 * 2/C/A: E0 10 38 F8..FB
901 * 3/D/B: E0 10 38 FC..FF
902 *
Darron Broad7396d3e2008-09-14 10:45:58 -0300903 * databyte[3]= 8421:8421
Darron Broad490c8682008-09-13 19:42:16 -0300904 * ABCD:WXYZ
905 * CLR :SET
906 *
907 * WX= PORT SELECT 0..3 (X=TONEBURST)
908 * Y = VOLTAGE (0=13V, 1=18V)
909 * Z = BAND (0=LOW, 1=HIGH(22K))
910 */
911 if(d->msg_len >= 4 && d->msg[2] == 0x38)
912 state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2);
913 if(debug)
914 dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]);
915 }
916
917 /* Wait for LNB ready */
918 ret = cx24116_wait_for_lnb(fe);
919 if(ret != 0)
920 return ret;
921
922 /* Wait for voltage/min repeat delay */
923 msleep(100);
924
925 /* Command */
926 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
927 if(ret != 0)
928 return ret;
929 /*
930 * Wait for send
Steven Toth0d467482008-09-04 01:14:43 -0300931 *
932 * Eutelsat spec:
Darron Broad490c8682008-09-13 19:42:16 -0300933 * >15ms delay + (XXX determine if FW does this, see set_tone)
934 * 13.5ms per byte +
935 * >15ms delay +
936 * 12.5ms burst +
937 * >15ms delay (XXX determine if FW does this, see set_tone)
Steven Toth0d467482008-09-04 01:14:43 -0300938 */
Darron Broad490c8682008-09-13 19:42:16 -0300939 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) );
Steven Toth0d467482008-09-04 01:14:43 -0300940
Darron Broad490c8682008-09-13 19:42:16 -0300941 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300942}
943
944/* Send DiSEqC burst */
945static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
946{
947 struct cx24116_state *state = fe->demodulator_priv;
Steven Toth0d467482008-09-04 01:14:43 -0300948 int ret;
949
Darron Broad490c8682008-09-13 19:42:16 -0300950 dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst);
Steven Toth0d467482008-09-04 01:14:43 -0300951
Darron Broad490c8682008-09-13 19:42:16 -0300952 /* DiSEqC burst */
Steven Toth0d467482008-09-04 01:14:43 -0300953 if (burst == SEC_MINI_A)
Darron Broad490c8682008-09-13 19:42:16 -0300954 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
Steven Toth0d467482008-09-04 01:14:43 -0300955 else if(burst == SEC_MINI_B)
Darron Broad490c8682008-09-13 19:42:16 -0300956 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B;
Steven Toth0d467482008-09-04 01:14:43 -0300957 else
958 return -EINVAL;
959
Darron Broad490c8682008-09-13 19:42:16 -0300960 /* DiSEqC toneburst */
961 if(toneburst != CX24116_DISEQC_MESGCACHE)
962 /* Burst is cached */
963 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300964
Darron Broad490c8682008-09-13 19:42:16 -0300965 /* Burst is to be sent with cached message */
Steven Toth0d467482008-09-04 01:14:43 -0300966
Darron Broad490c8682008-09-13 19:42:16 -0300967 /* Wait for LNB ready */
968 ret = cx24116_wait_for_lnb(fe);
969 if(ret != 0)
970 return ret;
Steven Toth0d467482008-09-04 01:14:43 -0300971
Darron Broad490c8682008-09-13 19:42:16 -0300972 /* Wait for voltage/min repeat delay */
973 msleep(100);
Steven Toth0d467482008-09-04 01:14:43 -0300974
Darron Broad490c8682008-09-13 19:42:16 -0300975 /* Command */
976 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
977 if(ret != 0)
978 return ret;
979
980 /*
981 * Wait for send
982 *
983 * Eutelsat spec:
984 * >15ms delay + (XXX determine if FW does this, see set_tone)
985 * 13.5ms per byte +
986 * >15ms delay +
987 * 12.5ms burst +
988 * >15ms delay (XXX determine if FW does this, see set_tone)
989 */
990 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 );
991
992 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300993}
994
995static void cx24116_release(struct dvb_frontend* fe)
996{
997 struct cx24116_state* state = fe->demodulator_priv;
998 dprintk("%s\n",__func__);
999 kfree(state);
1000}
1001
1002static struct dvb_frontend_ops cx24116_ops;
1003
1004struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
1005 struct i2c_adapter* i2c)
1006{
1007 struct cx24116_state* state = NULL;
1008 int ret;
1009
1010 dprintk("%s\n",__func__);
1011
1012 /* allocate memory for the internal state */
1013 state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
1014 if (state == NULL) {
1015 printk("Unable to kmalloc\n");
Darron Broad7396d3e2008-09-14 10:45:58 -03001016 goto error1;
Steven Toth0d467482008-09-04 01:14:43 -03001017 }
1018
1019 /* setup the state */
1020 memset(state, 0, sizeof(struct cx24116_state));
1021
1022 state->config = config;
1023 state->i2c = i2c;
1024
1025 /* check if the demod is present */
1026 ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE);
1027 if (ret != 0x0501) {
1028 printk("Invalid probe, probably not a CX24116 device\n");
Darron Broad7396d3e2008-09-14 10:45:58 -03001029 goto error2;
Steven Toth0d467482008-09-04 01:14:43 -03001030 }
1031
1032 /* create dvb_frontend */
1033 memcpy(&state->frontend.ops, &cx24116_ops, sizeof(struct dvb_frontend_ops));
1034 state->frontend.demodulator_priv = state;
1035 return &state->frontend;
1036
Darron Broad7396d3e2008-09-14 10:45:58 -03001037error2: kfree(state);
Darron Broad490c8682008-09-13 19:42:16 -03001038error1: return NULL;
Steven Toth0d467482008-09-04 01:14:43 -03001039}
Darron Broad490c8682008-09-13 19:42:16 -03001040/*
1041 * Initialise or wake up device
1042 *
1043 * Power config will reset and load initial firmware if required
1044 */
Steven Toth0d467482008-09-04 01:14:43 -03001045static int cx24116_initfe(struct dvb_frontend* fe)
1046{
Darron Broad490c8682008-09-13 19:42:16 -03001047 struct cx24116_state* state = fe->demodulator_priv;
1048 struct cx24116_cmd cmd;
1049 int ret;
1050
Steven Toth0d467482008-09-04 01:14:43 -03001051 dprintk("%s()\n",__func__);
1052
Darron Broad490c8682008-09-13 19:42:16 -03001053 /* Power on */
1054 cx24116_writereg(state, 0xe0, 0);
1055 cx24116_writereg(state, 0xe1, 0);
1056 cx24116_writereg(state, 0xea, 0);
1057
1058 /* Firmware CMD 36: Power config */
1059 cmd.args[0x00] = CMD_TUNERSLEEP;
1060 cmd.args[0x01] = 0;
1061 cmd.len= 0x02;
1062 ret = cx24116_cmd_execute(fe, &cmd);
1063 if(ret != 0)
1064 return ret;
1065
Steven Toth0d467482008-09-04 01:14:43 -03001066 return cx24116_diseqc_init(fe);
1067}
1068
Darron Broad490c8682008-09-13 19:42:16 -03001069/*
1070 * Put device to sleep
1071 */
1072static int cx24116_sleep(struct dvb_frontend* fe)
1073{
1074 struct cx24116_state* state = fe->demodulator_priv;
1075 struct cx24116_cmd cmd;
1076 int ret;
1077
1078 dprintk("%s()\n",__func__);
1079
1080 /* Firmware CMD 36: Power config */
1081 cmd.args[0x00] = CMD_TUNERSLEEP;
1082 cmd.args[0x01] = 1;
1083 cmd.len= 0x02;
1084 ret = cx24116_cmd_execute(fe, &cmd);
1085 if(ret != 0)
1086 return ret;
1087
1088 /* Power off (Shutdown clocks) */
1089 cx24116_writereg(state, 0xea, 0xff);
1090 cx24116_writereg(state, 0xe1, 1);
1091 cx24116_writereg(state, 0xe0, 1);
1092
1093 return 0;
1094}
1095
Steven Tothe7fee0f32008-09-11 10:23:01 -03001096static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp)
Steven Toth0d467482008-09-04 01:14:43 -03001097{
1098 dprintk("%s(..)\n", __func__);
1099 return 0;
1100}
1101
Steven Tothbfbf2da2008-09-12 01:37:37 -03001102static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp)
Steven Toth0d467482008-09-04 01:14:43 -03001103{
Steven Tothbfbf2da2008-09-12 01:37:37 -03001104 dprintk("%s(..)\n", __func__);
Steven Toth0d467482008-09-04 01:14:43 -03001105 return 0;
1106}
1107
1108/* dvb-core told us to tune, the tv property cache will be complete,
1109 * it's safe for is to pull values and use them for tuning purposes.
1110 */
1111static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
1112{
1113 struct cx24116_state *state = fe->demodulator_priv;
Steven Toth56f06802008-09-11 10:19:27 -03001114 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Steven Toth0d467482008-09-04 01:14:43 -03001115 struct cx24116_cmd cmd;
1116 fe_status_t tunerstat;
Darron Broad490c8682008-09-13 19:42:16 -03001117 int i, status, ret, retune = 1;
Steven Toth0d467482008-09-04 01:14:43 -03001118
1119 dprintk("%s()\n",__func__);
1120
1121 state->dnxt.modulation = c->modulation;
1122 state->dnxt.frequency = c->frequency;
1123
Darron Broad490c8682008-09-13 19:42:16 -03001124 switch(c->delivery_system) {
1125 case SYS_DVBS:
1126 dprintk("%s: DVB-S delivery system selected\n",__func__);
1127 state->dnxt.pilot = PILOT_OFF;
Darron Broad7396d3e2008-09-14 10:45:58 -03001128 state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
1129 state->dnxt.rolloff = c->rolloff;
Darron Broad490c8682008-09-13 19:42:16 -03001130 break;
1131 case SYS_DVBS2:
1132 dprintk("%s: DVB-S2 delivery system selected\n",__func__);
1133 if(c->pilot == PILOT_AUTO)
1134 retune++;
1135 state->dnxt.pilot = c->pilot;
1136 switch(c->rolloff) {
1137 case ROLLOFF_20:
1138 state->dnxt.rolloff_val= CX24116_ROLLOFF_020;
1139 break;
1140 case ROLLOFF_25:
1141 state->dnxt.rolloff_val= CX24116_ROLLOFF_025;
1142 break;
1143 case ROLLOFF_35:
1144 state->dnxt.rolloff_val= CX24116_ROLLOFF_035;
1145 break;
1146 case ROLLOFF_AUTO:
1147 return -EOPNOTSUPP;
1148 }
1149 state->dnxt.rolloff = c->rolloff;
1150 break;
1151 default:
1152 dprintk("%s: unsupported delivery system selected (%d)\n",
1153 __func__, c->delivery_system);
1154 return -EOPNOTSUPP;
1155 }
1156
Steven Toth0d467482008-09-04 01:14:43 -03001157 if ((ret = cx24116_set_inversion(state, c->inversion)) != 0)
1158 return ret;
1159
1160 if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) != 0)
1161 return ret;
1162
1163 if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) != 0)
1164 return ret;
1165
1166 /* discard the 'current' tuning parameters and prepare to tune */
1167 cx24116_clone_params(fe);
1168
Darron Broad490c8682008-09-13 19:42:16 -03001169 dprintk("%s: retune = %d\n", __func__, retune);
1170 dprintk("%s: rolloff = %d\n", __func__, state->dcur.rolloff);
1171 dprintk("%s: pilot = %d\n", __func__, state->dcur.pilot);
Steven Toth0d467482008-09-04 01:14:43 -03001172 dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency);
1173 dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
1174 dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
1175 state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
1176 dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__,
1177 state->dcur.inversion, state->dcur.inversion_val);
1178
Darron Broad490c8682008-09-13 19:42:16 -03001179 /* This is also done in advise/acquire on HVR4000 but not on LITE */
Steven Toth0d467482008-09-04 01:14:43 -03001180 if (state->config->set_ts_params)
1181 state->config->set_ts_params(fe, 0);
1182
Darron Broad490c8682008-09-13 19:42:16 -03001183 /* Set/Reset B/W */
1184 cmd.args[0x00] = CMD_BANDWIDTH;
1185 cmd.args[0x01] = 0x01;
1186 cmd.len= 0x02;
1187 ret = cx24116_cmd_execute(fe, &cmd);
1188 if (ret != 0)
1189 return ret;
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001190
Steven Toth0d467482008-09-04 01:14:43 -03001191 /* Prepare a tune request */
1192 cmd.args[0x00] = CMD_TUNEREQUEST;
1193
1194 /* Frequency */
1195 cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
1196 cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
1197 cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
1198
1199 /* Symbol Rate */
1200 cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
1201 cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
1202
1203 /* Automatic Inversion */
1204 cmd.args[0x06] = state->dcur.inversion_val;
1205
1206 /* Modulation / FEC & Pilot Off */
1207 cmd.args[0x07] = state->dcur.fec_val;
1208
Darron Broad490c8682008-09-13 19:42:16 -03001209 if (state->dcur.pilot == PILOT_ON)
1210 cmd.args[0x07] |= CX24116_PILOT;
Steven Toth0d467482008-09-04 01:14:43 -03001211
1212 cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
1213 cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
1214 cmd.args[0x0a] = 0x00;
1215 cmd.args[0x0b] = 0x00;
Darron Broad490c8682008-09-13 19:42:16 -03001216 cmd.args[0x0c] = state->dcur.rolloff_val;
Steven Toth0d467482008-09-04 01:14:43 -03001217 cmd.args[0x0d] = state->dcur.fec_mask;
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001218
Darron Broad490c8682008-09-13 19:42:16 -03001219 if (state->dcur.symbol_rate > 30000000) {
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001220 cmd.args[0x0e] = 0x04;
1221 cmd.args[0x0f] = 0x00;
1222 cmd.args[0x10] = 0x01;
1223 cmd.args[0x11] = 0x77;
1224 cmd.args[0x12] = 0x36;
Darron Broad490c8682008-09-13 19:42:16 -03001225 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
1226 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001227 } else {
1228 cmd.args[0x0e] = 0x06;
1229 cmd.args[0x0f] = 0x00;
1230 cmd.args[0x10] = 0x00;
1231 cmd.args[0x11] = 0xFA;
1232 cmd.args[0x12] = 0x24;
Darron Broad490c8682008-09-13 19:42:16 -03001233 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
1234 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001235 }
1236
Steven Toth0d467482008-09-04 01:14:43 -03001237 cmd.len= 0x13;
1238
1239 /* We need to support pilot and non-pilot tuning in the
1240 * driver automatically. This is a workaround for because
1241 * the demod does not support autodetect.
1242 */
1243 do {
Darron Broad490c8682008-09-13 19:42:16 -03001244 /* Reset status register */
1245 status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK;
1246 cx24116_writereg(state, CX24116_REG_SSTATUS, status);
Steven Toth0d467482008-09-04 01:14:43 -03001247
1248 /* Tune */
1249 ret = cx24116_cmd_execute(fe, &cmd);
1250 if( ret != 0 )
1251 break;
1252
Darron Broad490c8682008-09-13 19:42:16 -03001253 /*
1254 * Wait for up to 500 ms before retrying
1255 *
1256 * If we are able to tune then generally it occurs within 100ms.
1257 * If it takes longer, try a different toneburst setting.
1258 */
1259 for(i = 0; i < 50 ; i++) {
1260 cx24116_read_status(fe, &tunerstat);
1261 status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
1262 if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
1263 dprintk("%s: Tuned\n",__func__);
1264 goto tuned;
1265 }
1266 msleep(10);
Steven Toth0d467482008-09-04 01:14:43 -03001267 }
Darron Broad490c8682008-09-13 19:42:16 -03001268
1269 dprintk("%s: Not tuned\n",__func__);
1270
1271 /* Toggle pilot bit when in auto-pilot */
1272 if(state->dcur.pilot == PILOT_AUTO)
1273 cmd.args[0x07] ^= CX24116_PILOT;
Steven Toth0d467482008-09-04 01:14:43 -03001274 }
1275 while(--retune);
1276
Darron Broad490c8682008-09-13 19:42:16 -03001277tuned: /* Set/Reset B/W */
1278 cmd.args[0x00] = CMD_BANDWIDTH;
1279 cmd.args[0x01] = 0x00;
1280 cmd.len= 0x02;
1281 ret = cx24116_cmd_execute(fe, &cmd);
1282 if (ret != 0)
1283 return ret;
1284
Steven Toth0d467482008-09-04 01:14:43 -03001285 return ret;
1286}
1287
1288static struct dvb_frontend_ops cx24116_ops = {
1289
1290 .info = {
1291 .name = "Conexant CX24116/CX24118",
1292 .type = FE_QPSK,
1293 .frequency_min = 950000,
1294 .frequency_max = 2150000,
1295 .frequency_stepsize = 1011, /* kHz for QPSK frontends */
1296 .frequency_tolerance = 5000,
1297 .symbol_rate_min = 1000000,
1298 .symbol_rate_max = 45000000,
1299 .caps = FE_CAN_INVERSION_AUTO |
1300 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1301 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
1302 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1303 FE_CAN_QPSK | FE_CAN_RECOVER
1304 },
1305
1306 .release = cx24116_release,
1307
1308 .init = cx24116_initfe,
Darron Broad490c8682008-09-13 19:42:16 -03001309 .sleep = cx24116_sleep,
Steven Toth0d467482008-09-04 01:14:43 -03001310 .read_status = cx24116_read_status,
1311 .read_ber = cx24116_read_ber,
1312 .read_signal_strength = cx24116_read_signal_strength,
1313 .read_snr = cx24116_read_snr,
1314 .read_ucblocks = cx24116_read_ucblocks,
1315 .set_tone = cx24116_set_tone,
1316 .set_voltage = cx24116_set_voltage,
1317 .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
1318 .diseqc_send_burst = cx24116_diseqc_send_burst,
1319
1320 .set_property = cx24116_set_property,
Steven Tothbfbf2da2008-09-12 01:37:37 -03001321 .get_property = cx24116_get_property,
Steven Toth0d467482008-09-04 01:14:43 -03001322 .set_frontend = cx24116_set_frontend,
1323};
1324
1325module_param(debug, int, 0644);
1326MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
1327
Darron Broad490c8682008-09-13 19:42:16 -03001328module_param(toneburst, int, 0644);
1329MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)");
1330
Steven Toth0d467482008-09-04 01:14:43 -03001331MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
1332MODULE_AUTHOR("Steven Toth");
1333MODULE_LICENSE("GPL");
1334
1335EXPORT_SYMBOL(cx24116_attach);