[linux-dvb] [PATCH] HD5000 Support

Mac Michaels wmichaels1 at earthlink.net
Tue Sep 27 21:05:26 CEST 2005


I suggest a few changes to this patch. I inserted it a a 
quote so that I can work my comments into it.

> Index: linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
> 
===================================================================
> RCS 
file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c,v
> retrieving revision 1.10
> diff -u -r1.10 flexcop-fe-tuner.c
> --- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c	10 Sep 
2005 12:43:48 -0000	1.10
> +++ linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c	25 Sep 
2005 16:52:08 -0000
> @@ -13,6 +13,8 @@
>  #include "bcm3510.h"
>  #include "stv0297_cs2.h"
>  #include "mt312.h"
> +#include "lgdt330x.h"
> +#include "dvb-pll.h"
>  
>  /* lnb control */
>  
> @@ -296,6 +298,51 @@
>  	return request_firmware(fw, name, fc->dev);
>  }
>  
> +static int lgdt3303_pll_set(struct dvb_frontend* fe, 
> +                            struct 
dvb_frontend_parameters* params)
> +{
> +	struct flexcop_device *fc = fe->dvb->priv;
> +	u8 buf[4];
> +	struct i2c_msg msg =
> +		{ .addr = 0x61, .flags = 0, .buf = buf, .len = 4 };
> +	int err;
> +
> +	dvb_pll_configure(&dvb_pll_tdvs_tua6034,buf, 
params->frequency, 0);
> +	dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 
0x%02x 0x%02x\n",
> +			__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
> +	if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
> +		printk(KERN_WARNING "lgdt3303: %s error "
> +			   "(addr %02x <- %02x, err = %i)\n",
> +			   __FUNCTION__, buf[0], buf[1], err);
> +		if (err < 0)
> +			return err;
> +		else
> +			return -EREMOTEIO;
> +	}
> +
> +	buf[0] = 0x86 | 0x18;
> +	buf[1] = 0x50;
> +	msg.len = 2;	
> +	if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
> +		printk(KERN_WARNING "lgdt3303: %s error "
> +			   "(addr %02x <- %02x, err = %i)\n",
> +			   __FUNCTION__, buf[0], buf[1], err);
> +		if (err < 0)
> +			return err;
> +		else
> +			return -EREMOTEIO;
> +	}
> +
> +        return 0;
> +}
> +
> +static struct lgdt330x_config air2pc_atsc_hd5000_config = 
{
> +	.demod_address    = 0x59,
> +	.demod_chip       = LGDT3303,
> +	.serial_mpeg      = 0x04,

I assume you are using parallel mode data transfer here.
+	.serial_mpeg      = 0x00,	/* Select parallel mode */

> +	.pll_set          = lgdt3303_pll_set,
> +};
> +
>  static struct nxt2002_config samsung_tbmv_config = {
>  	.demod_address    = 0x0a,
>  	.request_firmware = flexcop_fe_request_firmware,
> @@ -407,6 +454,11 @@
>  		fc->dev_type          = FC_AIR_ATSC2;
>  		info("found the nxt2002 at i2c address: 
0x%02x",samsung_tbmv_config.demod_address);
>  	} else
> +	/* try the air atsc 3nd generation (lgdt3303) */
> +	if ((fc->fe = 
lgdt330x_attach(&air2pc_atsc_hd5000_config, 
&fc->i2c_adap)) != NULL) {
> +		fc->dev_type          = FC_AIR_ATSC3;
> +		info("found the lgdt3303 at i2c address: 
0x%02x",air2pc_atsc_hd5000_config.demod_address);
> +	} else
>  	/* try the air atsc 1nd generation (bcm3510)/panasonic 
ct10s */
>  	if ((fc->fe = 
bcm3510_attach(&air2pc_atsc_first_gen_config, 
&fc->i2c_adap)) != NULL) {
>  		fc->dev_type          = FC_AIR_ATSC1;
> Index: linux/drivers/media/dvb/b2c2/flexcop-misc.c
> 
===================================================================
> RCS 
file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/b2c2/flexcop-misc.c,v
> retrieving revision 1.4
> diff -u -r1.4 flexcop-misc.c
> --- linux/drivers/media/dvb/b2c2/flexcop-misc.c	22 Jun 
2005 18:53:25 -0000	1.4
> +++ linux/drivers/media/dvb/b2c2/flexcop-misc.c	25 Sep 
2005 16:52:08 -0000
> @@ -51,6 +51,7 @@
>  	"Sky2PC/SkyStar 2 DVB-S",
>  	"Sky2PC/SkyStar 2 DVB-S (old version)",
>  	"Cable2PC/CableStar 2 DVB-C",
> +	"Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
>  };
>  
>  const char *flexcop_bus_names[] = {
> Index: linux/drivers/media/dvb/b2c2/flexcop-reg.h
> 
===================================================================
> RCS 
file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/b2c2/flexcop-reg.h,v
> retrieving revision 1.5
> diff -u -r1.5 flexcop-reg.h
> --- linux/drivers/media/dvb/b2c2/flexcop-reg.h	12 Jun 2005 
09:36:19 -0000	1.5
> +++ linux/drivers/media/dvb/b2c2/flexcop-reg.h	25 Sep 2005 
16:52:08 -0000
> @@ -26,6 +26,7 @@
>  	FC_SKY,
>  	FC_SKY_OLD,
>  	FC_CABLE,
> +	FC_AIR_ATSC3,
>  } flexcop_device_type_t;
>  
>  typedef enum {
> Index: linux/drivers/media/dvb/b2c2/flexcop.c
> 
===================================================================
> RCS 
file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/b2c2/flexcop.c,v
> retrieving revision 1.7
> diff -u -r1.7 flexcop.c
> --- linux/drivers/media/dvb/b2c2/flexcop.c	22 Jun 2005 
18:53:25 -0000	1.7
> +++ linux/drivers/media/dvb/b2c2/flexcop.c	25 Sep 2005 
16:52:09 -0000
> @@ -193,6 +193,7 @@
>  	v204 = fc->read_ibi_reg(fc,misc_204);
>  	v204.misc_204.Per_reset_sig = 0;
>  	fc->write_ibi_reg(fc,misc_204,v204);
> +	msleep(1);
>  	v204.misc_204.Per_reset_sig = 1;
>  	fc->write_ibi_reg(fc,misc_204,v204);
>  }
> Index: linux/drivers/media/dvb/frontends/lgdt330x.c
> 
===================================================================
> RCS 
file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/frontends/lgdt330x.c,v
> retrieving revision 1.10
> diff -u -r1.10 lgdt330x.c
> --- linux/drivers/media/dvb/frontends/lgdt330x.c	10 Sep 
2005 08:12:36 -0000	1.10
> +++ linux/drivers/media/dvb/frontends/lgdt330x.c	25 Sep 
2005 16:52:09 -0000
> @@ -27,6 +27,7 @@
>   *   DViCO FusionHDTV 3 Gold-T
>   *   DViCO FusionHDTV 5 Gold
>   *   DViCO FusionHDTV 5 Lite
> + *   Air2PC HD5000
>   *
>   * TODO:
>   * signal strength always returns 0.
> @@ -218,7 +219,8 @@
>  	};
>  
>  	static u8 lgdt3303_init_data[] = {
> -		0x4c, 0x14
> +		0x4c, 0x14,
> +		0x87, 0xF3

This may be a problem. This change flips the polarity of the 
clock for the mpeg data transfer clock. The best I can tell 
the CX2388x requires the default high clock. This change 
flips that and may cause problems. It should be 
conditionalized. 

>  	};
>  
>  	struct lgdt330x_state* state = fe->demodulator_priv;
> @@ -535,12 +537,28 @@
>  
>  static int lgdt330x_read_signal_strength(struct 
dvb_frontend* fe, u16* strength)
>  {
> -	/* not directly available. */
> -	*strength = 0;
> +
> +	struct lgdt330x_state* state = fe->demodulator_priv;
> +	u8 buf[3];
> +        
> +        switch (state->config->demod_chip) {
> +        case LGDT3302:
> +		i2c_read_demod_bytes(state, LGDT3302_AGC_RFIF_ACC0, 
buf, sizeof(buf));
> +                break;
> +        case LGDT3303:
> +		i2c_read_demod_bytes(state, LGDT3303_AGC_RFIF_ACC0, 
buf, sizeof(buf));
> +                break;
> +        default:
> +		return -ENODEV;
> +        }
> +
> +	/* This math was given from example from the windows 
bbti driver */
> +	*strength = (1700 - ((buf[0] & 0x07) << 8 | buf[2])) * 
(0xFFFF/1700);

Why did you pick the IF AGC instead of the RF AGC? 

I do not understand this math. The value returned is a 12 
bit signed value. The sign is ignored. This is not good. 
The calculation will always be meaningless because a small 
negative number will look like a large positive number and 
a large negative number will look like a small positive 
number. It totally renders that data useless.

Next this useless number with a range of 0 to 2047 is 
subtracted from 1700. Since 1700 is less than 2047 we may 
have a signed number as the result. The result range is 
-1700 to 347.

Now multiply this by 38 and we get a number that has a range 
of -64600  to 13186. This is returned as a unsigned 16 bit 
number with a range of 0 to 65535.

I just do not understand this math. It takes some 
assumptions to get this to make any sense at all:

1) The sign of the number read from the chip never changes.

2) The value range of the least significant 11 bits read 
from the chip is 0 to1700.

