TerraTec Cinergy T USB RC: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
Line 39: | Line 39: | ||
input: NEWMI USB2.0 DVB-T TV Stick as /devices/pci0000:00/0000:00:1a.7/usb3/3-3/3-3:1.1/input/input8 |
input: NEWMI USB2.0 DVB-T TV Stick as /devices/pci0000:00/0000:00:1a.7/usb3/3-3/3-3:1.1/input/input8 |
||
generic-usb 0003:0CCD:0097.0002: input,hidraw0: USB HID v1.01 Keyboard [NEWMI USB2.0 DVB-T TV Stick] on usb-0000:00:1a.7-3/input1 |
generic-usb 0003:0CCD:0097.0002: input,hidraw0: USB HID v1.01 Keyboard [NEWMI USB2.0 DVB-T TV Stick] on usb-0000:00:1a.7-3/input1 |
||
</pre> |
|||
=== [http://www.mail-archive.com/linux-media@vger.kernel.org/msg16117.html patch] with changes to linux-2.6.35.4 === |
|||
<pre> |
|||
diff -Nru linux-2.6.35.4/drivers/media/common/tuners/Kconfig /usr/src/linux-2.6.35.4/drivers/media/common/tuners/Kconfig |
|||
--- linux-2.6.35.4/drivers/media/common/tuners/Kconfig 2010-08-27 01:47:12.000000000 +0200 |
|||
+++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/Kconfig 2011-01-04 13:59:07.642000010 +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 -Nru linux-2.6.35.4/drivers/media/common/tuners/Makefile /usr/src/linux-2.6.35.4/drivers/media/common/tuners/Makefile |
|||
--- linux-2.6.35.4/drivers/media/common/tuners/Makefile 2010-08-27 01:47:12.000000000 +0200 |
|||
+++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/Makefile 2011-01-04 13:59:50.733000011 +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 -Nru linux-2.6.35.4/drivers/media/common/tuners/tda18218.c /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218.c |
|||
--- linux-2.6.35.4/drivers/media/common/tuners/tda18218.c 1970-01-01 01:00:00.000000000 +0100 |
|||
+++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218.c 2011-01-04 15:22:54.068000023 +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], ¶msbuf[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 -Nru linux-2.6.35.4/drivers/media/common/tuners/tda18218.h /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218.h |
|||
--- linux-2.6.35.4/drivers/media/common/tuners/tda18218.h 1970-01-01 01:00:00.000000000 +0100 |
|||
+++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218.h 2011-01-04 14:03:39.306000007 +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 |
|||
diff -Nru linux-2.6.35.4/drivers/media/common/tuners/tda18218_priv.h /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218_priv.h |
|||
--- linux-2.6.35.4/drivers/media/common/tuners/tda18218_priv.h 1970-01-01 01:00:00.000000000 +0100 |
|||
+++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218_priv.h 2011-01-04 14:04:36.744000011 +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 -Nru linux-2.6.35.4/drivers/media/dvb/dvb-usb/af9015.c /usr/src/linux-2.6.35.4/drivers/media/dvb/dvb-usb/af9015.c |
|||
--- linux-2.6.35.4/drivers/media/dvb/dvb-usb/af9015.c 2010-08-27 01:47:12.000000000 +0200 |
|||
+++ /usr/src/linux-2.6.35.4/drivers/media/dvb/dvb-usb/af9015.c 2011-01-05 10:21:43.993000001 +0100 |
|||
@@ -31,6 +31,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); |
|||
@@ -272,7 +273,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]; |
|||
@@ -285,7 +287,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; |
|||
@@ -300,7 +303,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; |
|||
@@ -314,7 +318,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; |
|||
@@ -556,46 +561,6 @@ |
|||
return ret; |
|||
} |
|||
-/* hash (and dump) eeprom */ |
|||
-static int af9015_eeprom_hash(struct usb_device *udev) |
|||
-{ |
|||
- 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}; |
|||
- |
|||
- 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; |
|||
- } |
|||
- |
|||
- 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; |
|||
-} |
|||
static int af9015_download_ir_table(struct dvb_usb_device *d) |
|||
{ |
|||
@@ -733,132 +698,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, |
|||
- ir_codes_af9015_table_a_link, ARRAY_SIZE(ir_codes_af9015_table_a_link), |
|||
- af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, |
|||
- { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, |
|||
- ir_codes_af9015_table_msi, ARRAY_SIZE(ir_codes_af9015_table_msi), |
|||
- af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, |
|||
- { AF9015_REMOTE_MYGICTV_U718, |
|||
- ir_codes_af9015_table_mygictv, ARRAY_SIZE(ir_codes_af9015_table_mygictv), |
|||
- af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, |
|||
- { AF9015_REMOTE_DIGITTRADE_DVB_T, |
|||
- ir_codes_af9015_table_digittrade, ARRAY_SIZE(ir_codes_af9015_table_digittrade), |
|||
- af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) }, |
|||
- { AF9015_REMOTE_AVERMEDIA_KS, |
|||
- ir_codes_af9015_table_avermedia, ARRAY_SIZE(ir_codes_af9015_table_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, |
|||
- ir_codes_af9015_table_leadtek, ARRAY_SIZE(ir_codes_af9015_table_leadtek), |
|||
- af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) }, |
|||
- { USB_VID_VISIONPLUS, |
|||
- ir_codes_af9015_table_twinhan, ARRAY_SIZE(ir_codes_af9015_table_twinhan), |
|||
- af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) }, |
|||
- { USB_VID_KWORLD_2, /* TODO: use correct rc keys */ |
|||
- ir_codes_af9015_table_twinhan, ARRAY_SIZE(ir_codes_af9015_table_twinhan), |
|||
- af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) }, |
|||
- { USB_VID_AVERMEDIA, |
|||
- ir_codes_af9015_table_avermedia, ARRAY_SIZE(ir_codes_af9015_table_avermedia), |
|||
- af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) }, |
|||
- { USB_VID_MSI_2, |
|||
- ir_codes_af9015_table_msi_digivox_iii, ARRAY_SIZE(ir_codes_af9015_table_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, |
|||
- ir_codes_af9015_table_msi, ARRAY_SIZE(ir_codes_af9015_table_msi), |
|||
- af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, |
|||
- { 0xa3703d00, |
|||
- ir_codes_af9015_table_a_link, ARRAY_SIZE(ir_codes_af9015_table_a_link), |
|||
- af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, |
|||
- { 0x9b7dc64e, |
|||
- ir_codes_af9015_table_mygictv, ARRAY_SIZE(ir_codes_af9015_table_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, |
|||
- ir_codes_af9015_table_trekstor, |
|||
- ARRAY_SIZE(ir_codes_af9015_table_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; |
|||
@@ -871,17 +716,158 @@ |
|||
if (ret) |
|||
goto error; |
|||
- ret = af9015_eeprom_hash(udev); |
|||
- if (ret) |
|||
- goto error; |
|||
- |
|||
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 = |
|||
+ ir_codes_af9015_table_a_link; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_msi; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_mygictv; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_digittrade; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_avermedia; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_leadtek; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_twinhan; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_twinhan; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_mygictv; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_msi; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_trekstor; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_avermedia; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 = |
|||
+ ir_codes_af9015_table_msi_digivox_iii; |
|||
+ af9015_properties[i].rc_key_map_size = |
|||
+ ARRAY_SIZE(ir_codes_af9015_table_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 */ |
|||
@@ -992,6 +978,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: |
|||
@@ -1003,9 +990,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; |
|||
@@ -1208,6 +1192,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; |
|||
@@ -1255,6 +1243,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; |
|||
@@ -1299,6 +1291,7 @@ |
|||
{USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)}, |
|||
/* 30 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)}, |
|||
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)}, |
|||
+ {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC)}, |
|||
{0}, |
|||
}; |
|||
MODULE_DEVICE_TABLE(usb, af9015_usb_table); |
|||
@@ -1607,8 +1600,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[32], NULL}, |
|||
.warm_ids = {NULL}, |
|||
}, |
|||
{ |
|||
diff -Nru linux-2.6.35.4/drivers/media/dvb/dvb-usb/dvb-usb-ids.h /usr/src/linux-2.6.35.4/drivers/media/dvb/dvb-usb/dvb-usb-ids.h |
|||
--- linux-2.6.35.4/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2010-08-27 01:47:12.000000000 +0200 |
|||
+++ /usr/src/linux-2.6.35.4/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2011-01-04 14:45:53.600000024 +0100 |
|||
@@ -133,6 +133,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 -Nru linux-2.6.35.4/drivers/media/dvb/frontends/af9013.c /usr/src/linux-2.6.35.4/drivers/media/dvb/frontends/af9013.c |
|||
--- linux-2.6.35.4/drivers/media/dvb/frontends/af9013.c 2010-08-27 01:47:12.000000000 +0200 |
|||
+++ /usr/src/linux-2.6.35.4/drivers/media/dvb/frontends/af9013.c 2011-01-04 14:48:59.535000023 +0100 |
|||
@@ -487,6 +487,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; |
|||
@@ -1389,6 +1403,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 -Nru linux-2.6.35.4/drivers/media/dvb/frontends/af9013_priv.h /usr/src/linux-2.6.35.4/drivers/media/dvb/frontends/af9013_priv.h |
|||
--- linux-2.6.35.4/drivers/media/dvb/frontends/af9013_priv.h 2010-08-27 01:47:12.000000000 +0200 |
|||
+++ /usr/src/linux-2.6.35.4/drivers/media/dvb/frontends/af9013_priv.h 2011-01-04 14:52:02.621000024 +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 }, |
|||
</pre> |
</pre> |
||
Revision as of 09:29, 5 January 2011
Vendor Device/Model |
Supported | ID on Interface |
Hardware | Firmware | Comment / Pictures | URL | E |
---|---|---|---|---|---|---|---|
TerraTec Cinergy T USB RC (mk II) | ✔ Yes, in kernel since 2.6.37 | 0ccd:0097 USB2.0 | Afatech AF9015A + TDA18218HN + EM24C02A | dvb-usb-af9015.fw | [1] |
Version 2 AF9015
USB ID: 0ccd:0097 Manufacturer: NEWMI
There is a patch available to support this device: http://www.mail-archive.com/linux-media@vger.kernel.org/msg16117.html
However, this patch doesnt fit anymore perfectly on 2.6.35.4 due to some changes on IR and there is no official support in dvb-hg; so this patch needs to be adapted and applied. Testing afterwards can be done as usual, for example with tzap, scan or w_scan. Needs also firmware dvb-usb-af9015.fw.
Uses tuner NXP TDA18218, which is quite similiar to TDA18271. Preliminary support for this tuner is added with the patch above.
After applying patch and loading dvb-usb-af9015 you should see the following:
usb 3-3: new high speed USB device using ehci_hcd and address 3 usb 3-3: New USB device found, idVendor=0ccd, idProduct=0097 usb 3-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 usb 3-3: Product: USB2.0 DVB-T TV Stick usb 3-3: Manufacturer: NEWMI usb 3-3: SerialNumber: xxxxxxxxxxxxxx dvb-usb: found a 'TerraTec Cinergy T Stick RC' in cold state, will try to load a firmware dvb-usb: downloading firmware from file 'dvb-usb-af9015.fw' dvb-usb: found a 'TerraTec Cinergy T Stick RC' in warm state. dvb-usb: will pass the complete MPEG2 transport stream to the software demuxer. DVB: registering new adapter (TerraTec Cinergy T Stick RC) af9013: firmware version:4.95.0 DVB: registering adapter 4 frontend 0 (Afatech AF9013 DVB-T)... NXP TDA18218 successfully identified. dvb-usb: TerraTec Cinergy T Stick RC successfully initialized and connected. input: NEWMI USB2.0 DVB-T TV Stick as /devices/pci0000:00/0000:00:1a.7/usb3/3-3/3-3:1.1/input/input8 generic-usb 0003:0CCD:0097.0002: input,hidraw0: USB HID v1.01 Keyboard [NEWMI USB2.0 DVB-T TV Stick] on usb-0000:00:1a.7-3/input1
patch with changes to linux-2.6.35.4
diff -Nru linux-2.6.35.4/drivers/media/common/tuners/Kconfig /usr/src/linux-2.6.35.4/drivers/media/common/tuners/Kconfig --- linux-2.6.35.4/drivers/media/common/tuners/Kconfig 2010-08-27 01:47:12.000000000 +0200 +++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/Kconfig 2011-01-04 13:59:07.642000010 +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 -Nru linux-2.6.35.4/drivers/media/common/tuners/Makefile /usr/src/linux-2.6.35.4/drivers/media/common/tuners/Makefile --- linux-2.6.35.4/drivers/media/common/tuners/Makefile 2010-08-27 01:47:12.000000000 +0200 +++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/Makefile 2011-01-04 13:59:50.733000011 +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 -Nru linux-2.6.35.4/drivers/media/common/tuners/tda18218.c /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218.c --- linux-2.6.35.4/drivers/media/common/tuners/tda18218.c 1970-01-01 01:00:00.000000000 +0100 +++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218.c 2011-01-04 15:22:54.068000023 +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], ¶msbuf[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 -Nru linux-2.6.35.4/drivers/media/common/tuners/tda18218.h /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218.h --- linux-2.6.35.4/drivers/media/common/tuners/tda18218.h 1970-01-01 01:00:00.000000000 +0100 +++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218.h 2011-01-04 14:03:39.306000007 +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 diff -Nru linux-2.6.35.4/drivers/media/common/tuners/tda18218_priv.h /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218_priv.h --- linux-2.6.35.4/drivers/media/common/tuners/tda18218_priv.h 1970-01-01 01:00:00.000000000 +0100 +++ /usr/src/linux-2.6.35.4/drivers/media/common/tuners/tda18218_priv.h 2011-01-04 14:04:36.744000011 +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 -Nru linux-2.6.35.4/drivers/media/dvb/dvb-usb/af9015.c /usr/src/linux-2.6.35.4/drivers/media/dvb/dvb-usb/af9015.c --- linux-2.6.35.4/drivers/media/dvb/dvb-usb/af9015.c 2010-08-27 01:47:12.000000000 +0200 +++ /usr/src/linux-2.6.35.4/drivers/media/dvb/dvb-usb/af9015.c 2011-01-05 10:21:43.993000001 +0100 @@ -31,6 +31,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); @@ -272,7 +273,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]; @@ -285,7 +287,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; @@ -300,7 +303,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; @@ -314,7 +318,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; @@ -556,46 +561,6 @@ return ret; } -/* hash (and dump) eeprom */ -static int af9015_eeprom_hash(struct usb_device *udev) -{ - 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}; - - 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; - } - - 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; -} static int af9015_download_ir_table(struct dvb_usb_device *d) { @@ -733,132 +698,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, - ir_codes_af9015_table_a_link, ARRAY_SIZE(ir_codes_af9015_table_a_link), - af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, - { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, - ir_codes_af9015_table_msi, ARRAY_SIZE(ir_codes_af9015_table_msi), - af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, - { AF9015_REMOTE_MYGICTV_U718, - ir_codes_af9015_table_mygictv, ARRAY_SIZE(ir_codes_af9015_table_mygictv), - af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, - { AF9015_REMOTE_DIGITTRADE_DVB_T, - ir_codes_af9015_table_digittrade, ARRAY_SIZE(ir_codes_af9015_table_digittrade), - af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) }, - { AF9015_REMOTE_AVERMEDIA_KS, - ir_codes_af9015_table_avermedia, ARRAY_SIZE(ir_codes_af9015_table_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, - ir_codes_af9015_table_leadtek, ARRAY_SIZE(ir_codes_af9015_table_leadtek), - af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) }, - { USB_VID_VISIONPLUS, - ir_codes_af9015_table_twinhan, ARRAY_SIZE(ir_codes_af9015_table_twinhan), - af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) }, - { USB_VID_KWORLD_2, /* TODO: use correct rc keys */ - ir_codes_af9015_table_twinhan, ARRAY_SIZE(ir_codes_af9015_table_twinhan), - af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) }, - { USB_VID_AVERMEDIA, - ir_codes_af9015_table_avermedia, ARRAY_SIZE(ir_codes_af9015_table_avermedia), - af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) }, - { USB_VID_MSI_2, - ir_codes_af9015_table_msi_digivox_iii, ARRAY_SIZE(ir_codes_af9015_table_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, - ir_codes_af9015_table_msi, ARRAY_SIZE(ir_codes_af9015_table_msi), - af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, - { 0xa3703d00, - ir_codes_af9015_table_a_link, ARRAY_SIZE(ir_codes_af9015_table_a_link), - af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, - { 0x9b7dc64e, - ir_codes_af9015_table_mygictv, ARRAY_SIZE(ir_codes_af9015_table_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, - ir_codes_af9015_table_trekstor, - ARRAY_SIZE(ir_codes_af9015_table_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; @@ -871,17 +716,158 @@ if (ret) goto error; - ret = af9015_eeprom_hash(udev); - if (ret) - goto error; - 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 = + ir_codes_af9015_table_a_link; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_msi; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_mygictv; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_digittrade; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_avermedia; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_leadtek; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_twinhan; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_twinhan; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_mygictv; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_msi; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_trekstor; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_avermedia; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 = + ir_codes_af9015_table_msi_digivox_iii; + af9015_properties[i].rc_key_map_size = + ARRAY_SIZE(ir_codes_af9015_table_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 */ @@ -992,6 +978,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: @@ -1003,9 +990,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; @@ -1208,6 +1192,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; @@ -1255,6 +1243,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; @@ -1299,6 +1291,7 @@ {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)}, /* 30 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)}, + {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1607,8 +1600,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[32], NULL}, .warm_ids = {NULL}, }, { diff -Nru linux-2.6.35.4/drivers/media/dvb/dvb-usb/dvb-usb-ids.h /usr/src/linux-2.6.35.4/drivers/media/dvb/dvb-usb/dvb-usb-ids.h --- linux-2.6.35.4/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2010-08-27 01:47:12.000000000 +0200 +++ /usr/src/linux-2.6.35.4/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2011-01-04 14:45:53.600000024 +0100 @@ -133,6 +133,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 -Nru linux-2.6.35.4/drivers/media/dvb/frontends/af9013.c /usr/src/linux-2.6.35.4/drivers/media/dvb/frontends/af9013.c --- linux-2.6.35.4/drivers/media/dvb/frontends/af9013.c 2010-08-27 01:47:12.000000000 +0200 +++ /usr/src/linux-2.6.35.4/drivers/media/dvb/frontends/af9013.c 2011-01-04 14:48:59.535000023 +0100 @@ -487,6 +487,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; @@ -1389,6 +1403,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 -Nru linux-2.6.35.4/drivers/media/dvb/frontends/af9013_priv.h /usr/src/linux-2.6.35.4/drivers/media/dvb/frontends/af9013_priv.h --- linux-2.6.35.4/drivers/media/dvb/frontends/af9013_priv.h 2010-08-27 01:47:12.000000000 +0200 +++ /usr/src/linux-2.6.35.4/drivers/media/dvb/frontends/af9013_priv.h 2011-01-04 14:52:02.621000024 +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 },