xref: /openbmc/linux/drivers/media/dvb-frontends/stv0288.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29a0bf528SMauro Carvalho Chehab /*
39a0bf528SMauro Carvalho Chehab 	Driver for ST STV0288 demodulator
49a0bf528SMauro Carvalho Chehab 	Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
59a0bf528SMauro Carvalho Chehab 		for Reel Multimedia
69a0bf528SMauro Carvalho Chehab 	Copyright (C) 2008 TurboSight.com, Bob Liu <bob@turbosight.com>
79a0bf528SMauro Carvalho Chehab 	Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
89a0bf528SMauro Carvalho Chehab 		Removed stb6000 specific tuner code and revised some
99a0bf528SMauro Carvalho Chehab 		procedures.
109a0bf528SMauro Carvalho Chehab 	2010-09-01 Josef Pavlik <josef@pavlik.it>
119a0bf528SMauro Carvalho Chehab 		Fixed diseqc_msg, diseqc_burst and set_tone problems
129a0bf528SMauro Carvalho Chehab 
139a0bf528SMauro Carvalho Chehab 
149a0bf528SMauro Carvalho Chehab */
159a0bf528SMauro Carvalho Chehab 
169a0bf528SMauro Carvalho Chehab #include <linux/init.h>
179a0bf528SMauro Carvalho Chehab #include <linux/kernel.h>
189a0bf528SMauro Carvalho Chehab #include <linux/module.h>
199a0bf528SMauro Carvalho Chehab #include <linux/string.h>
209a0bf528SMauro Carvalho Chehab #include <linux/slab.h>
219a0bf528SMauro Carvalho Chehab #include <linux/jiffies.h>
229a0bf528SMauro Carvalho Chehab #include <asm/div64.h>
239a0bf528SMauro Carvalho Chehab 
24fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h>
259a0bf528SMauro Carvalho Chehab #include "stv0288.h"
269a0bf528SMauro Carvalho Chehab 
279a0bf528SMauro Carvalho Chehab struct stv0288_state {
289a0bf528SMauro Carvalho Chehab 	struct i2c_adapter *i2c;
299a0bf528SMauro Carvalho Chehab 	const struct stv0288_config *config;
309a0bf528SMauro Carvalho Chehab 	struct dvb_frontend frontend;
319a0bf528SMauro Carvalho Chehab 
329a0bf528SMauro Carvalho Chehab 	u8 initialised:1;
339a0bf528SMauro Carvalho Chehab 	u32 tuner_frequency;
349a0bf528SMauro Carvalho Chehab 	u32 symbol_rate;
350df289a2SMauro Carvalho Chehab 	enum fe_code_rate fec_inner;
369a0bf528SMauro Carvalho Chehab 	int errmode;
379a0bf528SMauro Carvalho Chehab };
389a0bf528SMauro Carvalho Chehab 
399a0bf528SMauro Carvalho Chehab #define STATUS_BER 0
409a0bf528SMauro Carvalho Chehab #define STATUS_UCBLOCKS 1
419a0bf528SMauro Carvalho Chehab 
429a0bf528SMauro Carvalho Chehab static int debug;
439a0bf528SMauro Carvalho Chehab static int debug_legacy_dish_switch;
449a0bf528SMauro Carvalho Chehab #define dprintk(args...) \
459a0bf528SMauro Carvalho Chehab 	do { \
469a0bf528SMauro Carvalho Chehab 		if (debug) \
479a0bf528SMauro Carvalho Chehab 			printk(KERN_DEBUG "stv0288: " args); \
489a0bf528SMauro Carvalho Chehab 	} while (0)
499a0bf528SMauro Carvalho Chehab 
509a0bf528SMauro Carvalho Chehab 
stv0288_writeregI(struct stv0288_state * state,u8 reg,u8 data)519a0bf528SMauro Carvalho Chehab static int stv0288_writeregI(struct stv0288_state *state, u8 reg, u8 data)
529a0bf528SMauro Carvalho Chehab {
539a0bf528SMauro Carvalho Chehab 	int ret;
549a0bf528SMauro Carvalho Chehab 	u8 buf[] = { reg, data };
559a0bf528SMauro Carvalho Chehab 	struct i2c_msg msg = {
569a0bf528SMauro Carvalho Chehab 		.addr = state->config->demod_address,
579a0bf528SMauro Carvalho Chehab 		.flags = 0,
589a0bf528SMauro Carvalho Chehab 		.buf = buf,
599a0bf528SMauro Carvalho Chehab 		.len = 2
609a0bf528SMauro Carvalho Chehab 	};
619a0bf528SMauro Carvalho Chehab 
629a0bf528SMauro Carvalho Chehab 	ret = i2c_transfer(state->i2c, &msg, 1);
639a0bf528SMauro Carvalho Chehab 
649a0bf528SMauro Carvalho Chehab 	if (ret != 1)
654bd69e7bSMauro Carvalho Chehab 		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
664bd69e7bSMauro Carvalho Chehab 			__func__, reg, data, ret);
679a0bf528SMauro Carvalho Chehab 
689a0bf528SMauro Carvalho Chehab 	return (ret != 1) ? -EREMOTEIO : 0;
699a0bf528SMauro Carvalho Chehab }
709a0bf528SMauro Carvalho Chehab 
stv0288_write(struct dvb_frontend * fe,const u8 buf[],int len)719a0bf528SMauro Carvalho Chehab static int stv0288_write(struct dvb_frontend *fe, const u8 buf[], int len)
729a0bf528SMauro Carvalho Chehab {
739a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
749a0bf528SMauro Carvalho Chehab 
759a0bf528SMauro Carvalho Chehab 	if (len != 2)
769a0bf528SMauro Carvalho Chehab 		return -EINVAL;
779a0bf528SMauro Carvalho Chehab 
789a0bf528SMauro Carvalho Chehab 	return stv0288_writeregI(state, buf[0], buf[1]);
799a0bf528SMauro Carvalho Chehab }
809a0bf528SMauro Carvalho Chehab 
stv0288_readreg(struct stv0288_state * state,u8 reg)819a0bf528SMauro Carvalho Chehab static u8 stv0288_readreg(struct stv0288_state *state, u8 reg)
829a0bf528SMauro Carvalho Chehab {
839a0bf528SMauro Carvalho Chehab 	int ret;
849a0bf528SMauro Carvalho Chehab 	u8 b0[] = { reg };
859a0bf528SMauro Carvalho Chehab 	u8 b1[] = { 0 };
869a0bf528SMauro Carvalho Chehab 	struct i2c_msg msg[] = {
879a0bf528SMauro Carvalho Chehab 		{
889a0bf528SMauro Carvalho Chehab 			.addr = state->config->demod_address,
899a0bf528SMauro Carvalho Chehab 			.flags = 0,
909a0bf528SMauro Carvalho Chehab 			.buf = b0,
919a0bf528SMauro Carvalho Chehab 			.len = 1
929a0bf528SMauro Carvalho Chehab 		}, {
939a0bf528SMauro Carvalho Chehab 			.addr = state->config->demod_address,
949a0bf528SMauro Carvalho Chehab 			.flags = I2C_M_RD,
959a0bf528SMauro Carvalho Chehab 			.buf = b1,
969a0bf528SMauro Carvalho Chehab 			.len = 1
979a0bf528SMauro Carvalho Chehab 		}
989a0bf528SMauro Carvalho Chehab 	};
999a0bf528SMauro Carvalho Chehab 
1009a0bf528SMauro Carvalho Chehab 	ret = i2c_transfer(state->i2c, msg, 2);
1019a0bf528SMauro Carvalho Chehab 
1029a0bf528SMauro Carvalho Chehab 	if (ret != 2)
1039a0bf528SMauro Carvalho Chehab 		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
1049a0bf528SMauro Carvalho Chehab 				__func__, reg, ret);
1059a0bf528SMauro Carvalho Chehab 
1069a0bf528SMauro Carvalho Chehab 	return b1[0];
1079a0bf528SMauro Carvalho Chehab }
1089a0bf528SMauro Carvalho Chehab 
stv0288_set_symbolrate(struct dvb_frontend * fe,u32 srate)1099a0bf528SMauro Carvalho Chehab static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate)
1109a0bf528SMauro Carvalho Chehab {
1119a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
1129a0bf528SMauro Carvalho Chehab 	unsigned int temp;
1139a0bf528SMauro Carvalho Chehab 	unsigned char b[3];
1149a0bf528SMauro Carvalho Chehab 
1159a0bf528SMauro Carvalho Chehab 	if ((srate < 1000000) || (srate > 45000000))
1169a0bf528SMauro Carvalho Chehab 		return -EINVAL;
1179a0bf528SMauro Carvalho Chehab 
1189a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x22, 0);
1199a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x23, 0);
1209a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x2b, 0xff);
1219a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x2c, 0xf7);
1229a0bf528SMauro Carvalho Chehab 
1239a0bf528SMauro Carvalho Chehab 	temp = (unsigned int)srate / 1000;
1249a0bf528SMauro Carvalho Chehab 
1259a0bf528SMauro Carvalho Chehab 	temp = temp * 32768;
1269a0bf528SMauro Carvalho Chehab 	temp = temp / 25;
1279a0bf528SMauro Carvalho Chehab 	temp = temp / 125;
1289a0bf528SMauro Carvalho Chehab 	b[0] = (unsigned char)((temp >> 12) & 0xff);
1299a0bf528SMauro Carvalho Chehab 	b[1] = (unsigned char)((temp >> 4) & 0xff);
1309a0bf528SMauro Carvalho Chehab 	b[2] = (unsigned char)((temp << 4) & 0xf0);
1319a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
1329a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x29, 0); /* SFRM */
1339a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x2a, 0); /* SFRL */
1349a0bf528SMauro Carvalho Chehab 
1359a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x28, b[0]);
1369a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x29, b[1]);
1379a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x2a, b[2]);
1389a0bf528SMauro Carvalho Chehab 	dprintk("stv0288: stv0288_set_symbolrate\n");
1399a0bf528SMauro Carvalho Chehab 
1409a0bf528SMauro Carvalho Chehab 	return 0;
1419a0bf528SMauro Carvalho Chehab }
1429a0bf528SMauro Carvalho Chehab 
stv0288_send_diseqc_msg(struct dvb_frontend * fe,struct dvb_diseqc_master_cmd * m)1439a0bf528SMauro Carvalho Chehab static int stv0288_send_diseqc_msg(struct dvb_frontend *fe,
1449a0bf528SMauro Carvalho Chehab 				    struct dvb_diseqc_master_cmd *m)
1459a0bf528SMauro Carvalho Chehab {
1469a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
1479a0bf528SMauro Carvalho Chehab 
1489a0bf528SMauro Carvalho Chehab 	int i;
1499a0bf528SMauro Carvalho Chehab 
1509a0bf528SMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1519a0bf528SMauro Carvalho Chehab 
1529a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x09, 0);
1539a0bf528SMauro Carvalho Chehab 	msleep(30);
1549a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x05, 0x12);/* modulated mode, single shot */
1559a0bf528SMauro Carvalho Chehab 
1569a0bf528SMauro Carvalho Chehab 	for (i = 0; i < m->msg_len; i++) {
1579a0bf528SMauro Carvalho Chehab 		if (stv0288_writeregI(state, 0x06, m->msg[i]))
1589a0bf528SMauro Carvalho Chehab 			return -EREMOTEIO;
1599a0bf528SMauro Carvalho Chehab 	}
1609a0bf528SMauro Carvalho Chehab 	msleep(m->msg_len*12);
1619a0bf528SMauro Carvalho Chehab 	return 0;
1629a0bf528SMauro Carvalho Chehab }
1639a0bf528SMauro Carvalho Chehab 
stv0288_send_diseqc_burst(struct dvb_frontend * fe,enum fe_sec_mini_cmd burst)1649a0bf528SMauro Carvalho Chehab static int stv0288_send_diseqc_burst(struct dvb_frontend *fe,
1650df289a2SMauro Carvalho Chehab 				     enum fe_sec_mini_cmd burst)
1669a0bf528SMauro Carvalho Chehab {
1679a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
1689a0bf528SMauro Carvalho Chehab 
1699a0bf528SMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1709a0bf528SMauro Carvalho Chehab 
1719a0bf528SMauro Carvalho Chehab 	if (stv0288_writeregI(state, 0x05, 0x03))/* burst mode, single shot */
1729a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
1739a0bf528SMauro Carvalho Chehab 
1749a0bf528SMauro Carvalho Chehab 	if (stv0288_writeregI(state, 0x06, burst == SEC_MINI_A ? 0x00 : 0xff))
1759a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
1769a0bf528SMauro Carvalho Chehab 
1779a0bf528SMauro Carvalho Chehab 	msleep(15);
1789a0bf528SMauro Carvalho Chehab 	if (stv0288_writeregI(state, 0x05, 0x12))
1799a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
1809a0bf528SMauro Carvalho Chehab 
1819a0bf528SMauro Carvalho Chehab 	return 0;
1829a0bf528SMauro Carvalho Chehab }
1839a0bf528SMauro Carvalho Chehab 
stv0288_set_tone(struct dvb_frontend * fe,enum fe_sec_tone_mode tone)1840df289a2SMauro Carvalho Chehab static int stv0288_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
1859a0bf528SMauro Carvalho Chehab {
1869a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
1879a0bf528SMauro Carvalho Chehab 
1889a0bf528SMauro Carvalho Chehab 	switch (tone) {
1899a0bf528SMauro Carvalho Chehab 	case SEC_TONE_ON:
1909a0bf528SMauro Carvalho Chehab 		if (stv0288_writeregI(state, 0x05, 0x10))/* cont carrier */
1919a0bf528SMauro Carvalho Chehab 			return -EREMOTEIO;
1929a0bf528SMauro Carvalho Chehab 	break;
1939a0bf528SMauro Carvalho Chehab 
1949a0bf528SMauro Carvalho Chehab 	case SEC_TONE_OFF:
1959a0bf528SMauro Carvalho Chehab 		if (stv0288_writeregI(state, 0x05, 0x12))/* burst mode off*/
1969a0bf528SMauro Carvalho Chehab 			return -EREMOTEIO;
1979a0bf528SMauro Carvalho Chehab 	break;
1989a0bf528SMauro Carvalho Chehab 
1999a0bf528SMauro Carvalho Chehab 	default:
2009a0bf528SMauro Carvalho Chehab 		return -EINVAL;
2019a0bf528SMauro Carvalho Chehab 	}
2029a0bf528SMauro Carvalho Chehab 	return 0;
2039a0bf528SMauro Carvalho Chehab }
2049a0bf528SMauro Carvalho Chehab 
2059a0bf528SMauro Carvalho Chehab static u8 stv0288_inittab[] = {
2069a0bf528SMauro Carvalho Chehab 	0x01, 0x15,
2079a0bf528SMauro Carvalho Chehab 	0x02, 0x20,
2089a0bf528SMauro Carvalho Chehab 	0x09, 0x0,
2099a0bf528SMauro Carvalho Chehab 	0x0a, 0x4,
2109a0bf528SMauro Carvalho Chehab 	0x0b, 0x0,
2119a0bf528SMauro Carvalho Chehab 	0x0c, 0x0,
2129a0bf528SMauro Carvalho Chehab 	0x0d, 0x0,
2139a0bf528SMauro Carvalho Chehab 	0x0e, 0xd4,
2149a0bf528SMauro Carvalho Chehab 	0x0f, 0x30,
2159a0bf528SMauro Carvalho Chehab 	0x11, 0x80,
2169a0bf528SMauro Carvalho Chehab 	0x12, 0x03,
2179a0bf528SMauro Carvalho Chehab 	0x13, 0x48,
2189a0bf528SMauro Carvalho Chehab 	0x14, 0x84,
2199a0bf528SMauro Carvalho Chehab 	0x15, 0x45,
2209a0bf528SMauro Carvalho Chehab 	0x16, 0xb7,
2219a0bf528SMauro Carvalho Chehab 	0x17, 0x9c,
2229a0bf528SMauro Carvalho Chehab 	0x18, 0x0,
2239a0bf528SMauro Carvalho Chehab 	0x19, 0xa6,
2249a0bf528SMauro Carvalho Chehab 	0x1a, 0x88,
2259a0bf528SMauro Carvalho Chehab 	0x1b, 0x8f,
2269a0bf528SMauro Carvalho Chehab 	0x1c, 0xf0,
2279a0bf528SMauro Carvalho Chehab 	0x20, 0x0b,
2289a0bf528SMauro Carvalho Chehab 	0x21, 0x54,
2299a0bf528SMauro Carvalho Chehab 	0x22, 0x0,
2309a0bf528SMauro Carvalho Chehab 	0x23, 0x0,
2319a0bf528SMauro Carvalho Chehab 	0x2b, 0xff,
2329a0bf528SMauro Carvalho Chehab 	0x2c, 0xf7,
2339a0bf528SMauro Carvalho Chehab 	0x30, 0x0,
2349a0bf528SMauro Carvalho Chehab 	0x31, 0x1e,
2359a0bf528SMauro Carvalho Chehab 	0x32, 0x14,
2369a0bf528SMauro Carvalho Chehab 	0x33, 0x0f,
2379a0bf528SMauro Carvalho Chehab 	0x34, 0x09,
2389a0bf528SMauro Carvalho Chehab 	0x35, 0x0c,
2399a0bf528SMauro Carvalho Chehab 	0x36, 0x05,
2409a0bf528SMauro Carvalho Chehab 	0x37, 0x2f,
2419a0bf528SMauro Carvalho Chehab 	0x38, 0x16,
2429a0bf528SMauro Carvalho Chehab 	0x39, 0xbe,
2439a0bf528SMauro Carvalho Chehab 	0x3a, 0x0,
2449a0bf528SMauro Carvalho Chehab 	0x3b, 0x13,
2459a0bf528SMauro Carvalho Chehab 	0x3c, 0x11,
2469a0bf528SMauro Carvalho Chehab 	0x3d, 0x30,
2479a0bf528SMauro Carvalho Chehab 	0x40, 0x63,
2489a0bf528SMauro Carvalho Chehab 	0x41, 0x04,
2499a0bf528SMauro Carvalho Chehab 	0x42, 0x20,
2509a0bf528SMauro Carvalho Chehab 	0x43, 0x00,
2519a0bf528SMauro Carvalho Chehab 	0x44, 0x00,
2529a0bf528SMauro Carvalho Chehab 	0x45, 0x00,
2539a0bf528SMauro Carvalho Chehab 	0x46, 0x00,
2549a0bf528SMauro Carvalho Chehab 	0x47, 0x00,
2559a0bf528SMauro Carvalho Chehab 	0x4a, 0x00,
2569a0bf528SMauro Carvalho Chehab 	0x50, 0x10,
2579a0bf528SMauro Carvalho Chehab 	0x51, 0x38,
2589a0bf528SMauro Carvalho Chehab 	0x52, 0x21,
2599a0bf528SMauro Carvalho Chehab 	0x58, 0x54,
2609a0bf528SMauro Carvalho Chehab 	0x59, 0x86,
2619a0bf528SMauro Carvalho Chehab 	0x5a, 0x0,
2629a0bf528SMauro Carvalho Chehab 	0x5b, 0x9b,
2639a0bf528SMauro Carvalho Chehab 	0x5c, 0x08,
2649a0bf528SMauro Carvalho Chehab 	0x5d, 0x7f,
2659a0bf528SMauro Carvalho Chehab 	0x5e, 0x0,
2669a0bf528SMauro Carvalho Chehab 	0x5f, 0xff,
2679a0bf528SMauro Carvalho Chehab 	0x70, 0x0,
2689a0bf528SMauro Carvalho Chehab 	0x71, 0x0,
2699a0bf528SMauro Carvalho Chehab 	0x72, 0x0,
2709a0bf528SMauro Carvalho Chehab 	0x74, 0x0,
2719a0bf528SMauro Carvalho Chehab 	0x75, 0x0,
2729a0bf528SMauro Carvalho Chehab 	0x76, 0x0,
2739a0bf528SMauro Carvalho Chehab 	0x81, 0x0,
2749a0bf528SMauro Carvalho Chehab 	0x82, 0x3f,
2759a0bf528SMauro Carvalho Chehab 	0x83, 0x3f,
2769a0bf528SMauro Carvalho Chehab 	0x84, 0x0,
2779a0bf528SMauro Carvalho Chehab 	0x85, 0x0,
2789a0bf528SMauro Carvalho Chehab 	0x88, 0x0,
2799a0bf528SMauro Carvalho Chehab 	0x89, 0x0,
2809a0bf528SMauro Carvalho Chehab 	0x8a, 0x0,
2819a0bf528SMauro Carvalho Chehab 	0x8b, 0x0,
2829a0bf528SMauro Carvalho Chehab 	0x8c, 0x0,
2839a0bf528SMauro Carvalho Chehab 	0x90, 0x0,
2849a0bf528SMauro Carvalho Chehab 	0x91, 0x0,
2859a0bf528SMauro Carvalho Chehab 	0x92, 0x0,
2869a0bf528SMauro Carvalho Chehab 	0x93, 0x0,
2879a0bf528SMauro Carvalho Chehab 	0x94, 0x1c,
2889a0bf528SMauro Carvalho Chehab 	0x97, 0x0,
2899a0bf528SMauro Carvalho Chehab 	0xa0, 0x48,
2909a0bf528SMauro Carvalho Chehab 	0xa1, 0x0,
2919a0bf528SMauro Carvalho Chehab 	0xb0, 0xb8,
2929a0bf528SMauro Carvalho Chehab 	0xb1, 0x3a,
2939a0bf528SMauro Carvalho Chehab 	0xb2, 0x10,
2949a0bf528SMauro Carvalho Chehab 	0xb3, 0x82,
2959a0bf528SMauro Carvalho Chehab 	0xb4, 0x80,
2969a0bf528SMauro Carvalho Chehab 	0xb5, 0x82,
2979a0bf528SMauro Carvalho Chehab 	0xb6, 0x82,
2989a0bf528SMauro Carvalho Chehab 	0xb7, 0x82,
2999a0bf528SMauro Carvalho Chehab 	0xb8, 0x20,
3009a0bf528SMauro Carvalho Chehab 	0xb9, 0x0,
3019a0bf528SMauro Carvalho Chehab 	0xf0, 0x0,
3029a0bf528SMauro Carvalho Chehab 	0xf1, 0x0,
3039a0bf528SMauro Carvalho Chehab 	0xf2, 0xc0,
3049a0bf528SMauro Carvalho Chehab 	0x51, 0x36,
3059a0bf528SMauro Carvalho Chehab 	0x52, 0x09,
3069a0bf528SMauro Carvalho Chehab 	0x53, 0x94,
3079a0bf528SMauro Carvalho Chehab 	0x54, 0x62,
3089a0bf528SMauro Carvalho Chehab 	0x55, 0x29,
3099a0bf528SMauro Carvalho Chehab 	0x56, 0x64,
3109a0bf528SMauro Carvalho Chehab 	0x57, 0x2b,
3119a0bf528SMauro Carvalho Chehab 	0xff, 0xff,
3129a0bf528SMauro Carvalho Chehab };
3139a0bf528SMauro Carvalho Chehab 
stv0288_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage volt)3140df289a2SMauro Carvalho Chehab static int stv0288_set_voltage(struct dvb_frontend *fe,
3150df289a2SMauro Carvalho Chehab 			       enum fe_sec_voltage volt)
3169a0bf528SMauro Carvalho Chehab {
3179a0bf528SMauro Carvalho Chehab 	dprintk("%s: %s\n", __func__,
3189a0bf528SMauro Carvalho Chehab 		volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
3199a0bf528SMauro Carvalho Chehab 		volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
3209a0bf528SMauro Carvalho Chehab 
3219a0bf528SMauro Carvalho Chehab 	return 0;
3229a0bf528SMauro Carvalho Chehab }
3239a0bf528SMauro Carvalho Chehab 
stv0288_init(struct dvb_frontend * fe)3249a0bf528SMauro Carvalho Chehab static int stv0288_init(struct dvb_frontend *fe)
3259a0bf528SMauro Carvalho Chehab {
3269a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
3279a0bf528SMauro Carvalho Chehab 	int i;
3289a0bf528SMauro Carvalho Chehab 	u8 reg;
3299a0bf528SMauro Carvalho Chehab 	u8 val;
3309a0bf528SMauro Carvalho Chehab 
3319a0bf528SMauro Carvalho Chehab 	dprintk("stv0288: init chip\n");
3329a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x41, 0x04);
3339a0bf528SMauro Carvalho Chehab 	msleep(50);
3349a0bf528SMauro Carvalho Chehab 
3359a0bf528SMauro Carvalho Chehab 	/* we have default inittab */
3369a0bf528SMauro Carvalho Chehab 	if (state->config->inittab == NULL) {
3379a0bf528SMauro Carvalho Chehab 		for (i = 0; !(stv0288_inittab[i] == 0xff &&
3389a0bf528SMauro Carvalho Chehab 				stv0288_inittab[i + 1] == 0xff); i += 2)
3399a0bf528SMauro Carvalho Chehab 			stv0288_writeregI(state, stv0288_inittab[i],
3409a0bf528SMauro Carvalho Chehab 					stv0288_inittab[i + 1]);
3419a0bf528SMauro Carvalho Chehab 	} else {
3429a0bf528SMauro Carvalho Chehab 		for (i = 0; ; i += 2)  {
3439a0bf528SMauro Carvalho Chehab 			reg = state->config->inittab[i];
3449a0bf528SMauro Carvalho Chehab 			val = state->config->inittab[i+1];
3459a0bf528SMauro Carvalho Chehab 			if (reg == 0xff && val == 0xff)
3469a0bf528SMauro Carvalho Chehab 				break;
3479a0bf528SMauro Carvalho Chehab 			stv0288_writeregI(state, reg, val);
3489a0bf528SMauro Carvalho Chehab 		}
3499a0bf528SMauro Carvalho Chehab 	}
3509a0bf528SMauro Carvalho Chehab 	return 0;
3519a0bf528SMauro Carvalho Chehab }
3529a0bf528SMauro Carvalho Chehab 
stv0288_read_status(struct dvb_frontend * fe,enum fe_status * status)3530df289a2SMauro Carvalho Chehab static int stv0288_read_status(struct dvb_frontend *fe, enum fe_status *status)
3549a0bf528SMauro Carvalho Chehab {
3559a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
3569a0bf528SMauro Carvalho Chehab 
3579a0bf528SMauro Carvalho Chehab 	u8 sync = stv0288_readreg(state, 0x24);
3589a0bf528SMauro Carvalho Chehab 	if (sync == 255)
3599a0bf528SMauro Carvalho Chehab 		sync = 0;
3609a0bf528SMauro Carvalho Chehab 
3619a0bf528SMauro Carvalho Chehab 	dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
3629a0bf528SMauro Carvalho Chehab 
3639a0bf528SMauro Carvalho Chehab 	*status = 0;
3649a0bf528SMauro Carvalho Chehab 	if (sync & 0x80)
3659a0bf528SMauro Carvalho Chehab 		*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
3669a0bf528SMauro Carvalho Chehab 	if (sync & 0x10)
3679a0bf528SMauro Carvalho Chehab 		*status |= FE_HAS_VITERBI;
3689a0bf528SMauro Carvalho Chehab 	if (sync & 0x08) {
3699a0bf528SMauro Carvalho Chehab 		*status |= FE_HAS_LOCK;
3709a0bf528SMauro Carvalho Chehab 		dprintk("stv0288 has locked\n");
3719a0bf528SMauro Carvalho Chehab 	}
3729a0bf528SMauro Carvalho Chehab 
3739a0bf528SMauro Carvalho Chehab 	return 0;
3749a0bf528SMauro Carvalho Chehab }
3759a0bf528SMauro Carvalho Chehab 
stv0288_read_ber(struct dvb_frontend * fe,u32 * ber)3769a0bf528SMauro Carvalho Chehab static int stv0288_read_ber(struct dvb_frontend *fe, u32 *ber)
3779a0bf528SMauro Carvalho Chehab {
3789a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
3799a0bf528SMauro Carvalho Chehab 
3809a0bf528SMauro Carvalho Chehab 	if (state->errmode != STATUS_BER)
3819a0bf528SMauro Carvalho Chehab 		return 0;
3829a0bf528SMauro Carvalho Chehab 	*ber = (stv0288_readreg(state, 0x26) << 8) |
3839a0bf528SMauro Carvalho Chehab 					stv0288_readreg(state, 0x27);
3849a0bf528SMauro Carvalho Chehab 	dprintk("stv0288_read_ber %d\n", *ber);
3859a0bf528SMauro Carvalho Chehab 
3869a0bf528SMauro Carvalho Chehab 	return 0;
3879a0bf528SMauro Carvalho Chehab }
3889a0bf528SMauro Carvalho Chehab 
3899a0bf528SMauro Carvalho Chehab 
stv0288_read_signal_strength(struct dvb_frontend * fe,u16 * strength)3909a0bf528SMauro Carvalho Chehab static int stv0288_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
3919a0bf528SMauro Carvalho Chehab {
3929a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
3939a0bf528SMauro Carvalho Chehab 
3949a0bf528SMauro Carvalho Chehab 	s32 signal =  0xffff - ((stv0288_readreg(state, 0x10) << 8));
3959a0bf528SMauro Carvalho Chehab 
3969a0bf528SMauro Carvalho Chehab 
3979a0bf528SMauro Carvalho Chehab 	signal = signal * 5 / 4;
3989a0bf528SMauro Carvalho Chehab 	*strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal;
3999a0bf528SMauro Carvalho Chehab 	dprintk("stv0288_read_signal_strength %d\n", *strength);
4009a0bf528SMauro Carvalho Chehab 
4019a0bf528SMauro Carvalho Chehab 	return 0;
4029a0bf528SMauro Carvalho Chehab }
stv0288_sleep(struct dvb_frontend * fe)4039a0bf528SMauro Carvalho Chehab static int stv0288_sleep(struct dvb_frontend *fe)
4049a0bf528SMauro Carvalho Chehab {
4059a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
4069a0bf528SMauro Carvalho Chehab 
4079a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x41, 0x84);
4089a0bf528SMauro Carvalho Chehab 	state->initialised = 0;
4099a0bf528SMauro Carvalho Chehab 
4109a0bf528SMauro Carvalho Chehab 	return 0;
4119a0bf528SMauro Carvalho Chehab }
stv0288_read_snr(struct dvb_frontend * fe,u16 * snr)4129a0bf528SMauro Carvalho Chehab static int stv0288_read_snr(struct dvb_frontend *fe, u16 *snr)
4139a0bf528SMauro Carvalho Chehab {
4149a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
4159a0bf528SMauro Carvalho Chehab 
4169a0bf528SMauro Carvalho Chehab 	s32 xsnr = 0xffff - ((stv0288_readreg(state, 0x2d) << 8)
4179a0bf528SMauro Carvalho Chehab 			   | stv0288_readreg(state, 0x2e));
4189a0bf528SMauro Carvalho Chehab 	xsnr = 3 * (xsnr - 0xa100);
4199a0bf528SMauro Carvalho Chehab 	*snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
4209a0bf528SMauro Carvalho Chehab 	dprintk("stv0288_read_snr %d\n", *snr);
4219a0bf528SMauro Carvalho Chehab 
4229a0bf528SMauro Carvalho Chehab 	return 0;
4239a0bf528SMauro Carvalho Chehab }
4249a0bf528SMauro Carvalho Chehab 
stv0288_read_ucblocks(struct dvb_frontend * fe,u32 * ucblocks)4259a0bf528SMauro Carvalho Chehab static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
4269a0bf528SMauro Carvalho Chehab {
4279a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
4289a0bf528SMauro Carvalho Chehab 
4299a0bf528SMauro Carvalho Chehab 	if (state->errmode != STATUS_BER)
4309a0bf528SMauro Carvalho Chehab 		return 0;
4319a0bf528SMauro Carvalho Chehab 	*ucblocks = (stv0288_readreg(state, 0x26) << 8) |
4329a0bf528SMauro Carvalho Chehab 					stv0288_readreg(state, 0x27);
4339a0bf528SMauro Carvalho Chehab 	dprintk("stv0288_read_ber %d\n", *ucblocks);
4349a0bf528SMauro Carvalho Chehab 
4359a0bf528SMauro Carvalho Chehab 	return 0;
4369a0bf528SMauro Carvalho Chehab }
4379a0bf528SMauro Carvalho Chehab 
stv0288_set_frontend(struct dvb_frontend * fe)4389a0bf528SMauro Carvalho Chehab static int stv0288_set_frontend(struct dvb_frontend *fe)
4399a0bf528SMauro Carvalho Chehab {
4409a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
4419a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
4429a0bf528SMauro Carvalho Chehab 
44373921344SJason A. Donenfeld 	u8 tda[3], reg, time_out = 0;
44473921344SJason A. Donenfeld 	s8 tm;
4459a0bf528SMauro Carvalho Chehab 
4469a0bf528SMauro Carvalho Chehab 	dprintk("%s : FE_SET_FRONTEND\n", __func__);
4479a0bf528SMauro Carvalho Chehab 
4489a0bf528SMauro Carvalho Chehab 	if (c->delivery_system != SYS_DVBS) {
4494bd69e7bSMauro Carvalho Chehab 		dprintk("%s: unsupported delivery system selected (%d)\n",
4509a0bf528SMauro Carvalho Chehab 			__func__, c->delivery_system);
4519a0bf528SMauro Carvalho Chehab 		return -EOPNOTSUPP;
4529a0bf528SMauro Carvalho Chehab 	}
4539a0bf528SMauro Carvalho Chehab 
4549a0bf528SMauro Carvalho Chehab 	if (state->config->set_ts_params)
4559a0bf528SMauro Carvalho Chehab 		state->config->set_ts_params(fe, 0);
4569a0bf528SMauro Carvalho Chehab 
4579a0bf528SMauro Carvalho Chehab 	/* only frequency & symbol_rate are used for tuner*/
4589a0bf528SMauro Carvalho Chehab 	if (fe->ops.tuner_ops.set_params) {
4599a0bf528SMauro Carvalho Chehab 		fe->ops.tuner_ops.set_params(fe);
4609a0bf528SMauro Carvalho Chehab 		if (fe->ops.i2c_gate_ctrl)
4619a0bf528SMauro Carvalho Chehab 			fe->ops.i2c_gate_ctrl(fe, 0);
4629a0bf528SMauro Carvalho Chehab 	}
4639a0bf528SMauro Carvalho Chehab 
4649a0bf528SMauro Carvalho Chehab 	udelay(10);
4659a0bf528SMauro Carvalho Chehab 	stv0288_set_symbolrate(fe, c->symbol_rate);
4669a0bf528SMauro Carvalho Chehab 	/* Carrier lock control register */
4679a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x15, 0xc5);
4689a0bf528SMauro Carvalho Chehab 
4699a0bf528SMauro Carvalho Chehab 	tda[2] = 0x0; /* CFRL */
4709a0bf528SMauro Carvalho Chehab 	for (tm = -9; tm < 7;) {
4719a0bf528SMauro Carvalho Chehab 		/* Viterbi status */
4729a0bf528SMauro Carvalho Chehab 		reg = stv0288_readreg(state, 0x24);
4739a0bf528SMauro Carvalho Chehab 		if (reg & 0x8)
4749a0bf528SMauro Carvalho Chehab 				break;
4759a0bf528SMauro Carvalho Chehab 		if (reg & 0x80) {
4769a0bf528SMauro Carvalho Chehab 			time_out++;
4779a0bf528SMauro Carvalho Chehab 			if (time_out > 10)
4789a0bf528SMauro Carvalho Chehab 				break;
4799a0bf528SMauro Carvalho Chehab 			tda[2] += 40;
4809a0bf528SMauro Carvalho Chehab 			if (tda[2] < 40)
4819a0bf528SMauro Carvalho Chehab 				tm++;
4829a0bf528SMauro Carvalho Chehab 		} else {
4839a0bf528SMauro Carvalho Chehab 			tm++;
4849a0bf528SMauro Carvalho Chehab 			tda[2] = 0;
4859a0bf528SMauro Carvalho Chehab 			time_out = 0;
4869a0bf528SMauro Carvalho Chehab 		}
4879a0bf528SMauro Carvalho Chehab 		tda[1] = (unsigned char)tm;
4889a0bf528SMauro Carvalho Chehab 		stv0288_writeregI(state, 0x2b, tda[1]);
4899a0bf528SMauro Carvalho Chehab 		stv0288_writeregI(state, 0x2c, tda[2]);
4909a0bf528SMauro Carvalho Chehab 		msleep(30);
4919a0bf528SMauro Carvalho Chehab 	}
4929a0bf528SMauro Carvalho Chehab 	state->tuner_frequency = c->frequency;
4939a0bf528SMauro Carvalho Chehab 	state->fec_inner = FEC_AUTO;
4949a0bf528SMauro Carvalho Chehab 	state->symbol_rate = c->symbol_rate;
4959a0bf528SMauro Carvalho Chehab 
4969a0bf528SMauro Carvalho Chehab 	return 0;
4979a0bf528SMauro Carvalho Chehab }
4989a0bf528SMauro Carvalho Chehab 
stv0288_i2c_gate_ctrl(struct dvb_frontend * fe,int enable)4999a0bf528SMauro Carvalho Chehab static int stv0288_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
5009a0bf528SMauro Carvalho Chehab {
5019a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
5029a0bf528SMauro Carvalho Chehab 
5039a0bf528SMauro Carvalho Chehab 	if (enable)
5049a0bf528SMauro Carvalho Chehab 		stv0288_writeregI(state, 0x01, 0xb5);
5059a0bf528SMauro Carvalho Chehab 	else
5069a0bf528SMauro Carvalho Chehab 		stv0288_writeregI(state, 0x01, 0x35);
5079a0bf528SMauro Carvalho Chehab 
5089a0bf528SMauro Carvalho Chehab 	udelay(1);
5099a0bf528SMauro Carvalho Chehab 
5109a0bf528SMauro Carvalho Chehab 	return 0;
5119a0bf528SMauro Carvalho Chehab }
5129a0bf528SMauro Carvalho Chehab 
stv0288_release(struct dvb_frontend * fe)5139a0bf528SMauro Carvalho Chehab static void stv0288_release(struct dvb_frontend *fe)
5149a0bf528SMauro Carvalho Chehab {
5159a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = fe->demodulator_priv;
5169a0bf528SMauro Carvalho Chehab 	kfree(state);
5179a0bf528SMauro Carvalho Chehab }
5189a0bf528SMauro Carvalho Chehab 
519bd336e63SMax Kellermann static const struct dvb_frontend_ops stv0288_ops = {
5209a0bf528SMauro Carvalho Chehab 	.delsys = { SYS_DVBS },
5219a0bf528SMauro Carvalho Chehab 	.info = {
5229a0bf528SMauro Carvalho Chehab 		.name			= "ST STV0288 DVB-S",
523f1b1eabfSMauro Carvalho Chehab 		.frequency_min_hz	=  950 * MHz,
524f1b1eabfSMauro Carvalho Chehab 		.frequency_max_hz	= 2150 * MHz,
525f1b1eabfSMauro Carvalho Chehab 		.frequency_stepsize_hz	=    1 * MHz,
5269a0bf528SMauro Carvalho Chehab 		.symbol_rate_min	= 1000000,
5279a0bf528SMauro Carvalho Chehab 		.symbol_rate_max	= 45000000,
5289a0bf528SMauro Carvalho Chehab 		.symbol_rate_tolerance	= 500,	/* ppm */
5299a0bf528SMauro Carvalho Chehab 		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
5309a0bf528SMauro Carvalho Chehab 		      FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
5319a0bf528SMauro Carvalho Chehab 		      FE_CAN_QPSK |
5329a0bf528SMauro Carvalho Chehab 		      FE_CAN_FEC_AUTO
5339a0bf528SMauro Carvalho Chehab 	},
5349a0bf528SMauro Carvalho Chehab 
5359a0bf528SMauro Carvalho Chehab 	.release = stv0288_release,
5369a0bf528SMauro Carvalho Chehab 	.init = stv0288_init,
5379a0bf528SMauro Carvalho Chehab 	.sleep = stv0288_sleep,
5389a0bf528SMauro Carvalho Chehab 	.write = stv0288_write,
5399a0bf528SMauro Carvalho Chehab 	.i2c_gate_ctrl = stv0288_i2c_gate_ctrl,
5409a0bf528SMauro Carvalho Chehab 	.read_status = stv0288_read_status,
5419a0bf528SMauro Carvalho Chehab 	.read_ber = stv0288_read_ber,
5429a0bf528SMauro Carvalho Chehab 	.read_signal_strength = stv0288_read_signal_strength,
5439a0bf528SMauro Carvalho Chehab 	.read_snr = stv0288_read_snr,
5449a0bf528SMauro Carvalho Chehab 	.read_ucblocks = stv0288_read_ucblocks,
5459a0bf528SMauro Carvalho Chehab 	.diseqc_send_master_cmd = stv0288_send_diseqc_msg,
5469a0bf528SMauro Carvalho Chehab 	.diseqc_send_burst = stv0288_send_diseqc_burst,
5479a0bf528SMauro Carvalho Chehab 	.set_tone = stv0288_set_tone,
5489a0bf528SMauro Carvalho Chehab 	.set_voltage = stv0288_set_voltage,
5499a0bf528SMauro Carvalho Chehab 
5509a0bf528SMauro Carvalho Chehab 	.set_frontend = stv0288_set_frontend,
5519a0bf528SMauro Carvalho Chehab };
5529a0bf528SMauro Carvalho Chehab 
stv0288_attach(const struct stv0288_config * config,struct i2c_adapter * i2c)5539a0bf528SMauro Carvalho Chehab struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
5549a0bf528SMauro Carvalho Chehab 				    struct i2c_adapter *i2c)
5559a0bf528SMauro Carvalho Chehab {
5569a0bf528SMauro Carvalho Chehab 	struct stv0288_state *state = NULL;
5579a0bf528SMauro Carvalho Chehab 	int id;
5589a0bf528SMauro Carvalho Chehab 
5599a0bf528SMauro Carvalho Chehab 	/* allocate memory for the internal state */
5609a0bf528SMauro Carvalho Chehab 	state = kzalloc(sizeof(struct stv0288_state), GFP_KERNEL);
5619a0bf528SMauro Carvalho Chehab 	if (state == NULL)
5629a0bf528SMauro Carvalho Chehab 		goto error;
5639a0bf528SMauro Carvalho Chehab 
5649a0bf528SMauro Carvalho Chehab 	/* setup the state */
5659a0bf528SMauro Carvalho Chehab 	state->config = config;
5669a0bf528SMauro Carvalho Chehab 	state->i2c = i2c;
5679a0bf528SMauro Carvalho Chehab 	state->initialised = 0;
5689a0bf528SMauro Carvalho Chehab 	state->tuner_frequency = 0;
5699a0bf528SMauro Carvalho Chehab 	state->symbol_rate = 0;
5709a0bf528SMauro Carvalho Chehab 	state->fec_inner = 0;
5719a0bf528SMauro Carvalho Chehab 	state->errmode = STATUS_BER;
5729a0bf528SMauro Carvalho Chehab 
5739a0bf528SMauro Carvalho Chehab 	stv0288_writeregI(state, 0x41, 0x04);
5749a0bf528SMauro Carvalho Chehab 	msleep(200);
5759a0bf528SMauro Carvalho Chehab 	id = stv0288_readreg(state, 0x00);
5769a0bf528SMauro Carvalho Chehab 	dprintk("stv0288 id %x\n", id);
5779a0bf528SMauro Carvalho Chehab 
5789a0bf528SMauro Carvalho Chehab 	/* register 0x00 contains 0x11 for STV0288  */
5799a0bf528SMauro Carvalho Chehab 	if (id != 0x11)
5809a0bf528SMauro Carvalho Chehab 		goto error;
5819a0bf528SMauro Carvalho Chehab 
5829a0bf528SMauro Carvalho Chehab 	/* create dvb_frontend */
5839a0bf528SMauro Carvalho Chehab 	memcpy(&state->frontend.ops, &stv0288_ops,
5849a0bf528SMauro Carvalho Chehab 			sizeof(struct dvb_frontend_ops));
5859a0bf528SMauro Carvalho Chehab 	state->frontend.demodulator_priv = state;
5869a0bf528SMauro Carvalho Chehab 	return &state->frontend;
5879a0bf528SMauro Carvalho Chehab 
5889a0bf528SMauro Carvalho Chehab error:
5899a0bf528SMauro Carvalho Chehab 	kfree(state);
5909a0bf528SMauro Carvalho Chehab 
5919a0bf528SMauro Carvalho Chehab 	return NULL;
5929a0bf528SMauro Carvalho Chehab }
593*86495af1SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(stv0288_attach);
5949a0bf528SMauro Carvalho Chehab 
5959a0bf528SMauro Carvalho Chehab module_param(debug_legacy_dish_switch, int, 0444);
5969a0bf528SMauro Carvalho Chehab MODULE_PARM_DESC(debug_legacy_dish_switch,
5979a0bf528SMauro Carvalho Chehab 		"Enable timing analysis for Dish Network legacy switches");
5989a0bf528SMauro Carvalho Chehab 
5999a0bf528SMauro Carvalho Chehab module_param(debug, int, 0644);
6009a0bf528SMauro Carvalho Chehab MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
6019a0bf528SMauro Carvalho Chehab 
6029a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("ST STV0288 DVB Demodulator driver");
6039a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Georg Acher, Bob Liu, Igor liplianin");
6049a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL");
6059a0bf528SMauro Carvalho Chehab 
606