PATCH 11/44 multiproto + backward compatibility [CX24123]

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

 




--- v4l-dvb/linux/drivers/media/dvb/frontends/cx24123.c	2006-06-30 19:59:10.000000000 +0400
+++ mp-bc1/linux/drivers/media/dvb/frontends/cx24123.c	2006-07-23 11:37:39.000000000 +0400
@@ -325,7 +325,62 @@ static int cx24123_get_inversion(struct 
 	return 0;
 }
 
-static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+static int cx24123_set_fec(struct cx24123_state* state, enum dvbfe_fec fec)
+{
+	u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
+
+	if ( (fec < DVBFE_FEC_NONE) || (fec > DVBFE_FEC_AUTO) )
+		fec = DVBFE_FEC_AUTO;
+
+	switch (fec) {
+	case DVBFE_FEC_1_2:
+		dprintk("%s:  set FEC to 1/2\n",__FUNCTION__);
+		cx24123_writereg(state, 0x0e, nom_reg | 0x01);
+		cx24123_writereg(state, 0x0f, 0x02);
+		break;
+	case DVBFE_FEC_2_3:
+		dprintk("%s:  set FEC to 2/3\n",__FUNCTION__);
+		cx24123_writereg(state, 0x0e, nom_reg | 0x02);
+		cx24123_writereg(state, 0x0f, 0x04);
+		break;
+	case DVBFE_FEC_3_4:
+		dprintk("%s:  set FEC to 3/4\n",__FUNCTION__);
+		cx24123_writereg(state, 0x0e, nom_reg | 0x03);
+		cx24123_writereg(state, 0x0f, 0x08);
+		break;
+	case DVBFE_FEC_4_5:
+		dprintk("%s:  set FEC to 4/5\n",__FUNCTION__);
+		cx24123_writereg(state, 0x0e, nom_reg | 0x04);
+		cx24123_writereg(state, 0x0f, 0x10);
+		break;
+	case DVBFE_FEC_5_6:
+		dprintk("%s:  set FEC to 5/6\n",__FUNCTION__);
+		cx24123_writereg(state, 0x0e, nom_reg | 0x05);
+		cx24123_writereg(state, 0x0f, 0x20);
+		break;
+	case DVBFE_FEC_6_7:
+		dprintk("%s:  set FEC to 6/7\n",__FUNCTION__);
+		cx24123_writereg(state, 0x0e, nom_reg | 0x06);
+		cx24123_writereg(state, 0x0f, 0x40);
+		break;
+	case DVBFE_FEC_7_8:
+		dprintk("%s:  set FEC to 7/8\n",__FUNCTION__);
+		cx24123_writereg(state, 0x0e, nom_reg | 0x07);
+		cx24123_writereg(state, 0x0f, 0x80);
+		break;
+	case DVBFE_FEC_AUTO:
+		dprintk("%s:  set FEC to auto\n",__FUNCTION__);
+		cx24123_writereg(state, 0x0f, 0xfe);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int cx24123_set_fec_compat(struct cx24123_state* state,
+				  fe_code_rate_t fec)
 {
 	u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
 
@@ -379,7 +434,7 @@ static int cx24123_set_fec(struct cx2412
 	return 0;
 }
 
-static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
+static int cx24123_get_fec_compat(struct cx24123_state* state, fe_code_rate_t *fec)
 {
 	int ret;
 
@@ -418,6 +473,46 @@ static int cx24123_get_fec(struct cx2412
 	return 0;
 }
 
+static int cx24123_get_fec(struct cx24123_state* state,
+				  enum dvbfe_fec *fec)
+{
+	int ret;
+
+	ret = cx24123_readreg (state, 0x1b);
+	if (ret < 0)
+		return ret;
+	ret = ret & 0x07;
+
+	switch (ret) {
+	case 1:
+		*fec = DVBFE_FEC_1_2;
+		break;
+	case 2:
+		*fec = DVBFE_FEC_2_3;
+		break;
+	case 3:
+		*fec = DVBFE_FEC_3_4;
+		break;
+	case 4:
+		*fec = DVBFE_FEC_4_5;
+		break;
+	case 5:
+		*fec = DVBFE_FEC_5_6;
+		break;
+	case 6:
+		*fec = DVBFE_FEC_6_7;
+		break;
+	case 7:
+		*fec = DVBFE_FEC_7_8;
+		break;
+	default:
+		/* this can happen when there's no lock */
+		*fec = DVBFE_FEC_NONE;
+	}
+
+	return 0;
+}
+
 /* Approximation of closest integer of log2(a/b). It actually gives the
    lowest integer i such that 2^i >= round(a/b) */
 static u32 cx24123_int_log2(u32 a, u32 b)
@@ -507,7 +602,8 @@ static int cx24123_set_symbolrate(struct
  * Based on the required frequency and symbolrate, the tuner AGC has to be configured
  * and the correct band selected. Calculate those values
  */
-static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_pll_calculate_compat(struct dvb_frontend* fe,
+					struct dvb_frontend_parameters *p)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	u32 ndiv = 0, adiv = 0, vco_div = 0;
@@ -569,11 +665,76 @@ static int cx24123_pll_calculate(struct 
 	return 0;
 }
 
+static int cx24123_pll_calculate(struct dvb_frontend* fe,
+				 struct dvbfe_params *p)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	u32 ndiv = 0, adiv = 0, vco_div = 0;
+	int i = 0;
+	int pump = 2;
+	int band = 0;
+	int num_bands = sizeof (cx24123_bandselect_vals) /
+			sizeof(cx24123_bandselect_vals[0]);
+
+	/* Defaults for low freq, low rate */
+	state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
+	state->VGAarg = cx24123_AGC_vals[0].VGAprogdata;
+	state->bandselectarg = cx24123_bandselect_vals[0].progdata;
+	vco_div = cx24123_bandselect_vals[0].VCOdivider;
+
+	/* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */
+	for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++)
+	{
+		if ((cx24123_AGC_vals[i].symbolrate_low <= p->delsys.dvbs.symbol_rate) &&
+		    (cx24123_AGC_vals[i].symbolrate_high >= p->delsys.dvbs.symbol_rate) ) {
+			state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
+			state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
+			state->FILTune = cx24123_AGC_vals[i].FILTune;
+		}
+	}
+
+	/* determine the band to use */
+	if(force_band < 1 || force_band > num_bands)
+	{
+		for (i = 0; i < num_bands; i++)
+		{
+			if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
+			    (cx24123_bandselect_vals[i].freq_high >= p->frequency) )
+				band = i;
+		}
+	}
+	else
+		band = force_band - 1;
+
+	state->bandselectarg = cx24123_bandselect_vals[band].progdata;
+	vco_div = cx24123_bandselect_vals[band].VCOdivider;
+
+	/* determine the charge pump current */
+	if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 )
+		pump = 0x01;
+	else
+		pump = 0x02;
+
+	/* Determine the N/A dividers for the requested lband freq (in kHz). */
+	/* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */
+	ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff;
+	adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f;
+
+	if (adiv == 0)
+		ndiv++;
+
+	/* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */
+	state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv;
+
+	return 0;
+}
+
 /*
  * Tuner data is 21 bits long, must be left-aligned in data.
  * Tuner cx24109 is written through a dedicated 3wire interface on the demod chip.
  */
-static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data)
+//static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data)
+static int cx24123_pll_writereg(struct dvb_frontend* fe, u32 data)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	unsigned long timeout;
@@ -626,7 +787,40 @@ static int cx24123_pll_writereg(struct d
 	return 0;
 }
 
