@@ -110,9 +110,30 @@ static int lgdt3304_soft_Reset(struct dv
return 0;
}
+#if 0
+static void print_regs(struct dvb_frontend *fe)
+{
+ int r050a;
+ int r011b;
+ int r011c;
+ int r0001;
+
+ r050a = lgdt3304_i2c_read_reg(fe, 0x050a);
+ r011b = lgdt3304_i2c_read_reg(fe, 0x011b);
+ r011c = lgdt3304_i2c_read_reg(fe, 0x011c);
+ r0001 = lgdt3304_i2c_read_reg(fe, 0x0001);
+
+ /*dprintk("read snr\n"); */
+ printk("050a: %x 011b: %x 011c: %x 0001: %x\n", r050a, r011b, r011c, r0001);
+ /*printk("011b : 0x%x\n", r011b); */
+ /*printk("011c : 0x%x\n", r011c); */
+}
+#endif
+
static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
int err = 0;
+#if 0
static __u8 lgdt3304_vsb8_data[] = {
/* 16bit , 8bit */
/* regs , val */
@@ -138,14 +159,49 @@ static int lgdt3304_set_parameters(struc
0x03, 0x14, 0xe1,
0x05, 0x0e, 0x5b,
};
+#endif
+ /* tested with kworld atsc 340u */
+ static __u8 lgdt3304_vsb8_data[] = {
+ 0x00, 0x00, 0x03,
+ 0x00, 0x0d, 0x02,
+ 0x00, 0x0e, 0x02,
+ 0x00, 0x12, 0x32,
+ 0x00, 0x13, 0xc4,
+ 0x01, 0x12, 0x17,
+ 0x01, 0x13, 0x15,
+ 0x01, 0x14, 0x18,
+ 0x01, 0x15, 0xff,
+ 0x01, 0x16, 0xbc,
+ 0x02, 0x14, 0x67,
+ 0x04, 0x24, 0x8d,
+ 0x04, 0x27, 0x12,
+ 0x04, 0x28, 0x4f,
+ 0x03, 0x08, 0x80,
+ 0x03, 0x09, 0x00,
+ 0x03, 0x0d, 0x14,
+ 0x03, 0x0e, 0x1c,
+ 0x03, 0x14, 0xe1,
+ /* 0x00, 0x02, 0x9b, */
+ /* 0x00, 0x02, 0x9a, */
+ 0x01, 0x06, 0x4f,
+ 0x01, 0x07, 0x0c,
+ 0x01, 0x08, 0xac,
+ 0x01, 0x09, 0xba,
+ 0x01, 0x26, 0xf9,
+ 0x00, 0x0d, 0x82,
+ 0x05, 0x0e, 0x5b,
+ 0x05, 0x0e, 0x5b,
+ };
+
+#if 0
/* not yet tested .. */
static __u8 lgdt3304_qam64_data[] = {
/* 16bit , 8bit */
/* regs , val */
0x00, 0x00, 0x18,
0x00, 0x0d, 0x02,
- //0x00, 0x0e, 0x02,
+ /*0x00, 0x0e, 0x02, */
0x00, 0x12, 0x2a,
0x00, 0x13, 0x00,
0x03, 0x14, 0xe3,
@@ -156,6 +212,7 @@ static int lgdt3304_set_parameters(struc
0x03, 0x0b, 0x9b,
0x05, 0x0e, 0x5b,
};
+#endif
#if 0
/* not yet tested */
@@ -178,41 +235,10 @@ static int lgdt3304_set_parameters(struc
};
#endif
- /* tested with KWorld a340 */
+ /* tested with Kworld 340u */
static __u8 lgdt3304_qam256_data[] = {
/* 16bit , 8bit */
/* regs , val */
- 0x00, 0x00, 0x01, //0x19,
- 0x00, 0x12, 0x2a,
- 0x00, 0x13, 0x80,
- 0x00, 0x0d, 0x02,
- 0x03, 0x14, 0xe3,
-
- 0x03, 0x0e, 0x1c,
- 0x03, 0x08, 0x66,
- 0x03, 0x09, 0x66,
- 0x03, 0x0a, 0x08,
- 0x03, 0x0b, 0x9b,
-
- 0x03, 0x0d, 0x14,
- //0x05, 0x0e, 0x5b,
- 0x01, 0x06, 0x4a,
- 0x01, 0x07, 0x3d,
- 0x01, 0x08, 0x70,
- 0x01, 0x09, 0xa3,
-
- 0x05, 0x04, 0xfd,
-
- 0x00, 0x0d, 0x82,
-
- 0x05, 0x0e, 0x5b,
-
- 0x05, 0x0e, 0x5b,
-
- 0x00, 0x02, 0x9a,
-
- 0x00, 0x02, 0x9b,
-
0x00, 0x00, 0x01,
0x00, 0x12, 0x2a,
0x00, 0x13, 0x80,
@@ -236,6 +262,8 @@ static int lgdt3304_set_parameters(struc
0x00, 0x0d, 0x82,
0x05, 0x0e, 0x5b,
+
+ 0x05, 0x0e, 0x5b,
};
struct lgdt3304_state *state = fe->demodulator_priv;
@@ -246,8 +274,11 @@ static int lgdt3304_set_parameters(struc
sizeof(lgdt3304_vsb8_data));
break;
case QAM_64:
+ printk("%s qam64 not tested yet\n", __func__);
+#if 0
err = i2c_write_demod_bytes(fe, lgdt3304_qam64_data,
sizeof(lgdt3304_qam64_data));
+#endif
break;
case QAM_256:
err = i2c_write_demod_bytes(fe, lgdt3304_qam256_data,
@@ -283,15 +314,37 @@ static int lgdt3304_sleep(struct dvb_fro
}
+/*
+ 050a: 6f 011b: 4 011c: 7 , WABC+
+
+050a: 0x0d generates dvbtraffic
+
+*/
+
static int lgdt3304_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct lgdt3304_state *state = fe->demodulator_priv;
+ /*int r050a; */
int r011d;
int qam_lck;
*status = 0;
dprintk("lgdt read status\n");
+ /*print_regs(fe); */
+
+ /* 60, e0, 61, 67, 63 */
+ /*
+030610: 1c 03 lgdt3304 >>> 01 1d
+030611: R05_I2C_STATUS 00
+030612: 1c 02 lgdt3304 e0
+030613: R05_I2C_STATUS 00
+030614: 1c 03 lgdt3304 >>> 04 09
+030615: R05_I2C_STATUS 00
+030616: 1c 02 lgdt3304 07
+ */
+
+ /*r050a = lgdt3304_i2c_read_reg(fe, 0x050a); */
r011d = lgdt3304_i2c_read_reg(fe, 0x011d);
dprintk("%02x\n", r011d);
@@ -308,7 +361,14 @@ static int lgdt3304_read_status(struct d
break;
case QAM_64:
case QAM_256:
+ /*
+ 0x78, 0x7f
+ 0x78, 0x7b, 0x7f
+ 0x79
+ 0x78 -- all 0 signal
+ */
qam_lck = r011d & 0x7;
+#if 1 /* orig */
switch(qam_lck) {
case 0x0: dprintk("Unlock\n");
break;
@@ -323,9 +383,53 @@ static int lgdt3304_read_status(struct d
*status |= FE_HAS_SIGNAL;
break;
}
+#endif
+
+#if 0 /****************/
+ switch (qam_lck) {
+ case 0x0:
+ dprintk("Unlock\n");
+ break;
+ case 0x4:
+ dprintk("1st Lock in acquisition state\n");
+ break;
+ case 0x6:
+ dprintk("2nd Lock in acquisition state\n");
+ break;
+ case 0x7:
+ dprintk("Final Lock in good reception state\n");
+ *status |= FE_HAS_CARRIER;
+ /**status |= FE_HAS_LOCK; */
+ *status |= FE_HAS_SYNC;
+ *status |= FE_HAS_SIGNAL;
+
+ if (r050a == 0x6f || r050a == 0x5f) { /* also 0x5f generates dvb traffic */
+ *status |= FE_HAS_LOCK;
+ }
+ break;
+ }
+#endif
+
+#if 0 /****************/
+ if (qam_lck & 0x1) {
+ *status |= FE_HAS_SIGNAL;
+ }
+ if (qam_lck & 0x2) {
+ *status |= FE_HAS_CARRIER;
+ }
+ if (qam_lck & 0x4) {
+ *status |= FE_HAS_SYNC;
+ }
+ if (qam_lck & 0x7) {
+ if (1) { /*(r050a == 0x6f || r050a == 0x5f) { // these genereate output with dvbtraffic */
+ *status |= FE_HAS_LOCK;
+ }
+ }
+#endif
+
break;
default:
- printk("%s unhandled modulation\n", __func__);
+ printk("%s unhandled modulation %d\n", __func__, state->current_modulation);
}
@@ -334,19 +438,89 @@ static int lgdt3304_read_status(struct d
static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber)
{
- dprintk("read ber\n");
+ //int r011c;
+
+ //dprintk("read ber\n");
+ //r011c = lgdt3304_i2c_read_reg(fe, 0x011c);
+ //*ber = r011c;
+
+ *ber = 0;
+
+ return 0;
+}
+
+static int lgdt3304_read_signal_strength(struct dvb_frontend *fe, __u16 *strength)
+{
+ //int r050a;
+ //dprintk("read snr\n");
+ //print_regs(fe);
+ //r050a = lgdt3304_i2c_read_reg(fe, 0x050a);
+ //*strength = r050a;
+ *strength = 0xffff;
+
return 0;
}
static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr)
{
+ //int r011b;
+ //int r011c;
+
dprintk("read snr\n");
+
+ //print_regs(fe);
+
+ //r011b = lgdt3304_i2c_read_reg(fe, 0x011b);
+ //r011c = lgdt3304_i2c_read_reg(fe, 0x011c);
+
+ //*snr = 0xffff - ((r011b << 8) | r011c);
+ //*snr = r011b;
+ *snr = 0xffff;
+
+ /*
+002658: 1c 03 lgdt3304 >>> 05 0a
+002659: R05_I2C_STATUS 00
+002660: 1c 02 lgdt3304 6f
+002661: R05_I2C_STATUS 00
+002662: 1c 03 lgdt3304 >>> 01 1b
+### 002663: ISOCH_TRANSFER - (not parsed)
+002664: R05_I2C_STATUS 00
+002665: 1c 02 lgdt3304 00
+002666: R05_I2C_STATUS 00
+002667: 1c 03 lgdt3304 >>> 01 1c
+002668: R05_I2C_STATUS 00
+002669: 1c 02 lgdt3304 b9
+002670: R05_I2C_STATUS 00
+
+2008-04-16 09:02:00.381 ERROR PropSet->Set() failed... hr=80070492
+2008-04-16 09:02:01.013 VERBOSE ServiceID: -1, PMT PID: -1, VPID: -1, APID: -1
+2008-04-16 09:02:01.013 VERBOSE SubmitTuningRequest() complete
+2008-04-16 09:02:01.013 VERBOSE ScanTransponder@2
+2008-04-16 09:02:01.117 VERBOSE ScanTransponder@2
+2008-04-16 09:02:01.154 VERBOSE locked=1 present=1 strength=35250 quality=89
+2008-04-16 09:02:01.155 VERBOSE ScanTransponder@4
+2008-04-16 09:02:01.155 VERBOSE ScanTransponder@5
+2008-04-16 09:02:01.155 VERBOSE ScanTransponder@6
+2008-04-16 09:02:01.155 VERBOSE locked=1 present=1 strength=35250 quality=89
+2008-04-16 09:02:01.156 VERBOSE SIGNAL???
+2008-04-16 09:02:01.156 VERBOSE ScanTransponder finished
+
+ */
+
return 0;
}
static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
{
- dprintk("read ucblocks\n");
+ //int r011d;
+
+ //dprintk("read ucblocks\n");
+ //r011d = lgdt3304_i2c_read_reg(fe, 0x011d);
+
+ //*ucblocks = r011d;
+
+ *ucblocks = 0;
+
return 0;
}
@@ -365,11 +539,14 @@ static struct dvb_frontend_ops demod_lgd
.frequency_stepsize = 62500,
.symbol_rate_min = 5056941,
.symbol_rate_max = 10762000,
- .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+ //.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+ //FIXME add QAM_64 when tested
+ .caps = FE_CAN_QAM_256 | FE_CAN_8VSB,
},
.init = lgdt3304_init,
.sleep = lgdt3304_sleep,
.set_frontend = lgdt3304_set_parameters,
+ .read_signal_strength = lgdt3304_read_signal_strength,
.read_snr = lgdt3304_read_snr,
.read_ber = lgdt3304_read_ber,
.read_status = lgdt3304_read_status,
@@ -1594,6 +1594,16 @@ struct em28xx_board em28xx_boards[] = {
.gpio = evga_indtube_analog,
} },
},
+ [EM2870_BOARD_KWORLD_340U] = {
+ .name = "KWorld ATSC 340U",
+ .tuner_type = TUNER_ABSENT, /* ok ... its a Philips TDA18271 */
+ .has_dvb = 1,
+ /*
+ .input = { {
+ .type = EM28XX_VMUX_DVB,
+ }, },
+ */
+ },
};
const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
@@ -1709,6 +1719,8 @@ struct usb_device_id em28xx_id_table[] =
.driver_info = EM2820_BOARD_IODATA_GVMVP_SZ },
{ USB_DEVICE(0xeb1a, 0x50a6),
.driver_info = EM2860_BOARD_GADMEI_UTV330 },
+ { USB_DEVICE(0x1b80, 0xa340),
+ .driver_info = EM2870_BOARD_KWORLD_340U },
{ },
};
MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2038,6 +2050,20 @@ void em28xx_pre_card_setup(struct em28xx
em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
msleep(70);
break;
+ case EM2870_BOARD_KWORLD_340U:
+ em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1); /* protocol? */
+ em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x4c", 1);
+ em28xx_write_regs(dev, 0x08, "\xfe", 1);
+ em28xx_write_regs(dev, 0x08, "\xde", 1);
+ em28xx_write_regs(dev, 0x08, "\xfe", 1);
+
+ em28xx_write_regs(dev, 0x08, "\xfd", 1);
+ em28xx_write_regs(dev, 0x08 /* wtf 0x04*/ , "\xff", 1);
+ em28xx_write_regs(dev, 0x08, "\xfd", 1);
+ em28xx_write_regs(dev, 0x08 /* wtf 0x04 */, "\xff", 1);
+ em28xx_write_regs(dev, 0x08, "\xfd", 1);
+
+ break;
}
em28xx_gpio_set(dev, dev->board.tuner_gpio);
@@ -30,10 +30,12 @@
#include "tuner-simple.h"
#include "lgdt330x.h"
+#include "lgdt3304.h"
#include "zl10353.h"
#include "s5h1409.h"
#include "mt352.h"
#include "mt352_priv.h" /* FIXME */
+#include "tda18271.h"
MODULE_DESCRIPTION("driver for em28xx based DVB cards");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -230,6 +232,10 @@ static struct lgdt330x_config em2880_lgd
.demod_chip = LGDT3303,
};
+static struct lgdt3304_config lgdt3304_atsc_config = {
+ .i2c_address = 0x0e
+};
+
static struct zl10353_config em28xx_zl10353_with_xc3028 = {
.demod_address = (0x1e >> 1),
.no_tuner = 1,
@@ -261,6 +267,9 @@ static struct drx397xD_config em28xx_drx
};
#endif
+static struct tda18271_config em28xx_tda18271_config = {
+};
+
static int mt352_terratec_xs_init(struct dvb_frontend *fe)
{
/* Values extracted from a USB trace of the Terratec Windows driver */
@@ -550,6 +559,12 @@ static int dvb_init(struct em28xx *dev)
}
break;
#endif
+ case EM2870_BOARD_KWORLD_340U:
+ dvb->frontend = dvb_attach(lgdt3304_attach,
+ &lgdt3304_atsc_config,
+ &dev->i2c_adap);
+ dvb_attach(tda18271_attach, dvb->frontend, 0x60, &dev->i2c_adap, &em28xx_tda18271_config);
+ break;
default:
printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
" isn't supported yet\n",
@@ -494,6 +494,7 @@ static char *i2c_devs[128] = {
[0xc2 >> 1] = "tuner (analog)",
[0xc4 >> 1] = "tuner (analog)",
[0xc6 >> 1] = "tuner (analog)",
+ [0x1c >> 1] = "lgdt3304",
};
/*
@@ -109,6 +109,7 @@
#define EM2882_BOARD_KWORLD_ATSC_315U 69
#define EM2882_BOARD_EVGA_INDTUBE 70
#define EM2820_BOARD_SILVERCREST_WEBCAM 71
+#define EM2870_BOARD_KWORLD_340U 72
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4