PATCH 10/44 multiproto + backward compatibility [CX24110]

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

 




--- v4l-dvb/linux/drivers/media/dvb/frontends/cx24110.c	2006-06-30 19:59:10.000000000 +0400
+++ mp-bc1/linux/drivers/media/dvb/frontends/cx24110.c	2006-07-23 11:37:31.000000000 +0400
@@ -178,7 +178,7 @@ static int cx24110_set_inversion (struct
 	return 0;
 }
 
-static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
+static int cx24110_set_fec_compat(struct cx24110_state* state, fe_code_rate_t fec)
 {
 /* fixme (low): error handling */
 
@@ -223,12 +223,84 @@ static int cx24110_set_fec (struct cx241
 	return 0;
 }
 
-static fe_code_rate_t cx24110_get_fec (struct cx24110_state* state)
+static int cx24110_set_fec(struct cx24110_state* state, enum dvbfe_fec fec)
+{
+	switch (fec) {
+	case DVBFE_FEC_AUTO:
+		cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) & 0xdf);
+		/* clear AcqVitDis bit */
+		cx24110_writereg(state, 0x18, 0xae);
+		/* allow all DVB standard code rates */
+		cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 0x3);
+		/* set nominal Viterbi rate 3/4 */
+		cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 0x3);
+		/* set current Viterbi rate 3/4 */
+		cx24110_writereg(state, 0x1a, 0x05); cx24110_writereg(state, 0x1b, 0x06);
+		/* set the puncture registers for code rate 3/4 */
+		break;
+	case DVBFE_FEC_1_2:
+		cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20);
+		cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 1);
+		/* set nominal Viterbi rate */
+		cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 1);
+		/* set current Viterbi rate */
+		cx24110_writereg(state, 0x1a, 0x01);
+		cx24110_writereg(state, 0x1b, 0x01);
+		/* not sure if this is the right way: I always used AutoAcq mode */
+		break;
+	case DVBFE_FEC_2_3:
+		cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20);
+		cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 2);
+		/* set nominal Viterbi rate */
+		cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 2);
+		/* set current Viterbi rate */
+		cx24110_writereg(state, 0x1a, 0x02);
+		cx24110_writereg(state, 0x1b, 0x03);
+		/* not sure if this is the right way: I always used AutoAcq mode */
+		break;
+	case DVBFE_FEC_3_4:
+		cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20);
+		cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 3);
+		/* set nominal Viterbi rate */
+		cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 3);
+		/* set current Viterbi rate */
+		cx24110_writereg(state, 0x1a, 0x05);
+		cx24110_writereg(state, 0x1b, 0x06);
+		/* not sure if this is the right way: I always used AutoAcq mode */
+		break;
+	case DVBFE_FEC_5_6:
+		cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20);
+		cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 5);
+		/* set nominal Viterbi rate */
+		cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 5);
+		/* set current Viterbi rate */
+		cx24110_writereg(state, 0x1a, 0x15);
+		cx24110_writereg(state, 0x1b, 0x1a);
+		/* not sure if this is the right way: I always used AutoAcq mode */
+		break;
+	case DVBFE_FEC_7_8:
+		cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20);
+		cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 7);
+		/* set nominal Viterbi rate */
+		cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 7);
+		/* set current Viterbi rate */
+		cx24110_writereg(state, 0x1a, 0x45);
+		cx24110_writereg(state, 0x1b, 0x7a);
+		/* not sure if this is the right way: I always used AutoAcq mode */
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static fe_code_rate_t cx24110_get_fec_compat(struct cx24110_state* state)
 {
 	int i;
 
-	i=cx24110_readreg(state,0x22)&0x0f;
-	if(!(i&0x08)) {
+	i = cx24110_readreg(state, 0x22) & 0x0f;
+	if (!(i & 0x08)) {
 		return FEC_1_2 + i - 1;
 	} else {
 /* fixme (low): a special code rate has been selected. In theory, we need to
@@ -239,6 +311,33 @@ static fe_code_rate_t cx24110_get_fec (s
 	}
 }
 
+static enum dvbfe_fec cx24110_get_fec(struct cx24110_state* state)
+{
+	int i;
+
+	i = cx24110_readreg(state, 0x22) & 0x0f;
+	switch (i) {
+	case 0:
+		return DVBFE_FEC_NONE;
+	case 1:
+		return DVBFE_FEC_1_2;
+	case 2:
+		return DVBFE_FEC_2_3;
+	case 3:
+		return DVBFE_FEC_3_4;
+	case 4:
+		return DVBFE_FEC_4_5;
+	case 5:
+		return DVBFE_FEC_5_6;
+	case 6:
+		return DVBFE_FEC_6_7;
+	case 7:
+		return DVBFE_FEC_7_8;
+	default:
+		return DVBFE_FEC_NONE;
+	}
+}
+
 static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
 {
 /* fixme (low): add error handling */
@@ -536,13 +635,14 @@ static int cx24110_set_frontend(struct d
 	struct cx24110_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.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);
 	}
 
 	cx24110_set_inversion (state, p->inversion);
-	cx24110_set_fec (state, p->u.qpsk.fec_inner);
+	cx24110_set_fec_compat(state, p->u.qpsk.fec_inner);
 	cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
 	cx24110_writereg(state,0x04,0x05); /* start aquisition */
 
@@ -571,7 +671,7 @@ static int cx24110_get_frontend(struct d
 	p->frequency += afc;
 	p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ?
 				INVERSION_ON : INVERSION_OFF;
-	p->u.qpsk.fec_inner = cx24110_get_fec (state);
+	p->u.qpsk.fec_inner = cx24110_get_fec_compat(state);
 
 	return 0;
 }
@@ -622,6 +722,95 @@ error:
 	return NULL;
 }
 
+static struct dvbfe_info dvbs_info	= {
+	.name				= "Conexant CX24110 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			= 2150000,
+	.frequency_step			= 1011,
+	.frequency_tolerance		= 29500,
+	.symbol_rate_min		= 1000000,
+	.symbol_rate_max		= 45000000
+};
+
+static int cx24110_set_params(struct dvb_frontend* fe,
+			      struct dvbfe_params *p)
+{
+	struct cx24110_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);
+	}
+
+	cx24110_set_inversion(state, p->inversion);
+	cx24110_set_fec(state, p->delsys.dvbs.fec);
+	cx24110_set_symbolrate(state, p->delsys.dvbs.symbol_rate);
+	cx24110_writereg(state,0x04,0x05); /* start aquisition */
+
+	return 0;
+}
+
+static int cx24110_get_params(struct dvb_frontend* fe,
+			      struct dvbfe_params *p)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+
+	s32 afc;
+	unsigned sclk;
+
+/* cannot read back tuner settings (freq). Need to have some private storage */
+
+	sclk = cx24110_readreg(state, 0x07) & 0x03;
+/* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz.
+ * Need 64 bit arithmetic. Is thiss possible in the kernel? */
+	if (sclk == 0)
+		sclk = 90999000L / 2L;
+	else if	(sclk == 1)
+		sclk = 60666000L;
+	else if (sclk == 2)
+		sclk = 80888000L;
+	else
+		sclk = 90999000L;
+
+	sclk >>= 8;
+	afc = sclk * (cx24110_readreg(state, 0x44) & 0x1f) +
+	      ((sclk * cx24110_readreg(state, 0x45)) >> 8) +
+	      ((sclk * cx24110_readreg(state, 0x46)) >> 16);
+
+	p->frequency += afc;
+	p->inversion = (cx24110_readreg(state, 0x22) & 0x10) ?
+				INVERSION_ON : INVERSION_OFF;
+
+	p->delsys.dvbs.fec = cx24110_get_fec(state);
+
+	return 0;
+}
+
+static int cx24110_get_info(struct dvb_frontend *fe,
+			    struct dvbfe_info *fe_info)
+{
+	memcpy(fe_info, &dvbs_info, sizeof (dvbs_info));
+
+	return 0;
+}
+
+static int cx24110_get_delsys(struct dvb_frontend *fe,
+			      enum dvbfe_delsys *fe_delsys)
+{
+	*fe_delsys = DVBFE_DELSYS_DVBS;
+
+	return 0;
+}
+
 static struct dvb_frontend_ops cx24110_ops = {
 
 	.info = {
@@ -654,6 +843,11 @@ static struct dvb_frontend_ops cx24110_o
 	.set_tone = cx24110_set_tone,
 	.set_voltage = cx24110_set_voltage,
 	.diseqc_send_burst = cx24110_diseqc_send_burst,
+
+	.set_params	= cx24110_set_params,
+	.get_params	= cx24110_get_params,
+	.get_info	= cx24110_get_info,
+	.get_delsys	= cx24110_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