diff mbox

em28xx: kworld 340u

Message ID 20090718213428.GA8854@localhost.localdomain (mailing list archive)
State Changes Requested
Delegated to: Douglas Landgraf
Headers show

Commit Message

acano@fastmail.fm July 18, 2009, 9:34 p.m. UTC
support for kworld 340u.  8vsb and qam256 work, qam64 untested.

Comments

Devin Heitmueller July 18, 2009, 10:13 p.m. UTC | #1
On Sat, Jul 18, 2009 at 5:34 PM, <acano@fastmail.fm> wrote:
> support for kworld 340u.  8vsb and qam256 work, qam64 untested.
>
>

Hello Acano,

You should talk to Jarod Wilson about this.  He did a bunch of work to
get the 340u working over the last couple of months, and you two could
probably collaborate on a unified solution.  There were also some
problems related to the fact that the device can have either the
tda18271c1 or the c2 (both have the same USB id), which would have to
be accommodated in the final solution.

The patch itself also needs alot of cleanup and doesn't meet the
coding standards.  It would need considerable cleanup before it could
be taken upstream.

Devin
Jarod Wilson July 20, 2009, 1:53 p.m. UTC | #2
On Saturday 18 July 2009 18:13:30 Devin Heitmueller wrote:
> On Sat, Jul 18, 2009 at 5:34 PM, <acano@fastmail.fm> wrote:
> > support for kworld 340u.  8vsb and qam256 work, qam64 untested.
> 
> Hello Acano,
> 
> You should talk to Jarod Wilson about this.  He did a bunch of work to
> get the 340u working over the last couple of months, and you two could
> probably collaborate on a unified solution.

Hrm. I really probably should have sent something to the list that
mentioned I'd done this, to prevent duplication... Oops.

> There were also some
> problems related to the fact that the device can have either the
> tda18271c1 or the c2 (both have the same USB id), which would have to
> be accommodated in the final solution.

But with luck, some combination of dvb_gpio changes will get them
both behaving... But yeah, this is the main thing currently holding
back what I've got being merged.

> The patch itself also needs alot of cleanup and doesn't meet the
> coding standards.  It would need considerable cleanup before it could
> be taken upstream.

Just took a quick look. I don't think there's anything in there I
haven't already got covered, and covered in a way that should already
be up to kernel coding standards. The other major difference with my
approach, is that rather than use the lgdt3304 driver to handle the
demod, I'm using a modified lgdt3305 driver with 3304 support added,
as its a FAR more complete driver, and the two are incredibly similar.

WIP patches from a few weeks back:

http://jwilson.fedorapeople.org/misc/lgdt3305-add-lgdt3304-support-20090623.patch
http://jwilson.fedorapeople.org/misc/em28xx-add-kworld-340u-using-lgdt3305-20090623.patch

But yeah, we still need to work out properly supporting both the C1 and
C2 variant of the stick -- my C1 works perfectly, Mike Krufky's C2 does
not... But it could be as simple as fixing up the dvb_gpio settings,
just need to get around to figuring out what the bare minimum are that
need to be reset on the C1, then see if that works better for the C2...
diff mbox

Patch

diff -r 27ddf3fe0ed9 linux/drivers/media/dvb/frontends/lgdt3304.c
--- a/linux/drivers/media/dvb/frontends/lgdt3304.c	Wed Jun 17 04:38:12 2009 +0000
+++ b/linux/drivers/media/dvb/frontends/lgdt3304.c	Sat Jul 18 17:21:13 2009 -0400
@@ -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,
diff -r 27ddf3fe0ed9 linux/drivers/media/video/em28xx/em28xx-cards.c
--- a/linux/drivers/media/video/em28xx/em28xx-cards.c	Wed Jun 17 04:38:12 2009 +0000
+++ b/linux/drivers/media/video/em28xx/em28xx-cards.c	Sat Jul 18 17:21:13 2009 -0400
@@ -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);
diff -r 27ddf3fe0ed9 linux/drivers/media/video/em28xx/em28xx-dvb.c
--- a/linux/drivers/media/video/em28xx/em28xx-dvb.c	Wed Jun 17 04:38:12 2009 +0000
+++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c	Sat Jul 18 17:21:13 2009 -0400
@@ -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",
diff -r 27ddf3fe0ed9 linux/drivers/media/video/em28xx/em28xx-i2c.c
--- a/linux/drivers/media/video/em28xx/em28xx-i2c.c	Wed Jun 17 04:38:12 2009 +0000
+++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c	Sat Jul 18 17:21:13 2009 -0400
@@ -494,6 +494,7 @@  static char *i2c_devs[128] = {
 	[0xc2 >> 1] = "tuner (analog)",
 	[0xc4 >> 1] = "tuner (analog)",
 	[0xc6 >> 1] = "tuner (analog)",
+	[0x1c >> 1] = "lgdt3304",
 };
 
 /*
diff -r 27ddf3fe0ed9 linux/drivers/media/video/em28xx/em28xx.h
--- a/linux/drivers/media/video/em28xx/em28xx.h	Wed Jun 17 04:38:12 2009 +0000
+++ b/linux/drivers/media/video/em28xx/em28xx.h	Sat Jul 18 17:21:13 2009 -0400
@@ -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