Note:

*    Only tested with qam256.


*    I changed the EM2880_DVB_MAX_PACKETSIZE value to 752.  Don't
know how you want to deal with that.


*    To compile you have to create a top level tda18271/ directory and
copy tda18271.h into it.  It's not in the kernel headers so you need
to get it from the kernel sources.


*    The following is getting set for cards that don't even have the
chip, so I boxed that stuff in.

      /* zl10353 powersaving */
      dvb_dev->init_override = dvb_dev->frontend->ops.init;
      dvb_dev->frontend->ops.sleep = em28xx_zl10353_sleep;
      dvb_dev->frontend->ops.init = em28xx_zl10353_init;


*    dvb_dmx_swfilter() is getting called twice in em2880-dvb.c and
corrupting data.
diff -r 677bbac6845b em2880-dvb.c
--- a/em2880-dvb.c	Sun Jul 20 17:52:57 2008 +0200
+++ b/em2880-dvb.c	Mon Jul 21 20:36:10 2008 -0400
@@ -42,10 +42,11 @@
 #include "lgdt3304/lgdt3304.h"
 #include "qt1010/qt1010.h"
 #include "mt2060/mt2060.h"
+#include "tda18271/tda18271.h"
 
 #include "lgdt330x.h"
 
-#define EM2880_DVB_MAX_PACKETSIZE 564
+#define EM2880_DVB_MAX_PACKETSIZE 752  //564
 #define EM2880_DVB_NUM_PACKETS 64
 #define EM2880_URB_COUNT 32
 
@@ -244,20 +245,21 @@
 	if (urb->status == -ENOENT)
 		return;
 
-	if (urb->actual_length > 0)
+	if (urb->actual_length > 0) {
 		dvb_dmx_swfilter(&dvb_dev->demux, urb->transfer_buffer,
 				 urb->actual_length);
-
-	for (i = 0; i < urb->number_of_packets; i++) {
-		if (urb->iso_frame_desc[i].status != 0) {
-			dprintk(1, "em2880-dvb.c: status != 0\n");
-			continue;
-		} else if (urb->iso_frame_desc[i].actual_length > 0)
-			dvb_dmx_swfilter(&dvb_dev->demux,
+	} else {
+		for (i = 0; i < urb->number_of_packets; i++) {
+			if (urb->iso_frame_desc[i].status != 0) {
+				dprintk(1, "em2880-dvb.c: status != 0\n");
+				continue;
+			} else if (urb->iso_frame_desc[i].actual_length > 0)
+				dvb_dmx_swfilter(&dvb_dev->demux,
 					urb->transfer_buffer +
 					urb->iso_frame_desc[i].offset,
 					urb->iso_frame_desc[i]
 					.actual_length);
+		}
 	}
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status)
@@ -430,6 +432,10 @@
 	.i2c_address = 0x62
 };
 
+static struct tda18271_config em2870_tda18271_config = {
+	//.i2c_address = 0xc0;
+};
+
 static int kworld355u_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct zl10353_state {
@@ -805,6 +811,7 @@
 				&em2880_kworld_355u_dev,
 				&dev->i2c_adap);
 		break;
+	case EM2870_BOARD_KWORLD_A340:
 	case EM2883_BOARD_TERRATEC_HYBRID_XS_ATSC:
 		dvb_dev->frontend = dvb_attach(lgdt3304_attach,
 				&lgdt3304_atsc_config, &dev->i2c_adap);
@@ -844,16 +851,38 @@
 			dvb_attach(qt1010_attach, dvb_dev->frontend,
 					&dev->i2c_adap, &em2870_qt1010_config);
 			break;
+		case TUNER_PHILIPS_TDA18271:
+			dvb_attach(tda18271_attach, dvb_dev->frontend, 0x60, &dev->i2c_adap, &em2870_tda18271_config);
+			break;
 		default:
 			printk(KERN_INFO"unsupported tuner (%d)\n",
 					dev->tuner_type);
 		}
 
