PATCH 13/44 multiproto + backward compatibility [DIB3000MB]

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

 




--- v4l-dvb/linux/drivers/media/dvb/frontends/dib3000mb.c	2006-06-30 19:59:10.000000000 +0400
+++ mp-bc1/linux/drivers/media/dvb/frontends/dib3000mb.c	2006-07-23 11:37:54.000000000 +0400
@@ -51,6 +51,8 @@ MODULE_PARM_DESC(debug, "set debugging l
 
 static int dib3000mb_get_frontend(struct dvb_frontend* fe,
 				  struct dvb_frontend_parameters *fep);
+static int dib3000mb_get_params(struct dvb_frontend *fe,
+				struct dvbfe_params *fep);
 
 static int dib3000mb_set_frontend(struct dvb_frontend* fe,
 				  struct dvb_frontend_parameters *fep, int tuner)
@@ -60,9 +62,10 @@ static int dib3000mb_set_frontend(struct
 	fe_code_rate_t fe_cr = FEC_NONE;
 	int search_state, seq;
 
-	if (tuner && fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe, fep);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	if (tuner && fe->ops.tuner_ops.set_params_compat) {
+		fe->ops.tuner_ops.set_params_compat(fe, fep);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
 
 		deb_setf("bandwidth: ");
 		switch (ofdm->bandwidth) {
@@ -313,6 +316,272 @@ static int dib3000mb_set_frontend(struct
 	return 0;
 }
 
+static int dib3000mb_set_param(struct dvb_frontend* fe,
+			       struct dvbfe_params *fep, int tuner)
+{
+	struct dib3000_state *state = fe->demodulator_priv;
+	struct dvbt_params *dvbt = &fep->delsys.dvbt;
+	enum dvbfe_fec fe_cr = DVBFE_FEC_NONE;
+	int search_state, seq;
+
+	if (tuner && fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, fep);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+
+		deb_setf("bandwidth: ");
+		switch (dvbt->bandwidth) {
+		case DVBFE_BANDWIDTH_8_MHZ:
+			deb_setf("8 MHz\n");
+			wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
+			wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
+			break;
+		case DVBFE_BANDWIDTH_7_MHZ:
+			deb_setf("7 MHz\n");
+			wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);
+			wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);
+			break;
+		case DVBFE_BANDWIDTH_6_MHZ:
+			deb_setf("6 MHz\n");
+			wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);
+			wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);
+			break;
+		case DVBFE_BANDWIDTH_AUTO:
+			return -EOPNOTSUPP;
+		default:
+			err("unkown bandwidth value.");
+			return -EINVAL;
+		}
+	}
+	wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
+
+	deb_setf("transmission mode: ");
+	switch (dvbt->transmission_mode) {
+	case DVBFE_TRANSMISSION_MODE_2K:
+		deb_setf("2k\n");
+		wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K);
+		break;
+	case DVBFE_TRANSMISSION_MODE_8K:
+		deb_setf("8k\n");
+		wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K);
+		break;
+	case DVBFE_TRANSMISSION_MODE_AUTO:
+		deb_setf("auto\n");
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	deb_setf("guard: ");
+	switch (dvbt->guard_interval) {
+	case DVBFE_GUARD_INTERVAL_1_32:
+		deb_setf("1_32\n");
+		wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32);
+		break;
+	case DVBFE_GUARD_INTERVAL_1_16:
+		deb_setf("1_16\n");
+		wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16);
+		break;
+	case DVBFE_GUARD_INTERVAL_1_8:
+		deb_setf("1_8\n");
+		wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8);
+		break;
+	case DVBFE_GUARD_INTERVAL_1_4:
+		deb_setf("1_4\n");
+		wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4);
+		break;
+	case DVBFE_GUARD_INTERVAL_AUTO:
+		deb_setf("auto\n");
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	deb_setf("inversion: ");
+	switch (fep->inversion) {
+	case INVERSION_OFF:
+		deb_setf("off\n");
+		wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF);
+		break;
+	case INVERSION_AUTO:
+		deb_setf("auto ");
+		break;
+	case INVERSION_ON:
+		deb_setf("on\n");
+		wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	deb_setf("constellation: ");
+	switch (dvbt->constellation) {
+	case DVBFE_MOD_QPSK:
+		deb_setf("qpsk\n");
+		wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK);
+		break;
+	case DVBFE_MOD_QAM16:
+		deb_setf("qam16\n");
+		wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM);
+		break;
+	case DVBFE_MOD_QAM64:
+		deb_setf("qam64\n");
+		wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM);
+		break;
+	case DVBFE_MOD_QAMAUTO:
+		break;
+	default:
+		return -EINVAL;
+	}
+	deb_setf("hierachy: ");
+	switch (dvbt->hierarchy) {
+	case DVBFE_HIERARCHY_OFF:
+		deb_setf("none ");
+		/* fall through */
+		break;
+	case DVBFE_HIERARCHY_ON:
+		switch (dvbt->alpha) {
+		case DVBFE_ALPHA_1:
+			deb_setf("alpha=1\n");
+			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1);
+			break;
+		case DVBFE_ALPHA_2:
+			deb_setf("alpha=2\n");
+			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2);
+			break;
+		case DVBFE_ALPHA_4:
+			deb_setf("alpha=4\n");
+			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4);
+			break;
+		}
+		break;
+	case DVBFE_HIERARCHY_AUTO:
+		deb_setf("alpha=auto\n");
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	deb_setf("hierarchy: ");
+	if (dvbt->hierarchy == DVBFE_HIERARCHY_OFF) {
+		deb_setf("none\n");
+		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF);
+		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP);
+		fe_cr = dvbt->code_rate_HP;
+	} else if (dvbt->hierarchy != DVBFE_HIERARCHY_AUTO) {
+		deb_setf("on\n");
+		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON);
+		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP);
+		fe_cr = dvbt->code_rate_LP;
+	}
+	deb_setf("fec: ");
+	switch (fe_cr) {
+	case DVBFE_FEC_1_2:
+		deb_setf("1_2\n");
+		wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2);
+		break;
+	case DVBFE_FEC_2_3:
+		deb_setf("2_3\n");
+		wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3);
+		break;
+	case DVBFE_FEC_3_4:
+		deb_setf("3_4\n");
+		wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4);
+		break;
+	case DVBFE_FEC_5_6:
+		deb_setf("5_6\n");
+		wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6);
+		break;
+	case DVBFE_FEC_7_8:
+		deb_setf("7_8\n");
+		wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8);
+		break;
+	case DVBFE_FEC_NONE:
+		deb_setf("none ");
+		break;
+	case DVBFE_FEC_AUTO:
+		deb_setf("auto\n");
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	seq = dib3000_seq
+		[dvbt->transmission_mode == DVBFE_TRANSMISSION_MODE_AUTO]
+		[dvbt->guard_interval == DVBFE_GUARD_INTERVAL_AUTO]
+		[fep->inversion == INVERSION_AUTO];
+
+	deb_setf("seq? %d\n", seq);
+
+	wr(DIB3000MB_REG_SEQ, seq);
+
+	wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);
+
+	if (dvbt->transmission_mode == DVBFE_TRANSMISSION_MODE_2K) {
+		if (dvbt->guard_interval == DVBFE_GUARD_INTERVAL_1_8) {
+			wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8);
+		} else {
+			wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT);
+		}
+
+		wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_2K);
+	} else {
+		wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_DEFAULT);
+	}
+
+	wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_OFF);
+	wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);
+	wr(DIB3000MB_REG_MOBILE_MODE, DIB3000MB_MOBILE_MODE_OFF);
+
+	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_high);
+
+	wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_ACTIVATE);
+
+	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC + DIB3000MB_RESTART_CTRL);
+	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
+
+	/* wait for AGC lock */
+	msleep(70);
+
+	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);
+
+	/* something has to be auto searched */
+	if (dvbt->constellation == DVBFE_MOD_QAMAUTO ||
+	    dvbt->hierarchy == DVBFE_HIERARCHY_AUTO ||
+		fe_cr == DVBFE_FEC_AUTO ||
+		fep->inversion == INVERSION_AUTO) {
+		int as_count=0;
+
+		deb_setf("autosearch enabled.\n");
+
+		wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);
+
+		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AUTO_SEARCH);
+		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
+
+		while ((search_state =
+				dib3000_search_status(
+					rd(DIB3000MB_REG_AS_IRQ_PENDING),
+					rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100)
+			msleep(1);
+
+		deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count);
+
+		if (search_state == 1) {
+			struct dvbfe_params feps;
+			if (dib3000mb_get_params(fe, &feps) == 0) {
+				deb_setf("reading tuning data from frontend succeeded.\n");
+				return dib3000mb_set_param(fe, &feps, 0);
+			}
+		}
+
+	} else {
+		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_CTRL);
+		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
+	}
+
+	return 0;
+}
 static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
 {
 	struct dib3000_state* state = fe->demodulator_priv;
@@ -552,6 +821,173 @@ static int dib3000mb_get_frontend(struct
 	return 0;
 }
 
+static int dib3000mb_get_params(struct dvb_frontend *fe,
+				struct dvbfe_params *fep)
+{
+	struct dib3000_state *state = fe->demodulator_priv;
+	struct dvbt_params *dvbt = &fep->delsys.dvbt;
+//	fe_code_rate_t *cr;
+	enum dvbfe_fec *cr;
+
+	u16 tps_val;
+	int inv_test1,inv_test2;
+	u32 dds_val, threshold = 0x800000;
+
+	if (!rd(DIB3000MB_REG_TPS_LOCK))
+		return 0;
+
+	dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB);
+	deb_getf("DDS_VAL: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB));
+	if (dds_val < threshold)
+		inv_test1 = 0;
+	else if (dds_val == threshold)
+		inv_test1 = 1;
+	else
+		inv_test1 = 2;
+
+	dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB);
+	deb_getf("DDS_FREQ: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB));
+	if (dds_val < threshold)
+		inv_test2 = 0;
+	else if (dds_val == threshold)
+		inv_test2 = 1;
+	else
+		inv_test2 = 2;
+
+	fep->inversion =
+		((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||
+		((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?
+		INVERSION_ON : INVERSION_OFF;
+
+	deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion);
+
+	switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {
+	case DIB3000_CONSTELLATION_QPSK:
+		deb_getf("QPSK ");
+		dvbt->constellation = DVBFE_MOD_QPSK;
+		break;
+	case DIB3000_CONSTELLATION_16QAM:
+		deb_getf("QAM16 ");
+		dvbt->constellation = DVBFE_MOD_QAM16;
+		break;
+	case DIB3000_CONSTELLATION_64QAM:
+		deb_getf("QAM64 ");
+		dvbt->constellation = DVBFE_MOD_QAM64;
+		break;
+	default:
+		err("Unexpected constellation returned by TPS (%d)", tps_val);
+		break;
+	}
+	deb_getf("TPS: %d\n", tps_val);
+
+	if (rd(DIB3000MB_REG_TPS_HRCH)) {
+		deb_getf("HRCH ON\n");
+		cr = &dvbt->code_rate_LP;
+		dvbt->code_rate_HP = DVBFE_FEC_NONE;
+		switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {
+		case DIB3000_ALPHA_0:
+			deb_getf("HIERARCHY_NONE ");
+			dvbt->hierarchy = DVBFE_HIERARCHY_OFF;
+			break;
+		case DIB3000_ALPHA_1:
+			deb_getf("HIERARCHY_1 ");
+			dvbt->hierarchy = DVBFE_HIERARCHY_ON;
+			dvbt->alpha = DVBFE_ALPHA_1;
+			break;
+		case DIB3000_ALPHA_2:
+			deb_getf("HIERARCHY_2 ");
+			dvbt->hierarchy = DVBFE_HIERARCHY_ON;
+			dvbt->alpha = DVBFE_ALPHA_2;
+			break;
+		case DIB3000_ALPHA_4:
+			deb_getf("HIERARCHY_4 ");
+			dvbt->hierarchy = DVBFE_HIERARCHY_ON;
+			dvbt->alpha = DVBFE_ALPHA_4;
+			break;
+		default:
+			err("Unexpected ALPHA value returned by TPS (%d)", tps_val);
+			break;
+		}
+		deb_getf("TPS: %d\n", tps_val);
+
+		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP);
+	} else {
+		deb_getf("HRCH OFF\n");
+		cr = &dvbt->code_rate_HP;
+		dvbt->code_rate_LP = DVBFE_FEC_NONE;
+		dvbt->hierarchy = DVBFE_HIERARCHY_OFF;
+
+		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP);
+	}
+
+	switch (tps_val) {
+	case DIB3000_FEC_1_2:
+		deb_getf("FEC_1_2 ");
+		*cr = DVBFE_FEC_1_2;
+		break;
+	case DIB3000_FEC_2_3:
+		deb_getf("FEC_2_3 ");
+		*cr = DVBFE_FEC_2_3;
+		break;
+	case DIB3000_FEC_3_4:
+		deb_getf("FEC_3_4 ");
+		*cr = DVBFE_FEC_3_4;
+		break;
+	case DIB3000_FEC_5_6:
+		deb_getf("FEC_5_6 ");
+		*cr = DVBFE_FEC_4_5;
+		break;
+	case DIB3000_FEC_7_8:
+		deb_getf("FEC_7_8 ");
+		*cr = DVBFE_FEC_7_8;
+		break;
+	default:
+		err("Unexpected FEC returned by TPS (%d)", tps_val);
+		break;
+	}
+	deb_getf("TPS: %d\n",tps_val);
+
+	switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {
+	case DIB3000_GUARD_TIME_1_32:
+		deb_getf("GUARD_INTERVAL_1_32 ");
+		dvbt->guard_interval = DVBFE_GUARD_INTERVAL_1_32;
+		break;
+	case DIB3000_GUARD_TIME_1_16:
+		deb_getf("GUARD_INTERVAL_1_16 ");
+		dvbt->guard_interval = DVBFE_GUARD_INTERVAL_1_16;
+		break;
+	case DIB3000_GUARD_TIME_1_8:
+		deb_getf("GUARD_INTERVAL_1_8 ");
+		dvbt->guard_interval = DVBFE_GUARD_INTERVAL_1_8;
+		break;
+	case DIB3000_GUARD_TIME_1_4:
+		deb_getf("GUARD_INTERVAL_1_4 ");
+		dvbt->guard_interval = DVBFE_GUARD_INTERVAL_1_4;
+		break;
+	default:
+		err("Unexpected Guard Time returned by TPS (%d)", tps_val);
+		break;
+	}
+	deb_getf("TPS: %d\n", tps_val);
+
+	switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {
+	case DIB3000_TRANSMISSION_MODE_2K:
+		deb_getf("TRANSMISSION_MODE_2K ");
+		dvbt->transmission_mode = DVBFE_TRANSMISSION_MODE_2K;
+		break;
+	case DIB3000_TRANSMISSION_MODE_8K:
+		deb_getf("TRANSMISSION_MODE_8K ");
+		dvbt->transmission_mode = DVBFE_TRANSMISSION_MODE_8K;
+		break;
+	default:
+		err("unexpected transmission mode return by TPS (%d)", tps_val);
+		break;
+	}
+	deb_getf("TPS: %d\n", tps_val);
+
+	return 0;
+}
+
 static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat)
 {
 	struct dib3000_state* state = fe->demodulator_priv;
@@ -643,6 +1079,12 @@ static int dib3000mb_set_frontend_and_tu
 	return dib3000mb_set_frontend(fe, fep, 1);
 }
 
+static int dib3000mb_set_params(struct dvb_frontend *fe,
+				struct dvbfe_params *fep)
+{
+	return dib3000mb_set_param(fe, fep, 1);
+}
+
 static void dib3000mb_release(struct dvb_frontend* fe)
 {
 	struct dib3000_state *state = fe->demodulator_priv;
@@ -730,6 +1172,41 @@ error:
 	return NULL;
 }
 
+static struct dvbfe_info dvbt_info	= {
+	.name				= "DiBcom 3000M-B 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			= 44250000,
+	.frequency_max			= 867250000,
+	.frequency_step			= 62500,
+};
+
+static int dib3000mb_get_info(struct dvb_frontend *fe,
+			      struct dvbfe_info *fe_info)
+{
+	memcpy(fe_info, &dvbt_info, sizeof (dvbt_info));
+
+	return 0;
+}
+
+static int dib3000mb_get_delsys(struct dvb_frontend *fe,
+				enum dvbfe_delsys *fe_delsys)
+{
+	*fe_delsys = DVBFE_DELSYS_DVBT;
+
+	return 0;
+}
+
+static enum dvbfe_algo dib3000mb_get_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_RECOVERY;
+}
+
 static struct dvb_frontend_ops dib3000mb_ops = {
 
 	.info = {
@@ -762,6 +1239,12 @@ static struct dvb_frontend_ops dib3000mb
 	.read_signal_strength = dib3000mb_read_signal_strength,
 	.read_snr = dib3000mb_read_snr,
 	.read_ucblocks = dib3000mb_read_unc_blocks,
+
+	.set_params		= dib3000mb_set_params,
+	.get_params		= dib3000mb_get_params,
+	.get_info		= dib3000mb_get_info,
+	.get_delsys		= dib3000mb_get_delsys,
+	.get_frontend_algo	= dib3000mb_get_algo,
 };
 
 MODULE_AUTHOR(DRIVER_AUTHOR);

_______________________________________________

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