diff mbox

AverTV TwinStar support

Message ID 492564760911210744n212a0740j4714b5761d68ccb0@mail.gmail.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

Piero Terzulli Nov. 21, 2009, 3:44 p.m. UTC
None
diff mbox

Patch

diff -ur v4l-dvb/linux/drivers/media/common/tuners/mxl5007t.c v4l-dvb.new/linux/drivers/media/common/tuners/mxl5007t.c
--- v4l-dvb/linux/drivers/media/common/tuners/mxl5007t.c	2009-10-01 21:13:56.000000000 +0200
+++ v4l-dvb.new/linux/drivers/media/common/tuners/mxl5007t.c	2009-09-29 01:43:36.000000000 +0200
@@ -375,7 +375,6 @@ 
 	mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if);
 	mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz);
 
-	set_reg_bits(state->tab_init, 0x04, 0x01, cfg->loop_thru_enable);
 	set_reg_bits(state->tab_init, 0x03, 0x08, cfg->clk_out_enable << 3);
 	set_reg_bits(state->tab_init, 0x03, 0x07, cfg->clk_out_amp);
 
@@ -480,15 +479,21 @@ 
 static int mxl5007t_write_regs(struct mxl5007t_state *state,
 			       struct reg_pair_t *reg_pair)
 {
-	unsigned int i = 0;
-	int ret = 0;
+	struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
+			       .buf = (u8 *)reg_pair, .len = 0 };
+	int ret;
+	int i = 0;
 
-	while ((ret == 0) && (reg_pair[i].reg || reg_pair[i].val)) {
-		ret = mxl5007t_write_reg(state,
-					 reg_pair[i].reg, reg_pair[i].val);
+	while (reg_pair[i].reg || reg_pair[i].val) {
 		i++;
+		msg.len += 2;
 	}
-	return ret;
+	ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
+	if (ret != 1) {
+		mxl_err("failed!");
+		return -EREMOTEIO;
+	}
+	return 0;
 }
 
 static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
@@ -865,6 +870,18 @@ 
 		/* check return value of mxl5007t_get_chip_id */
 		if (mxl_fail(ret))
 			goto fail;
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		ret = mxl5007t_write_reg(state, 0x04, state->config->loop_thru_enable);
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+
+		/* check return value of mxl5007t_get_chip_id */
+		if (mxl_fail(ret))
+			goto fail;
 		break;
 	default:
 		/* existing tuner instance */
diff -ur v4l-dvb/linux/drivers/media/common/tuners/mxl5007t.h v4l-dvb.new/linux/drivers/media/common/tuners/mxl5007t.h
--- v4l-dvb/linux/drivers/media/common/tuners/mxl5007t.h	2009-10-01 21:13:56.000000000 +0200
+++ v4l-dvb.new/linux/drivers/media/common/tuners/mxl5007t.h	2009-09-29 01:43:36.000000000 +0200
@@ -73,7 +73,7 @@ 
 	enum mxl5007t_xtal_freq xtal_freq_hz;
 	enum mxl5007t_if_freq if_freq_hz;
 	unsigned int invert_if:1;
-	unsigned int loop_thru_enable:1;
+	unsigned int loop_thru_enable:2;
 	unsigned int clk_out_enable:1;
 };
 
diff -ur v4l-dvb/linux/drivers/media/dvb/dvb-usb/af9035.c v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/af9035.c
--- v4l-dvb/linux/drivers/media/dvb/dvb-usb/af9035.c	2009-10-01 21:15:00.000000000 +0200
+++ v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/af9035.c	2009-09-29 01:43:28.000000000 +0200
@@ -25,6 +25,7 @@ 
 #include "af9035.h"
 #include "af9033.h"
 #include "tua9001.h"
+#include "mxl5007t.h"
 
 static int dvb_usb_af9035_debug;
 module_param_named(debug, dvb_usb_af9035_debug, int, 0644);
