Using the previous patch, the compiler will complain about a missing
file (tda18218.h). Please use this updated version of the patch, also
made by Nikola.

Have fun with it, it's working fine here!

Regards, Bert

On Wed, Feb 24, 2010 at 22:42, Bert Massop <bert.mas...@gmail.com> wrote:
>
> This is a forward of the original email from Nikola Pajkovsky. Just
> for the records, so it is on the list.
>
> This solves the problem of the tuner id:179 not supported error, when
> loading the AF9015 driver.
>
> Thank you, Nikola!
>
> Regards,
> Bert Massop
>
> ---------- Forwarded message ----------
> From: Nikola Pajkovsky <npajk...@redhat.com>
> Date: Wed, Feb 24, 2010 at 11:54
> Subject: Re: af901x: NXP TDA18218
> To: Antti Palosaari <cr...@iki.fi>
> Cc: jan.sund...@aland.net, bert.mas...@gmail.com,
> mkru...@kernellabs.com, dheitmuel...@kernellabs.com
>
>
> Hello,
>
>    here is my solution, I can watch Vancouver right now :). I don't
> look at the patch if there is some mistake(no time watch Vancouver),
> but I will when I will have some free time.
> Attached patch apply against this souce (hg clone
> http://linuxtv.org/hg/~anttip/af9015/).
>
> Firmware:
> wget http://jusst.de/manu/fw/AFA/dvb-usb-af9015.fw_a-link
> sudo mv dvb-usb-af9015.fw_a-link /lib/firmware/dvb-usb-af9015.fw
>
> Have a nice day ;)
>
> On 23.2.2010 14:02, Antti Palosaari wrote:
> >
> > Hello,
> > I just got info from one user about this driver, looks like Terratec have 
> > driver.
> > http://forum.ubuntuusers.de/topic/probleme-beim-installieren-terratec-cinergy-t/3/?highlight=terratec+cinergy+t+stick
> >
> > Antti
> >
> > Nikola Pajkovsky wrote:
> >>
> >> Hello,
> >>
> >>    is any chance that will be support for TDA182118?
> >>
> >> Regards,
> >>
> >
>
>
> --
> Nikola
diff -r 0f41fd7df85d linux/drivers/media/common/tuners/Kconfig
--- a/linux/drivers/media/common/tuners/Kconfig	Thu Feb 11 02:33:12 2010 +0200
+++ b/linux/drivers/media/common/tuners/Kconfig	Thu Feb 25 17:21:11 2010 +0100
@@ -179,4 +179,11 @@
 	help
 	  A driver for the silicon tuner MAX2165 from Maxim.
 
+config MEDIA_TUNER_TDA18218
+	tristate "NXP TDA18218 silicon tuner"
+	depends on VIDEO_MEDIA && I2C
+	default m if MEDIA_TUNER_CUSTOMISE
+	help
+	  A driver for the silicon tuner TDA18218 from NXP.
+
 endif # MEDIA_TUNER_CUSTOMISE
diff -r 0f41fd7df85d linux/drivers/media/common/tuners/Makefile
--- a/linux/drivers/media/common/tuners/Makefile	Thu Feb 11 02:33:12 2010 +0200
+++ b/linux/drivers/media/common/tuners/Makefile	Thu Feb 25 17:21:11 2010 +0100
@@ -24,6 +24,7 @@
 obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
 obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
 obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
+obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff -r 0f41fd7df85d linux/drivers/media/common/tuners/tda18218.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linux/drivers/media/common/tuners/tda18218.c	Thu Feb 25 17:21:11 2010 +0100
@@ -0,0 +1,471 @@
+/*
+ *  Driver for NXP TDA18218 silicon tuner
+ *
+ *  Copyright (C) 2010 Lauris Ding <ld...@gmx.de>
+ *  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 "tda18218.h"
+#include "compat.h"
+#include "tda18218_priv.h"
+
+static int tda18218_write_reg(struct dvb_frontend *fe, u8 reg, u8 val)
+{
+	struct tda18218_priv *priv = fe->tuner_priv;
+	u8 buf[2] = { reg, val };
+	struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0,
+			       .buf = buf, .len = 2 };
+	int ret;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	/* write register */
+	ret = i2c_transfer(priv->i2c, &msg, 1);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	if (ret != 1)
+		printk(KERN_WARNING "I2C write failed ret: %d reg: %02x\n", ret, reg);
+
+	return (ret == 1 ? 0 : ret);
+}
+
+static int tda18218_write_regs(struct dvb_frontend *fe, u8 reg,
+	u8 *val, u8 len)
+{
+	struct tda18218_priv *priv = fe->tuner_priv;
+	u8 buf[1+len];
+	struct i2c_msg msg = {
+		.addr = priv->cfg->i2c_address,
+		.flags = 0,
+		.len = sizeof(buf),
+		.buf = buf };
+		
+	int ret;
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+	
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	ret = i2c_transfer(priv->i2c, &msg, 1);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (ret != 1)
+		printk(KERN_WARNING "I2C write failed ret: %d reg: %02x len: %d\n", ret, reg, len);
+	
+	return (ret == 1 ? 0 : ret);
+}
+
+/*static int tda18218_read_reg(struct tda18218_priv *priv, u16 reg, u8 *val)
+{
+	u8 obuf[3] = { reg >> 8, reg & 0xff, 0 };
+	u8 ibuf[1];
+	struct i2c_msg msg[2] = {
+		{
+			.addr = 0x3a,
+			.flags = 0,
+			.len = sizeof(obuf),
+			.buf = obuf
+		}, {
+			.addr = 0x3a,
+			.flags = I2C_M_RD,
+			.len = sizeof(ibuf),
+			.buf = ibuf
+		}
+	};
+
+	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+		printk(KERN_WARNING "I2C read failed reg:%04x\n", reg);
+		return -EREMOTEIO;
+	}
+	*val = ibuf[0];
+	return 0;
+}*/
+
+static int tda18218_read_regs(struct dvb_frontend *fe)
+{
+	struct tda18218_priv *priv = fe->tuner_priv;
+	u8 *regs = priv->tda18218_regs;
+	u8 buf = 0x00;
+	int ret;
+	//int i;
+	struct i2c_msg msg[] = {
+		{ .addr = 0xc0, .flags = 0,
+		  .buf = &buf, .len = 1 },
+		{ .addr = 0xc0, .flags = I2C_M_RD,
+		  .buf = regs, .len = 59 }
+	};
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	/* read all registers */
+	ret = i2c_transfer(priv->i2c, msg, 2);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	if (ret != 2)
+		printk(KERN_WARNING "I2C read failed ret: %d\n", ret);
+	
+	/*for(i = 0; i <= 58; i++)
+		printk("Register %d: %02x\n", i, 0xff & regs[i]);*/
+
+	return (ret == 2 ? 0 : ret);
+}
+
+static int tda18218_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct tda18218_priv *priv = fe->tuner_priv;
+	u8 *regs = priv->tda18218_regs;
+	u8 Fc, BP;
+	int i, ret;
+	u16 if1, bw;
+	u32 freq;
+	
+	u8 paramsbuf[4][6] = {
+		{ 0x03, 0x1a },
+		{ 0x04, 0x0a },
+		{ 0x01, 0x0f },
+		{ 0x01, 0x0f },
+	};
+	
+	u8 agcbuf[][2] = {
+		{ 0x1a, 0x0e },
+		{ 0x20, 0x60 },
+		{ 0x23, 0x02 },
+		{ 0x20, 0xa0 },
+		{ 0x23, 0x09 },
+		{ 0x20, 0xe0 },
+		{ 0x23, 0x0c },
+		{ 0x20, 0x40 },
+		{ 0x23, 0x01 },
+		{ 0x20, 0x80 },
+		{ 0x23, 0x08 },
+		{ 0x20, 0xc0 },
+		{ 0x23, 0x0b },
+		{ 0x24, 0x1c },
+		{ 0x24, 0x0c },
+	};
+	
+	switch (params->u.ofdm.bandwidth) {
+	case BANDWIDTH_6_MHZ:
+		bw = 6000;
+		Fc = 0;
+		break;
+	case BANDWIDTH_7_MHZ:
+		bw = 7000;
+		Fc = 1;
+		break;
+	case BANDWIDTH_8_MHZ:
+		bw = 8000;
+		Fc = 2;
+		break;
+	default:
+		printk(KERN_WARNING "Invalid bandwidth");
+		return -EINVAL;
+	}
+	
+	if1 = bw / 2;
+	
+	if((params->frequency >= 174000000) && (params->frequency < 188000000)) {
+		BP = 3;
+	}
+	else if((params->frequency >= 188000000) && (params->frequency < 253000000)) {
+		BP = 4;
+	}
+	else if((params->frequency >= 253000000) && (params->frequency < 343000000)) {
+		BP = 5;
+	}
+	else if((params->frequency >= 343000000) && (params->frequency <= 870000000)) {
+		BP = 6;
+	}
+	else {
+		printk(KERN_WARNING "Frequency out of range");
+		return -EINVAL;
+	}
+	
+	freq = params->frequency;
+	freq /= 1000;
+	freq +=if1;
+	freq *= 16;
+	
+	tda18218_read_regs(fe);
+	
+	paramsbuf[0][2] = regs[0x1a] | BP;
+	paramsbuf[0][3] = regs[0x1b] & ~3;
+	paramsbuf[0][3] = regs[0x1b] | Fc;
+	paramsbuf[0][4] = regs[0x1c] | 0x0a;
+	
+	paramsbuf[1][2] = freq >> 16;
+	paramsbuf[1][3] = freq >> 8;
+	paramsbuf[1][4] = (freq & 0xf0) | (regs[0x0c] & 0x0f);
+	paramsbuf[1][5] = 0xff;
+	paramsbuf[2][2] = regs[0x0f] | 0x40;
+	paramsbuf[3][2] = 0x09;
+	
+	tda18218_write_reg(fe, 0x04, 0x03);
+
+	for(i = 0; i < ARRAY_SIZE(paramsbuf); i++) {
+
+		/* write registers */
+		ret = tda18218_write_regs(fe, paramsbuf[i][1], &paramsbuf[i][2], paramsbuf[i][0]);
+
+		if (ret)
+			goto error;
+	}
+	for(i = 0; i < ARRAY_SIZE(agcbuf); i++) {
+		tda18218_write_reg(fe, agcbuf[i][0], agcbuf[i][1]);
+	}
+	
+	//tda18218_write_reg(fe, 0x03, 0x00);
+	//tda18218_write_reg(fe, 0x04, 0x00);
+	//tda18218_write_reg(fe, 0x20, 0xc7);
+	
+	msleep(60);
+	i = 0;
+	while(i < 10) {
+		tda18218_read_regs(fe);
+		if((regs[0x01] & 0x60) == 0x60)
+			printk(KERN_INFO "We've got a lock!"); break;
+		msleep(20);
+		i++;
+	}
+	
+	priv->bandwidth = params->u.ofdm.bandwidth;
+	priv->frequency = params->frequency;
+	return 0;
+error:
+	return ret;
+}
+
+static int tda18218_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct tda18218_priv *priv = fe->tuner_priv;
+	*frequency = priv->frequency;
+	return 0;
+}
+
+static int tda18218_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct tda18218_priv *priv = fe->tuner_priv;
+	*bandwidth = priv->bandwidth;
+	return 0;
+}
+
+static int tda18218_init(struct dvb_frontend *fe)
+{
+	//struct tda18218_priv *priv = fe->tuner_priv;
+	//u8 *regs = priv->tda18218_regs;
+	int i;
+	int ret;
+	
+	u8 initbuf[][18] = {
+		{ 0x10, 0x05, 0x00, 0x00, 0xd0, 0x00, 0x40, 0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00, 0x01 },
+		{ 0x0b, 0x15, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x0e, 0x29, 0x98, 0x00, 0x00, 0x58 },
+		{ 0x10, 0x24, 0x0c, 0x48, 0x85, 0xc9, 0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00, 0x8a, 0x00 },
+		{ 0x07, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6 },
+	};
+	
+	u8 initbuf2[4];
+
+	for(i = 0; i < ARRAY_SIZE(initbuf); i++) {
+		
+		/* write registers */
+		ret = tda18218_write_regs(fe, initbuf[i][1], &initbuf[i][2], initbuf[i][0]);
+
+		if (ret != 0) {
+			printk(KERN_ERR "init: ERROR: i2c_transfer returned: %d\n", ret);
+			return -EREMOTEIO;
+		}
+		if(i == 1) {
+			tda18218_write_reg(fe, 0x22, 0x8c);
+		}
+	}
+	
+	tda18218_write_reg(fe, 0x05, 0x80);
+	tda18218_write_reg(fe, 0x05, 0x00);
+	tda18218_write_reg(fe, 0x05, 0x20);
+	tda18218_write_reg(fe, 0x05, 0x00);
+	tda18218_write_reg(fe, 0x27, 0xde);
+	tda18218_write_reg(fe, 0x17, 0xf8);
+	tda18218_write_reg(fe, 0x18, 0x0f);
+	tda18218_write_reg(fe, 0x1c, 0x8b);
+	tda18218_write_reg(fe, 0x29, 0x02);
+	tda18218_write_reg(fe, 0x19, 0x1a);
+	tda18218_write_reg(fe, 0x11, 0x13);
+
+	initbuf2[0] = 0x0a;
+	initbuf2[1] = 0x5c;
+	initbuf2[2] = 0xc6;
+	initbuf2[3] = 0x07;
+	tda18218_write_regs(fe, initbuf2[0], &initbuf2[1], 3);
+	tda18218_write_reg(fe, 0x0f, 0x49);
+	tda18218_write_reg(fe, 0x05, 0x40);
+	tda18218_write_reg(fe, 0x05, 0x00);
+	tda18218_write_reg(fe, 0x05, 0x20);
+	tda18218_write_reg(fe, 0x11, 0xed);
+	tda18218_write_reg(fe, 0x0f, 0x49);
+	tda18218_write_reg(fe, 0x19, 0x2a);
+	tda18218_write_reg(fe, 0x05, 0x58);
+	tda18218_write_reg(fe, 0x05, 0x18);
+	tda18218_write_reg(fe, 0x05, 0x38);
+	tda18218_write_reg(fe, 0x29, 0x03);
+	tda18218_write_reg(fe, 0x19, 0x1a);
+	tda18218_write_reg(fe, 0x11, 0x13);
+	initbuf2[0] = 0x0a;
+	initbuf2[1] = 0xbe;
+	initbuf2[2] = 0x6e;
+	initbuf2[3] = 0x07;
+	tda18218_write_regs(fe, initbuf2[0], &initbuf2[1], 3);
+	tda18218_write_reg(fe, 0x0f, 0x49);
+	tda18218_write_reg(fe, 0x05, 0x58);
+	tda18218_write_reg(fe, 0x05, 0x18);
+	tda18218_write_reg(fe, 0x05, 0x38);
+	tda18218_write_reg(fe, 0x11, 0xed);
+	tda18218_write_reg(fe, 0x0f, 0x49);
+	tda18218_write_reg(fe, 0x19, 0x2a);
+	tda18218_write_reg(fe, 0x05, 0x58);
+	tda18218_write_reg(fe, 0x05, 0x18);
+	tda18218_write_reg(fe, 0x05, 0x38);
+	tda18218_write_reg(fe, 0x19, 0x0a);
+	tda18218_write_reg(fe, 0x27, 0xc9);
+	tda18218_write_reg(fe, 0x11, 0x13);
+	initbuf2[0] = 0x17;
+	initbuf2[1] = 0xf0;
+	initbuf2[2] = 0x19;
+	initbuf2[3] = 0x00;
+	tda18218_write_regs(fe, initbuf2[0], &initbuf2[1], 2);
+	tda18218_write_reg(fe, 0x1c, 0x98);
+	tda18218_write_reg(fe, 0x29, 0x03);
+	tda18218_write_reg(fe, 0x2a, 0x00);
+	tda18218_write_reg(fe, 0x2a, 0x01);
+	tda18218_write_reg(fe, 0x2a, 0x02);
+	tda18218_write_reg(fe, 0x2a, 0x03);
+	tda18218_write_reg(fe, 0x1c, 0x98);
+	tda18218_write_reg(fe, 0x18, 0x19);
+	tda18218_write_reg(fe, 0x22, 0x9c);
+	tda18218_write_reg(fe, 0x1f, 0x58);
+	tda18218_write_reg(fe, 0x24, 0x0c);
+	tda18218_write_reg(fe, 0x1c, 0x88);
+	tda18218_write_reg(fe, 0x20, 0x10);
+	tda18218_write_reg(fe, 0x21, 0x4c);
+	tda18218_write_reg(fe, 0x20, 0x00);
+	tda18218_write_reg(fe, 0x21, 0x48);
+	tda18218_write_reg(fe, 0x1f, 0x5b);
+	tda18218_write_reg(fe, 0x20, 0x00);
+	tda18218_write_reg(fe, 0x1f, 0x59);
+	tda18218_write_reg(fe, 0x20, 0x00);
+	tda18218_write_reg(fe, 0x1f, 0x5a);
+	tda18218_write_reg(fe, 0x20, 0x00);
+	tda18218_write_reg(fe, 0x1f, 0x5f);
+	tda18218_write_reg(fe, 0x20, 0x00);
+	tda18218_write_reg(fe, 0x1f, 0x5d);
+	tda18218_write_reg(fe, 0x20, 0x00);
+	tda18218_write_reg(fe, 0x1f, 0x5e);
+	tda18218_write_reg(fe, 0x20, 0x00);
+	tda18218_write_reg(fe, 0x20, 0x60);
+	tda18218_write_reg(fe, 0x23, 0x02);
+	tda18218_write_reg(fe, 0x20, 0xa0);
+	tda18218_write_reg(fe, 0x23, 0x09);
+	tda18218_write_reg(fe, 0x20, 0xe0);
+	tda18218_write_reg(fe, 0x23, 0x0c);
+	tda18218_write_reg(fe, 0x20, 0x40);
+	tda18218_write_reg(fe, 0x23, 0x01);
+	tda18218_write_reg(fe, 0x20, 0x80);
+	tda18218_write_reg(fe, 0x23, 0x08);
+	tda18218_write_reg(fe, 0x20, 0xc0);
+	tda18218_write_reg(fe, 0x23, 0x0b);
+	tda18218_write_reg(fe, 0x1c, 0x98);
+	tda18218_write_reg(fe, 0x22, 0x8c);
+	initbuf2[0] = 0x17;
+	initbuf2[1] = 0xb0;
+	initbuf2[2] = 0x59;
+	initbuf2[3] = 0x00;
+	//tda18218_write_regs(fe, initbuf2[0], &initbuf2[1], 2);
+	initbuf2[0] = 0x1a;
+	initbuf2[1] = 0x0e;
+	initbuf2[2] = 0x2a;
+	initbuf2[3] = 0x98;
+	tda18218_write_regs(fe, initbuf2[0], &initbuf2[1], 3);
+	initbuf2[0] = 0x17;
+	initbuf2[1] = 0xb0;
+	initbuf2[2] = 0x59;
+	initbuf2[3] = 0x00;
+	tda18218_write_regs(fe, initbuf2[0], &initbuf2[1], 2);
+	tda18218_write_reg(fe, 0x2d, 0x81);
+	tda18218_write_reg(fe, 0x29, 0x02);
+	
+	return 0;
+}
+	
+static int tda18218_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static const struct dvb_tuner_ops tda18218_tuner_ops = {
+	.info = {
+		.name           = "NXP TDA18218",
+		.frequency_min  = TDA18218_MIN_FREQ,
+		.frequency_max  = TDA18218_MAX_FREQ,
+		.frequency_step = TDA18218_STEP,
+	},
+
+	.release       = tda18218_release,
+	.init          = tda18218_init,
+	
+	.set_params = tda18218_set_params,
+	.get_frequency = tda18218_get_frequency,
+	.get_bandwidth = tda18218_get_bandwidth,
+};
+
+struct dvb_frontend * tda18218_attach(struct dvb_frontend *fe,
+				    struct i2c_adapter *i2c,
+				    struct tda18218_config *cfg)
+{
+	struct tda18218_priv *priv = NULL;
+
+	priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->cfg = cfg;
+	priv->i2c = i2c;
+
+	fe->tuner_priv = priv;
+	
+	tda18218_read_regs(fe);
+	if (priv->tda18218_regs[0x00] != 0xc0) {
+		printk(KERN_WARNING "Device is not a TDA18218!\n");
+		kfree(priv);
+		return NULL;
+	}
+	
+	printk(KERN_INFO "NXP TDA18218 successfully identified.\n");
+	memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
+	       sizeof(struct dvb_tuner_ops));
+	
+	return fe;
+}
+EXPORT_SYMBOL(tda18218_attach);
+
+MODULE_DESCRIPTION("NXP TDA18218 silicon tuner driver");
+MODULE_AUTHOR("Lauris Ding <ld...@gmx.de>");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff -r 0f41fd7df85d linux/drivers/media/common/tuners/tda18218.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linux/drivers/media/common/tuners/tda18218.h	Thu Feb 25 17:21:11 2010 +0100
@@ -0,0 +1,44 @@
+/*
+ *  Driver for  NXP TDA18218 silicon tuner
+ *
+ *  Copyright (C) 2010 Lauris Ding <ld...@gmx.de>
+ *
+ *  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 TDA18218_H
+#define TDA18218_H
+
+#include "dvb_frontend.h"
+
+struct tda18218_config {
+	u8 i2c_address;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_TDA18218) || (defined(CONFIG_MEDIA_TUNER_TDA18218_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
+					  struct i2c_adapter *i2c,
+					  struct tda18218_config *cfg);
+#else
+static inline struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
+						 struct i2c_adapter *i2c,
+						 struct tda18218_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_MEDIA_TUNER_TDA18218
+
+#endif
\ No newline at end of file
diff -r 0f41fd7df85d linux/drivers/media/common/tuners/tda18218_priv.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linux/drivers/media/common/tuners/tda18218_priv.h	Thu Feb 25 17:21:11 2010 +0100
@@ -0,0 +1,36 @@
+/*
+ *  Driver for NXP TDA18218 silicon tuner
+ *
+ *  Copyright (C) 2010 Lauris Ding <ld...@gmx.de>
+ *  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 TDA18218_PRIV_H
+#define TDA18218_PRIV_H
+
+#define TDA18218_STEP         1000 /* 1 kHz */
+#define TDA18218_MIN_FREQ   174000000 /*   174 MHz */
+#define TDA18218_MAX_FREQ  864000000 /*  864 MHz */
+
+struct tda18218_priv {
+	u8 tda18218_regs[0x3b];
+	struct tda18218_config *cfg;
+	struct i2c_adapter *i2c;
+
+	u32 frequency;
+	u32 bandwidth;
+};
+
+#endif
diff -r 0f41fd7df85d linux/drivers/media/dvb/dvb-usb/af9015.c
--- a/linux/drivers/media/dvb/dvb-usb/af9015.c	Thu Feb 11 02:33:12 2010 +0200
+++ b/linux/drivers/media/dvb/dvb-usb/af9015.c	Thu Feb 25 17:21:11 2010 +0100
@@ -20,11 +20,7 @@
  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
 