-static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24123_pll_tune_compat(struct dvb_frontend* fe,
+				   struct dvb_frontend_parameters *p)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk("frequency=%i\n", p->frequency);
+
+	if (cx24123_pll_calculate_compat(fe, p) != 0) {
+		printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* Write the new VCO/VGA */
+	cx24123_pll_writereg(fe, state->VCAarg);
+	cx24123_pll_writereg(fe, state->VGAarg);
+
+	/* Write the new bandselect and pll args */
+	cx24123_pll_writereg(fe, state->bandselectarg);
+	cx24123_pll_writereg(fe, state->pllarg);
+
+	/* set the FILTUNE voltage */
+	val = cx24123_readreg(state, 0x28) & ~0x3;
+	cx24123_writereg(state, 0x27, state->FILTune >> 2);
+	cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3));
+
+	dprintk("%s:  pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg,
+			state->bandselectarg,state->pllarg);
+
+	return 0;
+}
+
+static int cx24123_pll_tune(struct dvb_frontend* fe,
+			    struct dvbfe_params *p)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	u8 val;
@@ -639,12 +833,12 @@ static int cx24123_pll_tune(struct dvb_f
 	}
 
 	/* Write the new VCO/VGA */
-	cx24123_pll_writereg(fe, p, state->VCAarg);
-	cx24123_pll_writereg(fe, p, state->VGAarg);
+	cx24123_pll_writereg(fe, state->VCAarg);
+	cx24123_pll_writereg(fe, state->VGAarg);
 
 	/* Write the new bandselect and pll args */
-	cx24123_pll_writereg(fe, p, state->bandselectarg);
-	cx24123_pll_writereg(fe, p, state->pllarg);
+	cx24123_pll_writereg(fe, state->bandselectarg);
+	cx24123_pll_writereg(fe, state->pllarg);
 
 	/* set the FILTUNE voltage */
 	val = cx24123_readreg(state, 0x28) & ~0x3;