@@ -40,9 +41,11 @@ 
 static struct af9033_config af9035_af9033_config[] = {
 	{
 		.demod_address = 0,
+		.tuner_address = 0,
 		.output_mode = AF9033_TS_MODE_USB,
 	}, {
 		.demod_address = 0,
+		.tuner_address = 0,
 		.output_mode = AF9033_TS_MODE_SERIAL,
 	}
 };
@@ -137,7 +140,7 @@ 
 	return ret;
 }
 
-static int af9035_write_regs(struct dvb_usb_device *d, u8 mbox, u16 reg,
+static int af9035_write_regs_bis(struct usb_device *d, u8 mbox, u16 reg,
 u8 *val, u8 len)
 {
 	u8 wbuf[6+len];
@@ -150,51 +153,74 @@ 
 	wbuf[4] = reg >> 8;
 	wbuf[5] = reg & 0xff;
 	memcpy(&wbuf[6], val, len);
-	return af9035_rw_udev(d->udev, &req);
+	return af9035_rw_udev(d, &req);
 }
 
-static int af9035_read_regs(struct dvb_usb_device *d, u8 mbox, u16 reg, u8 *val,
+static int af9035_write_regs(struct dvb_usb_device *d, u8 mbox, u16 reg,
+u8 *val, u8 len)
+{
+	return af9035_write_regs_bis(d->udev, mbox, reg, val, len);
+}
+
+static int af9035_read_regs_bis(struct usb_device *d, u8 mbox, u16 reg, u8 *val,
 	u8 len)
 {
 	u8 wbuf[] = {len, 2, 0, 0, reg >> 8, reg & 0xff};
 	struct af9035_req req = {CMD_REG_DEMOD_READ, mbox, sizeof(wbuf), wbuf,
 		len, val};
-	return af9035_rw_udev(d->udev, &req);
+	return af9035_rw_udev(d, &req);
+}
+
+static int af9035_read_regs(struct dvb_usb_device *d, u8 mbox, u16 reg, u8 *val,
+	u8 len)
+{
+	return af9035_read_regs_bis(d->udev, mbox, reg, val, len);
+}
+
+static int af9035_write_reg_bis(struct usb_device *d, u8 mbox, u16 reg, u8 val)
+{
+	return af9035_write_regs_bis(d, mbox, reg, &val, 1);
 }
 
 static int af9035_write_reg(struct dvb_usb_device *d, u8 mbox, u16 reg, u8 val)
 {
-	return af9035_write_regs(d, mbox, reg, &val, 1);
+	return af9035_write_regs_bis(d->udev, mbox, reg, &val, 1);
 }
 
-static int af9035_read_reg(struct dvb_usb_device *d, u8 mbox, u16 reg, u8 *val)
+static int af9035_read_reg_bis(struct usb_device *d, u8 mbox, u16 reg, u8 *val)
 {
-	return af9035_read_regs(d, mbox, reg, val, 1);
+	return af9035_read_regs_bis(d, mbox, reg, val, 1);
 }
 
-static int af9035_write_reg_bits(struct dvb_usb_device *d, u8 mbox, u16 reg,
+static int af9035_write_reg_bits_bis(struct usb_device *d, u8 mbox, u16 reg,
 	u8 pos, u8 len, u8 val)
 {
 	int ret;
 	u8 tmp, mask;
 
-	ret = af9035_read_reg(d, mbox, reg, &tmp);
+	ret = af9035_read_reg_bis(d, mbox, reg, &tmp);
 	if (ret)
 		return ret;
 
 	mask = regmask[len - 1] << pos;
 	tmp = (tmp & ~mask) | ((val << pos) & mask);
 
-	return af9035_write_reg(d, mbox, reg, tmp);
+	return af9035_write_reg_bis(d, mbox, reg, tmp);
+}
+
+static int af9035_write_reg_bits(struct dvb_usb_device *d, u8 mbox, u16 reg,
+	u8 pos, u8 len, u8 val)
+{
+	return af9035_write_reg_bits_bis(d->udev, mbox, reg, pos, len, val);
 }
 
-static int af9035_read_reg_bits(struct dvb_usb_device *d, u8 mbox, u16 reg,
+static int af9035_read_reg_bits_bis(struct usb_device *d, u8 mbox, u16 reg,
 	u8 pos, u8 len, u8 *val)
 {
 	int ret;
 	u8 tmp;
 
-	ret = af9035_read_reg(d, mbox, reg, &tmp);
+	ret = af9035_read_reg_bis(d, mbox, reg, &tmp);
 	if (ret)
 		return ret;
 	*val = (tmp >> pos) & regmask[len - 1];
@@ -221,21 +247,29 @@ 
 				af9035_af9033_config[0].demod_address ||
 			    msg[i].addr ==
 				af9035_af9033_config[1].demod_address) {
+				if (af9035_af9033_config[1].demod_address && (msg[i].addr == af9035_af9033_config[1].demod_address))
+					mbox += 0x10;
 				ret = af9035_read_regs(d, mbox, reg,
 					&msg[i+1].buf[0], msg[i+1].len);
 			} else {
 				/* FIXME */
 				u8 wbuf[5];
-				u8 rbuf[2];
+				u8 rbuf[BUF_SIZE];
 				struct af9035_req req = {CMD_REG_TUNER_READ,
-					LINK, sizeof(wbuf), wbuf, sizeof(rbuf),
+					LINK, sizeof(wbuf), wbuf, msg[i + 1].len,
 					rbuf};
-				wbuf[0] = 0x02; /* read len */
+				if (af9035_af9033_config[1].tuner_address &&
+					(msg[i].addr == af9035_af9033_config[1].tuner_address)) {
+					msg[i].addr = af9035_af9033_config[0].tuner_address;
+					req.mbox += 0x10;
+				}
+				wbuf[0] = msg[i + 1].len; /* read len */
 				wbuf[1] = msg[i].addr; /* tuner i2c addr */
 				wbuf[2] = 0x01; /* reg width */
 				wbuf[3] = 0x00; /* reg MSB */
 				wbuf[4] = msg[i].buf[0]; /* reg LSB */
 				ret = af9035_rw_udev(d->udev, &req);
+				memcpy (msg[i + 1].buf, rbuf, msg[i + 1].len);
 			}
 			i += 2;
 		} else {
@@ -243,19 +277,24 @@ 
 				af9035_af9033_config[0].demod_address ||
 			    msg[i].addr ==
 				af9035_af9033_config[1].demod_address) {
+				if (af9035_af9033_config[1].demod_address && (msg[i].addr == af9035_af9033_config[1].demod_address))
+					mbox += 0x10;
 				ret = af9035_write_regs(d, mbox, reg,
 					&msg[i].buf[3], msg[i].len-3);
 			} else {
-				u8 wbuf[7];
+				u8 wbuf[BUF_SIZE];
 				struct af9035_req req = {CMD_REG_TUNER_WRITE,
-					LINK, sizeof(wbuf), wbuf, 0, NULL};
-				wbuf[0] = 0x02; /* write len */
+					LINK, 4 + msg[i].len, wbuf, 0, NULL};
+				if (af9035_af9033_config[1].tuner_address &&
+					(msg[i].addr == af9035_af9033_config[1].tuner_address)) {
+					msg[i].addr = af9035_af9033_config[0].tuner_address;
+					req.mbox += 0x10;
+				}
+				wbuf[0] = msg[i].len - 1; /* write len */
 				wbuf[1] = msg[i].addr; /* tuner i2c addr */
 				wbuf[2] = 0x01; /* reg width */
 				wbuf[3] = 0x00; /* reg MSB */
-				wbuf[4] = msg[i].buf[0]; /* reg LSB */
-				wbuf[5] = msg[i].buf[1]; /* reg val MSB */
-				wbuf[6] = msg[i].buf[2]; /* reg val LSB */
+				memcpy (&wbuf[4], msg[i].buf, msg[i].len);
 				ret = af9035_rw_udev(d->udev, &req);
 			}
 			i += 1;
@@ -424,8 +463,9 @@ 
 	u8 wbuf[1];
 	u8 rbuf[4];
 	struct af9035_firmware_header fw_hdr;
-	struct af9035_req req = {0, LINK, 0, NULL, 0, NULL};
-	struct af9035_req req_fw_dl = {CMD_FW_DOWNLOAD, LINK, 0, wbuf, 0, NULL};
+	struct af9035_req req = {0, LINK, 0, NULL, 1, rbuf};
+	struct af9035_req req_fw_dl = {CMD_FW_DOWNLOAD, LINK, 0, NULL, 0, NULL};
+	struct af9035_req req_rom = {CMD_SCATTER_WRITE, LINK, 0, NULL, 1, rbuf};
 	struct af9035_req req_fw_ver = {CMD_QUERYINFO, LINK, 1, wbuf, 4, rbuf};
 
 	/* read firmware segment info from beginning of the firmware file */
@@ -485,6 +525,25 @@ 
 				err("firmware download failed:%d", ret);
 				goto error;
 			}
+		} else if (fw_hdr.segment[i].type == SEGMENT_ROM_COPY){
+			packets = fw_hdr.segment[i].len / FW_PACKET_MAX_DATA;
+			remainder = fw_hdr.segment[i].len % FW_PACKET_MAX_DATA;
+			len = FW_PACKET_MAX_DATA;
+			for (j = 0; j <= packets; j++) {
+				if (j == packets)  /* size of the last packet */
+					len = remainder;
+
+				req_rom.wlen = len;
+				req_rom.wbuf = fw_data_ptr;
+				ret = af9035_rw_udev(udev, &req_rom);
+				if (ret) {
+					err("firmware download failed at " \
+						"segment:%d packet:%d err:%d", \
+						i, j, ret);
+					goto error;
+				}
+				fw_data_ptr += len;
+			}
 		} else {
 			deb_info("%s: segment type:%d not implemented\n",
 				__func__, fw_hdr.segment[i].type);
@@ -556,7 +615,7 @@ 
 			af9035_config.dual_mode = 0;
 		} else {
 			af9035_properties[i].adapter[0].stream.u.bulk.buffersize
-				= TS_USB20_MAX_PACKET_SIZE;
+				= TS_USB20_FRAME_SIZE;
 		}
 	}
 
