PATCH 32/44 multiproto + backward compatibility [STV097]

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

 



--- v4l-dvb/linux/drivers/media/dvb/frontends/stv0297.c	2006-06-30 19:59:10.000000000 +0400
+++ mp-bc1/linux/drivers/media/dvb/frontends/stv0297.c	2006-07-23 11:40:31.000000000 +0400
@@ -232,7 +232,7 @@ static void stv0297_set_initialdemodfreq
 	stv0297_writereg(state, 0x20, tmp);
 }
 
-static int stv0297_set_qam(struct stv0297_state *state, fe_modulation_t modulation)
+static int stv0297_set_qam_compat(struct stv0297_state *state, fe_modulation_t modulation)
 {
 	int val = 0;
 
@@ -266,6 +266,35 @@ static int stv0297_set_qam(struct stv029
 	return 0;
 }
 
+static int stv0297_set_qam(struct stv0297_state *state, enum dvbfe_modulation modulation)
+{
+	int val = 0;
+
+	switch (modulation) {
+	case DVBFE_MOD_QAM16:
+		val = 0;
+		break;
+	case DVBFE_MOD_QAM32:
+		val = 1;
+		break;
+	case DVBFE_MOD_QAM64:
+		val = 4;
+		break;
+	case DVBFE_MOD_QAM128:
+		val = 2;
+		break;
+	case DVBFE_MOD_QAM256:
+		val = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	stv0297_writereg_mask(state, 0x00, 0x70, val << 4);
+
+	return 0;
+}
+
 static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_inversion_t inversion)
 {
 	int val = 0;
@@ -432,9 +461,10 @@ static int stv0297_set_frontend(struct d
 	}
 
 	stv0297_init(fe);
-	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.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);
 	}
 
 	/* clear software interrupts */