-#include <linux/hash.h>
-
-#endif
 #include "af9015.h"
 #include "af9013.h"
 #include "mt2060.h"
@@ -32,6 +28,7 @@
 #include "tda18271.h"
 #include "mxl5005s.h"
 #include "mc44s803.h"
+#include "tda18218.h"
 
 static int dvb_usb_af9015_debug;
 module_param_named(debug, dvb_usb_af9015_debug, int, 0644);
@@ -273,7 +270,8 @@
 
 	while (i < num) {
 		if (msg[i].addr == af9015_af9013_config[0].demod_address ||
-		    msg[i].addr == af9015_af9013_config[1].demod_address) {
+		    msg[i].addr == af9015_af9013_config[1].demod_address  ||
+		    msg[i].addr == 0x3a) {
 			addr = msg[i].buf[0] << 8;
 			addr += msg[i].buf[1];
 			mbox = msg[i].buf[2];
@@ -286,7 +284,8 @@
 
 		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
 			if (msg[i].addr ==
-				af9015_af9013_config[0].demod_address)
+				af9015_af9013_config[0].demod_address ||
+			    msg[i].addr == 0x3a)
 				req.cmd = READ_MEMORY;
 			else
 				req.cmd = READ_I2C;
@@ -301,7 +300,8 @@
 		} else if (msg[i].flags & I2C_M_RD) {
 			ret = -EINVAL;
 			if (msg[i].addr ==
-				af9015_af9013_config[0].demod_address)
+				af9015_af9013_config[0].demod_address ||
+			    msg[i].addr == 0x3a)
 				goto error;
 			else
 				req.cmd = READ_I2C;
@@ -315,7 +315,8 @@
 			i += 1;
 		} else {
 			if (msg[i].addr ==
-				af9015_af9013_config[0].demod_address)
+				af9015_af9013_config[0].demod_address ||
+			    msg[i].addr == 0x3a)
 				req.cmd = WRITE_MEMORY;
 			else
 				req.cmd = WRITE_I2C;
@@ -560,24 +561,11 @@
 	return ret;
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+/* dump eeprom */
 static int af9015_eeprom_dump(struct dvb_usb_device *d)
-#else
-/* hash (and dump) eeprom */
-static int af9015_eeprom_hash(struct usb_device *udev)
-#endif
 {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
 	u8 reg, val;
-#else
-	static const unsigned int eeprom_size = 256;
-	unsigned int reg;
-	int ret;
-	u8 val, *eeprom;
-	struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
-#endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
 	for (reg = 0; ; reg++) {
 		if (reg % 16 == 0) {
 			if (reg)
@@ -590,43 +578,9 @@
 			deb_info(KERN_CONT " --");
 		if (reg == 0xff)
 			break;
-#else
-	eeprom = kmalloc(eeprom_size, GFP_KERNEL);
-	if (eeprom == NULL)
-		return -ENOMEM;
-
-	for (reg = 0; reg < eeprom_size; reg++) {
-		req.addr = reg;
-		ret = af9015_rw_udev(udev, &req);
-		if (ret)
-			goto free;
-		eeprom[reg] = val;
-#endif
 	}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
 	deb_info(KERN_CONT "\n");
 	return 0;
-#else
-	if (dvb_usb_af9015_debug & 0x01)
-		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom,
-				eeprom_size);
-
-	BUG_ON(eeprom_size % 4);
-
-	af9015_config.eeprom_sum = 0;
-	for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) {
-		af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32;
-		af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]);
-	}
-
-	deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum);
-
-	ret = 0;
-free:
-	kfree(eeprom);
-	return ret;
-#endif
 }
 
 static int af9015_download_ir_table(struct dvb_usb_device *d)