@@ -635,6 +694,9 @@ 
 		case AF9033_TUNER_TUA9001:
 			af9035_af9033_config[i].rf_spec_inv = 1;
 			break;
+		case AF9033_TUNER_MXL5007t:
+			af9035_af9033_config[i].rf_spec_inv = 1;
+			break;
 		default:
 			warn("tuner ID:%d not supported, please report!", val);
 			return -ENODEV;
@@ -648,6 +710,48 @@ 
 	if (ret)
 		err("eeprom read failed:%d", ret);
 
+	if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_AVERMEDIA &&
+	    le16_to_cpu(udev->descriptor.idProduct) == USB_PID_AVERMEDIA_A825) {
+		deb_info("%s: AverMedia A825: overriding config\n", __func__);
+		/* set correct IF */
+		for (i = 0; i < af9035_properties[0].num_adapters; i++) {
+			af9035_af9033_config[i].if_freq = 4570000;
+		}
+	}
+
+	return ret;
+}
+
+static int af9035_aux_init(struct usb_device *d)
+{
+	int ret;
+	u8 tmp, i;
+
+	/* get demod crystal and ADC freqs */
+	ret = af9035_read_reg_bits_bis(d, LINK,
+		r_io_mux_pwron_clk_strap, io_mux_pwron_clk_strap_pos,
+		io_mux_pwron_clk_strap_len, &tmp);
+	if (ret)
+		goto error;
+
+	for (i = 0; i < af9035_properties[0].num_adapters; i++) {
+		af9035_af9033_config[i].crystal_clock =
+			clock_table[tmp].crystal;
+		af9035_af9033_config[i].adc_clock =
+			clock_table[tmp].adc;
+	}
+
+	/* write 2nd demod I2C address to device */
+	ret = af9035_write_reg_bis(d, LINK, 0x417f,
+		af9035_af9033_config[1].demod_address);
+	if (ret)
+		goto error;
+
+	/* enable / disable clock out for 2nd demod for power saving */
+	ret = af9035_write_reg_bis(d, LINK, p_reg_top_clkoen,
+		af9035_config.dual_mode);
+
+error:
 	return ret;
 }
 
