[go: nahoru, domu]

11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Driver for Philips TDA8083 based QPSK Demodulator
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Copyright (C) 2001 Convergence Integrated Media GmbH
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    written by Ralph Metzler <ralph@convergence.de>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    adoption to the new DVB frontend API and diagnostic ioctl's
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    by Holger Waechtler <holger@convergence.de>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is free software; you can redistribute it and/or modify
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    it under the terms of the GNU General Public License as published by
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    the Free Software Foundation; either version 2 of the License, or
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    (at your option) any later version.
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is distributed in the hope that it will be useful,
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    but WITHOUT ANY WARRANTY; without even the implied warranty of
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    GNU General Public License for more details.
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    You should have received a copy of the GNU General Public License
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    along with this program; if not, write to the Free Software
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
324e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/jiffies.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "dvb_frontend.h"
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "tda8083.h"
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct tda8083_state {
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_adapter* i2c;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* configuration settings */
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct tda8083_config* config;
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct dvb_frontend frontend;
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug;
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dprintk(args...) \
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do { \
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (debug) printk(KERN_DEBUG "tda8083: " args); \
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (0)
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 tda8083_init_tab [] = {
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea,
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10,
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8,
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00,
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x00, 0x00, 0x00, 0x00
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 buf [] = { reg, data };
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
679101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab	ret = i2c_transfer(state->i2c, &msg, 1);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
699101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab	if (ret != 1)
709101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab		dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
71271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison			__func__, reg, ret);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
739101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab	return (ret != 1) ? -1 : 0;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len)
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 },
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } };
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = i2c_transfer(state->i2c, msg, 2);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret != 2)
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
86271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison			__func__, reg1, ret);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
889101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab	return ret == 2 ? 0 : -1;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 tda8083_readreg (struct tda8083_state* state, u8 reg)
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 val;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_readregs (state, reg, &val, 1);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return val;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_set_inversion (struct tda8083_state* state, fe_spectral_inversion_t inversion)
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*  XXX FIXME: implement other modes than FEC_AUTO */
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (inversion == INVERSION_AUTO)
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_set_fec (struct tda8083_state* state, fe_code_rate_t fec)
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fec == FEC_AUTO)
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return tda8083_writereg (state, 0x07, 0xff);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fec >= FEC_1_2 && fec <= FEC_8_9)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return tda8083_writereg (state, 0x07, 1 << (FEC_8_9 - fec));
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EINVAL;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic fe_code_rate_t tda8083_get_fec (struct tda8083_state* state)
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 index;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8 };
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	index = tda8083_readreg(state, 0x0e) & 0x07;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return fec_tab [index];
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_set_symbolrate (struct tda8083_state* state, u32 srate)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1339101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab	u32 ratio;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 tmp;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 filter;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (srate > 32000000)
1389101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab		srate = 32000000;
1399101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab	if (srate < 500000)
1409101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab		srate = 500000;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	filter = 0;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (srate < 24000000)
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		filter = 2;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (srate < 16000000)
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		filter = 3;
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp = 31250 << 16;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ratio = tmp / srate;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp = (tmp % srate) << 8;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ratio = (ratio << 8) + tmp / srate;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp = (tmp % srate) << 8;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ratio = (ratio << 8) + tmp / srate;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dprintk("tda8083: ratio == %08x\n", (unsigned int) ratio);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x05, filter);
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x02, (ratio >> 16) & 0xff);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x03, (ratio >>  8) & 0xff);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x04, (ratio      ) & 0xff);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x3c);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x04);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long start = jiffies;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (jiffies - start < timeout &&
1759101e6222cb115240e24160bb90cce425bb74de5Mauro Carvalho Chehab	       !(tda8083_readreg(state, 0x02) & 0x80))
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(50);
178c2c1b4156a447f113ef4d167decce29399c2667cPeter Senna Tschudin	}
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t tone)
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x26, 0xf1);
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (tone) {
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SEC_TONE_OFF:
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return tda8083_writereg (state, 0x29, 0x00);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SEC_TONE_ON:
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return tda8083_writereg (state, 0x29, 0x80);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1922028c71d54e7bd7eb4470d5968f581f9f9284406Joe Perches	}
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_set_voltage (struct tda8083_state* state, fe_sec_voltage_t voltage)
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (voltage) {
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SEC_VOLTAGE_13:
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return tda8083_writereg (state, 0x20, 0x00);
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SEC_VOLTAGE_18:
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return tda8083_writereg (state, 0x20, 0x11);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
2042028c71d54e7bd7eb4470d5968f581f9f9284406Joe Perches	}
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_cmd_t burst)
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (burst) {
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SEC_MINI_A:
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tda8083_writereg (state, 0x29, (5 << 2));  /* send burst A */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SEC_MINI_B:
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tda8083_writereg (state, 0x29, (7 << 2));  /* send B */
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
218c2c1b4156a447f113ef4d167decce29399c2667cPeter Senna Tschudin	}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_wait_diseqc_fifo (state, 100);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_send_diseqc_msg (struct dvb_frontend* fe,
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    struct dvb_diseqc_master_cmd *m)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
228b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x29, (m->msg_len - 3) | (1 << 2)); /* enable */
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=0; i<m->msg_len; i++)
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tda8083_writereg (state, 0x23 + i, m->msg[i]);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x29, (m->msg_len - 3) | (3 << 2)); /* send!! */
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_wait_diseqc_fifo (state, 100);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
245b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 signal = ~tda8083_readreg (state, 0x01);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 sync = tda8083_readreg (state, 0x02);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*status = 0;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (signal > 10)
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*status |= FE_HAS_SIGNAL;
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sync & 0x01)
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*status |= FE_HAS_CARRIER;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sync & 0x02)
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*status |= FE_HAS_VITERBI;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sync & 0x10)
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*status |= FE_HAS_SYNC;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
264dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	if (sync & 0x20) /* frontend can not lock */
265dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich		*status |= FE_TIMEDOUT;
266dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((sync & 0x1f) == 0x1f)
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*status |= FE_HAS_LOCK;
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
273dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrichstatic int tda8083_read_ber(struct dvb_frontend* fe, u32* ber)
274dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich{
275dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	struct tda8083_state* state = fe->demodulator_priv;
276dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	int ret;
277dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	u8 buf[3];
278dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich
279dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf))))
280dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich		return ret;
281dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich
282dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	*ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
283dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich
284dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	return 0;
285dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich}
286dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
289b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 signal = ~tda8083_readreg (state, 0x01);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*strength = (signal << 8) | signal;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
299b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 _snr = tda8083_readreg (state, 0x08);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*snr = (_snr << 8) | _snr;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
307dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrichstatic int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
308dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich{
309dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	struct tda8083_state* state = fe->demodulator_priv;
310dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich
311dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	*ucblocks = tda8083_readreg(state, 0x0f);
312dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	if (*ucblocks == 0xff)
313dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich		*ucblocks = 0xffffffff;
314dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich
315dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	return 0;
316dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich}
317dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich
318042e5eb79f3c9eba2ad382f079834af20cbecc17Mauro Carvalho Chehabstatic int tda8083_set_frontend(struct dvb_frontend *fe)
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
320042e5eb79f3c9eba2ad382f079834af20cbecc17Mauro Carvalho Chehab	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
321b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
323dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher	if (fe->ops.tuner_ops.set_params) {
32414d24d148c7521b2b88b396652e36f55d061e195Mauro Carvalho Chehab		fe->ops.tuner_ops.set_params(fe);
325dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
326d21eac0385dd11d3118ffd374451916fa413c0dfAndrew de Quincey	}
327d21eac0385dd11d3118ffd374451916fa413c0dfAndrew de Quincey
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_set_inversion (state, p->inversion);
329042e5eb79f3c9eba2ad382f079834af20cbecc17Mauro Carvalho Chehab	tda8083_set_fec(state, p->fec_inner);
330042e5eb79f3c9eba2ad382f079834af20cbecc17Mauro Carvalho Chehab	tda8083_set_symbolrate(state, p->symbol_rate);
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x3c);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x04);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3387c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehabstatic int tda8083_get_frontend(struct dvb_frontend *fe)
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3407c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehab	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
341b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*  FIXME: get symbolrate & frequency offset...*/
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*p->frequency = ???;*/
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p->inversion = (tda8083_readreg (state, 0x0e) & 0x80) ?
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			INVERSION_ON : INVERSION_OFF;
347042e5eb79f3c9eba2ad382f079834af20cbecc17Mauro Carvalho Chehab	p->fec_inner = tda8083_get_fec(state);
348042e5eb79f3c9eba2ad382f079834af20cbecc17Mauro Carvalho Chehab	/*p->symbol_rate = tda8083_get_symbolrate (state);*/
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_sleep(struct dvb_frontend* fe)
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
355b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x02);
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_init(struct dvb_frontend* fe)
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
363b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=0; i<44; i++)
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tda8083_writereg (state, i, tda8083_init_tab[i]);
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x3c);
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x04);
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
377b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_send_diseqc_burst (state, burst);
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x3c);
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x04);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_diseqc_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
388b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_set_tone (state, tone);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x3c);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x04);
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tda8083_diseqc_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
399b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_set_voltage (state, voltage);
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x3c);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tda8083_writereg (state, 0x00, 0x04);
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void tda8083_release(struct dvb_frontend* fe)
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
410b8742700f13163ffa00cddce2a3c940b9ab2ab5aJohannes Stezenbach	struct tda8083_state* state = fe->demodulator_priv;
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(state);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dvb_frontend_ops tda8083_ops;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    struct i2c_adapter* i2c)
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tda8083_state* state = NULL;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* allocate memory for the internal state */
422084e24acc906c162c92de7df807190856ae60928Matthias Schwarzott	state = kzalloc(sizeof(struct tda8083_state), GFP_KERNEL);
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (state == NULL) goto error;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* setup the state */
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->config = config;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->i2c = i2c;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the demod is there */
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((tda8083_readreg(state, 0x00)) != 0x05) goto error;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* create dvb_frontend */
433dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher	memcpy(&state->frontend.ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->frontend.demodulator_priv = state;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return &state->frontend;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror:
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(state);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dvb_frontend_ops tda8083_ops = {
443042e5eb79f3c9eba2ad382f079834af20cbecc17Mauro Carvalho Chehab	.delsys = { SYS_DVBS },
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.info = {
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name			= "Philips TDA8083 DVB-S",
4464f76b672c4f9ceb9e7e0aa6224293da0ae7430daOliver Endriss		.frequency_min		= 920000,     /* TDA8060 */
4474f76b672c4f9ceb9e7e0aa6224293da0ae7430daOliver Endriss		.frequency_max		= 2200000,    /* TDA8060 */
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.frequency_stepsize	= 125,   /* kHz for QPSK frontends */
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*      .frequency_tolerance	= ???,*/
4504f76b672c4f9ceb9e7e0aa6224293da0ae7430daOliver Endriss		.symbol_rate_min	= 12000000,
4514f76b672c4f9ceb9e7e0aa6224293da0ae7430daOliver Endriss		.symbol_rate_max	= 30000000,
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*      .symbol_rate_tolerance	= ???,*/
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.caps = FE_CAN_INVERSION_AUTO |
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FE_CAN_QPSK | FE_CAN_MUTE_TS
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.release = tda8083_release,
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init = tda8083_init,
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.sleep = tda8083_sleep,
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
465042e5eb79f3c9eba2ad382f079834af20cbecc17Mauro Carvalho Chehab	.set_frontend = tda8083_set_frontend,
466042e5eb79f3c9eba2ad382f079834af20cbecc17Mauro Carvalho Chehab	.get_frontend = tda8083_get_frontend,
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_status = tda8083_read_status,
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_signal_strength = tda8083_read_signal_strength,
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_snr = tda8083_read_snr,
471dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	.read_ber = tda8083_read_ber,
472dbb2e6392b4fe350e549cdc2d42cebf3b3574a6aChristoph Haubrich	.read_ucblocks = tda8083_read_ucblocks,
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.diseqc_send_master_cmd = tda8083_send_diseqc_msg,
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.diseqc_send_burst = tda8083_diseqc_send_burst,
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_tone = tda8083_diseqc_set_tone,
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_voltage = tda8083_diseqc_set_voltage,
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0644);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Philips TDA8083 DVB-S Demodulator");
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(tda8083_attach);
488