@@ -765,132 +719,12 @@
 	return ret;
 }
 
-struct af9015_setup {
-	unsigned int id;
-	struct dvb_usb_rc_key *rc_key_map;
-	unsigned int rc_key_map_size;
-	u8 *ir_table;
-	unsigned int ir_table_size;
-};
-
-static const struct af9015_setup *af9015_setup_match(unsigned int id,
-		const struct af9015_setup *table)
-{
-	for (; table->rc_key_map; table++)
-		if (table->id == id)
-			return table;
-	return NULL;
-}
-
-static const struct af9015_setup af9015_setup_modparam[] = {
-	{ AF9015_REMOTE_A_LINK_DTU_M,
-		af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link),
-		af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) },
-	{ AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
-		af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi),
-		af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) },
-	{ AF9015_REMOTE_MYGICTV_U718,
-		af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv),
-		af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) },
-	{ AF9015_REMOTE_DIGITTRADE_DVB_T,
-		af9015_rc_keys_digittrade, ARRAY_SIZE(af9015_rc_keys_digittrade),
-		af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) },
-	{ AF9015_REMOTE_AVERMEDIA_KS,
-		af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia),
-		af9015_ir_table_avermedia_ks, ARRAY_SIZE(af9015_ir_table_avermedia_ks) },
-	{ }
-};
-
-/* don't add new entries here anymore, use hashes instead */
-static const struct af9015_setup af9015_setup_usbids[] = {
-	{ USB_VID_LEADTEK,
-		af9015_rc_keys_leadtek, ARRAY_SIZE(af9015_rc_keys_leadtek),
-		af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) },
-	{ USB_VID_VISIONPLUS,
-		af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan),
-		af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) },
-	{ USB_VID_KWORLD_2, /* TODO: use correct rc keys */
-		af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan),
-		af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) },
-	{ USB_VID_AVERMEDIA,
-		af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia),
-		af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) },
-	{ USB_VID_MSI_2,
-		af9015_rc_keys_msi_digivox_iii, ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii),
-		af9015_ir_table_msi_digivox_iii, ARRAY_SIZE(af9015_ir_table_msi_digivox_iii) },
-	{ }
-};
-
-static const struct af9015_setup af9015_setup_hashes[] = {
-	{ 0xb8feb708,
-		af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi),
-		af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) },
-	{ 0xa3703d00,
-		af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link),
-		af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) },
-	{ 0x9b7dc64e,
-		af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv),
-		af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) },
-	{ }
-};
-
-static void af9015_set_remote_config(struct usb_device *udev,
-		struct dvb_usb_device_properties *props)
-{
-	const struct af9015_setup *table = NULL;
-
-	if (dvb_usb_af9015_remote) {
-		/* load remote defined as module param */
-		table = af9015_setup_match(dvb_usb_af9015_remote,
-				af9015_setup_modparam);
-	} else {
-		u16 vendor = le16_to_cpu(udev->descriptor.idVendor);
-
-		table = af9015_setup_match(af9015_config.eeprom_sum,
-				af9015_setup_hashes);
-
-		if (!table && vendor == USB_VID_AFATECH) {
-			/* Check USB manufacturer and product strings and try
-			   to determine correct remote in case of chip vendor
-			   reference IDs are used.
-			   DO NOT ADD ANYTHING NEW HERE. Use hashes instead.
-			 */
-			char manufacturer[10];
-			memset(manufacturer, 0, sizeof(manufacturer));
-			usb_string(udev, udev->descriptor.iManufacturer,
-				manufacturer, sizeof(manufacturer));
-			if (!strcmp("MSI", manufacturer)) {
-				/* iManufacturer 1 MSI
-				   iProduct      2 MSI K-VOX */
-				table = af9015_setup_match(
-					AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
-					af9015_setup_modparam);
-			} else if (udev->descriptor.idProduct ==
-				cpu_to_le16(USB_PID_TREKSTOR_DVBT)) {
-				table = &(const struct af9015_setup){ 0,
-					af9015_rc_keys_trekstor,
-					ARRAY_SIZE(af9015_rc_keys_trekstor),
-					af9015_ir_table_trekstor,
-					ARRAY_SIZE(af9015_ir_table_trekstor)
-				};
-			}
-		} else if (!table)
-			table = af9015_setup_match(vendor, af9015_setup_usbids);
-	}
-
-	if (table) {
-		props->rc_key_map = table->rc_key_map;
-		props->rc_key_map_size = table->rc_key_map_size;
-		af9015_config.ir_table = table->ir_table;
-		af9015_config.ir_table_size = table->ir_table_size;
-	}
-}
-
 static int af9015_read_config(struct usb_device *udev)
 {
 	int ret;
 	u8 val, i, offset = 0;
 	struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
+	char manufacturer[10];
 
 	/* IR remote controller */
 	req.addr = AF9015_EEPROM_IR_MODE;
@@ -902,20 +736,158 @@
 	}
 	if (ret)
 		goto error;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
