PATCH 31/44 multiproto + backward compatibility [SP887x]

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

 



--- v4l-dvb/linux/drivers/media/dvb/frontends/sp887x.c	2006-06-30 19:59:10.000000000 +0400
+++ mp-bc1/linux/drivers/media/dvb/frontends/sp887x.c	2006-07-23 11:40:21.000000000 +0400
@@ -210,7 +210,7 @@ static int sp887x_initial_setup (struct 
 	return 0;
 };
 
-static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
+static int configure_reg0xc05_compat(struct dvb_frontend_parameters *p, u16 *reg0xc05)
 {
 	int known_parameters = 1;
 
@@ -281,6 +281,82 @@ static int configure_reg0xc05 (struct dv
 	return 0;
 }
 
+static int configure_reg0xc05(struct dvbfe_params *p, u16 *reg0xc05)
+{
+	int known_parameters = 1;
+
+	*reg0xc05 = 0x000;
+
+	switch (p->delsys.dvbt.constellation) {
+	case DVBFE_MOD_QPSK:
+		break;
+	case DVBFE_MOD_QAM16:
+		*reg0xc05 |= (1 << 10);
+		break;
+	case DVBFE_MOD_QAM64:
+		*reg0xc05 |= (2 << 10);
+		break;
+	case DVBFE_MOD_QAMAUTO:
+		known_parameters = 0;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	switch (p->delsys.dvbt.hierarchy) {
+	case DVBFE_HIERARCHY_OFF:
+		break;
+	case DVBFE_HIERARCHY_ON:
+		break;
+		switch (p->delsys.dvbt.alpha) {
+		case DVBFE_ALPHA_1:
+			*reg0xc05 |= (1 << 7);
+			break;
+		case DVBFE_ALPHA_2:
+			*reg0xc05 |= (2 << 7);
+			break;
+		case DVBFE_ALPHA_4:
+			*reg0xc05 |= (3 << 7);
+			break;
+		}
+		break;
+	case DVBFE_HIERARCHY_AUTO:
+		known_parameters = 0;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	switch (p->delsys.dvbt.code_rate_HP) {
+	case DVBFE_FEC_1_2:
+		break;
+	case DVBFE_FEC_2_3:
+		*reg0xc05 |= (1 << 3);
+		break;
+	case DVBFE_FEC_3_4:
+		*reg0xc05 |= (2 << 3);
+		break;
+	case DVBFE_FEC_5_6:
+		*reg0xc05 |= (3 << 3);
+		break;
+	case DVBFE_FEC_7_8:
+		*reg0xc05 |= (4 << 3);
+		break;
+	case DVBFE_FEC_AUTO:
+		known_parameters = 0;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	if (known_parameters)
+		*reg0xc05 |= (2 << 1);	/* use specified parameters */
+	else
+		*reg0xc05 |= (1 << 1);	/* enable autoprobing */
+
+	return 0;
+}
+
 /**
  *  estimates division of two 24bit numbers,
  *  derived from the ves1820/stv0299 driver code
@@ -303,9 +379,9 @@ static void divide (int n, int d, int *q
 	}
 }
 
-static void sp887x_correct_offsets (struct sp887x_state* state,
-				    struct dvb_frontend_parameters *p,
-				    int actual_freq)
+static void sp887x_correct_offsets_compat(struct sp887x_state* state,
+					  struct dvb_frontend_parameters *p,
+					  int actual_freq)
 {
 	static const u32 srate_correction [] = { 1879617, 4544878, 8098561 };
 	int bw_index = p->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
@@ -334,6 +410,38 @@ static void sp887x_correct_offsets (stru
 	sp887x_writereg(state, 0x30a, frequency_shift & 0xfff);
 }
 
+static void sp887x_correct_offsets(struct sp887x_state* state,
+				   struct dvbfe_params *p,
+				   int actual_freq)
+{
+	static const u32 srate_correction [] = { 1879617, 0, 4544878, 8098561, 0 };
+
+	int bw_index = p->delsys.dvbt.bandwidth - DVBFE_BANDWIDTH_8_MHZ;
+	int freq_offset = actual_freq - p->frequency;
+	int sysclock = 61003; //[kHz]
+	int ifreq = 36000000;
+	int freq;
+	int frequency_shift;
+
+	if (p->inversion == INVERSION_ON)
+		freq = ifreq - freq_offset;
+	else
+		freq = ifreq + freq_offset;
+
+	divide(freq / 333, sysclock, NULL, &frequency_shift);
+
+	if (p->inversion == INVERSION_ON)
+		frequency_shift = -frequency_shift;
+
+	/* sample rate correction */
+	sp887x_writereg(state, 0x319, srate_correction[fls(bw_index)] >> 12);
+	sp887x_writereg(state, 0x31a, srate_correction[fls(bw_index)] & 0xfff);
+
+	/* carrier offset correction */
+	sp887x_writereg(state, 0x309, frequency_shift >> 12);
+	sp887x_writereg(state, 0x30a, frequency_shift & 0xfff);
+}
+
 static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
 					     struct dvb_frontend_parameters *p)
 {
@@ -346,15 +454,16 @@ static int sp887x_setup_frontend_paramet
 	    p->u.ofdm.bandwidth != BANDWIDTH_6_MHZ)
 		return -EINVAL;
 
-	if ((err = configure_reg0xc05(p, &reg0xc05)))
+	if ((err = configure_reg0xc05_compat(p, &reg0xc05)))
 		return err;
 
 	sp887x_microcontroller_stop(state);
 
 	/* setup the PLL */
-	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);
 	}
 	if (fe->ops.tuner_ops.get_frequency) {
 		fe->ops.tuner_ops.get_frequency(fe, &actual_freq);
@@ -366,7 +475,7 @@ static int sp887x_setup_frontend_paramet
 	/* read status reg in order to clear <pending irqs */
 	sp887x_readreg(state, 0x200);
 
-	sp887x_correct_offsets(state, p, actual_freq);
+	sp887x_correct_offsets_compat(state, p, actual_freq);
 
 	/* filter for 6/7/8 Mhz channel */
 	if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
@@ -578,6 +687,105 @@ error:
 	return NULL;
 }
 