@@ -678,49 +782,37 @@ 
 
 static int af9035_af9033_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	int ret;
-	u8 tmp, i;
-
-	if (adap->id == 0) {
-		/* get demod crystal and ADC freqs */
-		ret = af9035_read_reg_bits(adap->dev, LINK,
-			r_io_mux_pwron_clk_strap, io_mux_pwron_clk_strap_pos,
-			io_mux_pwron_clk_strap_len, &tmp);
-		if (ret)
-			goto error;
-
-		for (i = 0; i < af9035_properties[0].num_adapters; i++) {
-			af9035_af9033_config[i].crystal_clock =
-				clock_table[tmp].crystal;
-			af9035_af9033_config[i].adc_clock =
-				clock_table[tmp].adc;
-		}
-
-		/* write 2nd demod I2C address to device */
-		ret = af9035_write_reg(adap->dev, LINK, 0x417f,
-			af9035_af9033_config[1].demod_address);
-		if (ret)
-			goto error;
-
-		/* enable / disable clock out for 2nd demod for power saving */
-		ret = af9035_write_reg(adap->dev, LINK, p_reg_top_clkoen,
-			af9035_config.dual_mode);
-		if (ret)
-			goto error;
-	}
-
 	/* attach demodulator */
 	adap->fe = dvb_attach(af9033_attach, &af9035_af9033_config[adap->id],
 		&adap->dev->i2c_adap);
 
 	return adap->fe == NULL ? -ENODEV : 0;
