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