3) The intent is to return a value with no units that is 
linear with the value from the chip such that a chip value 
of 0 to 1700 results in a returned value of 65535 to 0.

> +                
>  	return 0;
>  }
>  

The changes from here to the end of the file modified by 
this patch optimize out some subtile differences between 
the lgdt3302 and lgdt3303 in the snr calculations. The two 
data sheets are different in this area.

I do not think this should be changed in this manner. I 
think the SNR_IN_DB section needs to be reworked to be 
available as an insmod option. I can make it available to 
both lgdt3302 and lgdt3303 chips then. I will do this work 
if there is interest.

> -static int lgdt3302_read_snr(struct dvb_frontend* fe, 
u16* snr)
> +static int lgdt330x_read_snr(struct dvb_frontend* fe, 
u16* snr)
>  {
>  #ifdef SNR_IN_DB
>  	/*
> @@ -598,7 +616,17 @@
>  	struct lgdt330x_state* state = (struct lgdt330x_state*) 
fe->demodulator_priv;
>  
>  	/* read both equalizer and phase tracker noise data */
> -	i2c_read_demod_bytes(state, EQPH_ERR0, buf, 
sizeof(buf));
> +        switch (state->config->demod_chip) {
> +        case LGDT3302:
> +		i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 
sizeof(buf));
> +                break;
> +        case LGDT3303:
> +		i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 
sizeof(buf));
> +                break;
> +        default:
> +		return -ENODEV;
> +        }
> +
>  
>  	if (state->current_modulation == VSB_8) {
>  		/* Equalizer Mean-Square Error Register for VSB */
> @@ -634,7 +662,16 @@
>  	struct lgdt330x_state* state = (struct lgdt330x_state*) 
fe->demodulator_priv;
>  
>  	/* read both equalizer and pase tracker noise data */
> -	i2c_read_demod_bytes(state, EQPH_ERR0, buf, 
sizeof(buf));
> +	switch (state->config->demod_chip) {
> +	case LGDT3302:
> +		i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 
sizeof(buf));
> +		break;
> +	case LGDT3303:
> +		i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 
sizeof(buf));
> +		break;
> +	default:
> +		return -ENODEV;
> +	}
>  
>  	if (state->current_modulation == VSB_8) {
>  #if 0
> @@ -660,37 +697,6 @@
>  	return 0;
>  }
>  
> -static int lgdt3303_read_snr(struct dvb_frontend* fe, 
u16* snr)
> -{
> -	/* Return the raw noise value */
> -	static u8 buf[5];/* read data buffer */
> -	static u32 noise;   /* noise value */
> -	struct lgdt330x_state* state = (struct lgdt330x_state*) 
fe->demodulator_priv;
> -
> -	if (state->current_modulation == VSB_8) {
> -
> -#if 0
> -		/* Equalizer Mean-Square Error Register for VSB */
> -		noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | 
buf[2];
> -#else
> -		/* Phase Tracker Mean-Square Error Register for VSB */
> -		noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
> -#endif
> -	} else {
> -
> -		/* Carrier Recovery Mean-Square Error for QAM */
> -		i2c_read_demod_bytes(state, 0x1a, buf, 2);
> -		noise = (buf[0] << 8) | buf[1];
> -	}
> -
> -	/* Small values for noise mean signal is better so 
invert noise */
> -	*snr = ~noise;
> -
> -	dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, 
noise, *snr);
> -
> -	return 0;
> -}
> -
>  static int lgdt330x_get_tune_settings(struct 
dvb_frontend* fe, struct dvb_frontend_tune_settings* 
fe_tune_settings)
>  {
>  	/* I have no idea about this - it may not be needed */
> @@ -773,7 +779,7 @@
>  	.read_status          = lgdt3302_read_status,
>  	.read_ber             = lgdt330x_read_ber,
>  	.read_signal_strength = lgdt330x_read_signal_strength,
> -	.read_snr             = lgdt3302_read_snr,
> +	.read_snr             = lgdt330x_read_snr,
>  	.read_ucblocks        = lgdt330x_read_ucblocks,
>  	.release              = lgdt330x_release,
>  };
> @@ -797,7 +803,7 @@
>  	.read_status          = lgdt3303_read_status,
>  	.read_ber             = lgdt330x_read_ber,
>  	.read_signal_strength = lgdt330x_read_signal_strength,
> -	.read_snr             = lgdt3303_read_snr,
> +	.read_snr             = lgdt330x_read_snr,
>  	.read_ucblocks        = lgdt330x_read_ucblocks,
>  	.release              = lgdt330x_release,
>  };
> Index: linux/drivers/media/dvb/frontends/lgdt330x_priv.h
> 
===================================================================
> RCS 
file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/frontends/lgdt330x_priv.h,v
> retrieving revision 1.2
> diff -u -r1.2 lgdt330x_priv.h
> --- linux/drivers/media/dvb/frontends/lgdt330x_priv.h	26 
Jul 2005 06:02:19 -0000	1.2
> +++ linux/drivers/media/dvb/frontends/lgdt330x_priv.h	25 
Sep 2005 16:52:09 -0000
> @@ -46,19 +46,27 @@
>  	AGC_FUNC_CTRL1= 0x32,
>  	AGC_FUNC_CTRL2= 0x33,
>  	AGC_FUNC_CTRL3= 0x34,
> -	AGC_RFIF_ACC0= 0x39,
> -	AGC_RFIF_ACC1= 0x3a,
> -	AGC_RFIF_ACC2= 0x3b,
> +	LGDT3302_AGC_RFIF_ACC0= 0x39,
> +	LGDT3302_AGC_RFIF_ACC1= 0x3a,
> +	LGDT3302_AGC_RFIF_ACC2= 0x3b,
>  	AGC_STATUS= 0x3f,
>  	SYNC_STATUS_VSB= 0x43,
> -	EQPH_ERR0= 0x47,
> -	EQ_ERR1= 0x48,
> -	EQ_ERR2= 0x49,
> -	PH_ERR1= 0x4a,
> -	PH_ERR2= 0x4b,
> +	LGDT3302_EQPH_ERR0= 0x47,
> +	LGDT3302_EQ_ERR1= 0x48,
> +	LGDT3302_EQ_ERR2= 0x49,
> +	LGDT3302_PH_ERR1= 0x4a,
> +	LGDT3302_PH_ERR2= 0x4b,
> +	LGDT3303_AGC_RFIF_ACC0= 0x52,
> +	LGDT3303_AGC_RFIF_ACC1= 0x53,
> +	LGDT3303_AGC_RFIF_ACC2= 0x54,
>  	DEMUX_CONTROL= 0x66,
>  	LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
>  	LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
> +	LGDT3303_EQPH_ERR0= 0x6e,
> +	LGDT3303_EQ_ERR1= 0x6f,
> +	LGDT3303_EQ_ERR2= 0x70,
> +	LGDT3303_PH_ERR1= 0x71,
> +	LGDT3303_PH_ERR2= 0x72,
>  	LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
>  	LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
>  };
> 

On Monday 26 September 2005 03:23 pm, Taylor Jacob wrote:
> I have been very busy with work today, and would have
> posted this earlier.. Sorry.
>
> Here is the "cleaned up" patch for adding support for the
> Air2PC/Airstar2 HD5000 (LGDT3303 Frontend).
>
> http://www.digitalregime.com/patches/hd5000-cleanup.patch
>
> Changes to note from the last one I submitted are:
>
> - I have tried to impliment the SNR for the LGDT3303
> since it appears to be the same formula for the 3302 and
> 3303..
>
> - I have also tried to impliment the signal level based
> on information I was provided by BBTI.. I am not sure if
> this is correct for the 3302, and it is a unitless
> measure since I have no idea how it was calcualted..  I
> would need to spend some time digging it spec sheets for
> both and see if I can come up with something, but I only
> have the 3303 right now..
>
> - The serial_mpeg value needed to be set to 0x04 for the
> demux to return data.. I am not sure as to why but the
> suggested value of 0x40 didn't return any data from teh
> demux. (Could this have something to do with the wiring
> of the frontend to the demux?)
>
> - The frontend reset delay added to flexcop.c was reduced
> from 100 or 200ms to a reasonable 1ms which gives
> adequate time for the 3303 to reset..
>
> Also to note:
>
> I have also put together a few liner patch to make the
> older version of the DVICO FusionHDTV Gold3 work.. I have
> one that has a LGDT3302 and has a card id of 18ac:d800
> instead of 18ac:d820
> (CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T), but appears to be
> the same.. I will validate this and post this
> seperately..
>
> Taylor
>
>
>
>
> _______________________________________________
> linux-dvb mailing list
> linux-dvb at linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb



More information about the linux-dvb mailing list