-
-error:
-	return ret;
 }
 
-static struct tua9001_config af9035_tua9001_config = {
-	.i2c_address = 0xc0,
+static struct tua9001_config af9035_tua9001_config[] = {
+	{
+		.i2c_address = 0xc0,
+	} , {
+		.i2c_address = 0xc1,
+	}
+};
+
+static struct mxl5007t_config af9035_mxl5007t_config[] = {
+	{
+		.xtal_freq_hz = MxL_XTAL_24_MHZ,
+		.if_freq_hz = MxL_IF_4_57_MHZ,
+		.invert_if = 0,
+		.loop_thru_enable = 0,
+		.clk_out_enable = 0,
+		.clk_out_amp = MxL_CLKOUT_AMP_0_94V,
+	} , {
+		.xtal_freq_hz = MxL_XTAL_24_MHZ,
+		.if_freq_hz = MxL_IF_4_57_MHZ,
+		.invert_if = 0,
+		.loop_thru_enable = 3,
+		.clk_out_enable = 1,
+		.clk_out_amp = MxL_CLKOUT_AMP_0_94V,
+	}
 };
 
 static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
@@ -730,34 +822,93 @@ 
 
 	switch (af9035_af9033_config[adap->id].tuner) {
 	case AF9033_TUNER_TUA9001:
-		/* gpiot3 TUA9001 RESETN
-		   gpiot2 TUA9001 RXEN */
-		ret = af9035_write_reg_bits(adap->dev, LINK,
-			p_reg_top_gpiot2_en, reg_top_gpiot2_en_pos,
-			reg_top_gpiot2_en_len, 1);
-		ret = af9035_write_reg_bits(adap->dev, LINK,
-			p_reg_top_gpiot2_on, reg_top_gpiot2_on_pos,
-			reg_top_gpiot2_on_len, 1);
-		ret = af9035_write_reg_bits(adap->dev, LINK,
-			p_reg_top_gpiot3_en, reg_top_gpiot3_en_pos,
-			reg_top_gpiot3_en_len, 1);
-		ret = af9035_write_reg_bits(adap->dev, LINK,
-			p_reg_top_gpiot3_on, reg_top_gpiot3_on_pos,
-			reg_top_gpiot3_on_len, 1);
-
-		/* reset tuner */
-		ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot3_o,
-			 reg_top_gpiot3_o_pos, reg_top_gpiot3_o_len, 0);
-		msleep(1);
-		ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot3_o,
-			 reg_top_gpiot3_o_pos, reg_top_gpiot3_o_len, 1);
-
-		/* activate tuner - TODO: do that like I2C gate control */
-		ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot2_o,
-			 reg_top_gpiot2_o_pos, reg_top_gpiot2_o_len, 1);
+		af9035_af9033_config[adap->id].tuner_address = af9035_tua9001_config[adap->id].i2c_address;
+		af9035_af9033_config[adap->id].tuner_address += adap->id;
+		if (adap->id == 0) {
+			/* gpiot3 TUA9001 RESETN
+			   gpiot2 TUA9001 RXEN */
+			ret = af9035_write_reg_bits(adap->dev, LINK,
+				p_reg_top_gpiot2_en, reg_top_gpiot2_en_pos,
+				reg_top_gpiot2_en_len, 1);
+			ret = af9035_write_reg_bits(adap->dev, LINK,
+				p_reg_top_gpiot2_on, reg_top_gpiot2_on_pos,
+				reg_top_gpiot2_on_len, 1);
+			ret = af9035_write_reg_bits(adap->dev, LINK,
+				p_reg_top_gpiot3_en, reg_top_gpiot3_en_pos,
+				reg_top_gpiot3_en_len, 1);
+			ret = af9035_write_reg_bits(adap->dev, LINK,
+				p_reg_top_gpiot3_on, reg_top_gpiot3_on_pos,
+				reg_top_gpiot3_on_len, 1);
+
+			/* reset tuner */
+			ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot3_o,
+				 reg_top_gpiot3_o_pos, reg_top_gpiot3_o_len, 0);
+			msleep(1);
+			ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot3_o,
+				 reg_top_gpiot3_o_pos, reg_top_gpiot3_o_len, 1);
+
+			/* activate tuner - TODO: do that like I2C gate control */
+			ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot2_o,
+				 reg_top_gpiot2_o_pos, reg_top_gpiot2_o_len, 1);
+		}
 
 		ret = dvb_attach(tua9001_attach, adap->fe, &adap->dev->i2c_adap,
-			&af9035_tua9001_config) == NULL ? -ENODEV : 0;
+			&af9035_tua9001_config[adap->id]) == NULL ? -ENODEV : 0;
+
+		break;
+	case AF9033_TUNER_MXL5007t:
+		af9035_af9033_config[adap->id].tuner_address = 0xc0;
+		af9035_af9033_config[adap->id].tuner_address += adap->id;
+		if (adap->id == 0) {
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh12_en,
+				1);
+
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh12_on,
+				1);
+
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh12_o,
+				0);
+
+			msleep(30);
+
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh12_o,
+				1);
+
+			msleep(300);
+
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh4_en,
+				1);
+
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh4_on,
+				1);
+
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh4_o,
+				0);
+
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh3_en,
+				1);
+
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh3_on,
+				1);
+
+			ret = af9035_write_reg(adap->dev, LINK,
+				p_reg_top_gpioh3_o,
+				1);
+		}
+
+		ret = dvb_attach(mxl5007t_attach, adap->fe, &adap->dev->i2c_adap,
+			af9035_af9033_config[adap->id].tuner_address,
+			&af9035_mxl5007t_config[adap->id]) == NULL ? -ENODEV : 0;
+
 		break;
 	default:
 		ret = -ENODEV;