-	ret = af9015_eeprom_hash(udev);
-	if (ret)
-		goto error;
-
-#endif
 	deb_info("%s: IR mode:%d\n", __func__, val);
 	for (i = 0; i < af9015_properties_count; i++) {
 		if (val == AF9015_IR_MODE_DISABLED) {
 			af9015_properties[i].rc_key_map = NULL;
 			af9015_properties[i].rc_key_map_size  = 0;
-		} else
-			af9015_set_remote_config(udev, &af9015_properties[i]);
+		} else if (dvb_usb_af9015_remote) {
+			/* load remote defined as module param */
+			switch (dvb_usb_af9015_remote) {
+			case AF9015_REMOTE_A_LINK_DTU_M:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_a_link;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_a_link);
+				af9015_config.ir_table = af9015_ir_table_a_link;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_a_link);
+				break;
+			case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_msi;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_msi);
+				af9015_config.ir_table = af9015_ir_table_msi;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_msi);
+				break;
+			case AF9015_REMOTE_MYGICTV_U718:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_mygictv;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_mygictv);
+				af9015_config.ir_table =
+				  af9015_ir_table_mygictv;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_mygictv);
+				break;
+			case AF9015_REMOTE_DIGITTRADE_DVB_T:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_digittrade;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_digittrade);
+				af9015_config.ir_table =
+				  af9015_ir_table_digittrade;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_digittrade);
+				break;
+			case AF9015_REMOTE_AVERMEDIA_KS:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_avermedia;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_avermedia);
+				af9015_config.ir_table =
+				  af9015_ir_table_avermedia_ks;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_avermedia_ks);
+				break;
+			}
+		} else {
+			switch (le16_to_cpu(udev->descriptor.idVendor)) {
+			case USB_VID_LEADTEK:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_leadtek;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_leadtek);
+				af9015_config.ir_table =
+				  af9015_ir_table_leadtek;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_leadtek);
+				break;
+			case USB_VID_VISIONPLUS:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_twinhan;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_twinhan);
+				af9015_config.ir_table =
+				  af9015_ir_table_twinhan;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_twinhan);
+				break;
+			case USB_VID_KWORLD_2:
+				/* TODO: use correct rc keys */
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_twinhan;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_twinhan);
+				af9015_config.ir_table = af9015_ir_table_kworld;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_kworld);
+				break;
+			/* Check USB manufacturer and product strings and try
+			   to determine correct remote in case of chip vendor
+			   reference IDs are used. */
+			case USB_VID_AFATECH:
+				memset(manufacturer, 0, sizeof(manufacturer));
+				usb_string(udev, udev->descriptor.iManufacturer,
+					manufacturer, sizeof(manufacturer));
+				if (!strcmp("Geniatech", manufacturer)) {
+					/* iManufacturer 1 Geniatech
+					   iProduct      2 AF9015 */
+					af9015_properties[i].rc_key_map =
+					  af9015_rc_keys_mygictv;
+					af9015_properties[i].rc_key_map_size =
+					  ARRAY_SIZE(af9015_rc_keys_mygictv);
+					af9015_config.ir_table =
+					  af9015_ir_table_mygictv;
+					af9015_config.ir_table_size =
+					  ARRAY_SIZE(af9015_ir_table_mygictv);
+				} else if (!strcmp("MSI", manufacturer)) {
+					/* iManufacturer 1 MSI
+					   iProduct      2 MSI K-VOX */
+					af9015_properties[i].rc_key_map =
+					  af9015_rc_keys_msi;
+					af9015_properties[i].rc_key_map_size =
+					  ARRAY_SIZE(af9015_rc_keys_msi);
+					af9015_config.ir_table =
+					  af9015_ir_table_msi;
+					af9015_config.ir_table_size =
+					  ARRAY_SIZE(af9015_ir_table_msi);
+				} else if (udev->descriptor.idProduct ==
+					cpu_to_le16(USB_PID_TREKSTOR_DVBT)) {
+					af9015_properties[i].rc_key_map =
+					  af9015_rc_keys_trekstor;
+					af9015_properties[i].rc_key_map_size =
+					  ARRAY_SIZE(af9015_rc_keys_trekstor);
+					af9015_config.ir_table =
+					  af9015_ir_table_trekstor;
+					af9015_config.ir_table_size =
+					  ARRAY_SIZE(af9015_ir_table_trekstor);
+				}
+				break;
+			case USB_VID_AVERMEDIA:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_avermedia;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_avermedia);
+				af9015_config.ir_table =
+				  af9015_ir_table_avermedia;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_avermedia);
+				break;
+			case USB_VID_MSI_2:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_msi_digivox_iii;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii);
+				af9015_config.ir_table =
+				  af9015_ir_table_msi_digivox_iii;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_msi_digivox_iii);
+				break;
+			}
+		}
 	}
 
 	/* TS mode - one or two receivers */