-		/* zl10353 powersaving */
-		dvb_dev->init_override = dvb_dev->frontend->ops.init;
+		switch (dev->model) {
+		case EM2883_BOARD_TERRATEC_HYBRID_XS_FM:
+		case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+		case EM2880_BOARD_TERRATEC_HYBRID_XS:
+		case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
+		case EM2882_BOARD_TERRATEC_HYBRID_XS:
+		case EM2870_BOARD_TERRATEC_XS:
+		case EM2881_BOARD_PINNACLE_HYBRID_PRO:
+		case EM2881_BOARD_DNT_DA2_HYBRID:
+		case EM2880_BOARD_MSI_DIGIVOX_AD:
+		case EM2880_BOARD_MSI_DIGIVOX_AD_II:
+		case EM2870_BOARD_KWORLD_350U:
+		case EM2883_BOARD_KWORLD_HYBRID_E323:
+		case EM2888_BOARD_KWORLD_HYBRID_E329:
+		case EM2888_BOARD_EMPIA_HYBRID:
+			/* zl10353 powersaving */
+			dvb_dev->init_override = dvb_dev->frontend->ops.init;
 
-		dvb_dev->frontend->ops.sleep = em28xx_zl10353_sleep;
-		dvb_dev->frontend->ops.init = em28xx_zl10353_init;
+			dvb_dev->frontend->ops.sleep = em28xx_zl10353_sleep;
+			dvb_dev->frontend->ops.init = em28xx_zl10353_init;
+			break;
+		default:
+			break;
+		}
 	}
 
 	if (NULL == dvb_dev->frontend) {
diff -r 677bbac6845b em28xx-cards.c
--- a/em28xx-cards.c	Sun Jul 20 17:52:57 2008 +0200
+++ b/em28xx-cards.c	Mon Jul 21 20:36:10 2008 -0400
@@ -2352,7 +2352,7 @@
 		.dvbnorms	= EETI_XC3028_DEFAULT_DVBT,
 #endif
 	},
-	[EM2883_BOARD_KWORLD_A340] = {
+	[EM2870_BOARD_KWORLD_A340] = {
 		.name         = "KWorld ATSC 340",
 		.tuner_type   = TUNER_PHILIPS_TDA18271,
 		.dev_modes    = EM28XX_ATSC,
@@ -2507,6 +2507,7 @@
 	{ USB_DEVICE(0x1b80, 0xe329), .driver_info = EM2888_BOARD_KWORLD_HYBRID_E329 },
 	{ USB_DEVICE(0xeb1a, 0x2889), .driver_info = EM2888_BOARD_EMPIA_HYBRID },
 	{ USB_DEVICE(0xeb1a, 0xe323), .driver_info = EM2883_BOARD_KWORLD_HYBRID_E323 },
+	{ USB_DEVICE(0x1b80, 0xa340), .driver_info = EM2870_BOARD_KWORLD_A340 },
 	{ USB_DEVICE(0xeb1a, 0xa139), .driver_info = EM2888_BOARD_LINCOLN_TV_FM },
 #if 0
 	{ USB_DEVICE(0x2304, 0x0242), .driver_info = EM2888_BOARD_DVB_TC_HYBRID },
@@ -3037,6 +3038,40 @@
 #endif
 		break;
 	}
+	case EM2870_BOARD_KWORLD_A340:
+	{
+		ret = em28xx_write_regs(dev, R0F_XCLK_REG, "\x07", 1);  // protocol?
+		if (ret < 0)
+			return ret;
+		ret = em28xx_write_regs(dev, R06_I2C_CLK_REG, "\x4c", 1);
+		if (ret < 0)
+			return ret;
+		ret = em28xx_write_regs(dev, 0x08, "\xfe", 1);
+		if (ret < 0)
+			return ret;
+		ret = em28xx_write_regs(dev, 0x04, "\xde", 1);
+		if (ret < 0)
+			return ret;
+		ret = em28xx_write_regs(dev, 0x04, "\xfe", 1);
+		if (ret < 0)
+			return ret;
+		ret = em28xx_write_regs(dev, 0x08, "\xfd", 1);
+		if (ret < 0)
+			return ret;
+		ret = em28xx_write_regs(dev, 0x04, "\xff", 1);
+		if (ret < 0)
+			return ret;
+		ret = em28xx_write_regs(dev, 0x08, "\xfd", 1);
+		if (ret < 0)
+			return ret;
+		ret = em28xx_write_regs(dev, 0x04, "\xff", 1);
+		if (ret < 0)
+			return ret;
+		ret = em28xx_write_regs(dev, 0x08, "\xfd", 1);
+		if (ret < 0)
+			return ret;
+		break;
+	}
 	default:
 		ret = dev->em28xx_write_regs(dev, R0F_XCLK_REG, "\x27", 1);
 		if (ret < 0)
diff -r 677bbac6845b em28xx.h
--- a/em28xx.h	Sun Jul 20 17:52:57 2008 +0200
+++ b/em28xx.h	Mon Jul 21 20:36:10 2008 -0400
@@ -120,7 +120,7 @@
 #define EM2883_BOARD_KWORLD_HYBRID_F306		  65
 #define EM2888_BOARD_KWORLD_HYBRID_E329		  66
 #define EM2883_BOARD_KWORLD_HYBRID_E323		  67
-#define EM2883_BOARD_KWORLD_A340		  68
+#define EM2870_BOARD_KWORLD_A340		  68
 #define EM2888_BOARD_LINCOLN_TV_FM		  69
 #define EM2888_BOARD_DVB_TC_HYBRID		  70
 #define EM2888_BOARD_EMPIA_HYBRID                 71
diff -r 677bbac6845b lgdt3304/lgdt3304.c
--- a/lgdt3304/lgdt3304.c	Sun Jul 20 17:52:57 2008 +0200
+++ b/lgdt3304/lgdt3304.c	Mon Jul 21 20:36:10 2008 -0400
@@ -37,6 +37,13 @@
 #include "dvb_frontend.h"
 #include "lgdt3304.h"
 
+static  unsigned int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"lgdt3304 debugging (default off)");
+
+#define dprintk(fmt, args...) if (debug) do {\
+			printk("lgdt3304 debug: " fmt, ##args); } while (0)
+
 struct lgdt3304_state
 {
         struct dvb_frontend frontend;
@@ -61,6 +68,7 @@
 
         for (i=0; i<len-1; i+=3){
 		if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
+			printk("%s i2c_transfer error %d\n", __FUNCTION__, err);
                         if (err < 0)
                                 return err;
                         else
@@ -90,8 +98,10 @@
 	i2cmsgs[1].len = 1;
 	i2cmsgs[1].buf = &buf;
 
-	if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0)
+	if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0) {
+		printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
 		return ret;
+	}
 
 	return buf;
 }