@@ -775,6 +926,7 @@ 
 	{USB_DEVICE(USB_VID_AFATECH,   USB_PID_AFATECH_AF9035_1003)},
 	{USB_DEVICE(USB_VID_AFATECH,   USB_PID_AFATECH_AF9035_9035)},
 /*  5 */{USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_T_STICK)},
+/*  6 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A825)},
 	{0},
 };
 
@@ -798,7 +950,7 @@ 
 				.tuner_attach = af9035_tuner_attach,
 				.stream = {
 					.type = USB_BULK,
-					.count = 6,
+					.count = 4,
 					.endpoint = 0x84,
 				},
 			},
@@ -808,12 +960,12 @@ 
 				.tuner_attach = af9035_tuner_attach,
 				.stream = {
 					.type = USB_BULK,
-					.count = 6,
+					.count = 4,
 					.endpoint = 0x85,
 					.u = {
 						.bulk = {
 							.buffersize =
-						TS_USB20_MAX_PACKET_SIZE,
+						TS_USB20_FRAME_SIZE,
 						}
 					}
 				},
@@ -824,7 +976,7 @@ 
 
 		.i2c_algo = &af9035_i2c_algo,
 
-		.num_device_descs = 2,
+		.num_device_descs = 3,
 		.devices = {
 			{
 				.name = "Afatech AF9035 DVB-T USB2.0 stick",
@@ -840,6 +992,11 @@ 
 				.cold_ids = {&af9035_usb_table[5], NULL},
 				.warm_ids = {NULL},
 			},
+			{
+				.name = "Avermedia TwinStar",
+				.cold_ids = {&af9035_usb_table[6], NULL},
+				.warm_ids = {NULL},
+			},
 		}
 	},
 };
@@ -862,6 +1019,10 @@ 
 		if (ret)
 			return ret;
 
+		ret = af9035_aux_init(udev);
+		if (ret)
+			return ret;
+
 		for (i = 0; i < af9035_properties_count; i++) {
 			ret = dvb_usb_device_init(intf, &af9035_properties[i],
 				THIS_MODULE, &d, adapter_nr);
diff -ur v4l-dvb/linux/drivers/media/dvb/dvb-usb/af9035.h v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/af9035.h
--- v4l-dvb/linux/drivers/media/dvb/dvb-usb/af9035.h	2009-10-01 21:15:00.000000000 +0200
+++ v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/af9035.h	2009-09-07 01:27:03.000000000 +0200
@@ -179,7 +179,7 @@ 
 };
 
 struct af9035_firmware_header {
-#define SEGMENT_MAX_COUNT 6
+#define SEGMENT_MAX_COUNT 50
 	u8 segment_count;
 	struct af9035_segment segment[SEGMENT_MAX_COUNT];
 };
diff -ur v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2009-10-01 21:15:00.000000000 +0200
+++ v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2009-09-29 01:59:52.000000000 +0200
@@ -187,6 +187,7 @@ 
 #define USB_PID_AVERMEDIA_A310				0xa310
 #define USB_PID_AVERMEDIA_A850				0x850a
 #define USB_PID_AVERMEDIA_A805				0xa805
+#define USB_PID_AVERMEDIA_A825				0x0825
 #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2	0x0081
diff -ur v4l-dvb/linux/drivers/media/dvb/frontends/af9033.c v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033.c
--- v4l-dvb/linux/drivers/media/dvb/frontends/af9033.c	2009-10-01 21:15:00.000000000 +0200
+++ v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033.c	2009-09-29 01:43:28.000000000 +0200
@@ -891,8 +891,7 @@ 
 		goto error;
 
 	/* set fpga latch */