@@ -1026,6 +998,7 @@
 		case AF9013_TUNER_MT2060_2:
 		case AF9013_TUNER_TDA18271:
 		case AF9013_TUNER_QT1010A:
+		case AF9013_TUNER_TDA18218:
 			af9015_af9013_config[i].rf_spec_inv = 1;
 			break;
 		case AF9013_TUNER_MXL5003D:
@@ -1037,9 +1010,6 @@
 			af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
 			af9015_af9013_config[i].rf_spec_inv = 1;
 			break;
-		case AF9013_TUNER_TDA18218:
-			warn("tuner NXP TDA18218 not supported yet");
-			return -ENODEV;
 		default:
 			warn("tuner id:%d not supported, please report!", val);
 			return -ENODEV;
@@ -1164,11 +1134,11 @@
 
 		deb_info("%s: init I2C\n", __func__);
 		ret = af9015_i2c_init(adap->dev);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+
+		/* dump eeprom (debug) */
 		ret = af9015_eeprom_dump(adap->dev);
 		if (ret)
 			return ret;
-#endif
 	} else {
 		/* select I2C adapter */
 		i2c_adap = &state->i2c_adap;
@@ -1247,6 +1217,10 @@
 	.dig_out = 1,
 };
 
+static struct tda18218_config af9015_tda18218_config = {
+	.i2c_address = 0xc0,
+};
+
 static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct af9015_state *state = adap->dev->priv;