@@ -100,6 +110,7 @@
 {
 	struct lgdt3304_state *state = fe->demodulator_priv;
 	char buffer[3] = { reg>>8, reg&0xff, val };
+	int ret;
 
 	struct i2c_msg i2cmsgs = {
 		.addr = state->addr,
@@ -107,7 +118,11 @@
 		.len = 3,
 		.buf=buffer
 	};
-	i2c_transfer(state->i2c, &i2cmsgs, 1);
+	ret = i2c_transfer(state->i2c, &i2cmsgs, 1);
+	if (ret != 1) {
+		printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
+		return ret;
+	}
 
 	return 0;
 }
@@ -122,7 +137,7 @@
 }
 
 static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
-	int err;
+	int err = 0;
 
 	static __u8 lgdt3304_vsb8_data[] = {
 		/* 16bit  , 8bit */
@@ -168,6 +183,7 @@
 		0x05, 0x0e, 0x5b,
 	};
 
+#if 0
 	/* not yet tested */
 	static __u8 lgdt3304_qam256_data[] = {
 		/* 16bit  , 8bit */
@@ -184,6 +200,67 @@
 		0x03, 0x0a, 0x08,
 		0x03, 0x0b, 0x9b,
 		0x03, 0x0d, 0x14,
+		0x05, 0x0e, 0x5b,
+	};
+#endif
+
+	/* tested with KWorld a340 */
+	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,
+		0x00, 0x0d, 0x02,
+		0x03, 0x14, 0xe3,
+
+		0x03, 0x0e, 0x1c,
+		0x03, 0x08, 0x66,
+		0x03, 0x09, 0x66,
+		0x03, 0x0a, 0x08,
+		0x03, 0x0b, 0x9b,
+
+		0x03, 0x0d, 0x14,
+		0x01, 0x06, 0x4a,
+		0x01, 0x07, 0x3d,
+		0x01, 0x08, 0x70,
+		0x01, 0x09, 0xa3,
+
+		0x05, 0x04, 0xfd,
+
+		0x00, 0x0d, 0x82,
+
 		0x05, 0x0e, 0x5b,
 	};
 
@@ -205,7 +282,12 @@
 		default:
 			break;
 		}
-		state->current_modulation = param->u.vsb.modulation;
+
+		if (err) {
+			printk("%s error setting modulation\n", __FUNCTION__);
+		} else {
+			state->current_modulation = param->u.vsb.modulation;
+		}
 	}
 	state->current_frequency = param->frequency;
 
@@ -234,16 +316,16 @@
 	int qam_lck;
 
 	*status = 0;
-	printk("lgdt read status\n");
+	dprintk("lgdt read status\n");
 	
 	r011d = lgdt3304_i2c_read_reg(fe, 0x011d);
 
-	printk("%02x\n", r011d);
+	dprintk("%02x\n", r011d);
 
 	switch(state->current_modulation) {
 	case VSB_8:
 		if (r011d & 0x80) {
-			printk("VSB Locked\n");
+			dprintk("VSB Locked\n");
 			*status |= FE_HAS_CARRIER;
 			*status |= FE_HAS_LOCK;
 			*status |= FE_HAS_SYNC;
@@ -254,13 +336,13 @@
 	case QAM_256:
 		qam_lck = r011d & 0x7;
 		switch(qam_lck) {
-			case 0x0: printk("Unlock\n");
+			case 0x0: dprintk("Unlock\n");
 				  break;
-			case 0x4: printk("1st Lock in acquisition state\n");
+			case 0x4: dprintk("1st Lock in acquisition state\n");
 				  break;
-			case 0x6: printk("2nd Lock in acquisition state\n");
+			case 0x6: dprintk("2nd Lock in acquisition state\n");
 				  break;
-			case 0x7: printk("Final Lock in good reception state\n");
+			case 0x7: dprintk("Final Lock in good reception state\n");
 				  *status |= FE_HAS_CARRIER;
 				  *status |= FE_HAS_LOCK;
 				  *status |= FE_HAS_SYNC;
@@ -269,7 +351,7 @@
 		}
 		break;
 	default:
-		    printk("unhandled modulation\n");
+		printk("%s unhandled modulation\n", __FUNCTION__);
 	}
 
 
@@ -278,26 +360,32 @@
 
 static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber)
 {
-	printk("read ber\n");
+	dprintk("read ber\n");
 	return 0;
 }
 
 static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr)
 {
-	printk("read snr\n");
+	dprintk("read snr\n");
 	return 0;
 }
 
 static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
 {
-	printk("read ucblocks\n");
+	dprintk("read ucblocks\n");
 	return 0;
+}
+
+static void lgdt3304_release(struct dvb_frontend *fe)
+{
+	struct lgdt3304_state *state = (struct lgdt3304_state *)fe->demodulator_priv;
+	kfree(state);
 }
 
 static struct dvb_frontend_ops demod_lgdt3304={
 	.info = {
 		.name = "LG 3304",
-		.type = FE_OFDM,
+		.type = FE_ATSC,
 		.frequency_min = 54000000,
 		.frequency_max = 858000000,
 		.frequency_stepsize = 62500,
@@ -311,7 +399,8 @@
 	.read_snr = lgdt3304_read_snr,
 	.read_ber = lgdt3304_read_ber,
 	.read_status = lgdt3304_read_status,
-	.read_ucblocks = lgdt3304_read_ucblocks
+	.read_ucblocks = lgdt3304_read_ucblocks,
+	.release = lgdt3304_release,
 };
 
 struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
@@ -322,6 +411,7 @@
 	state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL);
 	memset(state, 0x0, sizeof(struct lgdt3304_state));
 	state->addr = config->i2c_address;
+	state->i2c = i2c;
 
 	memcpy(&state->frontend.ops, &demod_lgdt3304, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
_______________________________________________
Em28xx mailing list
[email protected]
http://mcentral.de/mailman/listinfo/em28xx

Reply via email to