@@ -876,9 +1070,9 @@ static int cx24123_set_frontend(struct d
 	state->currentsymbolrate = p->u.qpsk.symbol_rate;
 
 	cx24123_set_inversion(state, p->inversion);
-	cx24123_set_fec(state, p->u.qpsk.fec_inner);
+	cx24123_set_fec_compat(state, p->u.qpsk.fec_inner);
 	cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
-	cx24123_pll_tune(fe, p);
+	cx24123_pll_tune_compat(fe, p);
 
 	/* Enable automatic aquisition and reset cycle */
 	cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
@@ -898,7 +1092,7 @@ static int cx24123_get_frontend(struct d
 		printk("%s: Failed to get inversion status\n",__FUNCTION__);
 		return -EREMOTEIO;
 	}
-	if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
+	if (cx24123_get_fec_compat(state, &p->u.qpsk.fec_inner) != 0) {
 		printk("%s: Failed to get fec status\n",__FUNCTION__);
 		return -EREMOTEIO;
 	}
@@ -987,6 +1181,93 @@ error:
 	return NULL;
 }
 
+static struct dvbfe_info dvbs_info	= {
+	.name				= "Conexant CX24123 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_4_5 |
+					  DVBFE_FEC_5_6 | DVBFE_FEC_6_7 |
+					  DVBFE_FEC_7_8 | DVBFE_FEC_AUTO
+	},
+
+	.frequency_min			= 950000,
+	.frequency_max			= 2150000,
+	.frequency_step			= 1011,
+	.frequency_tolerance		= 5000,
+	.symbol_rate_min		= 1000000,
+	.symbol_rate_max		= 45000000
+};
+
+static int cx24123_set_params(struct dvb_frontend* fe,
+			      struct dvbfe_params *p)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+
+	dprintk("%s:  set_frontend\n",__FUNCTION__);
+
+	if (state->config->set_ts_params)
+		state->config->set_ts_params(fe, 0);
+
+	state->currentfreq = p->frequency;
+	state->currentsymbolrate = p->delsys.dvbs.symbol_rate;
+
+	cx24123_set_inversion(state, p->inversion);
+	cx24123_set_fec(state, p->delsys.dvbs.fec);
+	cx24123_set_symbolrate(state, p->delsys.dvbs.symbol_rate);
+	cx24123_pll_tune(fe, p);
+
+	/* Enable automatic aquisition and reset cycle */
+	cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
+	cx24123_writereg(state, 0x00, 0x10);
+	cx24123_writereg(state, 0x00, 0);
+
+	return 0;
+}
+
+static int cx24123_get_params(struct dvb_frontend* fe,
+			      struct dvbfe_params *p)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+
+	dprintk("%s:  get_frontend\n",__FUNCTION__);
+
+	if (cx24123_get_inversion(state, &p->inversion) != 0) {
+		printk("%s: Failed to get inversion status\n",__FUNCTION__);
+		return -EREMOTEIO;
+	}
+	if (cx24123_get_fec(state, &p->delsys.dvbs.fec) != 0) {
+		printk("%s: Failed to get fec status\n",__FUNCTION__);
+		return -EREMOTEIO;
+	}
+	p->frequency = state->currentfreq;
+	p->delsys.dvbs.symbol_rate = state->currentsymbolrate;
+
+	return 0;
+}
+
+static int cx24123_get_info(struct dvb_frontend *fe,
+			    struct dvbfe_info *fe_info)
+{
+	memcpy(fe_info, &dvbs_info, sizeof (dvbs_info));
+
+	return 0;
+}
+
+static int cx24123_get_delsys(struct dvb_frontend *fe,
+			      enum dvbfe_delsys *fe_delsys)
+{
+	*fe_delsys = DVBFE_DELSYS_DVBS;
+
+	return 0;
+}
+
+static enum dvbfe_algo cx24123_get_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_RECOVERY;
+}
+
 static struct dvb_frontend_ops cx24123_ops = {
 
 	.info = {
@@ -1019,6 +1300,12 @@ static struct dvb_frontend_ops cx24123_o
 	.diseqc_send_burst = cx24123_diseqc_send_burst,
 	.set_tone = cx24123_set_tone,
 	.set_voltage = cx24123_set_voltage,
+
+	.set_params		= cx24123_set_params,
+	.get_params		= cx24123_get_params,
+	.get_info		= cx24123_get_info,
+	.get_delsys		= cx24123_get_delsys,
+	.get_frontend_algo	= cx24123_get_algo,
 };
 
 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