blob: 44ec5b9a469580b943c3f92ca1bcbfd6163f6171 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 Driver for Spase SP8870 demodulator
3
4 Copyright (C) 1999 Juergen Peitz
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21*/
22/*
23 * This driver needs external firmware. Please use the command
24 * "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to
Ville Skytt\รค12e66f62006-01-09 15:25:38 -020025 * download/extract it, and then copy it to /usr/lib/hotplug/firmware
26 * or /lib/firmware (depending on configuration of firmware hotplug).
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 */
28#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
29
30#include <linux/init.h>
31#include <linux/module.h>
32#include <linux/moduleparam.h>
33#include <linux/device.h>
34#include <linux/firmware.h>
35#include <linux/delay.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080036#include <linux/string.h>
37#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
39#include "dvb_frontend.h"
40#include "sp8870.h"
41
42
43struct sp8870_state {
44
45 struct i2c_adapter* i2c;
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 const struct sp8870_config* config;
48
49 struct dvb_frontend frontend;
50
51 /* demodulator private data */
52 u8 initialised:1;
53};
54
55static int debug;
56#define dprintk(args...) \
57 do { \
58 if (debug) printk(KERN_DEBUG "sp8870: " args); \
59 } while (0)
60
61/* firmware size for sp8870 */
62#define SP8870_FIRMWARE_SIZE 16382
63
64/* starting point for firmware in file 'Sc_main.mc' */
65#define SP8870_FIRMWARE_OFFSET 0x0A
66
67static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
68{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -080069 u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 4 };
71 int err;
72
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -080073 if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
75 return -EREMOTEIO;
76 }
77
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -080078 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070079}
80
81static int sp8870_readreg (struct sp8870_state* state, u16 reg)
82{
83 int ret;
84 u8 b0 [] = { reg >> 8 , reg & 0xff };
85 u8 b1 [] = { 0, 0 };
86 struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
87 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
88
89 ret = i2c_transfer (state->i2c, msg, 2);
90
91 if (ret != 2) {
92 dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
93 return -1;
94 }
95
96 return (b1[0] << 8 | b1[1]);
97}
98
99static int sp8870_firmware_upload (struct sp8870_state* state, const struct firmware *fw)
100{
101 struct i2c_msg msg;
102 char *fw_buf = fw->data;
103 int fw_pos;
104 u8 tx_buf[255];
105 int tx_len;
106 int err = 0;
107
108 dprintk ("%s: ...\n", __FUNCTION__);
109
110 if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
111 return -EINVAL;
112
113 // system controller stop
114 sp8870_writereg(state, 0x0F00, 0x0000);
115
116 // instruction RAM register hiword
117 sp8870_writereg(state, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
118
119 // instruction RAM MWR
120 sp8870_writereg(state, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
121
122 // do firmware upload
123 fw_pos = SP8870_FIRMWARE_OFFSET;
124 while (fw_pos < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET){
125 tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - 252) ? 252 : SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - fw_pos;
126 // write register 0xCF0A
127 tx_buf[0] = 0xCF;
128 tx_buf[1] = 0x0A;
129 memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
130 msg.addr = state->config->demod_address;
131 msg.flags = 0;
132 msg.buf = tx_buf;
133 msg.len = tx_len + 2;
134 if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
135 printk("%s: firmware upload failed!\n", __FUNCTION__);
136 printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
137 return err;
138 }
139 fw_pos += tx_len;
140 }
141
142 dprintk ("%s: done!\n", __FUNCTION__);
143 return 0;
144};
145
146static void sp8870_microcontroller_stop (struct sp8870_state* state)
147{
148 sp8870_writereg(state, 0x0F08, 0x000);
149 sp8870_writereg(state, 0x0F09, 0x000);
150
151 // microcontroller STOP
152 sp8870_writereg(state, 0x0F00, 0x000);
153}
154
155static void sp8870_microcontroller_start (struct sp8870_state* state)
156{
157 sp8870_writereg(state, 0x0F08, 0x000);
158 sp8870_writereg(state, 0x0F09, 0x000);
159
160 // microcontroller START
161 sp8870_writereg(state, 0x0F00, 0x001);
162 // not documented but if we don't read 0x0D01 out here
163 // we don't get a correct data valid signal
164 sp8870_readreg(state, 0x0D01);
165}
166
167static int sp8870_read_data_valid_signal(struct sp8870_state* state)
168{
169 return (sp8870_readreg(state, 0x0D02) > 0);
170}
171
172static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
173{
174 int known_parameters = 1;
175
176 *reg0xc05 = 0x000;
177
178 switch (p->u.ofdm.constellation) {
179 case QPSK:
180 break;
181 case QAM_16:
182 *reg0xc05 |= (1 << 10);
183 break;
184 case QAM_64:
185 *reg0xc05 |= (2 << 10);
186 break;
187 case QAM_AUTO:
188 known_parameters = 0;
189 break;
190 default:
191 return -EINVAL;
192 };
193
194 switch (p->u.ofdm.hierarchy_information) {
195 case HIERARCHY_NONE:
196 break;
197 case HIERARCHY_1:
198 *reg0xc05 |= (1 << 7);
199 break;
200 case HIERARCHY_2:
201 *reg0xc05 |= (2 << 7);
202 break;
203 case HIERARCHY_4:
204 *reg0xc05 |= (3 << 7);
205 break;
206 case HIERARCHY_AUTO:
207 known_parameters = 0;
208 break;
209 default:
210 return -EINVAL;
211 };
212
213 switch (p->u.ofdm.code_rate_HP) {
214 case FEC_1_2:
215 break;
216 case FEC_2_3:
217 *reg0xc05 |= (1 << 3);
218 break;
219 case FEC_3_4:
220 *reg0xc05 |= (2 << 3);
221 break;
222 case FEC_5_6:
223 *reg0xc05 |= (3 << 3);
224 break;
225 case FEC_7_8:
226 *reg0xc05 |= (4 << 3);
227 break;
228 case FEC_AUTO:
229 known_parameters = 0;
230 break;
231 default:
232 return -EINVAL;
233 };
234
235 if (known_parameters)
236 *reg0xc05 |= (2 << 1); /* use specified parameters */
237 else
238 *reg0xc05 |= (1 << 1); /* enable autoprobing */
239
240 return 0;
241}
242
243static int sp8870_wake_up(struct sp8870_state* state)
244{
245 // enable TS output and interface pins
246 return sp8870_writereg(state, 0xC18, 0x00D);
247}
248
249static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
250 struct dvb_frontend_parameters *p)
251{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700252 struct sp8870_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 int err;
254 u16 reg0xc05;
255
256 if ((err = configure_reg0xc05(p, &reg0xc05)))
257 return err;
258
259 // system controller stop
260 sp8870_microcontroller_stop(state);
261
262 // set tuner parameters
Patrick Boettcherdea74862006-05-14 05:01:31 -0300263 if (fe->ops.tuner_ops.set_params) {
264 fe->ops.tuner_ops.set_params(fe, p);
265 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
Andrew de Quinceye9f9c0d2006-04-18 17:47:10 -0300266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
268 // sample rate correction bit [23..17]
269 sp8870_writereg(state, 0x0319, 0x000A);
270
271 // sample rate correction bit [16..0]
272 sp8870_writereg(state, 0x031A, 0x0AAB);
273
274 // integer carrier offset
275 sp8870_writereg(state, 0x0309, 0x0400);
276
277 // fractional carrier offset
278 sp8870_writereg(state, 0x030A, 0x0000);
279
280 // filter for 6/7/8 Mhz channel
281 if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
282 sp8870_writereg(state, 0x0311, 0x0002);
283 else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
284 sp8870_writereg(state, 0x0311, 0x0001);
285 else
286 sp8870_writereg(state, 0x0311, 0x0000);
287
288 // scan order: 2k first = 0x0000, 8k first = 0x0001
289 if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)
290 sp8870_writereg(state, 0x0338, 0x0000);
291 else
292 sp8870_writereg(state, 0x0338, 0x0001);
293
294 sp8870_writereg(state, 0xc05, reg0xc05);
295
296 // read status reg in order to clear pending irqs
297 sp8870_readreg(state, 0x200);
298
299 // system controller start
300 sp8870_microcontroller_start(state);
301
302 return 0;
303}
304
305static int sp8870_init (struct dvb_frontend* fe)
306{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700307 struct sp8870_state* state = fe->demodulator_priv;
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800308 const struct firmware *fw = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
310 sp8870_wake_up(state);
311 if (state->initialised) return 0;
312 state->initialised = 1;
313
314 dprintk ("%s\n", __FUNCTION__);
315
316
317 /* request the firmware, this will block until someone uploads it */
318 printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE);
319 if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) {
320 printk("sp8870: no firmware upload (timeout or file not found?)\n");
321 release_firmware(fw);
322 return -EIO;
323 }
324
325 if (sp8870_firmware_upload(state, fw)) {
326 printk("sp8870: writing firmware to device failed\n");
327 release_firmware(fw);
328 return -EIO;
329 }
330 printk("sp8870: firmware upload complete\n");
331
332 /* enable TS output and interface pins */
333 sp8870_writereg(state, 0xc18, 0x00d);
334
335 // system controller stop
336 sp8870_microcontroller_stop(state);
337
338 // ADC mode
339 sp8870_writereg(state, 0x0301, 0x0003);
340
341 // Reed Solomon parity bytes passed to output
342 sp8870_writereg(state, 0x0C13, 0x0001);
343
344 // MPEG clock is suppressed if no valid data
345 sp8870_writereg(state, 0x0C14, 0x0001);
346
347 /* bit 0x010: enable data valid signal */
348 sp8870_writereg(state, 0x0D00, 0x010);
349 sp8870_writereg(state, 0x0D01, 0x000);
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 return 0;
352}
353
354static int sp8870_read_status (struct dvb_frontend* fe, fe_status_t * fe_status)
355{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700356 struct sp8870_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 int status;
358 int signal;
359
360 *fe_status = 0;
361
362 status = sp8870_readreg (state, 0x0200);
363 if (status < 0)
364 return -EIO;
365
366 signal = sp8870_readreg (state, 0x0303);
367 if (signal < 0)
368 return -EIO;
369
370 if (signal > 0x0F)
371 *fe_status |= FE_HAS_SIGNAL;
372 if (status & 0x08)
373 *fe_status |= FE_HAS_SYNC;
374 if (status & 0x04)
375 *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
376
377 return 0;
378}
379
380static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
381{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700382 struct sp8870_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 int ret;
384 u32 tmp;
385
386 *ber = 0;
387
388 ret = sp8870_readreg(state, 0xC08);
389 if (ret < 0)
390 return -EIO;
391
392 tmp = ret & 0x3F;
393
394 ret = sp8870_readreg(state, 0xC07);
395 if (ret < 0)
396 return -EIO;
397
398 tmp = ret << 6;
399
400 if (tmp >= 0x3FFF0)
401 tmp = ~0;
402
403 *ber = tmp;
404
405 return 0;
406}
407
408static int sp8870_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
409{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700410 struct sp8870_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 int ret;
412 u16 tmp;
413
414 *signal = 0;
415
416 ret = sp8870_readreg (state, 0x306);
417 if (ret < 0)
418 return -EIO;
419
420 tmp = ret << 8;
421
422 ret = sp8870_readreg (state, 0x303);
423 if (ret < 0)
424 return -EIO;
425
426 tmp |= ret;
427
428 if (tmp)
429 *signal = 0xFFFF - tmp;
430
431 return 0;
432}
433
434static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks)
435{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700436 struct sp8870_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 int ret;
438
439 *ublocks = 0;
440
441 ret = sp8870_readreg(state, 0xC0C);
442 if (ret < 0)
443 return -EIO;
444
445 if (ret == 0xFFFF)
446 ret = ~0;
447
448 *ublocks = ret;
449
450 return 0;
451}
452
453// number of trials to recover from lockup
454#define MAXTRIALS 5
455// maximum checks for data valid signal
456#define MAXCHECKS 100
457
458// only for debugging: counter for detected lockups
459static int lockups = 0;
460// only for debugging: counter for channel switches
461static int switches = 0;
462
463static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
464{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700465 struct sp8870_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
467 /*
468 The firmware of the sp8870 sometimes locks up after setting frontend parameters.
469 We try to detect this by checking the data valid signal.
470 If it is not set after MAXCHECKS we try to recover the lockup by setting
471 the frontend parameters again.
472 */
473
474 int err = 0;
475 int valid = 0;
476 int trials = 0;
477 int check_count = 0;
478
479 dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
480
481 for (trials = 1; trials <= MAXTRIALS; trials++) {
482
483 if ((err = sp8870_set_frontend_parameters(fe, p)))
484 return err;
485
486 for (check_count = 0; check_count < MAXCHECKS; check_count++) {
487// valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
488 valid = sp8870_read_data_valid_signal(state);
489 if (valid) {
490 dprintk("%s: delay = %i usec\n",
491 __FUNCTION__, check_count * 10);
492 break;
493 }
494 udelay(10);
495 }
496 if (valid)
497 break;
498 }
499
500 if (!valid) {
501 printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
502 return -EIO;
503 }
504
505 if (debug) {
506 if (valid) {
507 if (trials > 1) {
508 printk("%s: firmware lockup!!!\n", __FUNCTION__);
509 printk("%s: recovered after %i trial(s))\n", __FUNCTION__, trials - 1);
510 lockups++;
511 }
512 }
513 switches++;
514 printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
515 }
516
517 return 0;
518}
519
520static int sp8870_sleep(struct dvb_frontend* fe)
521{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700522 struct sp8870_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
524 // tristate TS output and disable interface pins
525 return sp8870_writereg(state, 0xC18, 0x000);
526}
527
528static int sp8870_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
529{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800530 fesettings->min_delay_ms = 350;
531 fesettings->step_size = 0;
532 fesettings->max_drift = 0;
533 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534}
535
Andrew de Quinceye9f9c0d2006-04-18 17:47:10 -0300536static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
537{
538 struct sp8870_state* state = fe->demodulator_priv;
539
540 if (enable) {
541 return sp8870_writereg(state, 0x206, 0x001);
542 } else {
543 return sp8870_writereg(state, 0x206, 0x000);
544 }
545}
546
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547static void sp8870_release(struct dvb_frontend* fe)
548{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700549 struct sp8870_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 kfree(state);
551}
552
553static struct dvb_frontend_ops sp8870_ops;
554
555struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
556 struct i2c_adapter* i2c)
557{
558 struct sp8870_state* state = NULL;
559
560 /* allocate memory for the internal state */
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700561 state = kmalloc(sizeof(struct sp8870_state), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 if (state == NULL) goto error;
563
564 /* setup the state */
565 state->config = config;
566 state->i2c = i2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 state->initialised = 0;
568
569 /* check if the demod is there */
570 if (sp8870_readreg(state, 0x0200) < 0) goto error;
571
572 /* create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300573 memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 state->frontend.demodulator_priv = state;
575 return &state->frontend;
576
577error:
578 kfree(state);
579 return NULL;
580}
581
582static struct dvb_frontend_ops sp8870_ops = {
583
584 .info = {
585 .name = "Spase SP8870 DVB-T",
586 .type = FE_OFDM,
587 .frequency_min = 470000000,
588 .frequency_max = 860000000,
589 .frequency_stepsize = 166666,
590 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
591 FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
592 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
593 FE_CAN_QPSK | FE_CAN_QAM_16 |
594 FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
595 FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER
596 },
597
598 .release = sp8870_release,
599
600 .init = sp8870_init,
601 .sleep = sp8870_sleep,
Andrew de Quinceye9f9c0d2006-04-18 17:47:10 -0300602 .i2c_gate_ctrl = sp8870_i2c_gate_ctrl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
604 .set_frontend = sp8870_set_frontend,
605 .get_tune_settings = sp8870_get_tune_settings,
606
607 .read_status = sp8870_read_status,
608 .read_ber = sp8870_read_ber,
609 .read_signal_strength = sp8870_read_signal_strength,
610 .read_ucblocks = sp8870_read_uncorrected_blocks,
611};
612
613module_param(debug, int, 0644);
614MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
615
616MODULE_DESCRIPTION("Spase SP8870 DVB-T Demodulator driver");
617MODULE_AUTHOR("Juergen Peitz");
618MODULE_LICENSE("GPL");
619
620EXPORT_SYMBOL(sp8870_attach);