@@ -1294,6 +1268,10 @@
 		ret = dvb_attach(mc44s803_attach, adap->fe, i2c_adap,
 			&af9015_mc44s803_config) == NULL ? -ENODEV : 0;
 		break;
+	case AF9013_TUNER_TDA18218:
+		ret = dvb_attach(tda18218_attach, adap->fe, i2c_adap,
+			&af9015_tda18218_config) == NULL ? -ENODEV : 0;
+		break;
 	case AF9013_TUNER_UNKNOWN:
 	default:
 		ret = -ENODEV;
@@ -1334,8 +1312,7 @@
 /* 25 */{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_399U_2)},
 	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_PC160_T)},
 	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_SVEON_STV20)},
-	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_TINYTWIN_2)},
-	{USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV2000DS)},
+	{USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC)},
 	{0},
 };
 MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1422,8 +1399,7 @@
 			},
 			{
 				.name = "DigitalNow TinyTwin DVB-T Receiver",
-				.cold_ids = {&af9015_usb_table[5],
-					     &af9015_usb_table[28], NULL},
+				.cold_ids = {&af9015_usb_table[5], NULL},
 				.warm_ids = {NULL},
 			},
 			{
@@ -1643,8 +1619,8 @@
 				.warm_ids = {NULL},
 			},
 			{
-				.name = "Leadtek WinFast DTV2000DS",
-				.cold_ids = {&af9015_usb_table[29], NULL},
+				.name = "TerraTec Cinergy T Stick RC",
+				.cold_ids = {&af9015_usb_table[28], NULL},
 				.warm_ids = {NULL},
 			},
 		}
diff -r 0f41fd7df85d linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	Thu Feb 11 02:33:12 2010 +0200
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	Thu Feb 25 17:21:11 2010 +0100
@@ -129,6 +129,7 @@
 #define USB_PID_KWORLD_VSTREAM_WARM			0x17df
 #define USB_PID_TERRATEC_CINERGY_T_USB_XE		0x0055
 #define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2		0x0069
+#define USB_PID_TERRATEC_CINERGY_T_STICK_RC        0x0097
 #define USB_PID_TWINHAN_VP7041_COLD			0x3201
 #define USB_PID_TWINHAN_VP7041_WARM			0x3202
 #define USB_PID_TWINHAN_VP7020_COLD			0x3203
diff -r 0f41fd7df85d linux/drivers/media/dvb/frontends/af9013.c
--- a/linux/drivers/media/dvb/frontends/af9013.c	Thu Feb 11 02:33:12 2010 +0200
+++ b/linux/drivers/media/dvb/frontends/af9013.c	Thu Feb 25 17:21:11 2010 +0100
@@ -488,6 +488,20 @@
 				break;
 			}
 		}
+		else if(state->config.tuner == AF9013_TUNER_TDA18218) {
+			switch (bw) {
+			case BANDWIDTH_6_MHZ:
+				if_sample_freq = 3000000; /* 3 MHz */
+				break;
+			case BANDWIDTH_7_MHZ:
+				if_sample_freq = 3500000; /* 3.5 MHz */
+				break;
+			case BANDWIDTH_8_MHZ:
+			default:
+				if_sample_freq = 4000000; /* 4 MHz */
+				break;
+			}
+		}
 
 		while (if_sample_freq > (adc_freq / 2))
 			if_sample_freq = if_sample_freq - adc_freq;
@@ -1390,6 +1404,7 @@
 		init = tuner_init_mt2060_2;
 		break;
 	case AF9013_TUNER_TDA18271:
+	case AF9013_TUNER_TDA18218:
 		len = ARRAY_SIZE(tuner_init_tda18271);
 		init = tuner_init_tda18271;
 		break;
diff -r 0f41fd7df85d linux/drivers/media/dvb/frontends/af9013.h
--- a/linux/drivers/media/dvb/frontends/af9013.h	Thu Feb 11 02:33:12 2010 +0200
+++ b/linux/drivers/media/dvb/frontends/af9013.h	Thu Feb 25 17:21:11 2010 +0100
@@ -44,7 +44,7 @@
 	AF9013_TUNER_MT2060_2   = 147, /* Microtune */
 	AF9013_TUNER_TDA18271   = 156, /* NXP */
 	AF9013_TUNER_QT1010A    = 162, /* Quantek */
-	AF9013_TUNER_TDA18218   = 179, /* NXP */
+	AF9013_TUNER_TDA18218    = 179, /* NXP */
 };
 
 /* AF9013/5 GPIOs (mostly guessed)
diff -r 0f41fd7df85d linux/drivers/media/dvb/frontends/af9013_priv.h
--- a/linux/drivers/media/dvb/frontends/af9013_priv.h	Thu Feb 11 02:33:12 2010 +0200
+++ b/linux/drivers/media/dvb/frontends/af9013_priv.h	Thu Feb 25 17:21:11 2010 +0100
@@ -789,8 +789,9 @@
 	{ 0x9bd9, 0, 8, 0x08 },
 };
 
-/* NXP TDA18271 tuner init
-   AF9013_TUNER_TDA18271   = 156 */
+/* NXP TDA18271 & TDA18218 tuner init
+   AF9013_TUNER_TDA18271   = 156
+   AF9013_TUNER_TDA18218   = 179 */
 static struct regdesc tuner_init_tda18271[] = {
 	{ 0x9bd5, 0, 8, 0x01 },
 	{ 0x9bd6, 0, 8, 0x04 },

Reply via email to