-	ret = af9033_write_reg_bits(state, OFDM, p_reg_dca_fpga_latch,
-		reg_dca_fpga_latch_pos, reg_dca_fpga_latch_len, 0);
+	ret = af9033_write_reg(state, OFDM, p_reg_dca_fpga_latch, 0);
 	if (ret)
 		goto error;
 
@@ -925,6 +924,10 @@ 
 		len = ARRAY_SIZE(tuner_init_tua9001);
 		init = tuner_init_tua9001;
 		break;
+	case AF9033_TUNER_MXL5007t:
+		len = ARRAY_SIZE(tuner_init_mxl5007t);
+		init = tuner_init_mxl5007t;
+		break;
 	default:
 		len = 0;
 		init = NULL;
@@ -981,6 +984,12 @@ 
 	if (ret)
 		goto error;
 
+	if (state->config.output_mode == AF9033_TS_MODE_SERIAL) {
+		ret = af9033_write_reg_bits(state, LINK, p_reg_top_hostb_mpeg_ser_mode,
+			reg_top_hostb_mpeg_ser_mode_pos, reg_top_hostb_mpeg_ser_mode_len, 1);
+		if (ret)
+			goto error;
+	}
 error:
 	if (ret)
 		deb_info("%s: failed:%d\n", __func__, ret);
@@ -1115,11 +1124,11 @@ 
 	   1670 - 1680 MHz L-BAND  band = 0x02
 	   otherwise               band = 0xff */
 	/* TODO: are both min/max ranges really required... */
-	if ((state->frequency >= 174000) && (state->frequency <= 230000))
+	if ((state->frequency >= 174000000) && (state->frequency <= 230000000))
 		tmp = 0x00; /* VHF */
-	else if ((state->frequency >= 350000) && (state->frequency <= 900000))
+	else if ((state->frequency >= 350000000) && (state->frequency <= 900000000))
 		tmp = 0x01; /* UHF */
-	else if ((state->frequency >= 1670000) && (state->frequency <= 1680000))
+	else if ((state->frequency >= 1670000000) && (state->frequency <= 1680000000))
 		tmp = 0x02; /* L-BAND */
 	else
 		tmp = 0xff;
diff -ur v4l-dvb/linux/drivers/media/dvb/frontends/af9033.h v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033.h
--- v4l-dvb/linux/drivers/media/dvb/frontends/af9033.h	2009-10-01 21:15:00.000000000 +0200
+++ v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033.h	2009-09-16 15:52:01.000000000 +0200
@@ -36,6 +36,7 @@ 
 enum af9033_tuner {
 	AF9033_TUNER_TUA9001    = 0x27, /* Infineon TUA 9001 */
 	AF9033_TUNER_FC0011     = 0x28, /* Fitipower FC0011 */
+	AF9033_TUNER_MXL5007t   = 0xa0, /* Maxlinear MXL5007t */
 };
 
 /* clock setting table:
@@ -60,6 +61,8 @@ 
 	/* demodulator's I2C address */
 	u8 demod_address;
 
+	u8 tuner_address;
+
 	/* xtal clock Hz */
 	u32 crystal_clock;
 
diff -ur v4l-dvb/linux/drivers/media/dvb/frontends/af9033_priv.h v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033_priv.h
--- v4l-dvb/linux/drivers/media/dvb/frontends/af9033_priv.h	2009-10-01 21:15:00.000000000 +0200
+++ v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033_priv.h	2009-09-06 23:55:51.000000000 +0200
@@ -305,5 +305,38 @@ 
 	{0xF1E6, 0x00},
 };
 
+static struct regdesc tuner_init_mxl5007t[] = {
+	{0x0046, 0x1b},
+	{0x0057, 0x01},
+	{0x0058, 0x01},
+	{0x005f, 0x00},
+	{0x0060, 0x00},
+	{0x0068, 0x96},
+	{0x0071, 0x05},
+	{0x0072, 0x02},
+	{0x0074, 0x01},
+	{0x0079, 0x01},
+	{0x0093, 0x00},
+	{0x0094, 0x00},
+	{0x0095, 0x00},
+	{0x0096, 0x00},
+	{0x00b3, 0x01},
+	{0x00c1, 0x01},
+	{0x00c2, 0x00},
+	{0xF007, 0x00},
+	{0xF00C, 0x19},
+	{0xF00D, 0x1a},
+	{0xF012, 0xda},
+	{0xF013, 0x00},
+	{0xF014, 0x00},
+	{0xF015, 0x02},
+	{0xF01F, 0x82},
+	{0xF020, 0x00},
+	{0xF029, 0x82},
+	{0xF02A, 0x00},
+	{0xF077, 0x02},
+	{0xF1E6, 0x00},
+};
+
 #endif /* AF9033_PRIV_H */