+static struct dvbfe_info dvbt_info	= {
+	.name				= "Spase SP887x DVB-T",
+	.delivery			= DVBFE_DELSYS_DVBT,
+	.delsys				= {
+		.dvbt.modulation	= DVBFE_MOD_OFDM,
+		.dvbt.stream_priority	= DVBFE_STREAM_PRIORITY_HP |
+					  DVBFE_STREAM_PRIORITY_LP,
+	},
+
+	.frequency_min			= 50500000,
+	.frequency_max			= 858000000,
+	.frequency_step			= 166666,
+};
+
+static int sp887x_set_params(struct dvb_frontend* fe,
+			     struct dvbfe_params *p)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+	int actual_freq, err;
+	u16 val, reg0xc05;
+
+	if (p->delsys.dvbt.bandwidth != DVBFE_BANDWIDTH_8_MHZ &&
+	    p->delsys.dvbt.bandwidth != DVBFE_BANDWIDTH_7_MHZ &&
+	    p->delsys.dvbt.bandwidth != DVBFE_BANDWIDTH_6_MHZ)
+		return -EINVAL;
+
+	if ((err = configure_reg0xc05(p, &reg0xc05)))
+		return err;
+
+	sp887x_microcontroller_stop(state);
+
+	/* setup the PLL */
+	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.get_frequency) {
+		fe->ops.tuner_ops.get_frequency(fe, &actual_freq);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	} else {
+		actual_freq = p->frequency;
+	}
+
+	/* read status reg in order to clear <pending irqs */
+	sp887x_readreg(state, 0x200);
+
+	sp887x_correct_offsets(state, p, actual_freq);
+
+	/* filter for 6/7/8 Mhz channel */
+	if (p->delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_6_MHZ)
+		val = 2;
+	else if (p->delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_7_MHZ)
+		val = 1;
+	else
+		val = 0;
+
+	sp887x_writereg(state, 0x311, val);
+
+	/* scan order: 2k first = 0, 8k first = 1 */
+	if (p->delsys.dvbt.transmission_mode == DVBFE_TRANSMISSION_MODE_2K)
+		sp887x_writereg(state, 0x338, 0x000);
+	else
+		sp887x_writereg(state, 0x338, 0x001);
+
+	sp887x_writereg(state, 0xc05, reg0xc05);
+
+	if (p->delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_6_MHZ)
+		val = 2 << 3;
+	else if (p->delsys.dvbt.bandwidth == DVBFE_BANDWIDTH_7_MHZ)
+		val = 3 << 3;
+	else
+		val = 0 << 3;
+
+	/* enable OFDM and SAW bits as lock indicators in sync register 0xf17,
+	 * optimize algorithm for given bandwidth...
+	 */
+	sp887x_writereg(state, 0xf14, 0x160 | val);
+	sp887x_writereg(state, 0xf15, 0x000);
+
+	sp887x_microcontroller_start(state);
+	return 0;
+}
+
+static int sp887x_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info)
+{
+	memcpy(fe_info, &dvbt_info, sizeof (dvbt_info));
+
+	return 0;
+}
+
+static int sp887x_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys)
+{
+	*fe_delsys = DVBFE_DELSYS_DVBT;
+
+	return 0;
+}
+
 static struct dvb_frontend_ops sp887x_ops = {
 
 	.info = {
@@ -606,6 +814,10 @@ static struct dvb_frontend_ops sp887x_op
 	.read_signal_strength = sp887x_read_signal_strength,
 	.read_snr = sp887x_read_snr,
 	.read_ucblocks = sp887x_read_ucblocks,
+
+	.set_params	= sp887x_set_params,
+	.get_info	= sp887x_get_info,
+	.get_delsys	= sp887x_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