blob: 30f82cb0928b3614bc62a2654b7eb7a6291ee243 [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 {
Steven Toth0a6393a2008-10-06 21:06:48 -0300347 fe_delivery_system_t delivery_system;
Steven Toth0d467482008-09-04 01:14:43 -0300348 fe_modulation_t modulation;
349 fe_code_rate_t fec;
350 u8 mask; /* In DVBS mode this is used to autodetect */
351 u8 val; /* Passed to the firmware to indicate mode selection */
352} CX24116_MODFEC_MODES[] = {
353 /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
Darron Broad490c8682008-09-13 19:42:16 -0300354
355 /*mod fec mask val */
Steven Toth0a6393a2008-10-06 21:06:48 -0300356 { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
357 { SYS_DVBS, QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */
358 { SYS_DVBS, QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */
359 { SYS_DVBS, QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */
360 { SYS_DVBS, QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */
361 { SYS_DVBS, QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */
362 { SYS_DVBS, QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */
363 { SYS_DVBS, QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */
364 { SYS_DVBS, QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */
365 { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
Steven Toth0d467482008-09-04 01:14:43 -0300366 /* NBC-QPSK */
Steven Toth0a6393a2008-10-06 21:06:48 -0300367 { SYS_DVBS2, QPSK, FEC_1_2, 0x00, 0x04 },
368 { SYS_DVBS2, QPSK, FEC_3_5, 0x00, 0x05 },
369 { SYS_DVBS2, QPSK, FEC_2_3, 0x00, 0x06 },
370 { SYS_DVBS2, QPSK, FEC_3_4, 0x00, 0x07 },
371 { SYS_DVBS2, QPSK, FEC_4_5, 0x00, 0x08 },
372 { SYS_DVBS2, QPSK, FEC_5_6, 0x00, 0x09 },
373 { SYS_DVBS2, QPSK, FEC_8_9, 0x00, 0x0a },
374 { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
Steven Toth0d467482008-09-04 01:14:43 -0300375 /* 8PSK */
Steven Toth0a6393a2008-10-06 21:06:48 -0300376 { SYS_DVBS2, PSK_8, FEC_3_5, 0x00, 0x0c },
377 { SYS_DVBS2, PSK_8, FEC_2_3, 0x00, 0x0d },
378 { SYS_DVBS2, PSK_8, FEC_3_4, 0x00, 0x0e },
379 { SYS_DVBS2, PSK_8, FEC_5_6, 0x00, 0x0f },
380 { SYS_DVBS2, PSK_8, FEC_8_9, 0x00, 0x10 },
381 { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
Darron Broad490c8682008-09-13 19:42:16 -0300382 /*
383 * `val' can be found in the FECSTATUS register when tuning.
384 * FECSTATUS will give the actual FEC in use if tuning was successful.
385 */
Steven Toth0d467482008-09-04 01:14:43 -0300386};
387
388static int cx24116_lookup_fecmod(struct cx24116_state* state,
389 fe_modulation_t m, fe_code_rate_t f)
390{
391 int i, ret = -EOPNOTSUPP;
392
Darron Broad490c8682008-09-13 19:42:16 -0300393 dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
394
Steven Toth0d467482008-09-04 01:14:43 -0300395 for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++)
396 {
397 if( (m == CX24116_MODFEC_MODES[i].modulation) &&
398 (f == CX24116_MODFEC_MODES[i].fec) )
399 {
400 ret = i;
401 break;
402 }
403 }
404
405 return ret;
406}
407
408static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec)
409{
410 int ret = 0;
Darron Broad490c8682008-09-13 19:42:16 -0300411
412 dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
Steven Toth0d467482008-09-04 01:14:43 -0300413
414 ret = cx24116_lookup_fecmod(state, mod, fec);
415
416 if(ret < 0)
417 return ret;
418
Darron Broad490c8682008-09-13 19:42:16 -0300419 state->dnxt.fec = fec;
Steven Toth0d467482008-09-04 01:14:43 -0300420 state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
421 state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
Darron Broad490c8682008-09-13 19:42:16 -0300422 dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
423 state->dnxt.fec_mask, state->dnxt.fec_val);
Steven Toth0d467482008-09-04 01:14:43 -0300424
425 return 0;
426}
427
428static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate)
429{
Darron Broad490c8682008-09-13 19:42:16 -0300430 dprintk("%s(%d)\n", __func__, rate);
Steven Toth0d467482008-09-04 01:14:43 -0300431
432 /* check if symbol rate is within limits */
Darron Broad490c8682008-09-13 19:42:16 -0300433 if ((rate > state->frontend.ops.info.symbol_rate_max) ||
434 (rate < state->frontend.ops.info.symbol_rate_min)) {
435 dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
436 return -EOPNOTSUPP;
437 }
Steven Toth0d467482008-09-04 01:14:43 -0300438
Darron Broad490c8682008-09-13 19:42:16 -0300439 state->dnxt.symbol_rate = rate;
440 dprintk("%s() symbol_rate = %d\n", __func__, rate);
441
442 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300443}
444
445static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw);
446
447static int cx24116_firmware_ondemand(struct dvb_frontend* fe)
448{
449 struct cx24116_state *state = fe->demodulator_priv;
450 const struct firmware *fw;
451 int ret = 0;
452
453 dprintk("%s()\n",__func__);
454
455 if (cx24116_readreg(state, 0x20) > 0)
456 {
457
458 if (state->skip_fw_load)
459 return 0;
460
461 /* Load firmware */
462 /* request the firmware, this will block until someone uploads it */
463 printk("%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE);
464 ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, &state->i2c->dev);
465 printk("%s: Waiting for firmware upload(2)...\n", __func__);
466 if (ret) {
467 printk("%s: No firmware uploaded (timeout or file not found?)\n", __func__);
468 return ret;
469 }
470
471 /* Make sure we don't recurse back through here during loading */
472 state->skip_fw_load = 1;
473
474 ret = cx24116_load_firmware(fe, fw);
475 if (ret)
476 printk("%s: Writing firmware to device failed\n", __func__);
477
478 release_firmware(fw);
479
480 printk("%s: Firmware upload %s\n", __func__, ret == 0 ? "complete" : "failed");
481
482 /* Ensure firmware is always loaded if required */
483 state->skip_fw_load = 0;
484 }
485
486 return ret;
487}
488
489/* Take a basic firmware command structure, format it and forward it for processing */
490static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd)
491{
492 struct cx24116_state *state = fe->demodulator_priv;
493 int i, ret;
494
495 dprintk("%s()\n", __func__);
496
497 /* Load the firmware if required */
498 if ( (ret = cx24116_firmware_ondemand(fe)) != 0)
499 {
500 printk("%s(): Unable initialise the firmware\n", __func__);
501 return ret;
502 }
503
504 /* Write the command */
505 for(i = 0; i < cmd->len ; i++)
506 {
507 dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
508 cx24116_writereg(state, i, cmd->args[i]);
509 }
510
511 /* Start execution and wait for cmd to terminate */
Darron Broad490c8682008-09-13 19:42:16 -0300512 cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
513 while( cx24116_readreg(state, CX24116_REG_EXECUTE) )
Steven Toth0d467482008-09-04 01:14:43 -0300514 {
515 msleep(10);
516 if(i++ > 64)
517 {
518 /* Avoid looping forever if the firmware does no respond */
519 printk("%s() Firmware not responding\n", __func__);
520 return -EREMOTEIO;
521 }
522 }
523 return 0;
524}
525
526static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
527{
528 struct cx24116_state* state = fe->demodulator_priv;
529 struct cx24116_cmd cmd;
Darron Broad490c8682008-09-13 19:42:16 -0300530 int i, ret;
531 unsigned char vers[4];
Steven Toth0d467482008-09-04 01:14:43 -0300532
533 dprintk("%s\n", __func__);
534 dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n"
535 ,fw->size
536 ,fw->data[0]
537 ,fw->data[1]
538 ,fw->data[ fw->size-2 ]
539 ,fw->data[ fw->size-1 ]
540 );
541
542 /* Toggle 88x SRST pin to reset demod */
543 if (state->config->reset_device)
544 state->config->reset_device(fe);
545
546 /* Begin the firmware load process */
547 /* Prepare the demod, load the firmware, cleanup after load */
Steven Toth0d467482008-09-04 01:14:43 -0300548
Darron Broad490c8682008-09-13 19:42:16 -0300549 /* Init PLL */
550 cx24116_writereg(state, 0xE5, 0x00);
551 cx24116_writereg(state, 0xF1, 0x08);
552 cx24116_writereg(state, 0xF2, 0x13);
553
554 /* Start PLL */
555 cx24116_writereg(state, 0xe0, 0x03);
556 cx24116_writereg(state, 0xe0, 0x00);
557
558 /* Unknown */
559 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
560 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
561
562 /* Unknown */
Steven Toth0d467482008-09-04 01:14:43 -0300563 cx24116_writereg(state, 0xF0, 0x03);
564 cx24116_writereg(state, 0xF4, 0x81);
565 cx24116_writereg(state, 0xF5, 0x00);
566 cx24116_writereg(state, 0xF6, 0x00);
567
568 /* write the entire firmware as one transaction */
569 cx24116_writeregN(state, 0xF7, fw->data, fw->size);
570
571 cx24116_writereg(state, 0xF4, 0x10);
572 cx24116_writereg(state, 0xF0, 0x00);
573 cx24116_writereg(state, 0xF8, 0x06);
574
Darron Broad490c8682008-09-13 19:42:16 -0300575 /* Firmware CMD 10: VCO config */
576 cmd.args[0x00] = CMD_SET_VCO;
Steven Toth0d467482008-09-04 01:14:43 -0300577 cmd.args[0x01] = 0x05;
578 cmd.args[0x02] = 0xdc;
579 cmd.args[0x03] = 0xda;
580 cmd.args[0x04] = 0xae;
581 cmd.args[0x05] = 0xaa;
582 cmd.args[0x06] = 0x04;
583 cmd.args[0x07] = 0x9d;
584 cmd.args[0x08] = 0xfc;
585 cmd.args[0x09] = 0x06;
586 cmd.len= 0x0a;
587 ret = cx24116_cmd_execute(fe, &cmd);
588 if (ret != 0)
589 return ret;
590
Darron Broad490c8682008-09-13 19:42:16 -0300591 cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
Steven Toth0d467482008-09-04 01:14:43 -0300592
Darron Broad490c8682008-09-13 19:42:16 -0300593 /* Firmware CMD 14: Tuner config */
594 cmd.args[0x00] = CMD_TUNERINIT;
Steven Toth0d467482008-09-04 01:14:43 -0300595 cmd.args[0x01] = 0x00;
596 cmd.args[0x02] = 0x00;
597 cmd.len= 0x03;
598 ret = cx24116_cmd_execute(fe, &cmd);
599 if (ret != 0)
600 return ret;
601
602 cx24116_writereg(state, 0xe5, 0x00);
603
Darron Broad490c8682008-09-13 19:42:16 -0300604 /* Firmware CMD 13: MPEG config */
605 cmd.args[0x00] = CMD_MPEGCONFIG;
Steven Toth0d467482008-09-04 01:14:43 -0300606 cmd.args[0x01] = 0x01;
607 cmd.args[0x02] = 0x75;
608 cmd.args[0x03] = 0x00;
Igor M. Liplianincc8c4f32008-09-09 13:57:47 -0300609 if (state->config->mpg_clk_pos_pol)
610 cmd.args[0x04] = state->config->mpg_clk_pos_pol;
611 else
612 cmd.args[0x04] = 0x02;
Steven Toth0d467482008-09-04 01:14:43 -0300613 cmd.args[0x05] = 0x00;
614 cmd.len= 0x06;
615 ret = cx24116_cmd_execute(fe, &cmd);
616 if (ret != 0)
617 return ret;
618
Darron Broad490c8682008-09-13 19:42:16 -0300619 /* Firmware CMD 35: Get firmware version */
620 cmd.args[0x00] = CMD_UPDFWVERS;
621 cmd.len= 0x02;
622 for(i=0; i<4; i++) {
623 cmd.args[0x01] = i;
624 ret = cx24116_cmd_execute(fe, &cmd);
625 if (ret != 0)
626 return ret;
627 vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX);
628 }
629 printk("%s: FW version %i.%i.%i.%i\n", __func__,
630 vers[0], vers[1], vers[2], vers[3]);
631
Steven Toth0d467482008-09-04 01:14:43 -0300632 return 0;
633}
634
635static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
636{
637 /* The isl6421 module will override this function in the fops. */
638 dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__);
639
640 return -EOPNOTSUPP;
641}
642
643static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status)
644{
645 struct cx24116_state *state = fe->demodulator_priv;
646
Darron Broad490c8682008-09-13 19:42:16 -0300647 int lock = cx24116_readreg(state, CX24116_REG_SSTATUS);
Steven Toth0d467482008-09-04 01:14:43 -0300648
649 dprintk("%s: status = 0x%02x\n", __func__, lock);
650
651 *status = 0;
652
Darron Broad490c8682008-09-13 19:42:16 -0300653 if (lock & CX24116_HAS_SIGNAL)
Steven Toth0d467482008-09-04 01:14:43 -0300654 *status |= FE_HAS_SIGNAL;
Darron Broad490c8682008-09-13 19:42:16 -0300655 if (lock & CX24116_HAS_CARRIER)
Steven Toth0d467482008-09-04 01:14:43 -0300656 *status |= FE_HAS_CARRIER;
Darron Broad490c8682008-09-13 19:42:16 -0300657 if (lock & CX24116_HAS_VITERBI)
Steven Toth0d467482008-09-04 01:14:43 -0300658 *status |= FE_HAS_VITERBI;
Darron Broad490c8682008-09-13 19:42:16 -0300659 if (lock & CX24116_HAS_SYNCLOCK)
Steven Toth0d467482008-09-04 01:14:43 -0300660 *status |= FE_HAS_SYNC | FE_HAS_LOCK;
661
662 return 0;
663}
664
Steven Toth0d467482008-09-04 01:14:43 -0300665static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber)
666{
Darron Broad490c8682008-09-13 19:42:16 -0300667 struct cx24116_state *state = fe->demodulator_priv;
668
Steven Toth0d467482008-09-04 01:14:43 -0300669 dprintk("%s()\n", __func__);
Darron Broad490c8682008-09-13 19:42:16 -0300670
671 *ber = ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) |
672 ( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) |
673 ( cx24116_readreg(state, CX24116_REG_BER8 ) << 8 ) |
674 cx24116_readreg(state, CX24116_REG_BER0 );
Steven Toth0d467482008-09-04 01:14:43 -0300675
676 return 0;
677}
678
Darron Broad490c8682008-09-13 19:42:16 -0300679/* TODO Determine function and scale appropriately */
Steven Toth0d467482008-09-04 01:14:43 -0300680static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
681{
682 struct cx24116_state *state = fe->demodulator_priv;
Darron Broad490c8682008-09-13 19:42:16 -0300683 struct cx24116_cmd cmd;
684 int ret;
685 u16 sig_reading;
686
687 dprintk("%s()\n", __func__);
688
689 /* Firmware CMD 19: Get AGC */
690 cmd.args[0x00] = CMD_GETAGC;
691 cmd.len= 0x01;
692 ret = cx24116_cmd_execute(fe, &cmd);
693 if (ret != 0)
694 return ret;
695
696 sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) |
697 ( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 );
698 *signal_strength= 0 - sig_reading;
699
700 dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength);
701
702 return 0;
703}
704
705/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
706static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr)
707{
708 struct cx24116_state *state = fe->demodulator_priv;
709 u8 snr_reading;
710 static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
711 0x00000,0x0199A,0x03333,0x04ccD,0x06667,
712 0x08000,0x0999A,0x0b333,0x0cccD,0x0e667,
Steven Toth0d467482008-09-04 01:14:43 -0300713 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 };
714
715 dprintk("%s()\n", __func__);
716
Darron Broad490c8682008-09-13 19:42:16 -0300717 snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY);
Steven Toth0d467482008-09-04 01:14:43 -0300718
Darron Broad490c8682008-09-13 19:42:16 -0300719 if(snr_reading >= 0xa0 /* 100% */)
720 *snr = 0xffff;
Steven Toth0d467482008-09-04 01:14:43 -0300721 else
Darron Broad490c8682008-09-13 19:42:16 -0300722 *snr = snr_tab [ ( snr_reading & 0xf0 ) >> 4 ] +
723 ( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 );
Steven Toth0d467482008-09-04 01:14:43 -0300724
Darron Broad490c8682008-09-13 19:42:16 -0300725 dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
726 snr_reading, *snr);
Steven Toth0d467482008-09-04 01:14:43 -0300727
728 return 0;
729}
730
Steven Toth0d467482008-09-04 01:14:43 -0300731static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
732{
Darron Broad490c8682008-09-13 19:42:16 -0300733 struct cx24116_state *state = fe->demodulator_priv;
734
Steven Toth0d467482008-09-04 01:14:43 -0300735 dprintk("%s()\n", __func__);
Darron Broad490c8682008-09-13 19:42:16 -0300736
737 *ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) |
738 cx24116_readreg(state, CX24116_REG_UCB0);
Steven Toth0d467482008-09-04 01:14:43 -0300739
740 return 0;
741}
742
743/* Overwrite the current tuning params, we are about to tune */
744static void cx24116_clone_params(struct dvb_frontend* fe)
745{
746 struct cx24116_state *state = fe->demodulator_priv;
747 memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
748}
749
Darron Broad490c8682008-09-13 19:42:16 -0300750/* Wait for LNB */
751static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
752{
753 struct cx24116_state *state = fe->demodulator_priv;
754 int i;
755
756 dprintk("%s() qstatus = 0x%02x\n", __func__,
757 cx24116_readreg(state, CX24116_REG_QSTATUS));
758
759 /* Wait for up to 300 ms */
760 for(i = 0; i < 30 ; i++) {
761 if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
762 return 0;
763 msleep(10);
764 }
765
766 dprintk("%s(): LNB not ready\n", __func__);
767
768 return -ETIMEDOUT; /* -EBUSY ? */
769}
770
Steven Toth0d467482008-09-04 01:14:43 -0300771static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
772{
773 struct cx24116_cmd cmd;
774 int ret;
775
776 dprintk("%s(%d)\n", __func__, tone);
777 if ( (tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF) ) {
778 printk("%s: Invalid, tone=%d\n", __func__, tone);
779 return -EINVAL;
780 }
781
Darron Broad490c8682008-09-13 19:42:16 -0300782 /* Wait for LNB ready */
783 ret = cx24116_wait_for_lnb(fe);
784 if(ret != 0)
785 return ret;
786
787 /* Min delay time after DiSEqC send */
788 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
789
Steven Toth0d467482008-09-04 01:14:43 -0300790 /* This is always done before the tone is set */
791 cmd.args[0x00] = CMD_SET_TONEPRE;
792 cmd.args[0x01] = 0x00;
793 cmd.len= 0x02;
794 ret = cx24116_cmd_execute(fe, &cmd);
795 if (ret != 0)
796 return ret;
797
798 /* Now we set the tone */
799 cmd.args[0x00] = CMD_SET_TONE;
800 cmd.args[0x01] = 0x00;
801 cmd.args[0x02] = 0x00;
802
803 switch (tone) {
804 case SEC_TONE_ON:
805 dprintk("%s: setting tone on\n", __func__);
806 cmd.args[0x03] = 0x01;
807 break;
808 case SEC_TONE_OFF:
809 dprintk("%s: setting tone off\n",__func__);
810 cmd.args[0x03] = 0x00;
811 break;
812 }
813 cmd.len= 0x04;
814
Darron Broad490c8682008-09-13 19:42:16 -0300815 /* Min delay time before DiSEqC send */
816 msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
817
Steven Toth0d467482008-09-04 01:14:43 -0300818 return cx24116_cmd_execute(fe, &cmd);
819}
820
821/* Initialise DiSEqC */
822static int cx24116_diseqc_init(struct dvb_frontend* fe)
823{
824 struct cx24116_state *state = fe->demodulator_priv;
Darron Broad490c8682008-09-13 19:42:16 -0300825 struct cx24116_cmd cmd;
826 int ret;
Steven Toth0d467482008-09-04 01:14:43 -0300827
Darron Broad490c8682008-09-13 19:42:16 -0300828 /* Firmware CMD 20: LNB/DiSEqC config */
829 cmd.args[0x00] = CMD_LNBCONFIG;
830 cmd.args[0x01] = 0x00;
831 cmd.args[0x02] = 0x10;
832 cmd.args[0x03] = 0x00;
833 cmd.args[0x04] = 0x8f;
834 cmd.args[0x05] = 0x28;
835 cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
836 cmd.args[0x07] = 0x01;
837 cmd.len= 0x08;
838 ret = cx24116_cmd_execute(fe, &cmd);
839 if (ret != 0)
840 return ret;
841
842 /* Prepare a DiSEqC command */
843 state->dsec_cmd.args[0x00] = CMD_LNBSEND;
844
845 /* DiSEqC burst */
846 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
847
848 /* Unknown */
849 state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
850 state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
851 state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */
852
853 /* DiSEqC message length */
854 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
855
856 /* Command length */
857 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS;
Steven Toth0d467482008-09-04 01:14:43 -0300858
859 return 0;
860}
861
862/* Send DiSEqC message with derived burst (hack) || previous burst */
863static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d)
864{
865 struct cx24116_state *state = fe->demodulator_priv;
Steven Toth0d467482008-09-04 01:14:43 -0300866 int i, ret;
867
868 /* Dump DiSEqC message */
869 if (debug) {
870 printk("cx24116: %s(", __func__);
871 for(i = 0 ; i < d->msg_len ;) {
872 printk("0x%02x", d->msg[i]);
873 if(++i < d->msg_len)
874 printk(", ");
Darron Broad490c8682008-09-13 19:42:16 -0300875 }
876 printk(") toneburst=%d\n", toneburst);
Steven Toth0d467482008-09-04 01:14:43 -0300877 }
878
Darron Broad490c8682008-09-13 19:42:16 -0300879 /* Validate length */
Steven Toth0d467482008-09-04 01:14:43 -0300880 if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
881 return -EINVAL;
882
Steven Toth0d467482008-09-04 01:14:43 -0300883 /* DiSEqC message */
884 for (i = 0; i < d->msg_len; i++)
Darron Broad490c8682008-09-13 19:42:16 -0300885 state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
Steven Toth0d467482008-09-04 01:14:43 -0300886
Darron Broad490c8682008-09-13 19:42:16 -0300887 /* DiSEqC message length */
888 state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
Steven Toth0d467482008-09-04 01:14:43 -0300889
Darron Broad490c8682008-09-13 19:42:16 -0300890 /* Command length */
891 state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
Steven Toth0d467482008-09-04 01:14:43 -0300892
Darron Broad490c8682008-09-13 19:42:16 -0300893 /* DiSEqC toneburst */
894 if(toneburst == CX24116_DISEQC_MESGCACHE)
895 /* Message is cached */
896 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300897
Darron Broad490c8682008-09-13 19:42:16 -0300898 else if(toneburst == CX24116_DISEQC_TONEOFF)
899 /* Message is sent without burst */
900 state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
901
902 else if(toneburst == CX24116_DISEQC_TONECACHE) {
903 /*
904 * Message is sent with derived else cached burst
905 *
906 * WRITE PORT GROUP COMMAND 38
907 *
908 * 0/A/A: E0 10 38 F0..F3
909 * 1/B/B: E0 10 38 F4..F7
910 * 2/C/A: E0 10 38 F8..FB
911 * 3/D/B: E0 10 38 FC..FF
912 *
Darron Broad7396d3e2008-09-14 10:45:58 -0300913 * databyte[3]= 8421:8421
Darron Broad490c8682008-09-13 19:42:16 -0300914 * ABCD:WXYZ
915 * CLR :SET
916 *
917 * WX= PORT SELECT 0..3 (X=TONEBURST)
918 * Y = VOLTAGE (0=13V, 1=18V)
919 * Z = BAND (0=LOW, 1=HIGH(22K))
920 */
921 if(d->msg_len >= 4 && d->msg[2] == 0x38)
922 state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2);
923 if(debug)
924 dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]);
925 }
926
927 /* Wait for LNB ready */
928 ret = cx24116_wait_for_lnb(fe);
929 if(ret != 0)
930 return ret;
931
932 /* Wait for voltage/min repeat delay */
933 msleep(100);
934
935 /* Command */
936 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
937 if(ret != 0)
938 return ret;
939 /*
940 * Wait for send
Steven Toth0d467482008-09-04 01:14:43 -0300941 *
942 * Eutelsat spec:
Darron Broad490c8682008-09-13 19:42:16 -0300943 * >15ms delay + (XXX determine if FW does this, see set_tone)
944 * 13.5ms per byte +
945 * >15ms delay +
946 * 12.5ms burst +
947 * >15ms delay (XXX determine if FW does this, see set_tone)
Steven Toth0d467482008-09-04 01:14:43 -0300948 */
Darron Broad490c8682008-09-13 19:42:16 -0300949 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) );
Steven Toth0d467482008-09-04 01:14:43 -0300950
Darron Broad490c8682008-09-13 19:42:16 -0300951 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300952}
953
954/* Send DiSEqC burst */
955static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
956{
957 struct cx24116_state *state = fe->demodulator_priv;
Steven Toth0d467482008-09-04 01:14:43 -0300958 int ret;
959
Darron Broad490c8682008-09-13 19:42:16 -0300960 dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst);
Steven Toth0d467482008-09-04 01:14:43 -0300961
Darron Broad490c8682008-09-13 19:42:16 -0300962 /* DiSEqC burst */
Steven Toth0d467482008-09-04 01:14:43 -0300963 if (burst == SEC_MINI_A)
Darron Broad490c8682008-09-13 19:42:16 -0300964 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
Steven Toth0d467482008-09-04 01:14:43 -0300965 else if(burst == SEC_MINI_B)
Darron Broad490c8682008-09-13 19:42:16 -0300966 state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B;
Steven Toth0d467482008-09-04 01:14:43 -0300967 else
968 return -EINVAL;
969
Darron Broad490c8682008-09-13 19:42:16 -0300970 /* DiSEqC toneburst */
971 if(toneburst != CX24116_DISEQC_MESGCACHE)
972 /* Burst is cached */
973 return 0;
Steven Toth0d467482008-09-04 01:14:43 -0300974
Darron Broad490c8682008-09-13 19:42:16 -0300975 /* Burst is to be sent with cached message */
Steven Toth0d467482008-09-04 01:14:43 -0300976
Darron Broad490c8682008-09-13 19:42:16 -0300977 /* Wait for LNB ready */
978 ret = cx24116_wait_for_lnb(fe);
979 if(ret != 0)
980 return ret;
Steven Toth0d467482008-09-04 01:14:43 -0300981
Darron Broad490c8682008-09-13 19:42:16 -0300982 /* Wait for voltage/min repeat delay */
983 msleep(100);
Steven Toth0d467482008-09-04 01:14:43 -0300984
Darron Broad490c8682008-09-13 19:42:16 -0300985 /* Command */
986 ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
987 if(ret != 0)
988 return ret;
989
990 /*
991 * Wait for send
992 *
993 * Eutelsat spec:
994 * >15ms delay + (XXX determine if FW does this, see set_tone)
995 * 13.5ms per byte +
996 * >15ms delay +
997 * 12.5ms burst +
998 * >15ms delay (XXX determine if FW does this, see set_tone)
999 */
1000 msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 );
1001
1002 return 0;
Steven Toth0d467482008-09-04 01:14:43 -03001003}
1004
1005static void cx24116_release(struct dvb_frontend* fe)
1006{
1007 struct cx24116_state* state = fe->demodulator_priv;
1008 dprintk("%s\n",__func__);
1009 kfree(state);
1010}
1011
1012static struct dvb_frontend_ops cx24116_ops;
1013
1014struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
1015 struct i2c_adapter* i2c)
1016{
1017 struct cx24116_state* state = NULL;
1018 int ret;
1019
1020 dprintk("%s\n",__func__);
1021
1022 /* allocate memory for the internal state */
1023 state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
1024 if (state == NULL) {
1025 printk("Unable to kmalloc\n");
Darron Broad7396d3e2008-09-14 10:45:58 -03001026 goto error1;
Steven Toth0d467482008-09-04 01:14:43 -03001027 }
1028
1029 /* setup the state */
1030 memset(state, 0, sizeof(struct cx24116_state));
1031
1032 state->config = config;
1033 state->i2c = i2c;
1034
1035 /* check if the demod is present */
1036 ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE);
1037 if (ret != 0x0501) {
1038 printk("Invalid probe, probably not a CX24116 device\n");
Darron Broad7396d3e2008-09-14 10:45:58 -03001039 goto error2;
Steven Toth0d467482008-09-04 01:14:43 -03001040 }
1041
1042 /* create dvb_frontend */
1043 memcpy(&state->frontend.ops, &cx24116_ops, sizeof(struct dvb_frontend_ops));
1044 state->frontend.demodulator_priv = state;
1045 return &state->frontend;
1046
Darron Broad7396d3e2008-09-14 10:45:58 -03001047error2: kfree(state);
Darron Broad490c8682008-09-13 19:42:16 -03001048error1: return NULL;
Steven Toth0d467482008-09-04 01:14:43 -03001049}
Darron Broad490c8682008-09-13 19:42:16 -03001050/*
1051 * Initialise or wake up device
1052 *
1053 * Power config will reset and load initial firmware if required
1054 */
Steven Toth0d467482008-09-04 01:14:43 -03001055static int cx24116_initfe(struct dvb_frontend* fe)
1056{
Darron Broad490c8682008-09-13 19:42:16 -03001057 struct cx24116_state* state = fe->demodulator_priv;
1058 struct cx24116_cmd cmd;
1059 int ret;
1060
Steven Toth0d467482008-09-04 01:14:43 -03001061 dprintk("%s()\n",__func__);
1062
Darron Broad490c8682008-09-13 19:42:16 -03001063 /* Power on */
1064 cx24116_writereg(state, 0xe0, 0);
1065 cx24116_writereg(state, 0xe1, 0);
1066 cx24116_writereg(state, 0xea, 0);
1067
1068 /* Firmware CMD 36: Power config */
1069 cmd.args[0x00] = CMD_TUNERSLEEP;
1070 cmd.args[0x01] = 0;
1071 cmd.len= 0x02;
1072 ret = cx24116_cmd_execute(fe, &cmd);
1073 if(ret != 0)
1074 return ret;
1075
Steven Toth0d467482008-09-04 01:14:43 -03001076 return cx24116_diseqc_init(fe);
1077}
1078
Darron Broad490c8682008-09-13 19:42:16 -03001079/*
1080 * Put device to sleep
1081 */
1082static int cx24116_sleep(struct dvb_frontend* fe)
1083{
1084 struct cx24116_state* state = fe->demodulator_priv;
1085 struct cx24116_cmd cmd;
1086 int ret;
1087
1088 dprintk("%s()\n",__func__);
1089
1090 /* Firmware CMD 36: Power config */
1091 cmd.args[0x00] = CMD_TUNERSLEEP;
1092 cmd.args[0x01] = 1;
1093 cmd.len= 0x02;
1094 ret = cx24116_cmd_execute(fe, &cmd);
1095 if(ret != 0)
1096 return ret;
1097
1098 /* Power off (Shutdown clocks) */
1099 cx24116_writereg(state, 0xea, 0xff);
1100 cx24116_writereg(state, 0xe1, 1);
1101 cx24116_writereg(state, 0xe0, 1);
1102
1103 return 0;
1104}
1105
Steven Tothe7fee0f32008-09-11 10:23:01 -03001106static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp)
Steven Toth0d467482008-09-04 01:14:43 -03001107{
1108 dprintk("%s(..)\n", __func__);
1109 return 0;
1110}
1111
Steven Tothbfbf2da2008-09-12 01:37:37 -03001112static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp)
Steven Toth0d467482008-09-04 01:14:43 -03001113{
Steven Tothbfbf2da2008-09-12 01:37:37 -03001114 dprintk("%s(..)\n", __func__);
Steven Toth0d467482008-09-04 01:14:43 -03001115 return 0;
1116}
1117
1118/* dvb-core told us to tune, the tv property cache will be complete,
1119 * it's safe for is to pull values and use them for tuning purposes.
1120 */
1121static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
1122{
1123 struct cx24116_state *state = fe->demodulator_priv;
Steven Toth56f06802008-09-11 10:19:27 -03001124 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
Steven Toth0d467482008-09-04 01:14:43 -03001125 struct cx24116_cmd cmd;
1126 fe_status_t tunerstat;
Darron Broad01a8f032008-10-03 11:47:46 -03001127 int i, status, ret, retune;
Steven Toth0d467482008-09-04 01:14:43 -03001128
1129 dprintk("%s()\n",__func__);
1130
Darron Broad490c8682008-09-13 19:42:16 -03001131 switch(c->delivery_system) {
1132 case SYS_DVBS:
1133 dprintk("%s: DVB-S delivery system selected\n",__func__);
Darron Broad01a8f032008-10-03 11:47:46 -03001134
1135 /* Only QPSK is supported for DVB-S */
1136 if(c->modulation != QPSK) {
1137 dprintk("%s: unsupported modulation selected (%d)\n",
1138 __func__, c->modulation);
1139 return -EOPNOTSUPP;
1140 }
1141
1142 /* Pilot doesn't exist in DVB-S, turn bit off */
1143 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1144 retune = 1;
1145
1146 /* DVB-S only supports 0.35 */
1147 if(c->rolloff != ROLLOFF_35) {
1148 dprintk("%s: unsupported rolloff selected (%d)\n",
1149 __func__, c->rolloff);
1150 return -EOPNOTSUPP;
1151 }
Darron Broad7396d3e2008-09-14 10:45:58 -03001152 state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
Darron Broad490c8682008-09-13 19:42:16 -03001153 break;
Darron Broad01a8f032008-10-03 11:47:46 -03001154
Darron Broad490c8682008-09-13 19:42:16 -03001155 case SYS_DVBS2:
1156 dprintk("%s: DVB-S2 delivery system selected\n",__func__);
Darron Broad01a8f032008-10-03 11:47:46 -03001157
1158 /*
1159 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
1160 * but not hardware auto detection
1161 */
Steven Toth0a6393a2008-10-06 21:06:48 -03001162 if(c->modulation != PSK_8 && c->modulation != QPSK) {
Darron Broad01a8f032008-10-03 11:47:46 -03001163 dprintk("%s: unsupported modulation selected (%d)\n",
1164 __func__, c->modulation);
1165 return -EOPNOTSUPP;
1166 }
1167
1168 switch(c->pilot) {
1169 case PILOT_AUTO: /* Not supported but emulated */
1170 retune = 2; /* Fall-through */
1171 case PILOT_OFF:
1172 state->dnxt.pilot_val = CX24116_PILOT_OFF;
1173 break;
1174 case PILOT_ON:
1175 state->dnxt.pilot_val = CX24116_PILOT_ON;
1176 break;
1177 default:
1178 dprintk("%s: unsupported pilot mode selected (%d)\n",
1179 __func__, c->pilot);
1180 return -EOPNOTSUPP;
1181 }
1182
Darron Broad490c8682008-09-13 19:42:16 -03001183 switch(c->rolloff) {
1184 case ROLLOFF_20:
1185 state->dnxt.rolloff_val= CX24116_ROLLOFF_020;
1186 break;
1187 case ROLLOFF_25:
1188 state->dnxt.rolloff_val= CX24116_ROLLOFF_025;
1189 break;
1190 case ROLLOFF_35:
1191 state->dnxt.rolloff_val= CX24116_ROLLOFF_035;
1192 break;
Darron Broad01a8f032008-10-03 11:47:46 -03001193 case ROLLOFF_AUTO: /* Rolloff must be explicit */
1194 default:
1195 dprintk("%s: unsupported rolloff selected (%d)\n",
1196 __func__, c->rolloff);
Darron Broad490c8682008-09-13 19:42:16 -03001197 return -EOPNOTSUPP;
1198 }
Darron Broad490c8682008-09-13 19:42:16 -03001199 break;
Darron Broad01a8f032008-10-03 11:47:46 -03001200
Darron Broad490c8682008-09-13 19:42:16 -03001201 default:
1202 dprintk("%s: unsupported delivery system selected (%d)\n",
1203 __func__, c->delivery_system);
1204 return -EOPNOTSUPP;
1205 }
Darron Broad01a8f032008-10-03 11:47:46 -03001206 state->dnxt.modulation = c->modulation;
1207 state->dnxt.frequency = c->frequency;
1208 state->dnxt.pilot = c->pilot;
1209 state->dnxt.rolloff = c->rolloff;
Darron Broad490c8682008-09-13 19:42:16 -03001210
Steven Toth0d467482008-09-04 01:14:43 -03001211 if ((ret = cx24116_set_inversion(state, c->inversion)) != 0)
1212 return ret;
1213
Darron Broad01a8f032008-10-03 11:47:46 -03001214 /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
Steven Toth0d467482008-09-04 01:14:43 -03001215 if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) != 0)
1216 return ret;
1217
1218 if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) != 0)
1219 return ret;
1220
1221 /* discard the 'current' tuning parameters and prepare to tune */
1222 cx24116_clone_params(fe);
1223
Darron Broad01a8f032008-10-03 11:47:46 -03001224 dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation);
Steven Toth0d467482008-09-04 01:14:43 -03001225 dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency);
Darron Broad01a8f032008-10-03 11:47:46 -03001226 dprintk("%s: pilot = %d (val = 0x%02x)\n", __func__,
1227 state->dcur.pilot, state->dcur.pilot_val);
1228 dprintk("%s: retune = %d\n", __func__, retune);
1229 dprintk("%s: rolloff = %d (val = 0x%02x)\n", __func__,
1230 state->dcur.rolloff, state->dcur.rolloff_val);
Steven Toth0d467482008-09-04 01:14:43 -03001231 dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
1232 dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
1233 state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
1234 dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__,
1235 state->dcur.inversion, state->dcur.inversion_val);
1236
Darron Broad490c8682008-09-13 19:42:16 -03001237 /* This is also done in advise/acquire on HVR4000 but not on LITE */
Steven Toth0d467482008-09-04 01:14:43 -03001238 if (state->config->set_ts_params)
1239 state->config->set_ts_params(fe, 0);
1240
Darron Broad490c8682008-09-13 19:42:16 -03001241 /* Set/Reset B/W */
1242 cmd.args[0x00] = CMD_BANDWIDTH;
1243 cmd.args[0x01] = 0x01;
1244 cmd.len= 0x02;
1245 ret = cx24116_cmd_execute(fe, &cmd);
1246 if (ret != 0)
1247 return ret;
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001248
Steven Toth0d467482008-09-04 01:14:43 -03001249 /* Prepare a tune request */
1250 cmd.args[0x00] = CMD_TUNEREQUEST;
1251
1252 /* Frequency */
1253 cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
1254 cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
1255 cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
1256
1257 /* Symbol Rate */
1258 cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
1259 cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
1260
1261 /* Automatic Inversion */
1262 cmd.args[0x06] = state->dcur.inversion_val;
1263
Darron Broad01a8f032008-10-03 11:47:46 -03001264 /* Modulation / FEC / Pilot */
1265 cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
Steven Toth0d467482008-09-04 01:14:43 -03001266
1267 cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
1268 cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
1269 cmd.args[0x0a] = 0x00;
1270 cmd.args[0x0b] = 0x00;
Darron Broad490c8682008-09-13 19:42:16 -03001271 cmd.args[0x0c] = state->dcur.rolloff_val;
Steven Toth0d467482008-09-04 01:14:43 -03001272 cmd.args[0x0d] = state->dcur.fec_mask;
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001273
Darron Broad490c8682008-09-13 19:42:16 -03001274 if (state->dcur.symbol_rate > 30000000) {
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001275 cmd.args[0x0e] = 0x04;
1276 cmd.args[0x0f] = 0x00;
1277 cmd.args[0x10] = 0x01;
1278 cmd.args[0x11] = 0x77;
1279 cmd.args[0x12] = 0x36;
Darron Broad490c8682008-09-13 19:42:16 -03001280 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
1281 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001282 } else {
1283 cmd.args[0x0e] = 0x06;
1284 cmd.args[0x0f] = 0x00;
1285 cmd.args[0x10] = 0x00;
1286 cmd.args[0x11] = 0xFA;
1287 cmd.args[0x12] = 0x24;
Darron Broad490c8682008-09-13 19:42:16 -03001288 cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
1289 cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
Igor M. Liplianin3f8e51a2008-09-09 13:22:29 -03001290 }
1291
Steven Toth0d467482008-09-04 01:14:43 -03001292 cmd.len= 0x13;
1293
1294 /* We need to support pilot and non-pilot tuning in the
1295 * driver automatically. This is a workaround for because
1296 * the demod does not support autodetect.
1297 */
1298 do {
Darron Broad490c8682008-09-13 19:42:16 -03001299 /* Reset status register */
1300 status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK;
1301 cx24116_writereg(state, CX24116_REG_SSTATUS, status);
Steven Toth0d467482008-09-04 01:14:43 -03001302
1303 /* Tune */
1304 ret = cx24116_cmd_execute(fe, &cmd);
1305 if( ret != 0 )
1306 break;
1307
Darron Broad490c8682008-09-13 19:42:16 -03001308 /*
1309 * Wait for up to 500 ms before retrying
1310 *
1311 * If we are able to tune then generally it occurs within 100ms.
1312 * If it takes longer, try a different toneburst setting.
1313 */
1314 for(i = 0; i < 50 ; i++) {
1315 cx24116_read_status(fe, &tunerstat);
1316 status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
1317 if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
1318 dprintk("%s: Tuned\n",__func__);
1319 goto tuned;
1320 }
1321 msleep(10);
Steven Toth0d467482008-09-04 01:14:43 -03001322 }
Darron Broad490c8682008-09-13 19:42:16 -03001323
1324 dprintk("%s: Not tuned\n",__func__);
1325
1326 /* Toggle pilot bit when in auto-pilot */
1327 if(state->dcur.pilot == PILOT_AUTO)
Darron Broad01a8f032008-10-03 11:47:46 -03001328 cmd.args[0x07] ^= CX24116_PILOT_ON;
Steven Toth0d467482008-09-04 01:14:43 -03001329 }
1330 while(--retune);
1331
Darron Broad490c8682008-09-13 19:42:16 -03001332tuned: /* Set/Reset B/W */
1333 cmd.args[0x00] = CMD_BANDWIDTH;
1334 cmd.args[0x01] = 0x00;
1335 cmd.len= 0x02;
1336 ret = cx24116_cmd_execute(fe, &cmd);
1337 if (ret != 0)
1338 return ret;
1339
Steven Toth0d467482008-09-04 01:14:43 -03001340 return ret;
1341}
1342
1343static struct dvb_frontend_ops cx24116_ops = {
1344
1345 .info = {
1346 .name = "Conexant CX24116/CX24118",
1347 .type = FE_QPSK,
1348 .frequency_min = 950000,
1349 .frequency_max = 2150000,
1350 .frequency_stepsize = 1011, /* kHz for QPSK frontends */
1351 .frequency_tolerance = 5000,
1352 .symbol_rate_min = 1000000,
1353 .symbol_rate_max = 45000000,
1354 .caps = FE_CAN_INVERSION_AUTO |
1355 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1356 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
1357 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1358 FE_CAN_QPSK | FE_CAN_RECOVER
1359 },
1360
1361 .release = cx24116_release,
1362
1363 .init = cx24116_initfe,
Darron Broad490c8682008-09-13 19:42:16 -03001364 .sleep = cx24116_sleep,
Steven Toth0d467482008-09-04 01:14:43 -03001365 .read_status = cx24116_read_status,
1366 .read_ber = cx24116_read_ber,
1367 .read_signal_strength = cx24116_read_signal_strength,
1368 .read_snr = cx24116_read_snr,
1369 .read_ucblocks = cx24116_read_ucblocks,
1370 .set_tone = cx24116_set_tone,
1371 .set_voltage = cx24116_set_voltage,
1372 .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
1373 .diseqc_send_burst = cx24116_diseqc_send_burst,
1374
1375 .set_property = cx24116_set_property,
Steven Tothbfbf2da2008-09-12 01:37:37 -03001376 .get_property = cx24116_get_property,
Steven Toth0d467482008-09-04 01:14:43 -03001377 .set_frontend = cx24116_set_frontend,
1378};
1379
1380module_param(debug, int, 0644);
1381MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
1382
Darron Broad490c8682008-09-13 19:42:16 -03001383module_param(toneburst, int, 0644);
1384MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)");
1385
Steven Toth0d467482008-09-04 01:14:43 -03001386MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
1387MODULE_AUTHOR("Steven Toth");
1388MODULE_LICENSE("GPL");
1389
1390EXPORT_SYMBOL(cx24116_attach);