10fcb8677SHans Verkuil // SPDX-License-Identifier: GPL-2.0-or-later
20fcb8677SHans Verkuil /*
30fcb8677SHans Verkuil Driver for Spase SP8870 demodulator
40fcb8677SHans Verkuil
50fcb8677SHans Verkuil Copyright (C) 1999 Juergen Peitz
60fcb8677SHans Verkuil
70fcb8677SHans Verkuil
80fcb8677SHans Verkuil */
90fcb8677SHans Verkuil /*
100fcb8677SHans Verkuil * This driver needs external firmware. Please use the command
110fcb8677SHans Verkuil * "<kerneldir>/scripts/get_dvb_firmware alps_tdlb7" to
120fcb8677SHans Verkuil * download/extract it, and then copy it to /usr/lib/hotplug/firmware
130fcb8677SHans Verkuil * or /lib/firmware (depending on configuration of firmware hotplug).
140fcb8677SHans Verkuil */
150fcb8677SHans Verkuil #define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
160fcb8677SHans Verkuil
170fcb8677SHans Verkuil #include <linux/init.h>
180fcb8677SHans Verkuil #include <linux/module.h>
190fcb8677SHans Verkuil #include <linux/device.h>
200fcb8677SHans Verkuil #include <linux/firmware.h>
210fcb8677SHans Verkuil #include <linux/delay.h>
220fcb8677SHans Verkuil #include <linux/string.h>
230fcb8677SHans Verkuil #include <linux/slab.h>
240fcb8677SHans Verkuil
250fcb8677SHans Verkuil #include <media/dvb_frontend.h>
260fcb8677SHans Verkuil #include "sp8870.h"
270fcb8677SHans Verkuil
280fcb8677SHans Verkuil
290fcb8677SHans Verkuil struct sp8870_state {
300fcb8677SHans Verkuil
310fcb8677SHans Verkuil struct i2c_adapter* i2c;
320fcb8677SHans Verkuil
330fcb8677SHans Verkuil const struct sp8870_config* config;
340fcb8677SHans Verkuil
350fcb8677SHans Verkuil struct dvb_frontend frontend;
360fcb8677SHans Verkuil
370fcb8677SHans Verkuil /* demodulator private data */
380fcb8677SHans Verkuil u8 initialised:1;
390fcb8677SHans Verkuil };
400fcb8677SHans Verkuil
410fcb8677SHans Verkuil static int debug;
420fcb8677SHans Verkuil #define dprintk(args...) \
430fcb8677SHans Verkuil do { \
440fcb8677SHans Verkuil if (debug) printk(KERN_DEBUG "sp8870: " args); \
450fcb8677SHans Verkuil } while (0)
460fcb8677SHans Verkuil
470fcb8677SHans Verkuil /* firmware size for sp8870 */
480fcb8677SHans Verkuil #define SP8870_FIRMWARE_SIZE 16382
490fcb8677SHans Verkuil
500fcb8677SHans Verkuil /* starting point for firmware in file 'Sc_main.mc' */
510fcb8677SHans Verkuil #define SP8870_FIRMWARE_OFFSET 0x0A
520fcb8677SHans Verkuil
sp8870_writereg(struct sp8870_state * state,u16 reg,u16 data)530fcb8677SHans Verkuil static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
540fcb8677SHans Verkuil {
550fcb8677SHans Verkuil u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
560fcb8677SHans Verkuil struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 4 };
570fcb8677SHans Verkuil int err;
580fcb8677SHans Verkuil
590fcb8677SHans Verkuil if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
600fcb8677SHans Verkuil dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
610fcb8677SHans Verkuil return -EREMOTEIO;
620fcb8677SHans Verkuil }
630fcb8677SHans Verkuil
640fcb8677SHans Verkuil return 0;
650fcb8677SHans Verkuil }
660fcb8677SHans Verkuil
sp8870_readreg(struct sp8870_state * state,u16 reg)670fcb8677SHans Verkuil static int sp8870_readreg (struct sp8870_state* state, u16 reg)
680fcb8677SHans Verkuil {
690fcb8677SHans Verkuil int ret;
700fcb8677SHans Verkuil u8 b0 [] = { reg >> 8 , reg & 0xff };
710fcb8677SHans Verkuil u8 b1 [] = { 0, 0 };
720fcb8677SHans Verkuil struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
730fcb8677SHans Verkuil { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
740fcb8677SHans Verkuil
750fcb8677SHans Verkuil ret = i2c_transfer (state->i2c, msg, 2);
760fcb8677SHans Verkuil
770fcb8677SHans Verkuil if (ret != 2) {
780fcb8677SHans Verkuil dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
790fcb8677SHans Verkuil return -1;
800fcb8677SHans Verkuil }
810fcb8677SHans Verkuil
820fcb8677SHans Verkuil return (b1[0] << 8 | b1[1]);
830fcb8677SHans Verkuil }
840fcb8677SHans Verkuil
sp8870_firmware_upload(struct sp8870_state * state,const struct firmware * fw)850fcb8677SHans Verkuil static int sp8870_firmware_upload (struct sp8870_state* state, const struct firmware *fw)
860fcb8677SHans Verkuil {
870fcb8677SHans Verkuil struct i2c_msg msg;
880fcb8677SHans Verkuil const char *fw_buf = fw->data;
890fcb8677SHans Verkuil int fw_pos;
900fcb8677SHans Verkuil u8 tx_buf[255];
910fcb8677SHans Verkuil int tx_len;
920fcb8677SHans Verkuil int err = 0;
930fcb8677SHans Verkuil
940fcb8677SHans Verkuil dprintk ("%s: ...\n", __func__);
950fcb8677SHans Verkuil
960fcb8677SHans Verkuil if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
970fcb8677SHans Verkuil return -EINVAL;
980fcb8677SHans Verkuil
990fcb8677SHans Verkuil // system controller stop
1000fcb8677SHans Verkuil sp8870_writereg(state, 0x0F00, 0x0000);
1010fcb8677SHans Verkuil
1020fcb8677SHans Verkuil // instruction RAM register hiword
1030fcb8677SHans Verkuil sp8870_writereg(state, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
1040fcb8677SHans Verkuil
1050fcb8677SHans Verkuil // instruction RAM MWR
1060fcb8677SHans Verkuil sp8870_writereg(state, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
1070fcb8677SHans Verkuil
1080fcb8677SHans Verkuil // do firmware upload
1090fcb8677SHans Verkuil fw_pos = SP8870_FIRMWARE_OFFSET;
1100fcb8677SHans Verkuil while (fw_pos < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET){
1110fcb8677SHans Verkuil tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - 252) ? 252 : SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - fw_pos;
1120fcb8677SHans Verkuil // write register 0xCF0A
1130fcb8677SHans Verkuil tx_buf[0] = 0xCF;
1140fcb8677SHans Verkuil tx_buf[1] = 0x0A;
1150fcb8677SHans Verkuil memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
1160fcb8677SHans Verkuil msg.addr = state->config->demod_address;
1170fcb8677SHans Verkuil msg.flags = 0;
1180fcb8677SHans Verkuil msg.buf = tx_buf;
1190fcb8677SHans Verkuil msg.len = tx_len + 2;
1200fcb8677SHans Verkuil if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
1210fcb8677SHans Verkuil printk("%s: firmware upload failed!\n", __func__);
1220fcb8677SHans Verkuil printk ("%s: i2c error (err == %i)\n", __func__, err);
1230fcb8677SHans Verkuil return err;
1240fcb8677SHans Verkuil }
1250fcb8677SHans Verkuil fw_pos += tx_len;
1260fcb8677SHans Verkuil }
1270fcb8677SHans Verkuil
1280fcb8677SHans Verkuil dprintk ("%s: done!\n", __func__);
1290fcb8677SHans Verkuil return 0;
1300fcb8677SHans Verkuil };
1310fcb8677SHans Verkuil
sp8870_microcontroller_stop(struct sp8870_state * state)1320fcb8677SHans Verkuil static void sp8870_microcontroller_stop (struct sp8870_state* state)
1330fcb8677SHans Verkuil {
1340fcb8677SHans Verkuil sp8870_writereg(state, 0x0F08, 0x000);
1350fcb8677SHans Verkuil sp8870_writereg(state, 0x0F09, 0x000);
1360fcb8677SHans Verkuil
1370fcb8677SHans Verkuil // microcontroller STOP
1380fcb8677SHans Verkuil sp8870_writereg(state, 0x0F00, 0x000);
1390fcb8677SHans Verkuil }
1400fcb8677SHans Verkuil
sp8870_microcontroller_start(struct sp8870_state * state)1410fcb8677SHans Verkuil static void sp8870_microcontroller_start (struct sp8870_state* state)
1420fcb8677SHans Verkuil {
1430fcb8677SHans Verkuil sp8870_writereg(state, 0x0F08, 0x000);
1440fcb8677SHans Verkuil sp8870_writereg(state, 0x0F09, 0x000);
1450fcb8677SHans Verkuil
1460fcb8677SHans Verkuil // microcontroller START
1470fcb8677SHans Verkuil sp8870_writereg(state, 0x0F00, 0x001);
1480fcb8677SHans Verkuil // not documented but if we don't read 0x0D01 out here
1490fcb8677SHans Verkuil // we don't get a correct data valid signal
1500fcb8677SHans Verkuil sp8870_readreg(state, 0x0D01);
1510fcb8677SHans Verkuil }
1520fcb8677SHans Verkuil
sp8870_read_data_valid_signal(struct sp8870_state * state)1530fcb8677SHans Verkuil static int sp8870_read_data_valid_signal(struct sp8870_state* state)
1540fcb8677SHans Verkuil {
1550fcb8677SHans Verkuil return (sp8870_readreg(state, 0x0D02) > 0);
1560fcb8677SHans Verkuil }
1570fcb8677SHans Verkuil
configure_reg0xc05(struct dtv_frontend_properties * p,u16 * reg0xc05)1580fcb8677SHans Verkuil static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
1590fcb8677SHans Verkuil {
1600fcb8677SHans Verkuil int known_parameters = 1;
1610fcb8677SHans Verkuil
1620fcb8677SHans Verkuil *reg0xc05 = 0x000;
1630fcb8677SHans Verkuil
1640fcb8677SHans Verkuil switch (p->modulation) {
1650fcb8677SHans Verkuil case QPSK:
1660fcb8677SHans Verkuil break;
1670fcb8677SHans Verkuil case QAM_16:
1680fcb8677SHans Verkuil *reg0xc05 |= (1 << 10);
1690fcb8677SHans Verkuil break;
1700fcb8677SHans Verkuil case QAM_64:
1710fcb8677SHans Verkuil *reg0xc05 |= (2 << 10);
1720fcb8677SHans Verkuil break;
1730fcb8677SHans Verkuil case QAM_AUTO:
1740fcb8677SHans Verkuil known_parameters = 0;
1750fcb8677SHans Verkuil break;
1760fcb8677SHans Verkuil default:
1770fcb8677SHans Verkuil return -EINVAL;
1780fcb8677SHans Verkuil }
1790fcb8677SHans Verkuil
1800fcb8677SHans Verkuil switch (p->hierarchy) {
1810fcb8677SHans Verkuil case HIERARCHY_NONE:
1820fcb8677SHans Verkuil break;
1830fcb8677SHans Verkuil case HIERARCHY_1:
1840fcb8677SHans Verkuil *reg0xc05 |= (1 << 7);
1850fcb8677SHans Verkuil break;
1860fcb8677SHans Verkuil case HIERARCHY_2:
1870fcb8677SHans Verkuil *reg0xc05 |= (2 << 7);
1880fcb8677SHans Verkuil break;
1890fcb8677SHans Verkuil case HIERARCHY_4:
1900fcb8677SHans Verkuil *reg0xc05 |= (3 << 7);
1910fcb8677SHans Verkuil break;
1920fcb8677SHans Verkuil case HIERARCHY_AUTO:
1930fcb8677SHans Verkuil known_parameters = 0;
1940fcb8677SHans Verkuil break;
1950fcb8677SHans Verkuil default:
1960fcb8677SHans Verkuil return -EINVAL;
1970fcb8677SHans Verkuil }
1980fcb8677SHans Verkuil
1990fcb8677SHans Verkuil switch (p->code_rate_HP) {
2000fcb8677SHans Verkuil case FEC_1_2:
2010fcb8677SHans Verkuil break;
2020fcb8677SHans Verkuil case FEC_2_3:
2030fcb8677SHans Verkuil *reg0xc05 |= (1 << 3);
2040fcb8677SHans Verkuil break;
2050fcb8677SHans Verkuil case FEC_3_4:
2060fcb8677SHans Verkuil *reg0xc05 |= (2 << 3);
2070fcb8677SHans Verkuil break;
2080fcb8677SHans Verkuil case FEC_5_6:
2090fcb8677SHans Verkuil *reg0xc05 |= (3 << 3);
2100fcb8677SHans Verkuil break;
2110fcb8677SHans Verkuil case FEC_7_8:
2120fcb8677SHans Verkuil *reg0xc05 |= (4 << 3);
2130fcb8677SHans Verkuil break;
2140fcb8677SHans Verkuil case FEC_AUTO:
2150fcb8677SHans Verkuil known_parameters = 0;
2160fcb8677SHans Verkuil break;
2170fcb8677SHans Verkuil default:
2180fcb8677SHans Verkuil return -EINVAL;
2190fcb8677SHans Verkuil }
2200fcb8677SHans Verkuil
2210fcb8677SHans Verkuil if (known_parameters)
2220fcb8677SHans Verkuil *reg0xc05 |= (2 << 1); /* use specified parameters */
2230fcb8677SHans Verkuil else
2240fcb8677SHans Verkuil *reg0xc05 |= (1 << 1); /* enable autoprobing */
2250fcb8677SHans Verkuil
2260fcb8677SHans Verkuil return 0;
2270fcb8677SHans Verkuil }
2280fcb8677SHans Verkuil
sp8870_wake_up(struct sp8870_state * state)2290fcb8677SHans Verkuil static int sp8870_wake_up(struct sp8870_state* state)
2300fcb8677SHans Verkuil {
2310fcb8677SHans Verkuil // enable TS output and interface pins
2320fcb8677SHans Verkuil return sp8870_writereg(state, 0xC18, 0x00D);
2330fcb8677SHans Verkuil }
2340fcb8677SHans Verkuil
sp8870_set_frontend_parameters(struct dvb_frontend * fe)2350fcb8677SHans Verkuil static int sp8870_set_frontend_parameters(struct dvb_frontend *fe)
2360fcb8677SHans Verkuil {
2370fcb8677SHans Verkuil struct dtv_frontend_properties *p = &fe->dtv_property_cache;
2380fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
2390fcb8677SHans Verkuil int err;
2400fcb8677SHans Verkuil u16 reg0xc05;
2410fcb8677SHans Verkuil
2420fcb8677SHans Verkuil if ((err = configure_reg0xc05(p, ®0xc05)))
2430fcb8677SHans Verkuil return err;
2440fcb8677SHans Verkuil
2450fcb8677SHans Verkuil // system controller stop
2460fcb8677SHans Verkuil sp8870_microcontroller_stop(state);
2470fcb8677SHans Verkuil
2480fcb8677SHans Verkuil // set tuner parameters
2490fcb8677SHans Verkuil if (fe->ops.tuner_ops.set_params) {
2500fcb8677SHans Verkuil fe->ops.tuner_ops.set_params(fe);
2510fcb8677SHans Verkuil if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
2520fcb8677SHans Verkuil }
2530fcb8677SHans Verkuil
2540fcb8677SHans Verkuil // sample rate correction bit [23..17]
2550fcb8677SHans Verkuil sp8870_writereg(state, 0x0319, 0x000A);
2560fcb8677SHans Verkuil
2570fcb8677SHans Verkuil // sample rate correction bit [16..0]
2580fcb8677SHans Verkuil sp8870_writereg(state, 0x031A, 0x0AAB);
2590fcb8677SHans Verkuil
2600fcb8677SHans Verkuil // integer carrier offset
2610fcb8677SHans Verkuil sp8870_writereg(state, 0x0309, 0x0400);
2620fcb8677SHans Verkuil
2630fcb8677SHans Verkuil // fractional carrier offset
2640fcb8677SHans Verkuil sp8870_writereg(state, 0x030A, 0x0000);
2650fcb8677SHans Verkuil
2660fcb8677SHans Verkuil // filter for 6/7/8 Mhz channel
2670fcb8677SHans Verkuil if (p->bandwidth_hz == 6000000)
2680fcb8677SHans Verkuil sp8870_writereg(state, 0x0311, 0x0002);
2690fcb8677SHans Verkuil else if (p->bandwidth_hz == 7000000)
2700fcb8677SHans Verkuil sp8870_writereg(state, 0x0311, 0x0001);
2710fcb8677SHans Verkuil else
2720fcb8677SHans Verkuil sp8870_writereg(state, 0x0311, 0x0000);
2730fcb8677SHans Verkuil
2740fcb8677SHans Verkuil // scan order: 2k first = 0x0000, 8k first = 0x0001
2750fcb8677SHans Verkuil if (p->transmission_mode == TRANSMISSION_MODE_2K)
2760fcb8677SHans Verkuil sp8870_writereg(state, 0x0338, 0x0000);
2770fcb8677SHans Verkuil else
2780fcb8677SHans Verkuil sp8870_writereg(state, 0x0338, 0x0001);
2790fcb8677SHans Verkuil
2800fcb8677SHans Verkuil sp8870_writereg(state, 0xc05, reg0xc05);
2810fcb8677SHans Verkuil
2820fcb8677SHans Verkuil // read status reg in order to clear pending irqs
2830fcb8677SHans Verkuil err = sp8870_readreg(state, 0x200);
2840fcb8677SHans Verkuil if (err < 0)
2850fcb8677SHans Verkuil return err;
2860fcb8677SHans Verkuil
2870fcb8677SHans Verkuil // system controller start
2880fcb8677SHans Verkuil sp8870_microcontroller_start(state);
2890fcb8677SHans Verkuil
2900fcb8677SHans Verkuil return 0;
2910fcb8677SHans Verkuil }
2920fcb8677SHans Verkuil
sp8870_init(struct dvb_frontend * fe)2930fcb8677SHans Verkuil static int sp8870_init (struct dvb_frontend* fe)
2940fcb8677SHans Verkuil {
2950fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
2960fcb8677SHans Verkuil const struct firmware *fw = NULL;
2970fcb8677SHans Verkuil
2980fcb8677SHans Verkuil sp8870_wake_up(state);
2990fcb8677SHans Verkuil if (state->initialised) return 0;
3000fcb8677SHans Verkuil state->initialised = 1;
3010fcb8677SHans Verkuil
3020fcb8677SHans Verkuil dprintk ("%s\n", __func__);
3030fcb8677SHans Verkuil
3040fcb8677SHans Verkuil
3050fcb8677SHans Verkuil /* request the firmware, this will block until someone uploads it */
3060fcb8677SHans Verkuil printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE);
3070fcb8677SHans Verkuil if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) {
3080fcb8677SHans Verkuil printk("sp8870: no firmware upload (timeout or file not found?)\n");
3090fcb8677SHans Verkuil return -EIO;
3100fcb8677SHans Verkuil }
3110fcb8677SHans Verkuil
3120fcb8677SHans Verkuil if (sp8870_firmware_upload(state, fw)) {
3130fcb8677SHans Verkuil printk("sp8870: writing firmware to device failed\n");
3140fcb8677SHans Verkuil release_firmware(fw);
3150fcb8677SHans Verkuil return -EIO;
3160fcb8677SHans Verkuil }
3170fcb8677SHans Verkuil release_firmware(fw);
3180fcb8677SHans Verkuil printk("sp8870: firmware upload complete\n");
3190fcb8677SHans Verkuil
3200fcb8677SHans Verkuil /* enable TS output and interface pins */
3210fcb8677SHans Verkuil sp8870_writereg(state, 0xc18, 0x00d);
3220fcb8677SHans Verkuil
3230fcb8677SHans Verkuil // system controller stop
3240fcb8677SHans Verkuil sp8870_microcontroller_stop(state);
3250fcb8677SHans Verkuil
3260fcb8677SHans Verkuil // ADC mode
3270fcb8677SHans Verkuil sp8870_writereg(state, 0x0301, 0x0003);
3280fcb8677SHans Verkuil
3290fcb8677SHans Verkuil // Reed Solomon parity bytes passed to output
3300fcb8677SHans Verkuil sp8870_writereg(state, 0x0C13, 0x0001);
3310fcb8677SHans Verkuil
3320fcb8677SHans Verkuil // MPEG clock is suppressed if no valid data
3330fcb8677SHans Verkuil sp8870_writereg(state, 0x0C14, 0x0001);
3340fcb8677SHans Verkuil
3350fcb8677SHans Verkuil /* bit 0x010: enable data valid signal */
3360fcb8677SHans Verkuil sp8870_writereg(state, 0x0D00, 0x010);
3370fcb8677SHans Verkuil sp8870_writereg(state, 0x0D01, 0x000);
3380fcb8677SHans Verkuil
3390fcb8677SHans Verkuil return 0;
3400fcb8677SHans Verkuil }
3410fcb8677SHans Verkuil
sp8870_read_status(struct dvb_frontend * fe,enum fe_status * fe_status)3420fcb8677SHans Verkuil static int sp8870_read_status(struct dvb_frontend *fe,
3430fcb8677SHans Verkuil enum fe_status *fe_status)
3440fcb8677SHans Verkuil {
3450fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
3460fcb8677SHans Verkuil int status;
3470fcb8677SHans Verkuil int signal;
3480fcb8677SHans Verkuil
3490fcb8677SHans Verkuil *fe_status = 0;
3500fcb8677SHans Verkuil
3510fcb8677SHans Verkuil status = sp8870_readreg (state, 0x0200);
3520fcb8677SHans Verkuil if (status < 0)
3530fcb8677SHans Verkuil return -EIO;
3540fcb8677SHans Verkuil
3550fcb8677SHans Verkuil signal = sp8870_readreg (state, 0x0303);
3560fcb8677SHans Verkuil if (signal < 0)
3570fcb8677SHans Verkuil return -EIO;
3580fcb8677SHans Verkuil
3590fcb8677SHans Verkuil if (signal > 0x0F)
3600fcb8677SHans Verkuil *fe_status |= FE_HAS_SIGNAL;
3610fcb8677SHans Verkuil if (status & 0x08)
3620fcb8677SHans Verkuil *fe_status |= FE_HAS_SYNC;
3630fcb8677SHans Verkuil if (status & 0x04)
3640fcb8677SHans Verkuil *fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
3650fcb8677SHans Verkuil
3660fcb8677SHans Verkuil return 0;
3670fcb8677SHans Verkuil }
3680fcb8677SHans Verkuil
sp8870_read_ber(struct dvb_frontend * fe,u32 * ber)3690fcb8677SHans Verkuil static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
3700fcb8677SHans Verkuil {
3710fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
3720fcb8677SHans Verkuil int ret;
3730fcb8677SHans Verkuil u32 tmp;
3740fcb8677SHans Verkuil
3750fcb8677SHans Verkuil *ber = 0;
3760fcb8677SHans Verkuil
3770fcb8677SHans Verkuil ret = sp8870_readreg(state, 0xC08);
3780fcb8677SHans Verkuil if (ret < 0)
3790fcb8677SHans Verkuil return -EIO;
3800fcb8677SHans Verkuil
3810fcb8677SHans Verkuil tmp = ret & 0x3F;
3820fcb8677SHans Verkuil
3830fcb8677SHans Verkuil ret = sp8870_readreg(state, 0xC07);
3840fcb8677SHans Verkuil if (ret < 0)
3850fcb8677SHans Verkuil return -EIO;
3860fcb8677SHans Verkuil
3870fcb8677SHans Verkuil tmp = ret << 6;
3880fcb8677SHans Verkuil if (tmp >= 0x3FFF0)
3890fcb8677SHans Verkuil tmp = ~0;
3900fcb8677SHans Verkuil
3910fcb8677SHans Verkuil *ber = tmp;
3920fcb8677SHans Verkuil
3930fcb8677SHans Verkuil return 0;
3940fcb8677SHans Verkuil }
3950fcb8677SHans Verkuil
sp8870_read_signal_strength(struct dvb_frontend * fe,u16 * signal)3960fcb8677SHans Verkuil static int sp8870_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
3970fcb8677SHans Verkuil {
3980fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
3990fcb8677SHans Verkuil int ret;
4000fcb8677SHans Verkuil u16 tmp;
4010fcb8677SHans Verkuil
4020fcb8677SHans Verkuil *signal = 0;
4030fcb8677SHans Verkuil
4040fcb8677SHans Verkuil ret = sp8870_readreg (state, 0x306);
4050fcb8677SHans Verkuil if (ret < 0)
4060fcb8677SHans Verkuil return -EIO;
4070fcb8677SHans Verkuil
4080fcb8677SHans Verkuil tmp = ret << 8;
4090fcb8677SHans Verkuil
4100fcb8677SHans Verkuil ret = sp8870_readreg (state, 0x303);
4110fcb8677SHans Verkuil if (ret < 0)
4120fcb8677SHans Verkuil return -EIO;
4130fcb8677SHans Verkuil
4140fcb8677SHans Verkuil tmp |= ret;
4150fcb8677SHans Verkuil
4160fcb8677SHans Verkuil if (tmp)
4170fcb8677SHans Verkuil *signal = 0xFFFF - tmp;
4180fcb8677SHans Verkuil
4190fcb8677SHans Verkuil return 0;
4200fcb8677SHans Verkuil }
4210fcb8677SHans Verkuil
sp8870_read_uncorrected_blocks(struct dvb_frontend * fe,u32 * ublocks)4220fcb8677SHans Verkuil static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks)
4230fcb8677SHans Verkuil {
4240fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
4250fcb8677SHans Verkuil int ret;
4260fcb8677SHans Verkuil
4270fcb8677SHans Verkuil *ublocks = 0;
4280fcb8677SHans Verkuil
4290fcb8677SHans Verkuil ret = sp8870_readreg(state, 0xC0C);
4300fcb8677SHans Verkuil if (ret < 0)
4310fcb8677SHans Verkuil return -EIO;
4320fcb8677SHans Verkuil
4330fcb8677SHans Verkuil if (ret == 0xFFFF)
4340fcb8677SHans Verkuil ret = ~0;
4350fcb8677SHans Verkuil
4360fcb8677SHans Verkuil *ublocks = ret;
4370fcb8677SHans Verkuil
4380fcb8677SHans Verkuil return 0;
4390fcb8677SHans Verkuil }
4400fcb8677SHans Verkuil
4410fcb8677SHans Verkuil /* number of trials to recover from lockup */
4420fcb8677SHans Verkuil #define MAXTRIALS 5
4430fcb8677SHans Verkuil /* maximum checks for data valid signal */
4440fcb8677SHans Verkuil #define MAXCHECKS 100
4450fcb8677SHans Verkuil
4460fcb8677SHans Verkuil /* only for debugging: counter for detected lockups */
4470fcb8677SHans Verkuil static int lockups;
4480fcb8677SHans Verkuil /* only for debugging: counter for channel switches */
4490fcb8677SHans Verkuil static int switches;
4500fcb8677SHans Verkuil
sp8870_set_frontend(struct dvb_frontend * fe)4510fcb8677SHans Verkuil static int sp8870_set_frontend(struct dvb_frontend *fe)
4520fcb8677SHans Verkuil {
4530fcb8677SHans Verkuil struct dtv_frontend_properties *p = &fe->dtv_property_cache;
4540fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
4550fcb8677SHans Verkuil
4560fcb8677SHans Verkuil /*
4570fcb8677SHans Verkuil The firmware of the sp8870 sometimes locks up after setting frontend parameters.
4580fcb8677SHans Verkuil We try to detect this by checking the data valid signal.
4590fcb8677SHans Verkuil If it is not set after MAXCHECKS we try to recover the lockup by setting
4600fcb8677SHans Verkuil the frontend parameters again.
4610fcb8677SHans Verkuil */
4620fcb8677SHans Verkuil
4630fcb8677SHans Verkuil int err = 0;
4640fcb8677SHans Verkuil int valid = 0;
4650fcb8677SHans Verkuil int trials = 0;
4660fcb8677SHans Verkuil int check_count = 0;
4670fcb8677SHans Verkuil
4680fcb8677SHans Verkuil dprintk("%s: frequency = %i\n", __func__, p->frequency);
4690fcb8677SHans Verkuil
4700fcb8677SHans Verkuil for (trials = 1; trials <= MAXTRIALS; trials++) {
4710fcb8677SHans Verkuil
4720fcb8677SHans Verkuil err = sp8870_set_frontend_parameters(fe);
4730fcb8677SHans Verkuil if (err)
4740fcb8677SHans Verkuil return err;
4750fcb8677SHans Verkuil
4760fcb8677SHans Verkuil for (check_count = 0; check_count < MAXCHECKS; check_count++) {
4770fcb8677SHans Verkuil // valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
4780fcb8677SHans Verkuil valid = sp8870_read_data_valid_signal(state);
4790fcb8677SHans Verkuil if (valid) {
4800fcb8677SHans Verkuil dprintk("%s: delay = %i usec\n",
4810fcb8677SHans Verkuil __func__, check_count * 10);
4820fcb8677SHans Verkuil break;
4830fcb8677SHans Verkuil }
4840fcb8677SHans Verkuil udelay(10);
4850fcb8677SHans Verkuil }
4860fcb8677SHans Verkuil if (valid)
4870fcb8677SHans Verkuil break;
4880fcb8677SHans Verkuil }
4890fcb8677SHans Verkuil
4900fcb8677SHans Verkuil if (!valid) {
4910fcb8677SHans Verkuil printk("%s: firmware crash!!!!!!\n", __func__);
4920fcb8677SHans Verkuil return -EIO;
4930fcb8677SHans Verkuil }
4940fcb8677SHans Verkuil
4950fcb8677SHans Verkuil if (debug) {
4960fcb8677SHans Verkuil if (valid) {
4970fcb8677SHans Verkuil if (trials > 1) {
4980fcb8677SHans Verkuil printk("%s: firmware lockup!!!\n", __func__);
4990fcb8677SHans Verkuil printk("%s: recovered after %i trial(s))\n", __func__, trials - 1);
5000fcb8677SHans Verkuil lockups++;
5010fcb8677SHans Verkuil }
5020fcb8677SHans Verkuil }
5030fcb8677SHans Verkuil switches++;
5040fcb8677SHans Verkuil printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
5050fcb8677SHans Verkuil }
5060fcb8677SHans Verkuil
5070fcb8677SHans Verkuil return 0;
5080fcb8677SHans Verkuil }
5090fcb8677SHans Verkuil
sp8870_sleep(struct dvb_frontend * fe)5100fcb8677SHans Verkuil static int sp8870_sleep(struct dvb_frontend* fe)
5110fcb8677SHans Verkuil {
5120fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
5130fcb8677SHans Verkuil
5140fcb8677SHans Verkuil // tristate TS output and disable interface pins
5150fcb8677SHans Verkuil return sp8870_writereg(state, 0xC18, 0x000);
5160fcb8677SHans Verkuil }
5170fcb8677SHans Verkuil
sp8870_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * fesettings)5180fcb8677SHans Verkuil static int sp8870_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
5190fcb8677SHans Verkuil {
5200fcb8677SHans Verkuil fesettings->min_delay_ms = 350;
5210fcb8677SHans Verkuil fesettings->step_size = 0;
5220fcb8677SHans Verkuil fesettings->max_drift = 0;
5230fcb8677SHans Verkuil return 0;
5240fcb8677SHans Verkuil }
5250fcb8677SHans Verkuil
sp8870_i2c_gate_ctrl(struct dvb_frontend * fe,int enable)5260fcb8677SHans Verkuil static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
5270fcb8677SHans Verkuil {
5280fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
5290fcb8677SHans Verkuil
5300fcb8677SHans Verkuil if (enable) {
5310fcb8677SHans Verkuil return sp8870_writereg(state, 0x206, 0x001);
5320fcb8677SHans Verkuil } else {
5330fcb8677SHans Verkuil return sp8870_writereg(state, 0x206, 0x000);
5340fcb8677SHans Verkuil }
5350fcb8677SHans Verkuil }
5360fcb8677SHans Verkuil
sp8870_release(struct dvb_frontend * fe)5370fcb8677SHans Verkuil static void sp8870_release(struct dvb_frontend* fe)
5380fcb8677SHans Verkuil {
5390fcb8677SHans Verkuil struct sp8870_state* state = fe->demodulator_priv;
5400fcb8677SHans Verkuil kfree(state);
5410fcb8677SHans Verkuil }
5420fcb8677SHans Verkuil
5430fcb8677SHans Verkuil static const struct dvb_frontend_ops sp8870_ops;
5440fcb8677SHans Verkuil
sp8870_attach(const struct sp8870_config * config,struct i2c_adapter * i2c)5450fcb8677SHans Verkuil struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
5460fcb8677SHans Verkuil struct i2c_adapter* i2c)
5470fcb8677SHans Verkuil {
5480fcb8677SHans Verkuil struct sp8870_state* state = NULL;
5490fcb8677SHans Verkuil
5500fcb8677SHans Verkuil /* allocate memory for the internal state */
5510fcb8677SHans Verkuil state = kzalloc(sizeof(struct sp8870_state), GFP_KERNEL);
5520fcb8677SHans Verkuil if (state == NULL) goto error;
5530fcb8677SHans Verkuil
5540fcb8677SHans Verkuil /* setup the state */
5550fcb8677SHans Verkuil state->config = config;
5560fcb8677SHans Verkuil state->i2c = i2c;
5570fcb8677SHans Verkuil state->initialised = 0;
5580fcb8677SHans Verkuil
5590fcb8677SHans Verkuil /* check if the demod is there */
5600fcb8677SHans Verkuil if (sp8870_readreg(state, 0x0200) < 0) goto error;
5610fcb8677SHans Verkuil
5620fcb8677SHans Verkuil /* create dvb_frontend */
5630fcb8677SHans Verkuil memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
5640fcb8677SHans Verkuil state->frontend.demodulator_priv = state;
5650fcb8677SHans Verkuil return &state->frontend;
5660fcb8677SHans Verkuil
5670fcb8677SHans Verkuil error:
5680fcb8677SHans Verkuil kfree(state);
5690fcb8677SHans Verkuil return NULL;
5700fcb8677SHans Verkuil }
5710fcb8677SHans Verkuil
5720fcb8677SHans Verkuil static const struct dvb_frontend_ops sp8870_ops = {
5730fcb8677SHans Verkuil .delsys = { SYS_DVBT },
5740fcb8677SHans Verkuil .info = {
5750fcb8677SHans Verkuil .name = "Spase SP8870 DVB-T",
5760fcb8677SHans Verkuil .frequency_min_hz = 470 * MHz,
5770fcb8677SHans Verkuil .frequency_max_hz = 860 * MHz,
5780fcb8677SHans Verkuil .frequency_stepsize_hz = 166666,
5790fcb8677SHans Verkuil .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
5800fcb8677SHans Verkuil FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
5810fcb8677SHans Verkuil FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
5820fcb8677SHans Verkuil FE_CAN_QPSK | FE_CAN_QAM_16 |
5830fcb8677SHans Verkuil FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
5840fcb8677SHans Verkuil FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER
5850fcb8677SHans Verkuil },
5860fcb8677SHans Verkuil
5870fcb8677SHans Verkuil .release = sp8870_release,
5880fcb8677SHans Verkuil
5890fcb8677SHans Verkuil .init = sp8870_init,
5900fcb8677SHans Verkuil .sleep = sp8870_sleep,
5910fcb8677SHans Verkuil .i2c_gate_ctrl = sp8870_i2c_gate_ctrl,
5920fcb8677SHans Verkuil
5930fcb8677SHans Verkuil .set_frontend = sp8870_set_frontend,
5940fcb8677SHans Verkuil .get_tune_settings = sp8870_get_tune_settings,
5950fcb8677SHans Verkuil
5960fcb8677SHans Verkuil .read_status = sp8870_read_status,
5970fcb8677SHans Verkuil .read_ber = sp8870_read_ber,
5980fcb8677SHans Verkuil .read_signal_strength = sp8870_read_signal_strength,
5990fcb8677SHans Verkuil .read_ucblocks = sp8870_read_uncorrected_blocks,
6000fcb8677SHans Verkuil };
6010fcb8677SHans Verkuil
6020fcb8677SHans Verkuil module_param(debug, int, 0644);
6030fcb8677SHans Verkuil MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
6040fcb8677SHans Verkuil
6050fcb8677SHans Verkuil MODULE_DESCRIPTION("Spase SP8870 DVB-T Demodulator driver");
6060fcb8677SHans Verkuil MODULE_AUTHOR("Juergen Peitz");
6070fcb8677SHans Verkuil MODULE_LICENSE("GPL");
6080fcb8677SHans Verkuil
609*86495af1SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(sp8870_attach);
610