@@ -497,7 +527,7 @@ static int stv0297_set_frontend(struct d
 	stv0297_writereg_mask(state, 0x69, 0x0f, 0x00);
 
 	/* set parameters */
-	stv0297_set_qam(state, p->u.qam.modulation);
+	stv0297_set_qam_compat(state, p->u.qam.modulation);
 	stv0297_set_symbolrate(state, p->u.qam.symbol_rate / 1000);
 	stv0297_set_sweeprate(state, sweeprate, p->u.qam.symbol_rate / 1000);
 	stv0297_set_carrieroffset(state, carrieroffset);
@@ -664,8 +694,284 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops stv0297_ops = {
+static struct dvbfe_info dvbc_info	= {
+	.name				= "STV0297 DVB-C",
+	.delivery			= DVBFE_DELSYS_DVBC,
+	.delsys				= {
+		.dvbc.modulation	= DVBFE_MOD_QAM16  | DVBFE_MOD_QAM32  |
+					  DVBFE_MOD_QAM64  | DVBFE_MOD_QAM128 |
+					  DVBFE_MOD_QAM256,
+	},
+
+	.frequency_min			= 64000000,
+	.frequency_max			= 1300000000,
+	.frequency_step			= 62500,
+	.symbol_rate_min		= 870000,
+	.symbol_rate_max		= 11700000,
+};
+
+static int stv0297_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info)
+{
+	memcpy(fe_info, &dvbc_info, sizeof (dvbc_info));
+
+	return 0;
+}
+
+static int stv0297_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys)
+{
+	*fe_delsys = DVBFE_DELSYS_DVBC;
+
+	return 0;
+}
+
+static int stv0297_set_params(struct dvb_frontend *fe, struct dvbfe_params *p)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+	int u_threshold;
+	int initial_u;
+	int blind_u;
+	int delay;
+	int sweeprate;
+	int carrieroffset;
+	unsigned long starttime;
+	unsigned long timeout;
+
+	enum fe_spectral_inversion inversion;
+
+	switch (p->delsys.dvbc.modulation) {
+	case DVBFE_MOD_QAM16:
+	case DVBFE_MOD_QAM32:
+	case DVBFE_MOD_QAM64:
+		delay = 100;
+		sweeprate = 1000;
+		break;
+
+	case DVBFE_MOD_QAM128:
+	case DVBFE_MOD_QAM256:
+		delay = 200;
+		sweeprate = 500;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// determine inversion dependant parameters
+	inversion = p->inversion;
+	if (state->config->invert)
+		inversion = (inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
+	carrieroffset = -330;
+	switch (inversion) {
+	case INVERSION_OFF:
+		break;
+
+	case INVERSION_ON:
+		sweeprate = -sweeprate;
+		carrieroffset = -carrieroffset;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	stv0297_init(fe);
+	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);
+	}
+
+	/* clear software interrupts */
+	stv0297_writereg(state, 0x82, 0x0);
+
+	/* set initial demodulation frequency */
+	stv0297_set_initialdemodfreq(state, 7250);
+
+	/* setup AGC */
+	stv0297_writereg_mask(state, 0x43, 0x10, 0x00);
+	stv0297_writereg(state, 0x41, 0x00);
+	stv0297_writereg_mask(state, 0x42, 0x03, 0x01);
+	stv0297_writereg_mask(state, 0x36, 0x60, 0x00);
+	stv0297_writereg_mask(state, 0x36, 0x18, 0x00);
+	stv0297_writereg_mask(state, 0x71, 0x80, 0x80);
+	stv0297_writereg(state, 0x72, 0x00);
+	stv0297_writereg(state, 0x73, 0x00);
+	stv0297_writereg_mask(state, 0x74, 0x0F, 0x00);
+	stv0297_writereg_mask(state, 0x43, 0x08, 0x00);
+	stv0297_writereg_mask(state, 0x71, 0x80, 0x00);
 
+	/* setup STL */
+	stv0297_writereg_mask(state, 0x5a, 0x20, 0x20);
+	stv0297_writereg_mask(state, 0x5b, 0x02, 0x02);
+	stv0297_writereg_mask(state, 0x5b, 0x02, 0x00);
+	stv0297_writereg_mask(state, 0x5b, 0x01, 0x00);
+	stv0297_writereg_mask(state, 0x5a, 0x40, 0x40);
+
+	/* disable frequency sweep */
+	stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
+
+	/* reset deinterleaver */
+	stv0297_writereg_mask(state, 0x81, 0x01, 0x01);
+	stv0297_writereg_mask(state, 0x81, 0x01, 0x00);
+
+	/* ??? */
+	stv0297_writereg_mask(state, 0x83, 0x20, 0x20);
+	stv0297_writereg_mask(state, 0x83, 0x20, 0x00);
+
+	/* reset equaliser */
+	u_threshold = stv0297_readreg(state, 0x00) & 0xf;
+	initial_u = stv0297_readreg(state, 0x01) >> 4;
+	blind_u = stv0297_readreg(state, 0x01) & 0xf;
+	stv0297_writereg_mask(state, 0x84, 0x01, 0x01);
+	stv0297_writereg_mask(state, 0x84, 0x01, 0x00);
+	stv0297_writereg_mask(state, 0x00, 0x0f, u_threshold);
+	stv0297_writereg_mask(state, 0x01, 0xf0, initial_u << 4);
+	stv0297_writereg_mask(state, 0x01, 0x0f, blind_u);
+
+	/* data comes from internal A/D */
+	stv0297_writereg_mask(state, 0x87, 0x80, 0x00);
+
+	/* clear phase registers */
+	stv0297_writereg(state, 0x63, 0x00);
+	stv0297_writereg(state, 0x64, 0x00);
+	stv0297_writereg(state, 0x65, 0x00);
+	stv0297_writereg(state, 0x66, 0x00);
+	stv0297_writereg(state, 0x67, 0x00);
+	stv0297_writereg(state, 0x68, 0x00);
+	stv0297_writereg_mask(state, 0x69, 0x0f, 0x00);
+
+	/* set parameters */
+	stv0297_set_qam(state, p->delsys.dvbc.modulation);
+	stv0297_set_symbolrate(state, p->delsys.dvbc.symbol_rate / 1000);
+	stv0297_set_sweeprate(state, sweeprate, p->delsys.dvbc.symbol_rate / 1000);
+	stv0297_set_carrieroffset(state, carrieroffset);
+	stv0297_set_inversion(state, inversion);
+
+	/* kick off lock */
+	/* Disable corner detection for higher QAMs */
+	if (p->delsys.dvbc.modulation == DVBFE_MOD_QAM128 ||
+	    p->delsys.dvbc.modulation == DVBFE_MOD_QAM256)
+		stv0297_writereg_mask(state, 0x88, 0x08, 0x00);
+	else
+		stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
+
+	stv0297_writereg_mask(state, 0x5a, 0x20, 0x00);
+	stv0297_writereg_mask(state, 0x6a, 0x01, 0x01);
+	stv0297_writereg_mask(state, 0x43, 0x40, 0x40);
+	stv0297_writereg_mask(state, 0x5b, 0x30, 0x00);
+	stv0297_writereg_mask(state, 0x03, 0x0c, 0x0c);
+	stv0297_writereg_mask(state, 0x03, 0x03, 0x03);
+	stv0297_writereg_mask(state, 0x43, 0x10, 0x10);
+
+	/* wait for WGAGC lock */
+	starttime = jiffies;
+	timeout = jiffies + msecs_to_jiffies(2000);
+	while (time_before(jiffies, timeout)) {
+		msleep(10);
+		if (stv0297_readreg(state, 0x43) & 0x08)
+			break;
+	}
+	if (time_after(jiffies, timeout)) {
+		goto timeout;
+	}
+	msleep(20);
+
+	/* wait for equaliser partial convergence */
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (time_before(jiffies, timeout)) {
+		msleep(10);
+
+		if (stv0297_readreg(state, 0x82) & 0x04) {
+			break;
+		}
+	}
+	if (time_after(jiffies, timeout)) {
+		goto timeout;
+	}
+
+	/* wait for equaliser full convergence */
+	timeout = jiffies + msecs_to_jiffies(delay);
+	while (time_before(jiffies, timeout)) {
+		msleep(10);
+
+		if (stv0297_readreg(state, 0x82) & 0x08) {
+			break;
+		}
+	}
+	if (time_after(jiffies, timeout)) {
+		goto timeout;
+	}
+
+	/* disable sweep */
+	stv0297_writereg_mask(state, 0x6a, 1, 0);
+	stv0297_writereg_mask(state, 0x88, 8, 0);
+
+	/* wait for main lock */
+	timeout = jiffies + msecs_to_jiffies(20);
+	while (time_before(jiffies, timeout)) {
+		msleep(10);
+
+		if (stv0297_readreg(state, 0xDF) & 0x80) {
+			break;
+		}
+	}
+	if (time_after(jiffies, timeout)) {
+		goto timeout;
+	}
+	msleep(100);
+
+	/* is it still locked after that delay? */
+	if (!(stv0297_readreg(state, 0xDF) & 0x80)) {
+		goto timeout;
+	}
+
+	/* success!! */
+	stv0297_writereg_mask(state, 0x5a, 0x40, 0x00);
+	state->base_freq = p->frequency;
+	return 0;
+
+timeout:
+	stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
+	return 0;
+}
+
+static int stv0297_get_params(struct dvb_frontend *fe, struct dvbfe_params *p)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+	int reg_00, reg_83;
+
+	reg_00 = stv0297_readreg(state, 0x00);
+	reg_83 = stv0297_readreg(state, 0x83);
+
+	p->frequency = state->base_freq;
+	p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF;
+	if (state->config->invert)
+		p->inversion = (p->inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
+	p->delsys.dvbc.symbol_rate = stv0297_get_symbolrate(state) * 1000;
+
+	switch ((reg_00 >> 4) & 0x7) {
+	case 0:
+		p->delsys.dvbc.modulation = DVBFE_MOD_QAM16;
+		break;
+	case 1:
+		p->delsys.dvbc.modulation = DVBFE_MOD_QAM32;
+		break;
+	case 2:
+		p->delsys.dvbc.modulation = DVBFE_MOD_QAM128;
+		break;
+	case 3:
+		p->delsys.dvbc.modulation = DVBFE_MOD_QAM256;
+		break;
+	case 4:
+		p->delsys.dvbc.modulation = DVBFE_MOD_QAM64;
+		break;
+	}
+
+	return 0;
+}
+
+static struct dvb_frontend_ops stv0297_ops = {
+	/*	Info is deprecated	*/
 	.info = {
 		 .name = "ST STV0297 DVB-C",
 		 .type = FE_QAM,
@@ -691,6 +997,11 @@ static struct dvb_frontend_ops stv0297_o
 	.read_signal_strength = stv0297_read_signal_strength,
 	.read_snr = stv0297_read_snr,
 	.read_ucblocks = stv0297_read_ucblocks,
+
+	.set_params	= stv0297_set_params,
+	.get_params	= stv0297_get_params,
+	.get_info	= stv0297_get_info,
+	.get_delsys	= stv0297_get_delsys,
 };
 
 MODULE_DESCRIPTION("ST STV0297 DVB-C Demodulator driver");
_______________________________________________

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