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, &reg0xc05)))
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