PATCH: New driver for Zarlink ZL10313 based Compro S350/S300

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi List,
Attached is a new driver for the Zarlink ZL10313/ZL10039 based ComproS350/S300 budget DVB-S cards. Everything except 2 way diseqc should work.


diff -r f637ac5a5898 linux/drivers/media/common/ir-keymaps.c--- a/linux/drivers/media/common/ir-keymaps.c	Fri Dec 28 00:32:41 2007 -0200+++ b/linux/drivers/media/common/ir-keymaps.c	Fri Dec 28 15:51:25 2007 +0200@@ -1898,3 +1898,40 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[I };  EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce);++IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = {+	[ 0x00 ] = KEY_TV,+	[ 0x01 ] = KEY_DVD,+	[ 0x04 ] = KEY_RECORD,+	[ 0x05 ] = KEY_VIDEO, /* TV/Video */+	[ 0x07 ] = KEY_STOP,+	[ 0x08 ] = KEY_PLAYPAUSE,+	[ 0x0a ] = KEY_REWIND,+	[ 0x0f ] = KEY_FASTFORWARD,+	[ 0x10 ] = KEY_CHANNELUP,+	[ 0x12 ] = KEY_VOLUMEUP,+	[ 0x13 ] = KEY_CHANNELDOWN,+	[ 0x14 ] = KEY_MUTE,+	[ 0x15 ] = KEY_VOLUMEDOWN,+	[ 0x16 ] = KEY_1,+	[ 0x17 ] = KEY_2,+	[ 0x18 ] = KEY_3,+	[ 0x19 ] = KEY_4,+	[ 0x1a ] = KEY_5,+	[ 0x1b ] = KEY_6,+	[ 0x1c ] = KEY_7,+	[ 0x1d ] = KEY_8,+	[ 0x1e ] = KEY_9,+	[ 0x1f ] = KEY_0,+	[ 0x21 ] = KEY_SLEEP,+	[ 0x24 ] = KEY_ZOOM,+	[ 0x25 ] = KEY_LAST,	/* Recall */+	[ 0x26 ] = KEY_SUBTITLE, /* CC */+	[ 0x27 ] = KEY_LANGUAGE, /* MTS */+	[ 0x29 ] = KEY_CHANNEL, /* SURF */+	[ 0x2b ] = KEY_A,+	[ 0x2c ] = KEY_B,+	[ 0x2f ] = KEY_SHUFFLE, /* Snapshot */+};++EXPORT_SYMBOL_GPL(ir_codes_videomate_s350);diff -r f637ac5a5898 linux/drivers/media/dvb/frontends/Kconfig--- a/linux/drivers/media/dvb/frontends/Kconfig	Fri Dec 28 00:32:41 2007 -0200+++ b/linux/drivers/media/dvb/frontends/Kconfig	Sat Dec 29 16:34:08 2007 +0200@@ -70,6 +70,13 @@ config DVB_TDA10086 	default m if DVB_FE_CUSTOMISE 	help 	  A DVB-S tuner module. Say Y when you want to support this frontend.++config DVB_ZL10313+	tristate "Zarlink ZL10313 DVB-S demodulator"+	depends on DVB_CORE && I2C+	default m if DVB_FE_CUSTOMISE+	help+	  A DVB-S demodulator module. Say Y when you want to support this frontend.  comment "DVB-T (terrestrial) frontends" 	depends on DVB_CORE@@ -369,6 +376,14 @@ config DVB_TUNER_XC5000 	  This device is only used inside a SiP called togther with a 	  demodulator for now. +config DVB_ZL10039+	tristate "Zarlink ZL10039 DVB-S tuner"+	depends on DVB_CORE && I2C+	default m if DVB_FE_CUSTOMISE+	help+	  A driver for the ZL10039 DVB-S tuner from Zarlink++ comment "Miscellaneous devices" 	depends on DVB_CORE diff -r f637ac5a5898 linux/drivers/media/dvb/frontends/Makefile--- a/linux/drivers/media/dvb/frontends/Makefile	Fri Dec 28 00:32:41 2007 -0200+++ b/linux/drivers/media/dvb/frontends/Makefile	Fri Dec 28 15:12:10 2007 +0200@@ -51,3 +51,5 @@ obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131 obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o obj-$(CONFIG_DVB_S5H1409) += s5h1409.o obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o+obj-$(CONFIG_DVB_ZL10313) += zl10313.o+obj-$(CONFIG_DVB_ZL10039) += zl10039.odiff -r f637ac5a5898 linux/drivers/media/dvb/frontends/zl10039.c--- /dev/null	Thu Jan 01 00:00:00 1970 +0000+++ b/linux/drivers/media/dvb/frontends/zl10039.c	Sat Dec 29 16:04:18 2007 +0200@@ -0,0 +1,260 @@+/*+ *  Driver for Zarlink ZL10039 DVB-S tuner+ *+ *  Copyright 2007 Jan Daniël Louw <jd.louw@xxxxxxxxxx>+ *+ *  This program is free software; you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation; either version 2 of the License, or+ *  (at your option) any later version.+ *+ *  This program is distributed in the hope that it will be useful,+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ *+ *  GNU General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program; if not, write to the Free Software+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=+ */++#include <linux/module.h>+#include <linux/init.h>+#include <linux/string.h>+#include <linux/slab.h>+#include <linux/dvb/frontend.h>++#include "dvb_frontend.h"+#include "zl10039.h"+#include "zl10039_priv.h"+++static int zl10039_read(const struct zl10039_state *state,+			const enum zl10039_reg_addr reg, u8 *buf,+			const size_t count)+{+	struct i2c_msg msg[2];+	u8 regbuf[1] = { reg };+	int i;++	io_printk("%s\n", __FUNCTION__);+	/* Write register address */+	msg[0].addr = state->config.tuner_address;+	msg[0].flags = 0;+	msg[0].buf = regbuf;+	msg[0].len = 1;+	/* Read count bytes */+	msg[1].addr = state->config.tuner_address;+	msg[1].flags = I2C_M_RD;+	msg[1].buf = buf;+	msg[1].len = count;+	if (i2c_transfer(state->i2c, msg, 2) != 2) {+		eprintk("%s: i2c read error\n", __FUNCTION__);+		return -EREMOTEIO;+	}+	for (i = 0; i < count; i++) {+		io_printk("R[%s] = 0x%x\n", zl10039_reg_names[reg + i], buf[i]);+	}+	return 0; /* Success */+}++static int zl10039_write(struct zl10039_state *state,+			const enum zl10039_reg_addr reg, const u8 *src,+			const size_t count)+{+	u8 buf[count + 1];+	struct i2c_msg msg;+	int i;++	io_printk("%s\n", __FUNCTION__);+	for (i = 0; i < count; i++) {+		io_printk("W[%s] = 0x%x\n", zl10039_reg_names[reg + i], src[i]);+	}+	/* Write register address and data in one go */+	buf[0] = reg;+	memcpy(&buf[1], src, count);+	msg.addr = state->config.tuner_address;+	msg.flags = 0;+	msg.buf = buf;+	msg.len = count + 1;+	if (i2c_transfer(state->i2c, &msg, 1) != 1) {+		eprintk("%s: i2c write error\n", __FUNCTION__);+		return -EREMOTEIO;+	}+	return 0; /* Success */+}++static inline int zl10039_readreg(struct zl10039_state *state,+				const enum zl10039_reg_addr reg, u8 *val)+{+	return zl10039_read(state, reg, val, 1);+}++static inline int zl10039_writereg(struct zl10039_state *state,+				const enum zl10039_reg_addr reg,+				const u8 val)+{+	return zl10039_write(state, reg, &val, 1);+}++static int zl10039_init(struct dvb_frontend *fe)+{+	struct zl10039_state *state = fe->tuner_priv;+	int ret;++	trace_printk("%s\n", __FUNCTION__);+	if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);+	/* Reset logic */+	ret = zl10039_writereg(state, GENERAL, 0x40);+	if (ret < 0) {+		eprintk("Note: i2c write error normal when resetting the "+			"tuner\n");+	}+	/* Wake up */+	ret = zl10039_writereg(state, GENERAL, 0x01);+	if (ret < 0) {+		eprintk("Tuner power up failed\n");+		return ret;+	}+	if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);+	return 0;+}++static int zl10039_sleep(struct dvb_frontend *fe)+{+	struct zl10039_state *state = fe->tuner_priv;+	int ret;++	trace_printk("%s\n", __FUNCTION__);+	if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);+	ret = zl10039_writereg(state, GENERAL, 0x80);+	if (ret < 0) {+		eprintk("Tuner sleep failed\n");+		return ret;+	}+	if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);+	return 0;+}++static int zl10039_set_params(struct dvb_frontend *fe,+			struct dvb_frontend_parameters *params)+{+	struct zl10039_state *state = fe->tuner_priv;+	u8 buf[6];+	u8 bf;+	u32 fbw;+	u32 div;+	int ret;++	trace_printk("%s\n", __FUNCTION__);+	params_printk("Set frequency = %d, symbol rate = %d\n",+			params->frequency, params->u.qpsk.symbol_rate);++	/* Assumed 10.111 MHz crystal oscillator */+	/* Cancelled num/den 80 to prevent overflow */+	div = (params->frequency * 1000) / 126387;+	fbw = (params->u.qpsk.symbol_rate * 27) / 32000;+	/* Cancelled num/den 10 to prevent overflow */+	bf = ((fbw * 5088) / 1011100) - 1;++	/*PLL divider*/+	buf[0] = (div >> 8) & 0x7f;+	buf[1] = (div >> 0) & 0xff;+	/*Reference divider*/+	/* Select reference ratio of 80 */+	buf[2] = 0x1D;+	/*PLL test modes*/+	buf[3] = 0x40;+	/*RF Control register*/+	buf[4] = 0x6E; /* Bypass enable */+	/*Baseband filter cutoff */+	buf[5] = bf;++	/* Open i2c gate */+	if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);+	/* BR = 10, Enable filter adjustment */+	ret = zl10039_writereg(state, BASE1, 0x0A);+	if (ret < 0) goto error;+	/* Write new config values */+	ret = zl10039_write(state, PLL0, buf, sizeof(buf));+	if (ret < 0) goto error;+	/* BR = 10, Disable filter adjustment */+	ret = zl10039_writereg(state, BASE1, 0x6A);+	if (ret < 0) goto error;++	zl10039_dump_registers(state);+	/* Close i2c gate */+	if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);+	return 0;+error:+	eprintk("Error setting tuner\n");+	return ret;+}++static struct dvb_tuner_ops zl10039_ops;++struct dvb_frontend * zl10039_attach(struct dvb_frontend *fe,+		const struct zl10039_config *config, struct i2c_adapter *i2c)+{+	struct zl10039_state *state = NULL;++	trace_printk("%s\n", __FUNCTION__);+	state = kmalloc(sizeof(struct zl10039_state), GFP_KERNEL);+	if (state == NULL) goto error;++	state->i2c = i2c;+	state->config.tuner_address = config->tuner_address;++	/* Open i2c gate */+	if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);+	/* check if this is a valid tuner */+	if (zl10039_readreg(state, GENERAL, &state->id) < 0) {+		/* Close i2c gate */+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);+		goto error;+	}+	/* Close i2c gate */+	if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);++	state->id = state->id & 0x0F;+	switch (state->id) {+	case ID_ZL10039:+		strcpy(fe->ops.tuner_ops.info.name,+			"Zarlink ZL10039 DVB-S tuner");+		break;+	default:+		eprintk("Chip ID does not match a known type\n");+		goto error;+	}+	memcpy(&fe->ops.tuner_ops, &zl10039_ops, sizeof(struct dvb_tuner_ops));+	fe->tuner_priv = state;+	iprintk("Tuner attached @ i2c address 0x%02x\n", config->tuner_address);+	return fe;+error:+	kfree(state);+	return NULL;+}++static int zl10039_release(struct dvb_frontend *fe)+{+	struct zl10039_state *state = fe->tuner_priv;++	trace_printk("%s\n", __FUNCTION__);+	kfree(state);+	fe->tuner_priv = NULL;+	return 0;+}++static struct dvb_tuner_ops zl10039_ops = {+	.release = zl10039_release,+	.init = zl10039_init,+	.sleep = zl10039_sleep,+	.set_params = zl10039_set_params,+};++EXPORT_SYMBOL(zl10039_attach);++MODULE_DESCRIPTION("Zarlink ZL10039 DVB-S tuner driver");+MODULE_AUTHOR("Jan Daniël Louw <jd.louw@xxxxxxxxxx>");+MODULE_LICENSE("GPL");diff -r f637ac5a5898 linux/drivers/media/dvb/frontends/zl10039.h--- /dev/null	Thu Jan 01 00:00:00 1970 +0000+++ b/linux/drivers/media/dvb/frontends/zl10039.h	Sat Dec 29 15:12:47 2007 +0200@@ -0,0 +1,46 @@+/*+    Driver for Zarlink ZL10039 DVB-S tuner++    Copyright (C) 2007 Jan Daniël Louw <jd.louw@xxxxxxxxxx>++    This program is free software; you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation; either version 2 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the++    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License+    along with this program; if not, write to the Free Software+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.+*/++#ifndef ZL10039_H+#define ZL10039_H++struct zl10039_config+{+	/* tuner's i2c address */+	u8 tuner_address;+};++#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \+	    && defined(MODULE))+struct dvb_frontend * zl10039_attach(struct dvb_frontend *fe,+					const struct zl10039_config *config,+					struct i2c_adapter *i2c);+#else+static inline struct dvb_frontend * zl10039_attach(struct dvb_frontend *fe,+					const struct zl10039_config *config,+					struct i2c_adapter *i2c)+{+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);+	return NULL;+}+#endif /* CONFIG_DVB_ZL10039 */++#endif /* ZL10039_H */diff -r f637ac5a5898 linux/drivers/media/dvb/frontends/zl10039_priv.h--- /dev/null	Thu Jan 01 00:00:00 1970 +0000+++ b/linux/drivers/media/dvb/frontends/zl10039_priv.h	Sat Dec 29 16:09:49 2007 +0200@@ -0,0 +1,121 @@+/*+ *  Driver for Zarlink ZL10039 DVB-S tuner+ *+ *  Copyright 2007 Jan Daniël Louw <jd.louw@xxxxxxxxxx>+ *+ *  This program is free software; you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation; either version 2 of the License, or+ *  (at your option) any later version.+ *+ *  This program is distributed in the hope that it will be useful,+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ *+ *  GNU General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program; if not, write to the Free Software+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=+ */++#ifndef DVB_FRONTENDS_ZL10039_PRIV+#define DVB_FRONTENDS_ZL10039_PRIV++/* Trace function calls */+#define DEBUG_CALL_TRACE	0+/* Trace read/write function calls - information overload */+#define DEBUG_IO_TRACE		0+/* Print register values at critical points */+#define DEBUG_DUMP_REGISTERS	0+/* Print important params passed to functions */+#define DEBUG_PRINT_PARAMS	0++#if DEBUG_CALL_TRACE+	#define trace_printk(args...) printk(KERN_DEBUG "tuner: zl10039: " args)+#else+	#define trace_printk(args...)+#endif++#if DEBUG_IO_TRACE+	#define io_printk(args...) printk(KERN_DEBUG "tuner: zl10039: " args)+#else+	#define io_printk(args...)+#endif++#if DEBUG_PRINT_PARAMS+	#define params_printk(args...) printk(KERN_DEBUG "tuner: zl10039: " \+						args)+#else+	#define params_printk(args...)+#endif++#define eprintk(args...) printk(KERN_ERR "tuner: zl10039: " args)+#define iprintk(args...) printk(KERN_INFO "tuner: zl10039: " args)++enum zl10039_model_id {+	ID_ZL10039 = 1+};++struct zl10039_state {+	struct i2c_adapter *i2c;+	struct zl10039_config config;+	u8 id;+};++enum zl10039_reg_addr {+	PLL0 = 0,+	PLL1,+	PLL2,+	PLL3,+	RFFE,+	BASE0,+	BASE1,+	BASE2,+	LO0,+	LO1,+	LO2,+	LO3,+	LO4,+	LO5,+	LO6,+	GENERAL+};++#if DEBUG_DUMP_REGISTERS || DEBUG_IO_TRACE+static const char *zl10039_reg_names[] = {+	"PLL_0", "PLL_1", "PLL_2", "PLL_3",+	"RF_FRONT_END", "BASE_BAND_0", "BASE_BAND_1", "BASE_BAND_2",+	"LOCAL_OSC_0", "LOCAL_OSC_1", "LOCAL_OSC_2", "LOCAL_OSC_3",+	"LOCAL_OSC_4", "LOCAL_OSC_5", "LOCAL_OSC_6", "GENERAL"+};+#endif++#if DEBUG_DUMP_REGISTERS+static int zl10039_read(const struct zl10039_state *state,+			const enum zl10039_reg_addr reg, u8 *buf,+			const size_t count);++static void zl10039_dump_registers(const struct zl10039_state *state)+{+	u8 buf[16];+	int ret;+	u8 reg;++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10039_read(state, PLL0, buf, sizeof(buf));+	if (ret < 0) return;+	for (reg = PLL0; reg <= GENERAL; reg += 4) {+		printk(KERN_DEBUG "%03x: [%02x %13s] [%02x %13s] [%02x %13s] "+			"[%02x %13s]\n", reg, buf[reg], zl10039_reg_names[reg],+			buf[reg+1], zl10039_reg_names[reg+1], buf[reg+2],+			zl10039_reg_names[reg+2], buf[reg+3],+			zl10039_reg_names[reg+3]);+	}+}+#else+static inline void zl10039_dump_registers(const struct zl10039_state *state) {}+#endif /* DEBUG_DUMP_REGISTERS */++#endif /* DVB_FRONTENDS_ZL10039_PRIV */+diff -r f637ac5a5898 linux/drivers/media/dvb/frontends/zl10313.c--- /dev/null	Thu Jan 01 00:00:00 1970 +0000+++ b/linux/drivers/media/dvb/frontends/zl10313.c	Sat Dec 29 15:51:31 2007 +0200@@ -0,0 +1,569 @@+/*+ *  Driver for Zarlink ZL10313 DVB-S demodulator+ *+ *  Copyright 2007 Jan Daniël Louw <jd.louw@xxxxxxxxxx>+ *+ *  This program is free software; you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation; either version 2 of the License, or+ *  (at your option) any later version.+ *+ *  This program is distributed in the hope that it will be useful,+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+ *+ *  GNU General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program; if not, write to the Free Software+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=+ */++#include <linux/module.h>+#include <linux/init.h>+#include <linux/string.h>+#include <linux/slab.h>+#include <linux/dvb/frontend.h>++#include "dvb_frontend.h"+#include "zl10313.h"+#include "zl10313_priv.h"+++static int zl10313_read(const struct zl10313_state *state,+			const enum zl10313_reg_addr reg,+			u8 *buf, const size_t count)+{+	struct i2c_msg msg[2];+	u8 regbuf[1] = { reg };+	int i;++	io_printk("%s\n", __FUNCTION__);+	/* Write address to read */+	msg[0].addr = state->config->demod_address;+	msg[0].flags = 0;+	msg[0].buf = regbuf;+	msg[0].len = 1;+	/* Read count bytes */+	msg[1].addr = state->config->demod_address;+	msg[1].flags = I2C_M_RD;+	msg[1].buf = buf;+	msg[1].len = count;++	if (i2c_transfer(state->i2c, msg, 2) != 2) {+		eprintk("%s: i2c read error\n", __FUNCTION__);+		return -EREMOTEIO;+	}+	for (i = 0; i < count; i++) {+		io_printk("R[%s] = 0x%x\n", zl10313_reg_names[reg + i], buf[i]);+	}+	return 0;+}++static int zl10313_write(struct zl10313_state *state,+			const enum zl10313_reg_addr reg, const void *src,+			const size_t count)+{+	u8 buf[count + 1];+	struct i2c_msg msg;+	int i;++	io_printk("%s\n", __FUNCTION__);+	for (i = 0; i < count; i++) {+		io_printk("R[%s] = 0x%x\n", zl10313_reg_names[reg + i], buf[i]);+	}+	buf[0] = reg;+	memcpy(&buf[1], src, count);+	msg.addr = state->config->demod_address;+	msg.flags = 0;+	msg.buf = buf;+	msg.len = count + 1;++	if (i2c_transfer(state->i2c, &msg, 1) != 1) {+		eprintk("%s: i2c write error\n", __FUNCTION__);+		return -EREMOTEIO;+	}+	return 0;+}++static inline int zl10313_readreg(struct zl10313_state *state,+				const enum zl10313_reg_addr reg, u8 *val)+{+	return zl10313_read(state, reg, val, 1);+}++static inline int zl10313_writereg(struct zl10313_state *state,+				const enum zl10313_reg_addr reg, const u8 val)+{+	return zl10313_write(state, reg, &val, 1);+}++static inline u32 zl10313_div(u32 a, u32 b)+{+	return (a + (b / 2)) / b;+}++static int zl10313_read_status(struct dvb_frontend *fe, fe_status_t *s)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;+	u8 status[3];++	trace_printk("%s\n", __FUNCTION__);+	*s = 0;+	ret = zl10313_read(state, QPSK_STAT_H, status, sizeof(status));+	if (ret < 0) return ret;+	if (status[0] & 0xc0)+		*s |= FE_HAS_SIGNAL;    /* signal noise ratio */+	if (status[0] & 0x04)+		*s |= FE_HAS_CARRIER;   /* qpsk carrier lock */+	if (status[2] & 0x02)+		*s |= FE_HAS_VITERBI;   /* viterbi lock */+	if (status[2] & 0x04)+		*s |= FE_HAS_SYNC;      /* byte align lock */+	if (status[0] & 0x01)+		*s |= FE_HAS_LOCK;      /* qpsk lock */++	return 0;+}++/* Reports only Reed-Solomon error count (Viterbi BER) */+/* IMPROVEMENT: Implement Viterbi error count (QPSK BER), a bit of a problem+		without IRQs? */+/* Viterbi BER = RS_BERCNT / (dt * CR * 2 * SR) */+static int zl10313_read_ber(struct dvb_frontend *fe, u32 *ber)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;+	u8 buf[3];++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_read(state, RS_BERCNT_H, buf, 3);+	if (ret < 0) return ret;+	*ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]);+	return 0;+}++/* Signal strength a number out of 1024 */+static int zl10313_read_signal_strength(struct dvb_frontend *fe,+					u16 * signal_strength)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;+	u8 buf[3];+	u16 agc;++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_read(state, AGC_H, buf, sizeof(buf));+	if (ret < 0) return ret;+	agc = (buf[0] << 2) | (buf[1] >> 6);+	*signal_strength = agc;+	return 0;+}++/* Holds for Eb/No between 0 and 12 dB */+static int zl10313_read_snr(struct dvb_frontend *fe, u16 *snr)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;+	u8 buf[2];++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_read(state, M_SNR_H, buf, sizeof(buf));+	if (ret < 0) return ret;+	*snr = (13312 - (((buf[0] & 0x7f) << 8) | buf[1])) / 683;+	return 0;+}++/* Block error rate = (ucblocks * 1632) / (dt * SR * 2 * CR) */+static int zl10313_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;+	u8 buf[2];++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_read(state, RS_UBC_H, buf, sizeof(buf));+	if (ret < 0) return ret;+	*ucblocks = (buf[0] << 8) | buf[1];+	return 0;+}++static int zl10313_get_inversion(struct zl10313_state *state,+		fe_spectral_inversion_t *i)+{+	int ret;+	u8 vit_mode;++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_readreg(state, VIT_MODE, &vit_mode);+	if (ret < 0) return ret;+	*i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF;+	return 0;+}++static int zl10313_get_symbol_rate(struct zl10313_state *state, u32 *sr)+{+	int ret;+	u16 monitor;+	u8 buf[2];++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_writereg(state, MON_CTRL, 0x03);+	if (ret < 0) return ret;+	ret = zl10313_read(state, MONITOR_H, buf, sizeof(buf));+	if (ret < 0) return ret;+	monitor = (buf[0] << 8) | buf[1];+	/* SR = monitor * 1000000 / 1024 */+	*sr = zl10313_div(monitor * 15625, 16);+	return 0;+}++static int zl10313_get_code_rate(struct zl10313_state *state,+					fe_code_rate_t *cr)+{+	const fe_code_rate_t fec_tab[8] = { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6,+			FEC_6_7, FEC_7_8, FEC_AUTO, FEC_AUTO };+	int ret;+	u8 fec_status;++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_readreg(state, FEC_STATUS, &fec_status);+	if (ret < 0) return ret;+	*cr = fec_tab[(fec_status >> 4) & 0x07];+	return 0;+}++static int zl10313_get_frontend(struct dvb_frontend *fe,+				struct dvb_frontend_parameters *p)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_get_inversion(state, &p->inversion);+	if (ret < 0) return ret;+	ret = zl10313_get_symbol_rate(state, &p->u.qpsk.symbol_rate);+	if (ret < 0) return ret;+	ret = zl10313_get_code_rate(state, &p->u.qpsk.fec_inner);+	if (ret < 0) return ret;+	p->frequency = state->prev_frequency;+	return 0;+}++static int zl10313_set_frontend(struct dvb_frontend *fe,+				struct dvb_frontend_parameters *p)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;+	u8 buf[5];+	u16 sr;+	const u8 fec_tab[10] = { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10,+				0x20, 0x3f, 0x3f };+	const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };++	trace_printk("%s\n", __FUNCTION__);+	params_printk("Setting freq: %d, fec: %s, inversion: %s\n",+		p->frequency, fec_str[p->u.qpsk.fec_inner],+		inv_str[p->inversion]);++	if ((p->frequency < fe->ops.info.frequency_min) ||+		(p->frequency > fe->ops.info.frequency_max)) return -EINVAL;++	if ((p->inversion < INVERSION_OFF) || (p->inversion > INVERSION_AUTO))+		return -EINVAL;++	if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) ||+		(p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max))+		return -EINVAL;++	if ((p->u.qpsk.fec_inner < FEC_NONE) ||+		(p->u.qpsk.fec_inner > FEC_AUTO)) return -EINVAL;++	if ((p->u.qpsk.fec_inner == FEC_4_5) ||+		(p->u.qpsk.fec_inner == FEC_8_9)) return -EINVAL;++	/* Set the tuner up first */+	fe->ops.tuner_ops.set_params(fe, p);++	/* sr = SR * 256 / 1000000 */+	sr = zl10313_div(p->u.qpsk.symbol_rate * 4, 15625);+	/* SYM_RATE */+	buf[0] = (sr >> 8) & 0x3f;+	buf[1] = (sr >> 0) & 0xff;+	/* VIT_MODE */+	buf[2] = inv_tab[p->inversion] | fec_tab[p->u.qpsk.fec_inner];+	/* QPSK_CTRL */+	buf[3] = 0x40; /* swap I and Q before QPSK demodulation */+	if (p->u.qpsk.symbol_rate < 10000000)+		buf[3] |= 0x04; /* use afc mode */+	/* GO */+	buf[4] = 0x01;++	ret = zl10313_write(state, SYM_RATE_H, buf, sizeof(buf));+	if (ret < 0) {+		eprintk("Demodulator failed setup\n");+		return ret;+	}+	state->prev_frequency = p->frequency;+	zl10313_dump_registers(state);++	return 0;+}++static int zl10313_sleep(struct dvb_frontend *fe)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;+	u8 config;++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_readreg(state, CONFIG, &config);+	if (ret < 0) return ret;+	/* enter standby */+	ret = zl10313_writereg(state, CONFIG, config & 0x7f);+	if (ret < 0) return ret;+	return 0;+}++static int zl10313_init(struct dvb_frontend *fe)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;+	u8 buf[2];++	trace_printk("%s\n", __FUNCTION__);+	/* Set up for QPSK DVB-S with 10MHz crystal ref */+	ret = zl10313_writereg(state, CONFIG, 0x8c);+	if (ret < 0) return ret;+	/* Wait 150 us to settle */+	udelay(150);+	/* Full reset */+	ret = zl10313_writereg(state, RESET, 0x80);+	if (ret < 0) return ret;+	/* Crucial for correct operation - differs from mt312 datasheet */+	ret = zl10313_writereg(state, GPP_CTRL, 0x80);+	if (ret < 0) return ret;+	/* Crucial for correct operation - unknown register in zl10313 */+	/* Don't know what this register is for in the zl10313 */+	ret = zl10313_writereg(state, VIT_ERRPER_M, 0x00);+	if (ret < 0) return ret;+	buf[0] = 182;+	buf[1] = zl10313_div(10111000, 88000);+	/*Set DISECQ ratio for 22KHz tone */+	ret = zl10313_write(state, SYS_CLK, buf, sizeof(buf));+	if (ret < 0) return ret;+	/* Supposed to set register 49 to value 50 - can't see any difference */+	ret = zl10313_writereg(state, SNR_THS_HIGH, 50);+	if (ret < 0) return ret;++	zl10313_dump_registers(state);++	return 0;+}++static int zl10313_send_master_cmd(struct dvb_frontend *fe,+				struct dvb_diseqc_master_cmd *c)+{+	struct zl10313_state *state = fe->demodulator_priv;+	int ret;+	u8 diseqc_mode;++	trace_printk("%s\n", __FUNCTION__);+	if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg))) return -EINVAL;++	ret = zl10313_readreg(state, DISEQC_MODE, &diseqc_mode);+	if (ret < 0) return ret;++	ret = zl10313_write(state, (0x80 | DISEQC_INSTR), c->msg, c->msg_len);+	if (ret < 0) return ret;++	ret = zl10313_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40) |+				((c->msg_len - 1) << 3) | 0x04);+	if (ret < 0) return ret;++	msleep(100);++	/* set DISEQC_MODE[2:0] to zero if a return message is expected */+	if (c->msg[0] & 0x02) {+		ret = zl10313_writereg(state, DISEQC_MODE, diseqc_mode & 0x40);+		if (ret < 0) return ret;+	}+	return 0;+}++static int zl10313_send_burst(struct dvb_frontend *fe,+				const fe_sec_mini_cmd_t c)+{+	struct zl10313_state *state = fe->demodulator_priv;+	const u8 mini_tab[2] = { 0x02, 0x03 };+	int ret;+	u8 diseqc_mode;++	trace_printk("%s\n", __FUNCTION__);+	params_printk("Set mini burst %s (enum %d)\n",  mini_cmd_name[c], c);+	if (c > SEC_MINI_B) return -EINVAL;+	ret = zl10313_readreg(state, DISEQC_MODE, &diseqc_mode);+	if (ret < 0) return ret;+	ret = zl10313_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40) |+				mini_tab[c]);+	if (ret < 0) return ret;+	return 0;+}++static int zl10313_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)+{+	struct zl10313_state *state = fe->demodulator_priv;+	const u8 tone_tab[2] = { 0x01, 0x00 };+	int ret;+	u8 diseqc_mode;++	trace_printk("%s\n", __FUNCTION__);+	params_printk("Set tone %s (enum %d)\n", tone_name[tone], tone);+	if (tone > SEC_TONE_OFF) return -EINVAL;+	ret = zl10313_readreg(state, DISEQC_MODE, &diseqc_mode);+	if (ret < 0) return ret;+	ret = zl10313_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40) |+				tone_tab[tone]);+	if (ret < 0) return ret;+	return 0;+}++static int zl10313_set_voltage(struct dvb_frontend *fe,+				fe_sec_voltage_t voltage)+{+	struct zl10313_state *state = fe->demodulator_priv;+	const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };+	int ret;+	u8 diseqc_mode;++	trace_printk("%s\n", __FUNCTION__);+	params_printk("Set voltage %s (enum %d)\n", volt_name[voltage],+			voltage);+	if (voltage > SEC_VOLTAGE_OFF) return -EINVAL;+	ret = zl10313_readreg(state, DISEQC_MODE, &diseqc_mode);+	if (ret < 0) return ret;+	ret = zl10313_writereg(state, DISEQC_MODE, (diseqc_mode & 0x07) |+				volt_tab[voltage]);+	if (ret < 0) return ret;+	return 0;+}++static void zl10313_release(struct dvb_frontend *fe)+{+	struct zl10313_state *state = fe->demodulator_priv;++	trace_printk("%s\n", __FUNCTION__);+	kfree(state);+}++static int zl10313_get_tune_settings(struct dvb_frontend *fe,+				struct dvb_frontend_tune_settings *fesettings)+{+	fesettings->min_delay_ms = 100;+	fesettings->step_size = 0;+	fesettings->max_drift = 0;+	return 0;+}++static int zl10313_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)+{+	struct zl10313_state *state = fe->demodulator_priv;+	u8 gpp_ctrl;+	int ret;++	trace_printk("%s,\n", __FUNCTION__);+	params_printk("Switching %d\n", enable);+	ret = zl10313_readreg(state, GPP_CTRL, &gpp_ctrl);+	if (ret < 0) return ret;+	if (enable) {+		return zl10313_writereg(state, GPP_CTRL, gpp_ctrl | 0x40);+	} else {+		return zl10313_writereg(state, GPP_CTRL, gpp_ctrl & ~0x40);+	}+}+++static struct dvb_frontend_ops zl10313_ops;++struct dvb_frontend * zl10313_attach(const struct zl10313_config *config,+					struct i2c_adapter *i2c)+{+	struct zl10313_state *state = NULL;++	trace_printk("%s\n", __FUNCTION__);++	state = kmalloc(sizeof(struct zl10313_state), GFP_KERNEL);+	if (state == NULL) goto error;++	state->config = config;+	state->i2c = i2c;+	memcpy(&state->frontend.ops, &zl10313_ops,+		sizeof(struct dvb_frontend_ops));++	/* check if this is a valid demodulator */+	if (zl10313_readreg(state, ID, &state->id) < 0) goto error;++	switch (state->id) {+	case ID_ZL10313:+		strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");+		break;+	default:+		eprintk("Chip ID does not match a known type\n");+		goto error;+	}+	state->frontend.demodulator_priv = state;+	iprintk("Demodulator attached @ i2c address 0x%02x\n",+		config->demod_address);++	zl10313_dump_registers(state);+	return &state->frontend;+error:+	kfree(state);+	return NULL;+}++static struct dvb_frontend_ops zl10313_ops = {++	.info = {+		.type			= FE_QPSK,+		.frequency_min		= 950000,+		.frequency_max		= 2150000,+		.frequency_stepsize	= 125,      /* kHz for QPSK frontends */+		.frequency_tolerance	= 29500,+		.symbol_rate_min	= 1000000,+		.symbol_rate_max	= 45000000,+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |+			FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 |+			FE_CAN_QPSK | FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO |+			FE_CAN_RECOVER+	},++	.release = zl10313_release,++	.init = zl10313_init,+	.sleep = zl10313_sleep,++	.set_frontend = zl10313_set_frontend,+	.get_frontend = zl10313_get_frontend,+	.get_tune_settings = zl10313_get_tune_settings,++	.read_status = zl10313_read_status,+	.read_ber = zl10313_read_ber,+	.read_signal_strength = zl10313_read_signal_strength,+	.read_snr = zl10313_read_snr,+	.read_ucblocks = zl10313_read_ucblocks,++	.diseqc_send_master_cmd = zl10313_send_master_cmd,+	.diseqc_send_burst = zl10313_send_burst,+	.set_voltage = zl10313_set_voltage,+	.set_tone = zl10313_set_tone,+	.i2c_gate_ctrl = zl10313_i2c_gate_ctrl,++};++MODULE_DESCRIPTION("Zarlink ZL10313 DVB-S demodulator driver");+MODULE_AUTHOR("Jan Daniël Louw <jd.louw@xxxxxxxxxx>");+MODULE_LICENSE("GPL");++EXPORT_SYMBOL(zl10313_attach);diff -r f637ac5a5898 linux/drivers/media/dvb/frontends/zl10313.h--- /dev/null	Thu Jan 01 00:00:00 1970 +0000+++ b/linux/drivers/media/dvb/frontends/zl10313.h	Sat Dec 29 14:12:24 2007 +0200@@ -0,0 +1,47 @@+/*+    Driver for Zarlink ZL10313 DVB-S demodulator++    Copyright (C) 2007 Jan Daniël Louw <jd.louw@xxxxxxxxxx>++    This program is free software; you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation; either version 2 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the++    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License+    along with this program; if not, write to the Free Software+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.+*/++#ifndef ZL10313_H+#define ZL10313_H+++struct zl10313_config+{+	/* demodulator's i2c address */+	u8 demod_address;+};+++#if defined(CONFIG_DVB_ZL10313) || (defined(CONFIG_DVB_ZL10313_MODULE) && \+defined(MODULE))+struct dvb_frontend * zl10313_attach(const struct zl10313_config *config,+					struct i2c_adapter *i2c);+#else+static inline struct dvb_frontend * zl10313_attach(+					const struct zl10313_config *config,+					struct i2c_adapter *i2c)+{+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);+	return NULL;+}+#endif /* CONFIG_DVB_ZL10313 */++#endif /* ZL10313_H */diff -r f637ac5a5898 linux/drivers/media/dvb/frontends/zl10313_priv.h--- /dev/null	Thu Jan 01 00:00:00 1970 +0000+++ b/linux/drivers/media/dvb/frontends/zl10313_priv.h	Sat Dec 29 16:09:33 2007 +0200@@ -0,0 +1,274 @@+/*+    Driver for Zarlink ZL10313 DVB-S Frontend++    Copyright (C) 2007 Jan Daniël Louw <jd.louw@xxxxxxxxxx>++    This program is free software; you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation; either version 2 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the++    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License+    along with this program; if not, write to the Free Software+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.++*/++#ifndef DVB_FRONTENDS_ZL10313_PRIV+#define DVB_FRONTENDS_ZL10313_PRIV++/* Trace function calls */+#define DEBUG_CALL_TRACE	0+/* Trace read/write function calls - information overload */+#define DEBUG_IO_TRACE		0+/* Print register values at critical points */+#define DEBUG_DUMP_REGISTERS	0+/* Print important params passed to functions */+#define DEBUG_PRINT_PARAMS	0++#if DEBUG_CALL_TRACE+	#define trace_printk(args...) printk(KERN_DEBUG "demodulator: " \+						"zl10313: " args)+#else+	#define trace_printk(args...)+#endif++#if DEBUG_IO_TRACE+	#define io_printk(args...) printk(KERN_DEBUG "demodulator: zl10313: " \+						args)+#else+	#define io_printk(args...)+#endif++#if DEBUG_PRINT_PARAMS+	#define params_printk(args...) printk(KERN_DEBUG \+					"demodulator: zl10313: " args)+#else+	#define params_printk(args...)+#endif++#define eprintk(args...) printk(KERN_ERR "demodulator: zl10313: " args)+#define iprintk(args...) printk(KERN_INFO "demodulator: zl10313: " args)++enum zl10313_model_id {+	ID_VP310 = 1,+	ID_MT312 = 3,+	ID_ZL10313 = 5+};++struct zl10313_state+{+	struct i2c_adapter *i2c;+	const struct zl10313_config *config;+	u8 id;+	u32 prev_frequency; /* Store previously set frequency */+	struct dvb_frontend frontend;+};++enum zl10313_reg_addr {+	QPSK_INT_H = 0,+	QPSK_INT_M = 1,+	QPSK_INT_L = 2,+	FEC_INT = 3,+	QPSK_STAT_H = 4,+	QPSK_STAT_L = 5,+	FEC_STATUS = 6,+	LNB_FREQ_H = 7,+	LNB_FREQ_L = 8,+	M_SNR_H = 9,+	M_SNR_L = 10,+	VIT_ERRCNT_H = 11,+	VIT_ERRCNT_M = 12,+	VIT_ERRCNT_L = 13,+	RS_BERCNT_H = 14,+	RS_BERCNT_M = 15,+	RS_BERCNT_L = 16,+	RS_UBC_H = 17,+	RS_UBC_L = 18,+	SIG_LEVEL = 19,+	GPP_CTRL = 20,+	RESET = 21,+	DISEQC_MODE = 22,+	SYM_RATE_H = 23,+	SYM_RATE_L = 24,+	VIT_MODE = 25,+	QPSK_CTRL = 26,+	GO = 27,+	IE_QPSK_H = 28,+	IE_QPSK_M = 29,+	IE_QPSK_L = 30,+	IE_FEC = 31,+	QPSK_STAT_EN = 32,+	FEC_STAT_EN = 33,+	SYS_CLK = 34,+	DISEQC_RATIO = 35,+	DISEQC_INSTR = 36,+	FR_LIM = 37,+	FR_OFF = 38,+	AGC_CTRL = 39,+	AGC_INIT = 40,+	AGC_REF = 41,+	AGC_MAX = 42,+	AGC_MIN = 43,+	AGC_LK_TH = 44,+	TS_AGC_LK_TH = 45,+	AGC_PWR_SET = 46,+	QPSK_MISC = 47,+	SNR_THS_LOW = 48,+	SNR_THS_HIGH = 49,+	TS_SW_RATE = 50,+	TS_SW_LIM_L = 51,+	TS_SW_LIM_H = 52,+	CS_SW_RATE_1 = 53,+	CS_SW_RATE_2 = 54,+	CS_SW_RATE_3 = 55,+	CS_SW_RATE_4 = 56,+	CS_SW_LIM = 57,+	TS_LPK = 58,+	TS_LPK_M = 59,+	TS_LPK_L = 60,+	CS_KPROP_H = 61,+	CS_KPROP_L = 62,+	CS_KINT_H = 63,+	CS_KINT_L = 64,+	QPSK_SCALE = 65,+	TLD_OUTCLK_TH = 66,+	TLD_INCLK_TH = 67,+	FLD_TH = 68,+	PLD_OUTLK3 = 69,+	PLD_OUTLK2 = 70,+	PLD_OUTLK1 = 71,+	PLD_OUTLK0 = 72,+	PLD_INLK3 = 73,+	PLD_INLK2 = 74,+	PLD_INLK1 = 75,+	PLD_INLK0 = 76,+	PLD_ACC_TIME = 77,+	SWEEP_PAR = 78,+	STARTUP_TIME = 79,+	LOSSLOCK_TH = 80,+	FEC_LOCK_TM = 81,+	LOSSLOCK_TM = 82,+	VIT_ERRPER_H = 83,+	VIT_ERRPER_M = 84,+	VIT_ERRPER_L = 85,+	VIT_SETUP = 86,+	VIT_REF0 = 87,+	VIT_REF1 = 88,+	VIT_REF2 = 89,+	VIT_REF3 = 90,+	VIT_REF4 = 91,+	VIT_REF5 = 92,+	VIT_REF6 = 93,+	VIT_MAXERR = 94,+	BA_SETUPT = 95,+	OP_CTRL = 96,+	FEC_SETUP = 97,+	PROG_SYNC = 98,+	AFC_SEAR_TH = 99,+	CSACC_DIF_TH = 100,+	QPSK_LK_CT = 101,+	QPSK_ST_CT = 102,+	MON_CTRL = 103,+	QPSK_RESET = 104,+	QPSK_TST_CT = 105,+	QPSK_TST_ST = 106,+	TEST_R = 107,+	AGC_H = 108,+	AGC_M = 109,+	AGC_L = 110,+	FREQ_ERR1_H = 111,+	FREQ_ERR1_M = 112,+	FREQ_ERR1_L = 113,+	FREQ_ERR2_H = 114,+	FREQ_ERR2_L = 115,+	SYM_RAT_OP_H = 116,+	SYM_RAT_OP_L = 117,+	DESEQC2_INT = 118,+	DISEQC2_STAT = 119,+	DISEQC2_FIFO = 120,+	DISEQC2_CTRL1 = 121,+	DISEQC2_CTRL2 = 122,+	MONITOR_H = 123,+	MONITOR_L = 124,+	TEST_MODE = 125,+	ID = 126,+	CONFIG = 127+};+++#if DEBUG_PRINT_PARAMS+	static const char *inv_str[] = {"OFF", "ON", "AUTO"};+	static const char *fec_str[] = {"NONE", "1/2", "2/3", "3/4", "4/5",+					"5/6", "6/7", "7/8", "8/9", "AUTO"};+	static const char *mini_cmd_name[] = {"SEC_MINI_A", "SEC_MINI_B"};+	static const char *tone_name[] = {"SEC_TONE_ON", "SEC_TONE_OFF"};+	static const char *volt_name[] = {"SEC_VOLTAGE_13", "SEC_VOLTAGE_18",+						"SEC_VOLTAGE_OFF"};+#endif++#if DEBUG_DUMP_REGISTERS || DEBUG_IO_TRACE+static const char *zl10313_reg_names[] = {+	"QPSK_INT_H", "QPSK_INT_M", "QPSK_INT_L", "FEC_INT", "QPSK_STAT_H",+	"QPSK_STAT_L", "FEC_STATUS", "LNB_FREQ_H", "LNB_FREQ_L", "M_SNR_H",+	"M_SNR_L", "VIT_ERRCNT_H", "VIT_ERRCNT_M", "VIT_ERRCNT_L",+	"RS_BERCNT_H", "RS_BERCNT_M", "RS_BERCNT_L", "RS_UBC_H", "RS_UBC_L",+	"SIG_LEVEL", "GPP_CTRL", "RESET", "DISEQC_MODE", "SYM_RATE_H",+	"SYM_RATE_L", "VIT_MODE", "QPSK_CTRL", "GO", "IE_QPSK_H", "IE_QPSK_M",+	"IE_QPSK_L", "IE_FEC", "QPSK_STAT_EN", "FEC_STAT_EN", "SYS_CLK",+	"DISEQC_RATIO", "DISEQC_INSTR", "FR_LIM", "FR_OFF", "AGC_CTRL",+	"AGC_INIT", "AGC_REF", "AGC_MAX", "AGC_MIN", "AGC_LK_TH",+	"TS_AGC_LK_TH", "AGC_PWR_SET", "QPSK_MISC", "SNR_THS_LOW",+	"SNR_THS_HIGH", "TS_SW_RATE", "TS_SW_LIM_L", "TS_SW_LIM_H",+	"CS_SW_RATE_1", "CS_SW_RATE_2", "CS_SW_RATE_3", "CS_SW_RATE_4",+	"CS_SW_LIM", "TS_LPK", "TS_LPK_M", "TS_LPK_L", "CS_KPROP_H",+	"CS_KPROP_L", "CS_KINT_H", "CS_KINT_L", "QPSK_SCALE", "TLD_OUTCLK_TH",+	"TLD_INCLK_TH", "FLD_TH", "PLD_OUTLK3", "PLD_OUTLK2", "PLD_OUTLK1",+	"PLD_OUTLK0", "PLD_INLK3", "PLD_INLK2", "PLD_INLK1", "PLD_INLK0",+	"PLD_ACC_TIME", "SWEEP_PAR", "STARTUP_TIME", "LOSSLOCK_TH",+	"FEC_LOCK_TM", "LOSSLOCK_TM", "VIT_ERRPER_H", "VIT_ERRPER_M",+	"VIT_ERRPER_L", "VIT_SETUP", "VIT_REF0", "VIT_REF1", "VIT_REF2",+	"VIT_REF3", "VIT_REF4", "VIT_REF5", "VIT_REF6", "VIT_MAXERR",+	"BA_SETUPT", "OP_CTRL", "FEC_SETUP", "PROG_SYNC", "AFC_SEAR_TH",+	"CSACC_DIF_TH", "QPSK_LK_CT", "QPSK_ST_CT", "MON_CTRL", "QPSK_RESET",+	"QPSK_TST_CT", "QPSK_TST_ST", "TEST_R", "AGC_H", "AGC_M", "AGC_L",+	"FREQ_ERR1_H", "FREQ_ERR1_M", "FREQ_ERR1_L", "FREQ_ERR2_H",+	"FREQ_ERR2_L", "SYM_RAT_OP_H", "SYM_RAT_OP_L", "DESEQC2_INT",+	"DISEQC2_STAT", "DISEQC2_FIFO", "DISEQC2_CTRL1", "DISEQC2_CTRL2",+	"MONITOR_H", "MONITOR_L", "TEST_MODE", "ID", "CONFIG", ""+};+#endif++#if DEBUG_DUMP_REGISTERS+static int zl10313_read(const struct zl10313_state *state,+			const enum zl10313_reg_addr reg, u8 *buf,+			const size_t count);++static void zl10313_dump_registers(const struct zl10313_state *state)+{+	int ret;+	u8 buf[128];+	u8 reg ;++	trace_printk("%s\n", __FUNCTION__);+	ret = zl10313_read(state, QPSK_INT_H, buf, sizeof(buf));+	if (ret < 0) return;+	for (reg = QPSK_INT_H; reg <= CONFIG; reg += 4) {+		printk(KERN_DEBUG "%03x: [%02x %13s] [%02x %13s] [%02x %13s] "+			"[%02x %13s]\n", reg, buf[reg], zl10313_reg_names[reg],+			buf[reg+1], zl10313_reg_names[reg+1], buf[reg+2],+			zl10313_reg_names[reg+2], buf[reg+3],+			zl10313_reg_names[reg+3]);+	}+}+#else+static inline void zl10313_dump_registers(const struct zl10313_state *state) {}+#endif /* DEBUG_DUMP_REGISTERS */++#endif /* DVB_FRONTENDS_ZL10313_PRIV */diff -r f637ac5a5898 linux/drivers/media/video/saa7134/Kconfig--- a/linux/drivers/media/video/saa7134/Kconfig	Fri Dec 28 00:32:41 2007 -0200+++ b/linux/drivers/media/video/saa7134/Kconfig	Fri Dec 28 17:41:56 2007 +0200@@ -37,6 +37,8 @@ config VIDEO_SAA7134_DVB 	select DVB_TDA826X if !DVB_FE_CUSTOMISE 	select DVB_TDA827X if !DVB_FE_CUSTOMISE 	select DVB_ISL6421 if !DVB_FE_CUSTOMISE+	select DVB_ZL10313 if !DVB_FE_CUSTOMISE+	select DVB_ZL10039 if !DVB_FE_CUSTOMISE 	---help--- 	  This adds support for DVB cards based on the 	  Philips saa7134 chip.diff -r f637ac5a5898 linux/drivers/media/video/saa7134/saa7134-cards.c--- a/linux/drivers/media/video/saa7134/saa7134-cards.c	Fri Dec 28 00:32:41 2007 -0200+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c	Fri Dec 28 15:34:49 2007 +0200@@ -3601,6 +3601,26 @@ struct saa7134_board saa7134_boards[] =  			.tv     = 1, 		}}, 	},+	[SAA7134_BOARD_VIDEOMATE_S350] = {+		/* Jan Daniël Louw <jd.louw@xxxxxxxxxx */+		.name		= "Compro VideoMate S350/S300",+		.audio_clock	= 0x00187de7,+		.tuner_type	= TUNER_ABSENT,+		.radio_type	= UNSET,+		.tuner_addr	= ADDR_UNSET,+		.radio_addr	= ADDR_UNSET,+		.mpeg		= SAA7134_MPEG_DVB,+		.inputs = {{+			.name	= name_comp1,+			.vmux	= 0,+			.amux	= LINE1,+		},{+			.name	= name_svideo,+			.vmux	= 8, /* Not tested */+			.amux	= LINE1+		}},+	},+ };  const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);@@ -4371,6 +4391,12 @@ struct pci_device_id saa7134_pci_tbl[] = 		.subvendor    = 0x4e42, 		.subdevice    = 0x3502, 		.driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS+	},{+		.vendor       = PCI_VENDOR_ID_PHILIPS,+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,+		.subvendor    = 0x185b,+		.subdevice    = 0xc900,+		.driver_data  = SAA7134_BOARD_VIDEOMATE_S350, 	},{ 		/* --- boards without eeprom + subsystem ID --- */ 		.vendor       = PCI_VENDOR_ID_PHILIPS,@@ -4624,6 +4650,11 @@ int saa7134_board_init1(struct saa7134_d 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x8c040007, 0x8c040007); 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd); 		break;+	case SAA7134_BOARD_VIDEOMATE_S350:+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00008000, 0x00008000);+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);+		dev->has_remote = SAA7134_REMOTE_GPIO;+		break; 	} 	return 0; }diff -r f637ac5a5898 linux/drivers/media/video/saa7134/saa7134-dvb.c--- a/linux/drivers/media/video/saa7134/saa7134-dvb.c	Fri Dec 28 00:32:41 2007 -0200+++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c	Sat Dec 29 15:58:59 2007 +0200@@ -38,6 +38,8 @@ #include "mt352_priv.h" /* FIXME */ #include "tda1004x.h" #include "nxt200x.h"+#include "zl10313.h"+#include "zl10039.h"  #include "tda10086.h" #include "tda826x.h"@@ -841,6 +843,17 @@ static struct nxt200x_config kworldatsc1 };  /* ==================================================================+ * ZL10313 based DVB-S cards+ */+static struct zl10313_config zl10313_compro_s350_config = {+	.demod_address = 0x0E,+};++static struct zl10039_config zl10039_compro_s350_config = {+	.tuner_address = 0x60+};++/* ==================================================================  * Core code  */ @@ -1044,6 +1057,15 @@ static int dvb_init(struct saa7134_dev * 	case SAA7134_BOARD_AVERMEDIA_SUPER_007: 		configure_tda827x_fe(dev, &avermedia_super_007_config); 		break;+	case SAA7134_BOARD_VIDEOMATE_S350:+		dev->dvb.frontend = dvb_attach(zl10313_attach,+				&zl10313_compro_s350_config, &dev->i2c_adap);+		if (dev->dvb.frontend) {+			dev->dvb.frontend = dvb_attach(zl10039_attach,+			dev->dvb.frontend, &zl10039_compro_s350_config,+			&dev->i2c_adap);+		}+		break; 	default: 		wprintk("Huh? unknown DVB card?\n"); 		break;diff -r f637ac5a5898 linux/drivers/media/video/saa7134/saa7134-input.c--- a/linux/drivers/media/video/saa7134/saa7134-input.c	Fri Dec 28 00:32:41 2007 -0200+++ b/linux/drivers/media/video/saa7134/saa7134-input.c	Fri Dec 28 15:44:52 2007 +0200@@ -352,6 +352,11 @@ int saa7134_input_init1(struct saa7134_d 		mask_keyup   = 0x8000000; 		polling      = 50; //ms 		break;+	case SAA7134_BOARD_VIDEOMATE_S350:+		ir_codes     = ir_codes_videomate_s350;+		mask_keycode = 0x003F00;+		mask_keydown = 0x040000;+		break; 	} 	if (NULL == ir_codes) { 		printk("%s: Oops: IR config error [card=%d]\n",diff -r f637ac5a5898 linux/drivers/media/video/saa7134/saa7134.h--- a/linux/drivers/media/video/saa7134/saa7134.h	Fri Dec 28 00:32:41 2007 -0200+++ b/linux/drivers/media/video/saa7134/saa7134.h	Fri Dec 28 15:48:46 2007 +0200@@ -247,6 +247,7 @@ struct saa7134_format { #define SAA7134_BOARD_SABRENT_TV_PCB05     115 #define SAA7134_BOARD_10MOONSTVMASTER3     116 #define SAA7134_BOARD_AVERMEDIA_SUPER_007  117+#define SAA7134_BOARD_VIDEOMATE_S350 118  #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8diff -r f637ac5a5898 linux/include/media/ir-common.h--- a/linux/include/media/ir-common.h	Fri Dec 28 00:32:41 2007 -0200+++ b/linux/include/media/ir-common.h	Fri Dec 28 15:55:36 2007 +0200@@ -140,6 +140,7 @@ extern IR_KEYTAB_TYPE ir_codes_encore_en extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE];+extern IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE];  #endif 
_______________________________________________linux-dvb mailing listlinux-dvb@xxxxxxxxxxxxxxx://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb


[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux