PATCH 37/44 multiproto + backward compatibility [TDA80xx]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



--- v4l-dvb/linux/drivers/media/dvb/frontends/tda80xx.c	2006-06-30 19:59:10.000000000 +0400
+++ mp-bc1/linux/drivers/media/dvb/frontends/tda80xx.c	2006-07-23 11:41:07.000000000 +0400
@@ -157,10 +157,10 @@ static __inline__ int tda80xx_writereg(s
 	return tda80xx_write(state, reg, &data, 1);
 }
 
-static int tda80xx_set_parameters(struct tda80xx_state* state,
-				  fe_spectral_inversion_t inversion,
-				  u32 symbol_rate,
-				  fe_code_rate_t fec_inner)
+static int tda80xx_set_parameters_compat(struct tda80xx_state* state,
+					 fe_spectral_inversion_t inversion,
+					 u32 symbol_rate,
+					 fe_code_rate_t fec_inner)
 {
 	u8 buf[15];
 	u64 ratio;
@@ -287,6 +287,166 @@ static int tda80xx_set_parameters(struct
 	return tda80xx_write(state, 0x01, buf, sizeof(buf));
 }
 
+static int tda80xx_set_parameters(struct tda80xx_state* state,
+				  fe_spectral_inversion_t inversion,
+				  u32 symbol_rate,
+				  enum dvbfe_fec fec)
+{
+	u8 buf[15];
+	u64 ratio;
+	u32 clk;
+	u32 k;
+	u32 sr = symbol_rate;
+	u32 gcd;
+	u8 scd;
+
+	if (symbol_rate > (state->clk * 3) / 16)
+		scd = 0;
+	else if (symbol_rate > (state->clk * 3) / 32)
+		scd = 1;
+	else if (symbol_rate > (state->clk * 3) / 64)
+		scd = 2;
+	else
+		scd = 3;
+
+	clk = scd ? (state->clk / (scd * 2)) : state->clk;
+
+	/*
+	 * Viterbi decoder:
+	 * Differential decoding off
+	 * Spectral inversion unknown
+	 * QPSK modulation
+	 */
+	if (inversion == INVERSION_ON)
+		buf[0] = 0x60;
+	else if (inversion == INVERSION_OFF)
+		buf[0] = 0x20;
+	else
+		buf[0] = 0x00;
+
+	/*
+	 * CLK ratio:
+	 * system clock frequency is up to 64 or 96 MHz
+	 *
+	 * formula:
+	 * r = k * clk / symbol_rate
+	 *
+	 * k:	2^21 for caa 0..3,
+	 *	2^20 for caa 4..5,
+	 *	2^19 for caa 6..7
+	 */
+	if (symbol_rate <= (clk * 3) / 32)
+		k = (1 << 19);
+	else if (symbol_rate <= (clk * 3) / 16)
+		k = (1 << 20);
+	else
+		k = (1 << 21);
+
+	gcd = tda80xx_gcd(clk, sr);
+	clk /= gcd;
+	sr /= gcd;
+
+	gcd = tda80xx_gcd(k, sr);
+	k /= gcd;
+	sr /= gcd;
+
+	ratio = (u64)k * (u64)clk;
+	do_div(ratio, sr);
+
+	buf[1] = ratio >> 16;
+	buf[2] = ratio >> 8;
+	buf[3] = ratio;
+
+	/* nyquist filter roll-off factor 35% */
+	buf[4] = 0x20;
+
+	clk = scd ? (state->clk / (scd * 2)) : state->clk;
+
+	/* Anti Alias Filter */
+	if (symbol_rate < (clk * 3) / 64)
+		printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate);
+	else if (symbol_rate <= clk / 16)
+		buf[4] |= 0x07;
+	else if (symbol_rate <= (clk * 3) / 32)
+		buf[4] |= 0x06;
+	else if (symbol_rate <= clk / 8)
+		buf[4] |= 0x05;
+	else if (symbol_rate <= (clk * 3) / 16)
+		buf[4] |= 0x04;
+	else if (symbol_rate <= clk / 4)
+		buf[4] |= 0x03;
+	else if (symbol_rate <= (clk * 3) / 8)
+		buf[4] |= 0x02;
+	else if (symbol_rate <= clk / 2)
+		buf[4] |= 0x01;
+	else
+		buf[4] |= 0x00;
+
+	/* Sigma Delta converter */
+	buf[5] = 0x00;
+
+	/* FEC: Possible puncturing rates */
+	if (fec == DVBFE_FEC_NONE)
+		buf[6] = 0x00;
+	else if ((fec >= DVBFE_FEC_1_2) && (fec_inner <= FEC_8_9))
+		buf[6] = (1 << (8 - fec_inner));
+	else if (fec_inner == FEC_AUTO)
+		buf[6] = 0xff;
+	else
+		return -EINVAL;
+
+	switch (fec) {
+	case DVBFE_FEC_NONE:
+		buf[6] = 0x00;
+		break;
+	case DVBFE_FEC_1_2:
+		buf[6] = 1 << 7;
+		break;
+	case DVBFE_FEC_2_3:
+		buf[6] = 1 << 6;
+		break;
+	case DVBFE_FEC_3_4:
+		buf[6] = 1 << 5;
+		break;
+	case DVBFE_FEC_4_5:
+		buf[6] = 1 << 4;
+		break;
+	case DVBFE_FEC_5_6:
+		buf[6] = 1 << 3;
+		break;
+	case DVBFE_FEC_6_7:
+		buf[6] = 1 << 2;
+		break;
+	case DVBFE_FEC_7_8:
+		buf[6] = 1 << 1;
+		break;
+	case DVBFE_FEC_8_9:
+		buf[6] = 1 << 0;
+		break;
+	}
+
+	/* carrier lock detector threshold value */
+	buf[7] = 0x30;
+	/* AFC1: proportional part settings */
+	buf[8] = 0x42;
+	/* AFC1: integral part settings */
+	buf[9] = 0x98;
+	/* PD: Leaky integrator SCPC mode */
+	buf[10] = 0x28;
+	/* AFC2, AFC1 controls */
+	buf[11] = 0x30;
+	/* PD: proportional part settings */
+	buf[12] = 0x42;
+	/* PD: integral part settings */
+	buf[13] = 0x99;
+	/* AGC */
+	buf[14] = 0x50 | scd;
+
+	printk("symbol_rate=%u clk=%u\n", symbol_rate, clk);
+
+	return tda80xx_write(state, 0x01, buf, sizeof (buf));
+}
+
 static int tda80xx_set_clk(struct tda80xx_state* state)
 {
 	u8 buf[2];
@@ -521,12 +681,32 @@ static int tda80xx_set_frontend(struct d
 {
 	struct tda80xx_state* state = fe->demodulator_priv;
 
+	if (fe->ops.tuner_ops.set_params_compat) {
+		fe->ops.tuner_ops.set_params_compat(fe, p);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	tda80xx_set_parameters_compat(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner);
+	tda80xx_set_clk(state);
+	//tda80xx_set_scpc_freq_offset(state);
+	state->afc_loop = 1;
+
+	return 0;
+}
+
+static int tda80xx_set_params(struct dvb_frontend* fe,
+			      struct dvbfe_params *p)
+{
+	struct tda80xx_state* state = fe->demodulator_priv;
+
 	if (fe->ops.tuner_ops.set_params) {
 		fe->ops.tuner_ops.set_params(fe, p);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
 	}
 
-	tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner);
+	tda80xx_set_parameters(state, p->inversion, p->delsys.dvbs.symbol_rate, p->delsys.dvbs.fec);
 	tda80xx_set_clk(state);
 	//tda80xx_set_scpc_freq_offset(state);
 	state->afc_loop = 1;
@@ -696,6 +876,37 @@ error:
 	return NULL;
 }
 
+static struct dvbfe_info dvbs_info	= {
+	.name				= "Philips TDA80xx DVB-S",
+	.delivery			= DVBFE_DELSYS_DVBS,
+	.delsys				= {
+		.dvbs.modulation	= DVBFE_MOD_QPSK,
+		.dvbs.fec		= DVBFE_FEC_1_2 | DVBFE_FEC_2_3 |
+					  DVBFE_FEC_3_4 | DVBFE_FEC_5_6 |
+					  DVBFE_FEC_7_8 | DVBFE_FEC_AUTO
+	},
+
+	.frequency_min			= 950000,
+	.frequency_max			= 2700000,
+	.frequency_step			= 125,
+	.symbol_rate_min		= 4500000,
+	.symbol_rate_max		= 45000000,
+};
+
+static int tda80xx_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info)
+{
+	memcpy(fe_info, &dvbs_info, sizeof (dvbs_info));
+
+	return 0;
+}
+
+static int tda80xx_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys)
+{
+	*fe_delsys = DVBFE_DELSYS_DVBS;
+
+	return 0;
+}
+
 static struct dvb_frontend_ops tda80xx_ops = {
 
 	.info = {
@@ -733,6 +944,11 @@ static struct dvb_frontend_ops tda80xx_o
 	.diseqc_send_burst = tda80xx_send_diseqc_burst,
 	.set_tone = tda80xx_set_tone,
 	.set_voltage = tda80xx_set_voltage,
+
+	.set_params	= tda80xx_set_params,
+	.get_params	= tda80xx_get_params,
+	.get_info	= tda80xx_get_info,
+	.get_delsys	= tda80xx_get_delsys,
 };
 
 module_param(debug, int, 0644);
_______________________________________________

linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux