1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
29a0bf528SMauro Carvalho Chehab /*
39a0bf528SMauro Carvalho Chehab  *    Support for OR51132 (pcHDTV HD-3000) - VSB/QAM
49a0bf528SMauro Carvalho Chehab  *
59a0bf528SMauro Carvalho Chehab  *    Copyright (C) 2007 Trent Piepho <xyzzy@speakeasy.org>
69a0bf528SMauro Carvalho Chehab  *
79a0bf528SMauro Carvalho Chehab  *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
89a0bf528SMauro Carvalho Chehab  *
99a0bf528SMauro Carvalho Chehab  *    Based on code from Jack Kelliher (kelliher@xmission.com)
109a0bf528SMauro Carvalho Chehab  *                           Copyright (C) 2002 & pcHDTV, inc.
119a0bf528SMauro Carvalho Chehab */
129a0bf528SMauro Carvalho Chehab 
139a0bf528SMauro Carvalho Chehab /*
149a0bf528SMauro Carvalho Chehab  * This driver needs two external firmware files. Please copy
159a0bf528SMauro Carvalho Chehab  * "dvb-fe-or51132-vsb.fw" and "dvb-fe-or51132-qam.fw" to
169a0bf528SMauro Carvalho Chehab  * /usr/lib/hotplug/firmware/ or /lib/firmware/
179a0bf528SMauro Carvalho Chehab  * (depending on configuration of firmware hotplug).
189a0bf528SMauro Carvalho Chehab  */
199a0bf528SMauro Carvalho Chehab #define OR51132_VSB_FIRMWARE "dvb-fe-or51132-vsb.fw"
209a0bf528SMauro Carvalho Chehab #define OR51132_QAM_FIRMWARE "dvb-fe-or51132-qam.fw"
219a0bf528SMauro Carvalho Chehab 
229a0bf528SMauro Carvalho Chehab #include <linux/kernel.h>
239a0bf528SMauro Carvalho Chehab #include <linux/module.h>
249a0bf528SMauro Carvalho Chehab #include <linux/init.h>
259a0bf528SMauro Carvalho Chehab #include <linux/delay.h>
269a0bf528SMauro Carvalho Chehab #include <linux/string.h>
279a0bf528SMauro Carvalho Chehab #include <linux/slab.h>
289a0bf528SMauro Carvalho Chehab #include <asm/byteorder.h>
299a0bf528SMauro Carvalho Chehab 
30f97fa3dcSAndy Shevchenko #include <linux/int_log.h>
31fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h>
329a0bf528SMauro Carvalho Chehab #include "or51132.h"
339a0bf528SMauro Carvalho Chehab 
349a0bf528SMauro Carvalho Chehab static int debug;
359a0bf528SMauro Carvalho Chehab #define dprintk(args...) \
369a0bf528SMauro Carvalho Chehab 	do { \
379a0bf528SMauro Carvalho Chehab 		if (debug) printk(KERN_DEBUG "or51132: " args); \
389a0bf528SMauro Carvalho Chehab 	} while (0)
399a0bf528SMauro Carvalho Chehab 
409a0bf528SMauro Carvalho Chehab 
419a0bf528SMauro Carvalho Chehab struct or51132_state
429a0bf528SMauro Carvalho Chehab {
439a0bf528SMauro Carvalho Chehab 	struct i2c_adapter* i2c;
449a0bf528SMauro Carvalho Chehab 
459a0bf528SMauro Carvalho Chehab 	/* Configuration settings */
469a0bf528SMauro Carvalho Chehab 	const struct or51132_config* config;
479a0bf528SMauro Carvalho Chehab 
489a0bf528SMauro Carvalho Chehab 	struct dvb_frontend frontend;
499a0bf528SMauro Carvalho Chehab 
509a0bf528SMauro Carvalho Chehab 	/* Demodulator private data */
510df289a2SMauro Carvalho Chehab 	enum fe_modulation current_modulation;
529a0bf528SMauro Carvalho Chehab 	u32 snr; /* Result of last SNR calculation */
539a0bf528SMauro Carvalho Chehab 
549a0bf528SMauro Carvalho Chehab 	/* Tuner private data */
559a0bf528SMauro Carvalho Chehab 	u32 current_frequency;
569a0bf528SMauro Carvalho Chehab };
579a0bf528SMauro Carvalho Chehab 
589a0bf528SMauro Carvalho Chehab 
599a0bf528SMauro Carvalho Chehab /* Write buffer to demod */
or51132_writebuf(struct or51132_state * state,const u8 * buf,int len)609a0bf528SMauro Carvalho Chehab static int or51132_writebuf(struct or51132_state *state, const u8 *buf, int len)
619a0bf528SMauro Carvalho Chehab {
629a0bf528SMauro Carvalho Chehab 	int err;
639a0bf528SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = state->config->demod_address,
649a0bf528SMauro Carvalho Chehab 			       .flags = 0, .buf = (u8*)buf, .len = len };
659a0bf528SMauro Carvalho Chehab 
669a0bf528SMauro Carvalho Chehab 	/* msleep(20); */ /* doesn't appear to be necessary */
679a0bf528SMauro Carvalho Chehab 	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
689a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: I2C write (addr 0x%02x len %d) error: %d\n",
699a0bf528SMauro Carvalho Chehab 		       msg.addr, msg.len, err);
709a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
719a0bf528SMauro Carvalho Chehab 	}
729a0bf528SMauro Carvalho Chehab 	return 0;
739a0bf528SMauro Carvalho Chehab }
749a0bf528SMauro Carvalho Chehab 
759a0bf528SMauro Carvalho Chehab /* Write constant bytes, e.g. or51132_writebytes(state, 0x04, 0x42, 0x00);
769a0bf528SMauro Carvalho Chehab    Less code and more efficient that loading a buffer on the stack with
779a0bf528SMauro Carvalho Chehab    the bytes to send and then calling or51132_writebuf() on that. */
789a0bf528SMauro Carvalho Chehab #define or51132_writebytes(state, data...)  \
799a0bf528SMauro Carvalho Chehab 	({ static const u8 _data[] = {data}; \
809a0bf528SMauro Carvalho Chehab 	or51132_writebuf(state, _data, sizeof(_data)); })
819a0bf528SMauro Carvalho Chehab 
829a0bf528SMauro Carvalho Chehab /* Read data from demod into buffer.  Returns 0 on success. */
or51132_readbuf(struct or51132_state * state,u8 * buf,int len)839a0bf528SMauro Carvalho Chehab static int or51132_readbuf(struct or51132_state *state, u8 *buf, int len)
849a0bf528SMauro Carvalho Chehab {
859a0bf528SMauro Carvalho Chehab 	int err;
869a0bf528SMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = state->config->demod_address,
879a0bf528SMauro Carvalho Chehab 			       .flags = I2C_M_RD, .buf = buf, .len = len };
889a0bf528SMauro Carvalho Chehab 
899a0bf528SMauro Carvalho Chehab 	/* msleep(20); */ /* doesn't appear to be necessary */
909a0bf528SMauro Carvalho Chehab 	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
919a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: I2C read (addr 0x%02x len %d) error: %d\n",
929a0bf528SMauro Carvalho Chehab 		       msg.addr, msg.len, err);
939a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
949a0bf528SMauro Carvalho Chehab 	}
959a0bf528SMauro Carvalho Chehab 	return 0;
969a0bf528SMauro Carvalho Chehab }
979a0bf528SMauro Carvalho Chehab 
989a0bf528SMauro Carvalho Chehab /* Reads a 16-bit demod register.  Returns <0 on error. */
or51132_readreg(struct or51132_state * state,u8 reg)999a0bf528SMauro Carvalho Chehab static int or51132_readreg(struct or51132_state *state, u8 reg)
1009a0bf528SMauro Carvalho Chehab {
1019a0bf528SMauro Carvalho Chehab 	u8 buf[2] = { 0x04, reg };
1029a0bf528SMauro Carvalho Chehab 	struct i2c_msg msg[2] = {
1039a0bf528SMauro Carvalho Chehab 		{.addr = state->config->demod_address, .flags = 0,
1049a0bf528SMauro Carvalho Chehab 		 .buf = buf, .len = 2 },
1059a0bf528SMauro Carvalho Chehab 		{.addr = state->config->demod_address, .flags = I2C_M_RD,
1069a0bf528SMauro Carvalho Chehab 		 .buf = buf, .len = 2 }};
1079a0bf528SMauro Carvalho Chehab 	int err;
1089a0bf528SMauro Carvalho Chehab 
1099a0bf528SMauro Carvalho Chehab 	if ((err = i2c_transfer(state->i2c, msg, 2)) != 2) {
1109a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: I2C error reading register %d: %d\n",
1119a0bf528SMauro Carvalho Chehab 		       reg, err);
1129a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
1139a0bf528SMauro Carvalho Chehab 	}
1149a0bf528SMauro Carvalho Chehab 	return buf[0] | (buf[1] << 8);
1159a0bf528SMauro Carvalho Chehab }
1169a0bf528SMauro Carvalho Chehab 
or51132_load_firmware(struct dvb_frontend * fe,const struct firmware * fw)1179a0bf528SMauro Carvalho Chehab static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
1189a0bf528SMauro Carvalho Chehab {
1199a0bf528SMauro Carvalho Chehab 	struct or51132_state* state = fe->demodulator_priv;
1209a0bf528SMauro Carvalho Chehab 	static const u8 run_buf[] = {0x7F,0x01};
1219a0bf528SMauro Carvalho Chehab 	u8 rec_buf[8];
1229a0bf528SMauro Carvalho Chehab 	u32 firmwareAsize, firmwareBsize;
1239a0bf528SMauro Carvalho Chehab 	int i,ret;
1249a0bf528SMauro Carvalho Chehab 
1255b5e0928SAlexey Dobriyan 	dprintk("Firmware is %zd bytes\n",fw->size);
1269a0bf528SMauro Carvalho Chehab 
1279a0bf528SMauro Carvalho Chehab 	/* Get size of firmware A and B */
1289a0bf528SMauro Carvalho Chehab 	firmwareAsize = le32_to_cpu(*((__le32*)fw->data));
1299a0bf528SMauro Carvalho Chehab 	dprintk("FirmwareA is %i bytes\n",firmwareAsize);
1309a0bf528SMauro Carvalho Chehab 	firmwareBsize = le32_to_cpu(*((__le32*)(fw->data+4)));
1319a0bf528SMauro Carvalho Chehab 	dprintk("FirmwareB is %i bytes\n",firmwareBsize);
1329a0bf528SMauro Carvalho Chehab 
1339a0bf528SMauro Carvalho Chehab 	/* Upload firmware */
1349a0bf528SMauro Carvalho Chehab 	if ((ret = or51132_writebuf(state, &fw->data[8], firmwareAsize))) {
1359a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: load_firmware error 1\n");
1369a0bf528SMauro Carvalho Chehab 		return ret;
1379a0bf528SMauro Carvalho Chehab 	}
1389a0bf528SMauro Carvalho Chehab 	if ((ret = or51132_writebuf(state, &fw->data[8+firmwareAsize],
1399a0bf528SMauro Carvalho Chehab 				    firmwareBsize))) {
1409a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: load_firmware error 2\n");
1419a0bf528SMauro Carvalho Chehab 		return ret;
1429a0bf528SMauro Carvalho Chehab 	}
1439a0bf528SMauro Carvalho Chehab 
1449a0bf528SMauro Carvalho Chehab 	if ((ret = or51132_writebuf(state, run_buf, 2))) {
1459a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: load_firmware error 3\n");
1469a0bf528SMauro Carvalho Chehab 		return ret;
1479a0bf528SMauro Carvalho Chehab 	}
1489a0bf528SMauro Carvalho Chehab 	if ((ret = or51132_writebuf(state, run_buf, 2))) {
1499a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: load_firmware error 4\n");
1509a0bf528SMauro Carvalho Chehab 		return ret;
1519a0bf528SMauro Carvalho Chehab 	}
1529a0bf528SMauro Carvalho Chehab 
1539a0bf528SMauro Carvalho Chehab 	/* 50ms for operation to begin */
1549a0bf528SMauro Carvalho Chehab 	msleep(50);
1559a0bf528SMauro Carvalho Chehab 
1569a0bf528SMauro Carvalho Chehab 	/* Read back ucode version to besure we loaded correctly and are really up and running */
1579a0bf528SMauro Carvalho Chehab 	/* Get uCode version */
1589a0bf528SMauro Carvalho Chehab 	if ((ret = or51132_writebytes(state, 0x10, 0x10, 0x00))) {
1599a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: load_firmware error a\n");
1609a0bf528SMauro Carvalho Chehab 		return ret;
1619a0bf528SMauro Carvalho Chehab 	}
1629a0bf528SMauro Carvalho Chehab 	if ((ret = or51132_writebytes(state, 0x04, 0x17))) {
1639a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: load_firmware error b\n");
1649a0bf528SMauro Carvalho Chehab 		return ret;
1659a0bf528SMauro Carvalho Chehab 	}
1669a0bf528SMauro Carvalho Chehab 	if ((ret = or51132_writebytes(state, 0x00, 0x00))) {
1679a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: load_firmware error c\n");
1689a0bf528SMauro Carvalho Chehab 		return ret;
1699a0bf528SMauro Carvalho Chehab 	}
1709a0bf528SMauro Carvalho Chehab 	for (i=0;i<4;i++) {
1719a0bf528SMauro Carvalho Chehab 		/* Once upon a time, this command might have had something
1729a0bf528SMauro Carvalho Chehab 		   to do with getting the firmware version, but it's
1739a0bf528SMauro Carvalho Chehab 		   not used anymore:
1749a0bf528SMauro Carvalho Chehab 		   {0x04,0x00,0x30,0x00,i+1} */
1759a0bf528SMauro Carvalho Chehab 		/* Read 8 bytes, two bytes at a time */
1769a0bf528SMauro Carvalho Chehab 		if ((ret = or51132_readbuf(state, &rec_buf[i*2], 2))) {
1779a0bf528SMauro Carvalho Chehab 			printk(KERN_WARNING
1789a0bf528SMauro Carvalho Chehab 			       "or51132: load_firmware error d - %d\n",i);
1799a0bf528SMauro Carvalho Chehab 			return ret;
1809a0bf528SMauro Carvalho Chehab 		}
1819a0bf528SMauro Carvalho Chehab 	}
1829a0bf528SMauro Carvalho Chehab 
1839a0bf528SMauro Carvalho Chehab 	printk(KERN_WARNING
1849a0bf528SMauro Carvalho Chehab 	       "or51132: Version: %02X%02X%02X%02X-%02X%02X%02X%02X (%02X%01X-%01X-%02X%01X-%01X)\n",
1859a0bf528SMauro Carvalho Chehab 	       rec_buf[1],rec_buf[0],rec_buf[3],rec_buf[2],
1869a0bf528SMauro Carvalho Chehab 	       rec_buf[5],rec_buf[4],rec_buf[7],rec_buf[6],
1879a0bf528SMauro Carvalho Chehab 	       rec_buf[3],rec_buf[2]>>4,rec_buf[2]&0x0f,
1889a0bf528SMauro Carvalho Chehab 	       rec_buf[5],rec_buf[4]>>4,rec_buf[4]&0x0f);
1899a0bf528SMauro Carvalho Chehab 
1909a0bf528SMauro Carvalho Chehab 	if ((ret = or51132_writebytes(state, 0x10, 0x00, 0x00))) {
1919a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: load_firmware error e\n");
1929a0bf528SMauro Carvalho Chehab 		return ret;
1939a0bf528SMauro Carvalho Chehab 	}
1949a0bf528SMauro Carvalho Chehab 	return 0;
1959a0bf528SMauro Carvalho Chehab };
1969a0bf528SMauro Carvalho Chehab 
or51132_init(struct dvb_frontend * fe)1979a0bf528SMauro Carvalho Chehab static int or51132_init(struct dvb_frontend* fe)
1989a0bf528SMauro Carvalho Chehab {
1999a0bf528SMauro Carvalho Chehab 	return 0;
2009a0bf528SMauro Carvalho Chehab }
2019a0bf528SMauro Carvalho Chehab 
or51132_read_ber(struct dvb_frontend * fe,u32 * ber)2029a0bf528SMauro Carvalho Chehab static int or51132_read_ber(struct dvb_frontend* fe, u32* ber)
2039a0bf528SMauro Carvalho Chehab {
2049a0bf528SMauro Carvalho Chehab 	*ber = 0;
2059a0bf528SMauro Carvalho Chehab 	return 0;
2069a0bf528SMauro Carvalho Chehab }
2079a0bf528SMauro Carvalho Chehab 
or51132_read_ucblocks(struct dvb_frontend * fe,u32 * ucblocks)2089a0bf528SMauro Carvalho Chehab static int or51132_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
2099a0bf528SMauro Carvalho Chehab {
2109a0bf528SMauro Carvalho Chehab 	*ucblocks = 0;
2119a0bf528SMauro Carvalho Chehab 	return 0;
2129a0bf528SMauro Carvalho Chehab }
2139a0bf528SMauro Carvalho Chehab 
or51132_sleep(struct dvb_frontend * fe)2149a0bf528SMauro Carvalho Chehab static int or51132_sleep(struct dvb_frontend* fe)
2159a0bf528SMauro Carvalho Chehab {
2169a0bf528SMauro Carvalho Chehab 	return 0;
2179a0bf528SMauro Carvalho Chehab }
2189a0bf528SMauro Carvalho Chehab 
or51132_setmode(struct dvb_frontend * fe)2199a0bf528SMauro Carvalho Chehab static int or51132_setmode(struct dvb_frontend* fe)
2209a0bf528SMauro Carvalho Chehab {
2219a0bf528SMauro Carvalho Chehab 	struct or51132_state* state = fe->demodulator_priv;
2229a0bf528SMauro Carvalho Chehab 	u8 cmd_buf1[3] = {0x04, 0x01, 0x5f};
2239a0bf528SMauro Carvalho Chehab 	u8 cmd_buf2[3] = {0x1c, 0x00, 0 };
2249a0bf528SMauro Carvalho Chehab 
2259a0bf528SMauro Carvalho Chehab 	dprintk("setmode %d\n",(int)state->current_modulation);
2269a0bf528SMauro Carvalho Chehab 
2279a0bf528SMauro Carvalho Chehab 	switch (state->current_modulation) {
2289a0bf528SMauro Carvalho Chehab 	case VSB_8:
2299a0bf528SMauro Carvalho Chehab 		/* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high */
2309a0bf528SMauro Carvalho Chehab 		cmd_buf1[2] = 0x50;
2319a0bf528SMauro Carvalho Chehab 		/* REC MODE inv IF spectrum, Normal */
2329a0bf528SMauro Carvalho Chehab 		cmd_buf2[1] = 0x03;
2339a0bf528SMauro Carvalho Chehab 		/* Channel MODE ATSC/VSB8 */
2349a0bf528SMauro Carvalho Chehab 		cmd_buf2[2] = 0x06;
2359a0bf528SMauro Carvalho Chehab 		break;
2369a0bf528SMauro Carvalho Chehab 	/* All QAM modes are:
2379a0bf528SMauro Carvalho Chehab 	   Auto-deinterleave; MPEGser, MPEG2tr, phase noise-high
2389a0bf528SMauro Carvalho Chehab 	   REC MODE Normal Carrier Lock */
2399a0bf528SMauro Carvalho Chehab 	case QAM_AUTO:
2409a0bf528SMauro Carvalho Chehab 		/* Channel MODE Auto QAM64/256 */
2419a0bf528SMauro Carvalho Chehab 		cmd_buf2[2] = 0x4f;
2429a0bf528SMauro Carvalho Chehab 		break;
2439a0bf528SMauro Carvalho Chehab 	case QAM_256:
2449a0bf528SMauro Carvalho Chehab 		/* Channel MODE QAM256 */
2459a0bf528SMauro Carvalho Chehab 		cmd_buf2[2] = 0x45;
2469a0bf528SMauro Carvalho Chehab 		break;
2479a0bf528SMauro Carvalho Chehab 	case QAM_64:
2489a0bf528SMauro Carvalho Chehab 		/* Channel MODE QAM64 */
2499a0bf528SMauro Carvalho Chehab 		cmd_buf2[2] = 0x43;
2509a0bf528SMauro Carvalho Chehab 		break;
2519a0bf528SMauro Carvalho Chehab 	default:
2529a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING
2539a0bf528SMauro Carvalho Chehab 		       "or51132: setmode: Modulation set to unsupported value (%d)\n",
2549a0bf528SMauro Carvalho Chehab 		       state->current_modulation);
2559a0bf528SMauro Carvalho Chehab 		return -EINVAL;
2569a0bf528SMauro Carvalho Chehab 	}
2579a0bf528SMauro Carvalho Chehab 
2589a0bf528SMauro Carvalho Chehab 	/* Set Receiver 1 register */
2599a0bf528SMauro Carvalho Chehab 	if (or51132_writebuf(state, cmd_buf1, 3)) {
2609a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: set_mode error 1\n");
2619a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
2629a0bf528SMauro Carvalho Chehab 	}
2639a0bf528SMauro Carvalho Chehab 	dprintk("set #1 to %02x\n", cmd_buf1[2]);
2649a0bf528SMauro Carvalho Chehab 
2659a0bf528SMauro Carvalho Chehab 	/* Set operation mode in Receiver 6 register */
2669a0bf528SMauro Carvalho Chehab 	if (or51132_writebuf(state, cmd_buf2, 3)) {
2679a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: set_mode error 2\n");
2689a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
2699a0bf528SMauro Carvalho Chehab 	}
2709a0bf528SMauro Carvalho Chehab 	dprintk("set #6 to 0x%02x%02x\n", cmd_buf2[1], cmd_buf2[2]);
2719a0bf528SMauro Carvalho Chehab 
2729a0bf528SMauro Carvalho Chehab 	return 0;
2739a0bf528SMauro Carvalho Chehab }
2749a0bf528SMauro Carvalho Chehab 
2759a0bf528SMauro Carvalho Chehab /* Some modulations use the same firmware.  This classifies modulations
2769a0bf528SMauro Carvalho Chehab    by the firmware they use. */
2779a0bf528SMauro Carvalho Chehab #define MOD_FWCLASS_UNKNOWN	0
2789a0bf528SMauro Carvalho Chehab #define MOD_FWCLASS_VSB		1
2799a0bf528SMauro Carvalho Chehab #define MOD_FWCLASS_QAM		2
modulation_fw_class(enum fe_modulation modulation)2800df289a2SMauro Carvalho Chehab static int modulation_fw_class(enum fe_modulation modulation)
2819a0bf528SMauro Carvalho Chehab {
2829a0bf528SMauro Carvalho Chehab 	switch(modulation) {
2839a0bf528SMauro Carvalho Chehab 	case VSB_8:
2849a0bf528SMauro Carvalho Chehab 		return MOD_FWCLASS_VSB;
2859a0bf528SMauro Carvalho Chehab 	case QAM_AUTO:
2869a0bf528SMauro Carvalho Chehab 	case QAM_64:
2879a0bf528SMauro Carvalho Chehab 	case QAM_256:
2889a0bf528SMauro Carvalho Chehab 		return MOD_FWCLASS_QAM;
2899a0bf528SMauro Carvalho Chehab 	default:
2909a0bf528SMauro Carvalho Chehab 		return MOD_FWCLASS_UNKNOWN;
2919a0bf528SMauro Carvalho Chehab 	}
2929a0bf528SMauro Carvalho Chehab }
2939a0bf528SMauro Carvalho Chehab 
or51132_set_parameters(struct dvb_frontend * fe)2949a0bf528SMauro Carvalho Chehab static int or51132_set_parameters(struct dvb_frontend *fe)
2959a0bf528SMauro Carvalho Chehab {
2969a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
2979a0bf528SMauro Carvalho Chehab 	int ret;
2989a0bf528SMauro Carvalho Chehab 	struct or51132_state* state = fe->demodulator_priv;
2999a0bf528SMauro Carvalho Chehab 	const struct firmware *fw;
3009a0bf528SMauro Carvalho Chehab 	const char *fwname;
3019a0bf528SMauro Carvalho Chehab 	int clock_mode;
3029a0bf528SMauro Carvalho Chehab 
3039a0bf528SMauro Carvalho Chehab 	/* Upload new firmware only if we need a different one */
3049a0bf528SMauro Carvalho Chehab 	if (modulation_fw_class(state->current_modulation) !=
3059a0bf528SMauro Carvalho Chehab 	    modulation_fw_class(p->modulation)) {
3069a0bf528SMauro Carvalho Chehab 		switch (modulation_fw_class(p->modulation)) {
3079a0bf528SMauro Carvalho Chehab 		case MOD_FWCLASS_VSB:
3089a0bf528SMauro Carvalho Chehab 			dprintk("set_parameters VSB MODE\n");
3099a0bf528SMauro Carvalho Chehab 			fwname = OR51132_VSB_FIRMWARE;
3109a0bf528SMauro Carvalho Chehab 
3119a0bf528SMauro Carvalho Chehab 			/* Set non-punctured clock for VSB */
3129a0bf528SMauro Carvalho Chehab 			clock_mode = 0;
3139a0bf528SMauro Carvalho Chehab 			break;
3149a0bf528SMauro Carvalho Chehab 		case MOD_FWCLASS_QAM:
3159a0bf528SMauro Carvalho Chehab 			dprintk("set_parameters QAM MODE\n");
3169a0bf528SMauro Carvalho Chehab 			fwname = OR51132_QAM_FIRMWARE;
3179a0bf528SMauro Carvalho Chehab 
3189a0bf528SMauro Carvalho Chehab 			/* Set punctured clock for QAM */
3199a0bf528SMauro Carvalho Chehab 			clock_mode = 1;
3209a0bf528SMauro Carvalho Chehab 			break;
3219a0bf528SMauro Carvalho Chehab 		default:
3229a0bf528SMauro Carvalho Chehab 			printk("or51132: Modulation type(%d) UNSUPPORTED\n",
3239a0bf528SMauro Carvalho Chehab 			       p->modulation);
3249a0bf528SMauro Carvalho Chehab 			return -1;
3259a0bf528SMauro Carvalho Chehab 		}
3269a0bf528SMauro Carvalho Chehab 		printk("or51132: Waiting for firmware upload(%s)...\n",
3279a0bf528SMauro Carvalho Chehab 		       fwname);
3289a0bf528SMauro Carvalho Chehab 		ret = request_firmware(&fw, fwname, state->i2c->dev.parent);
3299a0bf528SMauro Carvalho Chehab 		if (ret) {
3304bd69e7bSMauro Carvalho Chehab 			printk(KERN_WARNING "or51132: No firmware uploaded(timeout or file not found?)\n");
3319a0bf528SMauro Carvalho Chehab 			return ret;
3329a0bf528SMauro Carvalho Chehab 		}
3339a0bf528SMauro Carvalho Chehab 		ret = or51132_load_firmware(fe, fw);
3349a0bf528SMauro Carvalho Chehab 		release_firmware(fw);
3359a0bf528SMauro Carvalho Chehab 		if (ret) {
3364bd69e7bSMauro Carvalho Chehab 			printk(KERN_WARNING "or51132: Writing firmware to device failed!\n");
3379a0bf528SMauro Carvalho Chehab 			return ret;
3389a0bf528SMauro Carvalho Chehab 		}
3399a0bf528SMauro Carvalho Chehab 		printk("or51132: Firmware upload complete.\n");
3409a0bf528SMauro Carvalho Chehab 		state->config->set_ts_params(fe, clock_mode);
3419a0bf528SMauro Carvalho Chehab 	}
3429a0bf528SMauro Carvalho Chehab 	/* Change only if we are actually changing the modulation */
3439a0bf528SMauro Carvalho Chehab 	if (state->current_modulation != p->modulation) {
3449a0bf528SMauro Carvalho Chehab 		state->current_modulation = p->modulation;
3459a0bf528SMauro Carvalho Chehab 		or51132_setmode(fe);
3469a0bf528SMauro Carvalho Chehab 	}
3479a0bf528SMauro Carvalho Chehab 
3489a0bf528SMauro Carvalho Chehab 	if (fe->ops.tuner_ops.set_params) {
3499a0bf528SMauro Carvalho Chehab 		fe->ops.tuner_ops.set_params(fe);
3509a0bf528SMauro Carvalho Chehab 		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
3519a0bf528SMauro Carvalho Chehab 	}
3529a0bf528SMauro Carvalho Chehab 
3539a0bf528SMauro Carvalho Chehab 	/* Set to current mode */
3549a0bf528SMauro Carvalho Chehab 	or51132_setmode(fe);
3559a0bf528SMauro Carvalho Chehab 
3569a0bf528SMauro Carvalho Chehab 	/* Update current frequency */
3579a0bf528SMauro Carvalho Chehab 	state->current_frequency = p->frequency;
3589a0bf528SMauro Carvalho Chehab 	return 0;
3599a0bf528SMauro Carvalho Chehab }
3609a0bf528SMauro Carvalho Chehab 
or51132_get_parameters(struct dvb_frontend * fe,struct dtv_frontend_properties * p)3617e3e68bcSMauro Carvalho Chehab static int or51132_get_parameters(struct dvb_frontend* fe,
3627e3e68bcSMauro Carvalho Chehab 				  struct dtv_frontend_properties *p)
3639a0bf528SMauro Carvalho Chehab {
3649a0bf528SMauro Carvalho Chehab 	struct or51132_state* state = fe->demodulator_priv;
3659a0bf528SMauro Carvalho Chehab 	int status;
3669a0bf528SMauro Carvalho Chehab 	int retry = 1;
3679a0bf528SMauro Carvalho Chehab 
3689a0bf528SMauro Carvalho Chehab start:
3699a0bf528SMauro Carvalho Chehab 	/* Receiver Status */
3709a0bf528SMauro Carvalho Chehab 	if ((status = or51132_readreg(state, 0x00)) < 0) {
3719a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: get_parameters: error reading receiver status\n");
3729a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
3739a0bf528SMauro Carvalho Chehab 	}
3749a0bf528SMauro Carvalho Chehab 	switch(status&0xff) {
3759a0bf528SMauro Carvalho Chehab 	case 0x06:
3769a0bf528SMauro Carvalho Chehab 		p->modulation = VSB_8;
3779a0bf528SMauro Carvalho Chehab 		break;
3789a0bf528SMauro Carvalho Chehab 	case 0x43:
3799a0bf528SMauro Carvalho Chehab 		p->modulation = QAM_64;
3809a0bf528SMauro Carvalho Chehab 		break;
3819a0bf528SMauro Carvalho Chehab 	case 0x45:
3829a0bf528SMauro Carvalho Chehab 		p->modulation = QAM_256;
3839a0bf528SMauro Carvalho Chehab 		break;
3849a0bf528SMauro Carvalho Chehab 	default:
3859a0bf528SMauro Carvalho Chehab 		if (retry--)
3869a0bf528SMauro Carvalho Chehab 			goto start;
3879a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
3889a0bf528SMauro Carvalho Chehab 		       status&0xff);
3899a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
3909a0bf528SMauro Carvalho Chehab 	}
3919a0bf528SMauro Carvalho Chehab 
3929a0bf528SMauro Carvalho Chehab 	/* FIXME: Read frequency from frontend, take AFC into account */
3939a0bf528SMauro Carvalho Chehab 	p->frequency = state->current_frequency;
3949a0bf528SMauro Carvalho Chehab 
3959a0bf528SMauro Carvalho Chehab 	/* FIXME: How to read inversion setting? Receiver 6 register? */
3969a0bf528SMauro Carvalho Chehab 	p->inversion = INVERSION_AUTO;
3979a0bf528SMauro Carvalho Chehab 
3989a0bf528SMauro Carvalho Chehab 	return 0;
3999a0bf528SMauro Carvalho Chehab }
4009a0bf528SMauro Carvalho Chehab 
or51132_read_status(struct dvb_frontend * fe,enum fe_status * status)4010df289a2SMauro Carvalho Chehab static int or51132_read_status(struct dvb_frontend *fe, enum fe_status *status)
4029a0bf528SMauro Carvalho Chehab {
4039a0bf528SMauro Carvalho Chehab 	struct or51132_state* state = fe->demodulator_priv;
4049a0bf528SMauro Carvalho Chehab 	int reg;
4059a0bf528SMauro Carvalho Chehab 
4069a0bf528SMauro Carvalho Chehab 	/* Receiver Status */
4079a0bf528SMauro Carvalho Chehab 	if ((reg = or51132_readreg(state, 0x00)) < 0) {
4089a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: read_status: error reading receiver status: %d\n", reg);
4099a0bf528SMauro Carvalho Chehab 		*status = 0;
4109a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
4119a0bf528SMauro Carvalho Chehab 	}
4129a0bf528SMauro Carvalho Chehab 	dprintk("%s: read_status %04x\n", __func__, reg);
4139a0bf528SMauro Carvalho Chehab 
4149a0bf528SMauro Carvalho Chehab 	if (reg & 0x0100) /* Receiver Lock */
4159a0bf528SMauro Carvalho Chehab 		*status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|
4169a0bf528SMauro Carvalho Chehab 			  FE_HAS_SYNC|FE_HAS_LOCK;
4179a0bf528SMauro Carvalho Chehab 	else
4189a0bf528SMauro Carvalho Chehab 		*status = 0;
4199a0bf528SMauro Carvalho Chehab 	return 0;
4209a0bf528SMauro Carvalho Chehab }
4219a0bf528SMauro Carvalho Chehab 
4229a0bf528SMauro Carvalho Chehab /* Calculate SNR estimation (scaled by 2^24)
4239a0bf528SMauro Carvalho Chehab 
4249a0bf528SMauro Carvalho Chehab    8-VSB SNR and QAM equations from Oren datasheets
4259a0bf528SMauro Carvalho Chehab 
4269a0bf528SMauro Carvalho Chehab    For 8-VSB:
4279a0bf528SMauro Carvalho Chehab      SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K
4289a0bf528SMauro Carvalho Chehab 
4299a0bf528SMauro Carvalho Chehab      Where K = 0 if NTSC rejection filter is OFF; and
4309a0bf528SMauro Carvalho Chehab 	   K = 3 if NTSC rejection filter is ON
4319a0bf528SMauro Carvalho Chehab 
4329a0bf528SMauro Carvalho Chehab    For QAM64:
4339a0bf528SMauro Carvalho Chehab      SNR[dB] = 10 * log10(897152044.8282 / MSE^2 )
4349a0bf528SMauro Carvalho Chehab 
4359a0bf528SMauro Carvalho Chehab    For QAM256:
4369a0bf528SMauro Carvalho Chehab      SNR[dB] = 10 * log10(907832426.314266  / MSE^2 )
4379a0bf528SMauro Carvalho Chehab 
4389a0bf528SMauro Carvalho Chehab    We re-write the snr equation as:
4399a0bf528SMauro Carvalho Chehab      SNR * 2^24 = 10*(c - 2*intlog10(MSE))
4409a0bf528SMauro Carvalho Chehab    Where for QAM256, c = log10(907832426.314266) * 2^24
4419a0bf528SMauro Carvalho Chehab    and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */
4429a0bf528SMauro Carvalho Chehab 
calculate_snr(u32 mse,u32 c)4439a0bf528SMauro Carvalho Chehab static u32 calculate_snr(u32 mse, u32 c)
4449a0bf528SMauro Carvalho Chehab {
4459a0bf528SMauro Carvalho Chehab 	if (mse == 0) /* No signal */
4469a0bf528SMauro Carvalho Chehab 		return 0;
4479a0bf528SMauro Carvalho Chehab 
4489a0bf528SMauro Carvalho Chehab 	mse = 2*intlog10(mse);
4499a0bf528SMauro Carvalho Chehab 	if (mse > c) {
4509a0bf528SMauro Carvalho Chehab 		/* Negative SNR, which is possible, but realisticly the
4519a0bf528SMauro Carvalho Chehab 		demod will lose lock before the signal gets this bad.  The
4529a0bf528SMauro Carvalho Chehab 		API only allows for unsigned values, so just return 0 */
4539a0bf528SMauro Carvalho Chehab 		return 0;
4549a0bf528SMauro Carvalho Chehab 	}
4559a0bf528SMauro Carvalho Chehab 	return 10*(c - mse);
4569a0bf528SMauro Carvalho Chehab }
4579a0bf528SMauro Carvalho Chehab 
or51132_read_snr(struct dvb_frontend * fe,u16 * snr)4589a0bf528SMauro Carvalho Chehab static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
4599a0bf528SMauro Carvalho Chehab {
4609a0bf528SMauro Carvalho Chehab 	struct or51132_state* state = fe->demodulator_priv;
4619a0bf528SMauro Carvalho Chehab 	int noise, reg;
4629a0bf528SMauro Carvalho Chehab 	u32 c, usK = 0;
4639a0bf528SMauro Carvalho Chehab 	int retry = 1;
4649a0bf528SMauro Carvalho Chehab 
4659a0bf528SMauro Carvalho Chehab start:
4669a0bf528SMauro Carvalho Chehab 	/* SNR after Equalizer */
4679a0bf528SMauro Carvalho Chehab 	noise = or51132_readreg(state, 0x02);
4689a0bf528SMauro Carvalho Chehab 	if (noise < 0) {
4699a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: read_snr: error reading equalizer\n");
4709a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
4719a0bf528SMauro Carvalho Chehab 	}
4729a0bf528SMauro Carvalho Chehab 	dprintk("read_snr noise (%d)\n", noise);
4739a0bf528SMauro Carvalho Chehab 
4749a0bf528SMauro Carvalho Chehab 	/* Read status, contains modulation type for QAM_AUTO and
4759a0bf528SMauro Carvalho Chehab 	   NTSC filter for VSB */
4769a0bf528SMauro Carvalho Chehab 	reg = or51132_readreg(state, 0x00);
4779a0bf528SMauro Carvalho Chehab 	if (reg < 0) {
4789a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: read_snr: error reading receiver status\n");
4799a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
4809a0bf528SMauro Carvalho Chehab 	}
4819a0bf528SMauro Carvalho Chehab 
4829a0bf528SMauro Carvalho Chehab 	switch (reg&0xff) {
4839a0bf528SMauro Carvalho Chehab 	case 0x06:
4849a0bf528SMauro Carvalho Chehab 		if (reg & 0x1000) usK = 3 << 24;
485df561f66SGustavo A. R. Silva 		fallthrough;
48606eeefe8SMauro Carvalho Chehab 	case 0x43: /* QAM64 */
4879a0bf528SMauro Carvalho Chehab 		c = 150204167;
4889a0bf528SMauro Carvalho Chehab 		break;
4899a0bf528SMauro Carvalho Chehab 	case 0x45:
4909a0bf528SMauro Carvalho Chehab 		c = 150290396;
4919a0bf528SMauro Carvalho Chehab 		break;
4929a0bf528SMauro Carvalho Chehab 	default:
4939a0bf528SMauro Carvalho Chehab 		printk(KERN_WARNING "or51132: unknown status 0x%02x\n", reg&0xff);
4949a0bf528SMauro Carvalho Chehab 		if (retry--) goto start;
4959a0bf528SMauro Carvalho Chehab 		return -EREMOTEIO;
4969a0bf528SMauro Carvalho Chehab 	}
4979a0bf528SMauro Carvalho Chehab 	dprintk("%s: modulation %02x, NTSC rej O%s\n", __func__,
4989a0bf528SMauro Carvalho Chehab 		reg&0xff, reg&0x1000?"n":"ff");
4999a0bf528SMauro Carvalho Chehab 
5009a0bf528SMauro Carvalho Chehab 	/* Calculate SNR using noise, c, and NTSC rejection correction */
5019a0bf528SMauro Carvalho Chehab 	state->snr = calculate_snr(noise, c) - usK;
5029a0bf528SMauro Carvalho Chehab 	*snr = (state->snr) >> 16;
5039a0bf528SMauro Carvalho Chehab 
5049a0bf528SMauro Carvalho Chehab 	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
5059a0bf528SMauro Carvalho Chehab 		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
5069a0bf528SMauro Carvalho Chehab 
5079a0bf528SMauro Carvalho Chehab 	return 0;
5089a0bf528SMauro Carvalho Chehab }
5099a0bf528SMauro Carvalho Chehab 
or51132_read_signal_strength(struct dvb_frontend * fe,u16 * strength)5109a0bf528SMauro Carvalho Chehab static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
5119a0bf528SMauro Carvalho Chehab {
5129a0bf528SMauro Carvalho Chehab 	/* Calculate Strength from SNR up to 35dB */
5139a0bf528SMauro Carvalho Chehab 	/* Even though the SNR can go higher than 35dB, there is some comfort */
5149a0bf528SMauro Carvalho Chehab 	/* factor in having a range of strong signals that can show at 100%   */
5159a0bf528SMauro Carvalho Chehab 	struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
5169a0bf528SMauro Carvalho Chehab 	u16 snr;
5179a0bf528SMauro Carvalho Chehab 	int ret;
5189a0bf528SMauro Carvalho Chehab 
5199a0bf528SMauro Carvalho Chehab 	ret = fe->ops.read_snr(fe, &snr);
5209a0bf528SMauro Carvalho Chehab 	if (ret != 0)
5219a0bf528SMauro Carvalho Chehab 		return ret;
5229a0bf528SMauro Carvalho Chehab 	/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
5239a0bf528SMauro Carvalho Chehab 	/* scale the range 0 - 35*2^24 into 0 - 65535 */
5249a0bf528SMauro Carvalho Chehab 	if (state->snr >= 8960 * 0x10000)
5259a0bf528SMauro Carvalho Chehab 		*strength = 0xffff;
5269a0bf528SMauro Carvalho Chehab 	else
5279a0bf528SMauro Carvalho Chehab 		*strength = state->snr / 8960;
5289a0bf528SMauro Carvalho Chehab 
5299a0bf528SMauro Carvalho Chehab 	return 0;
5309a0bf528SMauro Carvalho Chehab }
5319a0bf528SMauro Carvalho Chehab 
or51132_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * fe_tune_settings)5329a0bf528SMauro Carvalho Chehab static int or51132_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
5339a0bf528SMauro Carvalho Chehab {
5349a0bf528SMauro Carvalho Chehab 	fe_tune_settings->min_delay_ms = 500;
5359a0bf528SMauro Carvalho Chehab 	fe_tune_settings->step_size = 0;
5369a0bf528SMauro Carvalho Chehab 	fe_tune_settings->max_drift = 0;
5379a0bf528SMauro Carvalho Chehab 
5389a0bf528SMauro Carvalho Chehab 	return 0;
5399a0bf528SMauro Carvalho Chehab }
5409a0bf528SMauro Carvalho Chehab 
or51132_release(struct dvb_frontend * fe)5419a0bf528SMauro Carvalho Chehab static void or51132_release(struct dvb_frontend* fe)
5429a0bf528SMauro Carvalho Chehab {
5439a0bf528SMauro Carvalho Chehab 	struct or51132_state* state = fe->demodulator_priv;
5449a0bf528SMauro Carvalho Chehab 	kfree(state);
5459a0bf528SMauro Carvalho Chehab }
5469a0bf528SMauro Carvalho Chehab 
547bd336e63SMax Kellermann static const struct dvb_frontend_ops or51132_ops;
5489a0bf528SMauro Carvalho Chehab 
or51132_attach(const struct or51132_config * config,struct i2c_adapter * i2c)5499a0bf528SMauro Carvalho Chehab struct dvb_frontend* or51132_attach(const struct or51132_config* config,
5509a0bf528SMauro Carvalho Chehab 				    struct i2c_adapter* i2c)
5519a0bf528SMauro Carvalho Chehab {
5529a0bf528SMauro Carvalho Chehab 	struct or51132_state* state = NULL;
5539a0bf528SMauro Carvalho Chehab 
5549a0bf528SMauro Carvalho Chehab 	/* Allocate memory for the internal state */
5559a0bf528SMauro Carvalho Chehab 	state = kzalloc(sizeof(struct or51132_state), GFP_KERNEL);
5569a0bf528SMauro Carvalho Chehab 	if (state == NULL)
5579a0bf528SMauro Carvalho Chehab 		return NULL;
5589a0bf528SMauro Carvalho Chehab 
5599a0bf528SMauro Carvalho Chehab 	/* Setup the state */
5609a0bf528SMauro Carvalho Chehab 	state->config = config;
5619a0bf528SMauro Carvalho Chehab 	state->i2c = i2c;
5629a0bf528SMauro Carvalho Chehab 	state->current_frequency = -1;
5639a0bf528SMauro Carvalho Chehab 	state->current_modulation = -1;
5649a0bf528SMauro Carvalho Chehab 
5659a0bf528SMauro Carvalho Chehab 	/* Create dvb_frontend */
5669a0bf528SMauro Carvalho Chehab 	memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
5679a0bf528SMauro Carvalho Chehab 	state->frontend.demodulator_priv = state;
5689a0bf528SMauro Carvalho Chehab 	return &state->frontend;
5699a0bf528SMauro Carvalho Chehab }
5709a0bf528SMauro Carvalho Chehab 
571bd336e63SMax Kellermann static const struct dvb_frontend_ops or51132_ops = {
5729a0bf528SMauro Carvalho Chehab 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
5739a0bf528SMauro Carvalho Chehab 	.info = {
5749a0bf528SMauro Carvalho Chehab 		.name			= "Oren OR51132 VSB/QAM Frontend",
575f1b1eabfSMauro Carvalho Chehab 		.frequency_min_hz	=  44 * MHz,
576f1b1eabfSMauro Carvalho Chehab 		.frequency_max_hz	= 958 * MHz,
577f1b1eabfSMauro Carvalho Chehab 		.frequency_stepsize_hz	= 166666,
5789a0bf528SMauro Carvalho Chehab 		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
5799a0bf528SMauro Carvalho Chehab 			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
5809a0bf528SMauro Carvalho Chehab 			FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO |
5819a0bf528SMauro Carvalho Chehab 			FE_CAN_8VSB
5829a0bf528SMauro Carvalho Chehab 	},
5839a0bf528SMauro Carvalho Chehab 
5849a0bf528SMauro Carvalho Chehab 	.release = or51132_release,
5859a0bf528SMauro Carvalho Chehab 
5869a0bf528SMauro Carvalho Chehab 	.init = or51132_init,
5879a0bf528SMauro Carvalho Chehab 	.sleep = or51132_sleep,
5889a0bf528SMauro Carvalho Chehab 
5899a0bf528SMauro Carvalho Chehab 	.set_frontend = or51132_set_parameters,
5909a0bf528SMauro Carvalho Chehab 	.get_frontend = or51132_get_parameters,
5919a0bf528SMauro Carvalho Chehab 	.get_tune_settings = or51132_get_tune_settings,
5929a0bf528SMauro Carvalho Chehab 
5939a0bf528SMauro Carvalho Chehab 	.read_status = or51132_read_status,
5949a0bf528SMauro Carvalho Chehab 	.read_ber = or51132_read_ber,
5959a0bf528SMauro Carvalho Chehab 	.read_signal_strength = or51132_read_signal_strength,
5969a0bf528SMauro Carvalho Chehab 	.read_snr = or51132_read_snr,
5979a0bf528SMauro Carvalho Chehab 	.read_ucblocks = or51132_read_ucblocks,
5989a0bf528SMauro Carvalho Chehab };
5999a0bf528SMauro Carvalho Chehab 
6009a0bf528SMauro Carvalho Chehab module_param(debug, int, 0644);
6019a0bf528SMauro Carvalho Chehab MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
6029a0bf528SMauro Carvalho Chehab 
6039a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("OR51132 ATSC [pcHDTV HD-3000] (8VSB & ITU J83 AnnexB FEC QAM64/256) Demodulator Driver");
6049a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Kirk Lapray");
6059a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Trent Piepho");
6069a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL");
6079a0bf528SMauro Carvalho Chehab 
608*86495af1SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(or51132_attach);
609