PATCH 2/44 multiproto + backward compatibility [DVB Core]

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

 




diff -Naurp v4l-dvb/linux/drivers/media/dvb/dvb-core/dvb_frontend.c mp-bc1/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
--- v4l-dvb/linux/drivers/media/dvb/dvb-core/dvb_frontend.c	2006-07-06 21:34:26.000000000 +0400
+++ mp-bc1/linux/drivers/media/dvb/dvb-core/dvb_frontend.c	2006-07-25 12:22:33.000000000 +0400
@@ -73,7 +73,7 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep,
 #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
 #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
 
-#define FE_ALGO_HW		1
+
 /*
  * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
  * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
@@ -95,7 +95,11 @@ struct dvb_frontend_private {
 
 	/* thread/frontend values */
 	struct dvb_device *dvbdev;
+	/*	Legacy datatype, superseded by dvbfe_params		*/
 	struct dvb_frontend_parameters parameters;
+	/*	dvbfe_params supersedes dvb_frontend_parameters		*/
+	struct dvbfe_params	fe_params;
+	struct dvbfe_info	fe_info;
 	struct dvb_fe_events events;
 	struct semaphore sem;
 	struct list_head list_head;
@@ -128,6 +132,58 @@ struct dvb_frontend_private {
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
 
+struct modcod_table {
+	u32 dvbfe_modcod;
+	u32 dvbfe_modulation;
+	u32 dvbfe_fec;
+};
+
+static struct modcod_table dvbs2_modcod_lookup[] = {
+	{ DVBFE_MODCOD_DUMMY_PLFRAME,	DVBFE_MOD_NONE,		DVBFE_FEC_NONE    },
+	{ DVBFE_MODCOD_QPSK_1_4,	DVBFE_MOD_QPSK,		DVBFE_FEC_1_4	  },
+	{ DVBFE_MODCOD_QPSK_1_3,	DVBFE_MOD_QPSK,		DVBFE_FEC_1_3	  },
+	{ DVBFE_MODCOD_QPSK_2_5,	DVBFE_MOD_QPSK,		DVBFE_FEC_2_5	  },
+	{ DVBFE_MODCOD_QPSK_1_2,	DVBFE_MOD_QPSK,		DVBFE_FEC_1_2	  },
+	{ DVBFE_MODCOD_QPSK_3_5,	DVBFE_MOD_QPSK,		DVBFE_FEC_3_5	  },
+	{ DVBFE_MODCOD_QPSK_2_3,	DVBFE_MOD_QPSK,		DVBFE_FEC_2_3	  },
+	{ DVBFE_MODCOD_QPSK_3_4,	DVBFE_MOD_QPSK,		DVBFE_FEC_3_4	  },
+	{ DVBFE_MODCOD_QPSK_4_5,	DVBFE_MOD_QPSK,		DVBFE_FEC_4_5	  },
+	{ DVBFE_MODCOD_QPSK_5_6,	DVBFE_MOD_QPSK,		DVBFE_FEC_5_6	  },
+	{ DVBFE_MODCOD_QPSK_8_9,	DVBFE_MOD_QPSK,		DVBFE_FEC_8_9	  },
+	{ DVBFE_MODCOD_QPSK_9_10,	DVBFE_MOD_QPSK,		DVBFE_FEC_9_10	  },
+	{ DVBFE_MODCOD_8PSK_3_5,	DVBFE_MOD_8PSK,		DVBFE_FEC_3_5	  },
+	{ DVBFE_MODCOD_8PSK_2_3,	DVBFE_MOD_8PSK,		DVBFE_FEC_2_3	  },
+	{ DVBFE_MODCOD_8PSK_3_4,	DVBFE_MOD_8PSK,		DVBFE_FEC_3_4	  },
+	{ DVBFE_MODCOD_8PSK_5_6,	DVBFE_MOD_8PSK,		DVBFE_FEC_5_6	  },
+	{ DVBFE_MODCOD_8PSK_8_9,	DVBFE_MOD_8PSK,		DVBFE_FEC_8_9	  },
+	{ DVBFE_MODCOD_8PSK_9_10,	DVBFE_MOD_8PSK,		DVBFE_FEC_9_10	  },
+	{ DVBFE_MODCOD_16APSK_2_3,	DVBFE_MOD_16APSK,	DVBFE_FEC_2_3	  },
+	{ DVBFE_MODCOD_16APSK_3_4,	DVBFE_MOD_16APSK,	DVBFE_FEC_3_4	  },
+	{ DVBFE_MODCOD_16APSK_4_5,	DVBFE_MOD_16APSK,	DVBFE_FEC_4_5	  },
+	{ DVBFE_MODCOD_16APSK_5_6,	DVBFE_MOD_16APSK,	DVBFE_FEC_5_6	  },
+	{ DVBFE_MODCOD_16APSK_8_9,	DVBFE_MOD_16APSK,	DVBFE_FEC_8_9	  },
+	{ DVBFE_MODCOD_16APSK_9_10,	DVBFE_MOD_16APSK,	DVBFE_FEC_9_10	  },
+	{ DVBFE_MODCOD_32APSK_3_4,	DVBFE_MOD_32APSK,	DVBFE_FEC_3_4	  },
+	{ DVBFE_MODCOD_32APSK_4_5,	DVBFE_MOD_32APSK,	DVBFE_FEC_4_5	  },
+	{ DVBFE_MODCOD_32APSK_5_6,	DVBFE_MOD_32APSK,	DVBFE_FEC_5_6	  },
+	{ DVBFE_MODCOD_32APSK_8_9,	DVBFE_MOD_32APSK,	DVBFE_FEC_8_9	  },
+	{ DVBFE_MODCOD_32APSK_9_10,	DVBFE_MOD_32APSK,	DVBFE_FEC_9_10	  },
+	{ DVBFE_MODCOD_RESERVED_1,	DVBFE_MOD_NONE,		DVBFE_FEC_NONE	  },
+	{ DVBFE_MODCOD_BPSK_1_3,	DVBFE_MOD_BPSK,		DVBFE_FEC_1_3	  },
+	{ DVBFE_MODCOD_BPSK_1_4,	DVBFE_MOD_BPSK,		DVBFE_FEC_1_4	  },
+	{ DVBFE_MODCOD_RESERVED_2,	DVBFE_MOD_NONE,		DVBFE_FEC_NONE    }
+};
+
+void decode_dvbs2_modcod(u32 dvbfe_modcod,
+			 enum dvbfe_modulation *modulation,
+			 enum dvbfe_fec *fec)
+{
+	BUG_ON(dvbfe_modcod >= ARRAY_SIZE(dvbs2_modcod_lookup));
+	*modulation = dvbs2_modcod_lookup[dvbfe_modcod].dvbfe_modulation;
+	*fec = dvbs2_modcod_lookup[dvbfe_modcod].dvbfe_fec;
+}
+EXPORT_SYMBOL(decode_dvbs2_modcod);
+
 static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
 {
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -149,13 +205,22 @@ static void dvb_frontend_add_event(struc
 
 	e = &events->events[events->eventw];
 
-	memcpy (&e->parameters, &fepriv->parameters,
+	if (fe->legacy)
+		memcpy(&e->parameters, &fepriv->parameters,
 		sizeof (struct dvb_frontend_parameters));
+	else
+		memcpy(&e->fe_params, &fepriv->fe_params, sizeof (struct dvbfe_params));
 
-	if (status & FE_HAS_LOCK)
-		if (fe->ops.get_frontend)
-			fe->ops.get_frontend(fe, &e->parameters);
-
+	if (fe->legacy) {
+		/*	Legacy		*/
+		if (status & FE_HAS_LOCK)
+			if (fe->ops.get_frontend)
+				fe->ops.get_frontend(fe, &e->parameters);
+	} else {
+		if (status & FE_HAS_LOCK)
+			if (fe->ops.get_params)
+				fe->ops.get_params(fe, &e->fe_params);
+	}
 	events->eventw = wp;
 
 	up (&events->sem);
@@ -250,6 +315,67 @@ static void dvb_frontend_swzigzag_update
 	fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
 }
 
+static int dvbfe_sanity_check(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	/*	Sanity checks		*/
+	if ((fepriv->fe_params.frequency < fepriv->fe_info.frequency_min) ||
+	    (fepriv->fe_params.frequency > fepriv->fe_info.frequency_max))
+		return -EINVAL;
+
+	switch (fepriv->fe_params.delivery) {
+	case DVBFE_DELSYS_DVBS:
+		if (!(fepriv->fe_params.delsys.dvbs.modulation &
+		      fepriv->fe_info.delsys.dvbs.modulation))
+			return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dvbs.fec &
+		      fepriv->fe_info.delsys.dvbs.fec))
+			return -EINVAL;
+	case DVBFE_DELSYS_DVBS2:
+		if (!(fepriv->fe_params.delsys.dvbs2.modulation &
+		      fepriv->fe_info.delsys.dvbs2.modulation))
+			return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dvbs2.fec &
+		      fepriv->fe_info.delsys.dvbs2.fec))
+			return -EINVAL;
+	case DVBFE_DELSYS_DSS:
+		if (!(fepriv->fe_params.delsys.dss.modulation &
+		      fepriv->fe_info.delsys.dss.modulation))
+			return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dss.fec &
+		      fepriv->fe_info.delsys.dss.fec))
+			return -EINVAL;
+	case DVBFE_DELSYS_DVBC:
+		if (!(fepriv->fe_params.delsys.dvbc.modulation &
+		      fepriv->fe_info.delsys.dvbc.modulation))
+			return -EINVAL;
+	case DVBFE_DELSYS_DVBT:
+		if (!(fepriv->fe_params.delsys.dvbt.constellation &
+		      fepriv->fe_info.delsys.dvbt.modulation))
+		      return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dvbt.priority &
+		      fepriv->fe_info.delsys.dvbt.stream_priority))
+		      return -EINVAL;
+	case DVBFE_DELSYS_DVBH:
+		if (!(fepriv->fe_params.delsys.dvbh.constellation &
+		      fepriv->fe_info.delsys.dvbh.modulation))
+		      return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dvbh.priority &
+		      fepriv->fe_info.delsys.dvbh.stream_priority))
+		      return -EINVAL;
+		break;
+	case DVBFE_DELSYS_ATSC:
+		if (!(fepriv->fe_params.delsys.atsc.modulation &
+		      fepriv->fe_info.delsys.atsc.modulation))
+			return -EINVAL;
+	default:
+		return -EINVAL;;
+	}
+
+	return 0;
+}
+
 /**
  * Performs automatic twiddling of frontend parameters.
  *
@@ -262,18 +388,32 @@ static int dvb_frontend_swzigzag_autotun
 	int autoinversion;
 	int ready = 0;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	int original_inversion = fepriv->parameters.inversion;
-	u32 original_frequency = fepriv->parameters.frequency;
-
-	/* are we using autoinversion? */
-	autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-			 (fepriv->parameters.inversion == INVERSION_AUTO));
+	struct dvbfe_info fe_info;
+	int original_inversion;
+	u32 original_frequency;
+
+	if (fe->legacy) {
+		/*	Legacy		*/
+		original_inversion = fepriv->parameters.inversion;
+		original_frequency = fepriv->parameters.frequency;
+		/* are we using autoinversion? */
+		/*	Legacy		*/
+		autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+				 (fepriv->parameters.inversion == INVERSION_AUTO));
+	} else {
+		/*	Superseding	*/
+		original_inversion = fepriv->fe_params.inversion;
+		original_frequency = fepriv->fe_params.frequency;
+		if (fe->ops.get_info)
+			fe->ops.get_info(fe, &fe_info);
 
+		autoinversion = ((!(fe_info.inversion & INVERSION_AUTO)) &&
+				 (fepriv->fe_params.inversion == INVERSION_AUTO));
+	}
 	/* setup parameters correctly */
 	while(!ready) {
 		/* calculate the lnb_drift */
 		fepriv->lnb_drift = fepriv->auto_step * fepriv->step_size;
-
 		/* wrap the auto_step if we've exceeded the maximum drift */
 		if (fepriv->lnb_drift > fepriv->max_drift) {
 			fepriv->auto_step = 0;
@@ -326,48 +466,88 @@ static int dvb_frontend_swzigzag_autotun
 	    (fepriv->auto_sub_step == 0) && check_wrapped) {
 		return 1;
 	}
-
 	dprintk("%s: drift:%i inversion:%i auto_step:%i "
 		"auto_sub_step:%i started_auto_step:%i\n",
-		__FUNCTION__, fepriv->lnb_drift, fepriv->inversion,
-		fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
-
-	/* set the frontend itself */
-	fepriv->parameters.frequency += fepriv->lnb_drift;
-	if (autoinversion)
-		fepriv->parameters.inversion = fepriv->inversion;
-	if (fe->ops.set_frontend)
-		fe->ops.set_frontend(fe, &fepriv->parameters);
-
-	fepriv->parameters.frequency = original_frequency;
-	fepriv->parameters.inversion = original_inversion;
+		__func__, fepriv->lnb_drift, fepriv->inversion,
+		fepriv->auto_step, fepriv->auto_sub_step,
+		fepriv->started_auto_step);
+
+	/*	set the frontend itself		*/
+
+	/*	Legacy		*/
+	if (fe->legacy)
+		fepriv->parameters.frequency += fepriv->lnb_drift;
+	else
+		/*	Supeseding	*/
+		fepriv->fe_params.frequency += fepriv->lnb_drift;
 
+	if (autoinversion) {
+		/*	Legacy		*/
+		if (fe->legacy)
+			fepriv->parameters.inversion = fepriv->inversion;
+		else
+			/*	Superseding	*/
+			fepriv->fe_params.inversion = fepriv->inversion;
+	}
+	/*	Legacy		*/
+	if (fe->legacy) {
+		if (fe->ops.set_frontend)
+			fe->ops.set_frontend(fe, &fepriv->parameters);
+	} else {
+		if ((dvbfe_sanity_check(fe) == 0)) {
+			/*	Superseding	*/
+			if (fe->ops.set_params)
+				fe->ops.set_params(fe, &fepriv->fe_params);
+		} else
+			return -EINVAL;
+	}
+	/*	Legacy		*/
+	if (fe->legacy) {
+		fepriv->parameters.frequency = original_frequency;
+		fepriv->parameters.inversion = original_inversion;
+	} else {
+		/*	Superseding	*/
+		fepriv->fe_params.frequency = original_frequency;
+		fepriv->fe_params.inversion = original_inversion;
+	}
 	fepriv->auto_sub_step++;
+
 	return 0;
 }
 
-static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
+static int dvb_frontend_swzigzag(struct dvb_frontend *fe)
 {
 	fe_status_t s;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvbfe_info fe_info;
 
 	/* if we've got no parameters, just keep idling */
 	if (fepriv->state & FESTATE_IDLE) {
 		fepriv->delay = 3*HZ;
 		fepriv->quality = 0;
-		return;
+		return 0;
 	}
 
 	/* in SCAN mode, we just set the frontend when asked and leave it alone */
 	if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
 		if (fepriv->state & FESTATE_RETUNE) {
-			if (fe->ops.set_frontend)
-				fe->ops.set_frontend(fe, &fepriv->parameters);
+			if (fe->legacy) {
+				/*	Legacy		*/
+				if (fe->ops.set_frontend)
+					fe->ops.set_frontend(fe, &fepriv->parameters);
+			} else {
+				if (dvbfe_sanity_check(fe) == 0) {
+					/*	Superseding	*/
+					if (fe->ops.set_params)
+						fe->ops.set_params(fe, &fepriv->fe_params);
+				} else
+					return -EINVAL;
+			}
 			fepriv->state = FESTATE_TUNED;
 		}
 		fepriv->delay = 3*HZ;
 		fepriv->quality = 0;
-		return;
+		return 0;
 	}
 
 	/* get the frontend status */
@@ -387,12 +567,24 @@ static void dvb_frontend_swzigzag(struct
 		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
 		fepriv->state = FESTATE_TUNED;
 
-		/* if we're tuned, then we have determined the correct inversion */
-		if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-		    (fepriv->parameters.inversion == INVERSION_AUTO)) {
-			fepriv->parameters.inversion = fepriv->inversion;
+		/*	Legacy		*/
+		if (fe->legacy) {
+			/* if we're tuned, then we have determined the correct inversion */
+			if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+			    (fepriv->parameters.inversion == INVERSION_AUTO)) {
+				fepriv->parameters.inversion = fepriv->inversion;
+			}
+		} else {
+			/*	Superseding	*/
+			/* if we're tuned, then we have determined the correct inversion */
+			if (fe->ops.get_info) {
+				fe->ops.get_info(fe, &fe_info);
+				if ((!(fe_info.inversion & INVERSION_AUTO)) &&
+				    (fepriv->fe_params.inversion == INVERSION_AUTO))
+					fepriv->fe_params.inversion = fepriv->inversion;
+			}
 		}
-		return;
+		return 0;
 	}
 
 	/* if we are tuned already, check we're still locked */
@@ -401,7 +593,7 @@ static void dvb_frontend_swzigzag(struct
 
 		/* we're tuned, and the lock is still good... */
 		if (s & FE_HAS_LOCK) {
-			return;
+			return 0;
 		} else { /* if we _WERE_ tuned, but now don't have a lock */
 			fepriv->state = FESTATE_ZIGZAG_FAST;
 			fepriv->started_auto_step = fepriv->auto_step;
@@ -409,20 +601,39 @@ static void dvb_frontend_swzigzag(struct
 		}
 	}
 
-	/* don't actually do anything if we're in the LOSTLOCK state,
-	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
-	if ((fepriv->state & FESTATE_LOSTLOCK) &&
-	    (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
-		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
-		return;
-	}
+	/*	Legacy		*/
+	if (fe->legacy) {
+		/* don't actually do anything if we're in the LOSTLOCK state,
+		 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
+		if ((fepriv->state & FESTATE_LOSTLOCK) && (fepriv->max_drift == 0)) {
+			if (fe->ops.get_frontend_algo)
+				if (fe->ops.get_frontend_algo(fe) == DVBFE_ALGO_RECOVERY)
+					dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+			return 0;
+		}
+	} else {
+		/**
+		 * don't actually do anything if we're in the LOSTLOCK state,
+		 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0
+		 */
+		if (fepriv->state & FESTATE_LOSTLOCK) {
+			if (fe->ops.get_frontend_algo) {
+				if ((fe->ops.get_frontend_algo(fe) == DVBFE_ALGO_RECOVERY) &&
+				    (fepriv->max_drift == 0)) {
 
+					dvb_frontend_swzigzag_update_delay(fepriv, s & DVBFE_HAS_LOCK);
+					return 0;
+				}
+			}
+		}
+	}
 	/* don't do anything if we're in the DISEQC state, since this
 	 * might be someone with a motorized dish controlled by DISEQC.
 	 * If its actually a re-tune, there will be a SET_FRONTEND soon enough.	*/
 	if (fepriv->state & FESTATE_DISEQC) {
 		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
-		return;
+		return 0;
 	}
 
 	/* if we're in the RETUNE state, set everything up for a brand
@@ -446,7 +657,7 @@ static void dvb_frontend_swzigzag(struct
 			 * Drop back to slow for the _next_ attempt */
 			fepriv->state = FESTATE_SEARCHING_SLOW;
 			fepriv->started_auto_step = fepriv->auto_step;
-			return;
+			return 0;
 		}
 		fepriv->check_wrapped = 1;
 
@@ -467,6 +678,8 @@ static void dvb_frontend_swzigzag(struct
 		 * state until we get a lock */
 		dvb_frontend_swzigzag_autotune(fe, 0);
 	}
+
+	return 0;
 }
 
 static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
@@ -510,7 +723,10 @@ static int dvb_frontend_thread(void *dat
 	unsigned long timeout;
 	char name [15];
 	fe_status_t s;
+	/*	Legacy datatype		*/
 	struct dvb_frontend_parameters *params;
+	/*	Superseding datatype	*/
+	struct dvbfe_params *fe_params = &fepriv->fe_params;
 
 	dprintk("%s\n", __FUNCTION__);
 
@@ -560,10 +776,24 @@ static int dvb_frontend_thread(void *dat
 			}
 			fepriv->reinitialise = 0;
 		}
+		/*	These callbacks do exist for devices that do have their
+		 *	own tuning algorithms!
+		 *
+		 *	If we don't have search, we don't have track either. But,
+		 *	being paranoid, we check whether both of them exists.
+		 *
+		 *	In this case the demod/tuner does zigzag internally based
+		 *	on information from the device itself rather than using a
+		 *	simple and blind swzigzag.
+		 */
+		if (fe->ops.search)
+			fe->ops.search(fe, fe_params);
+		if (fe->ops.track)
+			fe->ops.track(fe, fe_params);
 
 		/* do an iteration of the tuning loop */
 		if (fe->ops.get_frontend_algo) {
-			if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
+			if (fe->ops.get_frontend_algo(fe) == DVBFE_ALGO_HW) {
 				/* have we been asked to retune? */
 				params = NULL;
 				if (fepriv->state & FESTATE_RETUNE) {
@@ -727,6 +957,7 @@ static int dvb_frontend_ioctl(struct ino
 	struct dvb_frontend *fe = dvbdev->priv;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	int err = -EOPNOTSUPP;
+	enum dvbfe_delsys delsys = 0;
 
 	dprintk ("%s\n", __FUNCTION__);
 
@@ -906,6 +1137,7 @@ static int dvb_frontend_ioctl(struct ino
 	case FE_SET_FRONTEND: {
 		struct dvb_frontend_tune_settings fetunesettings;
 
+		fe->legacy = 1;
 		memcpy (&fepriv->parameters, parg,
 			sizeof (struct dvb_frontend_parameters));
 
@@ -921,9 +1153,9 @@ static int dvb_frontend_ioctl(struct ino
 		if (fe->ops.info.type == FE_OFDM) {
 			/* without hierachical coding code_rate_LP is irrelevant,
 			 * so we tolerate the otherwise invalid FEC_NONE setting */
-			if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
-			    fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE)
-				fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO;
+				if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
+					fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE)
+					fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO;
 		}
 
 		/* get frontend-specific tuning settings */
@@ -974,6 +1206,7 @@ static int dvb_frontend_ioctl(struct ino
 		break;
 
 	case FE_GET_FRONTEND:
+		fe->legacy = 1;
 		if (fe->ops.get_frontend) {
 			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
 			err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
@@ -984,6 +1217,106 @@ static int dvb_frontend_ioctl(struct ino
 		fepriv->tune_mode_flags = (unsigned long) parg;
 		err = 0;
 		break;
+
+	case DVBFE_SET_PARAMS: {
+		struct dvb_frontend_tune_settings fetunesettings;
+
+		fe->legacy = 0;
+		memcpy(&fepriv->fe_params, parg, sizeof (struct dvbfe_params));
+		memset(&fetunesettings, 0, sizeof (struct dvb_frontend_tune_settings));
+		memcpy(&fetunesettings.fe_params, parg, sizeof (struct dvbfe_params));
+		/* force auto frequency inversion if requested */
+		if (dvb_force_auto_inversion) {
+			fepriv->fe_params.inversion = DVBFE_INVERSION_AUTO;
+			fetunesettings.fe_params.inversion = DVBFE_INVERSION_AUTO;
+		}
+		if (fe->ops.get_delsys) {
+			fe->ops.get_delsys(fe, &delsys);
+			if ((delsys == DVBFE_DELSYS_DVBT) ||
+			    (delsys == DVBFE_DELSYS_DVBH)) {
+
+				/* without hierachical coding code_rate_LP is irrelevant,
+				 * so we tolerate the otherwise invalid FEC_NONE setting */
+				if (fepriv->fe_params.delsys.dvbt.hierarchy == DVBFE_HIERARCHY_OFF &&
+				    fepriv->fe_params.delsys.dvbt.code_rate_LP == DVBFE_FEC_NONE)
+
+					fepriv->fe_params.delsys.dvbt.code_rate_LP = DVBFE_FEC_AUTO;
+			}
+		}
+
+		/* get frontend-specific tuning settings */
+		if (fe->ops.get_tune_settings &&
+		   (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
+
+			fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+			fepriv->max_drift = fetunesettings.max_drift;
+			fepriv->step_size = fetunesettings.step_size;
+		} else {
+			/* default values */
+			switch (fepriv->fe_info.delivery) {
+			case DVBFE_DELSYS_DVBS:
+				fepriv->min_delay = HZ / 20;
+				fepriv->step_size = fepriv->fe_params.delsys.dvbs.symbol_rate / 16000;
+				fepriv->max_drift = fepriv->fe_params.delsys.dvbs.symbol_rate / 2000;
+				break;
+			case DVBFE_DELSYS_DVBS2:
+				break;
+			case DVBFE_DELSYS_DSS:
+				break;
+			case DVBFE_DELSYS_DVBC:
+				fepriv->min_delay = HZ / 20;
+				fepriv->step_size = 0; /* no zigzag */
+				fepriv->max_drift = 0;
+				break;
+			case DVBFE_DELSYS_DVBT:
+				fepriv->min_delay = HZ / 20;
+				fepriv->step_size = fepriv->fe_info.frequency_step * 2;
+				fepriv->max_drift = (fepriv->fe_info.frequency_step * 2) + 1;
+				break;
+			case DVBFE_DELSYS_DVBH:
+				break;
+			case DVBFE_DELSYS_ATSC:
+				fepriv->min_delay = HZ / 20;
+				fepriv->step_size = 0;
+				fepriv->max_drift = 0;
+				break;
+			default:
+				return -EINVAL;
+			}
+		}
+		if (dvb_override_tune_delay > 0)
+			fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
+
+		fepriv->state = FESTATE_RETUNE;
+		dvb_frontend_wakeup(fe);
+		dvb_frontend_add_event(fe, 0);
+		fepriv->status = 0;
+		err = 0;
+		break;
+	}
+
+	case DVBFE_GET_PARAMS:
+		fe->legacy = 0;
+		if (fe->ops.get_params) {
+			memcpy(parg, &fepriv->fe_params, sizeof (struct dvbfe_params));
+			err = fe->ops.get_params(fe, (struct dvbfe_params*) parg);
+		}
+		break;
+	case DVBFE_GET_DELSYS:
+		fe->legacy = 0;
+		if (fe->ops.get_delsys) {
+			err = fe->ops.get_delsys(fe, (enum dvbfe_delsys *) parg);
+		}
+		break;
+	case DVBFE_GET_INFO:
+		printk("%s: DVBFE_GET_INFO\n", __func__);
+		fe->legacy = 0;
+		if (fe->ops.get_info) {
+			memcpy(&fepriv->fe_info, (struct dvbfe_info *) parg, sizeof (struct dvbfe_info));
+			err = fe->ops.get_info(fe, &fepriv->fe_info);
+			memcpy(parg, &fepriv->fe_info, sizeof (struct dvbfe_info));
+		}
+		break;
 	};
 
 	up (&fepriv->sem);
diff -Naurp v4l-dvb/linux/drivers/media/dvb/dvb-core/dvb_frontend.h mp-bc1/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
--- v4l-dvb/linux/drivers/media/dvb/dvb-core/dvb_frontend.h	2006-06-30 19:59:10.000000000 +0400
+++ mp-bc1/linux/drivers/media/dvb/dvb-core/dvb_frontend.h	2006-07-23 11:35:56.000000000 +0400
@@ -45,6 +45,7 @@ struct dvb_frontend_tune_settings {
 	int step_size;
 	int max_drift;
 	struct dvb_frontend_parameters parameters;
+	struct dvbfe_params fe_params;
 };
 
 struct dvb_frontend;
@@ -61,6 +62,73 @@ struct dvb_tuner_info {
 	u32 bandwidth_step;
 };
 
+enum dvbfe_modcod {
+	DVBFE_MODCOD_DUMMY_PLFRAME	= 0,
+	DVBFE_MODCOD_QPSK_1_4,
+	DVBFE_MODCOD_QPSK_1_3,
+	DVBFE_MODCOD_QPSK_2_5,
+	DVBFE_MODCOD_QPSK_1_2,
+	DVBFE_MODCOD_QPSK_3_5,
+	DVBFE_MODCOD_QPSK_2_3,
+	DVBFE_MODCOD_QPSK_3_4,
+	DVBFE_MODCOD_QPSK_4_5,
+	DVBFE_MODCOD_QPSK_5_6,
+	DVBFE_MODCOD_QPSK_8_9,
+	DVBFE_MODCOD_QPSK_9_10,
+	DVBFE_MODCOD_8PSK_3_5,
+	DVBFE_MODCOD_8PSK_2_3,
+	DVBFE_MODCOD_8PSK_3_4,
+	DVBFE_MODCOD_8PSK_5_6,
+	DVBFE_MODCOD_8PSK_8_9,
+	DVBFE_MODCOD_8PSK_9_10,
+	DVBFE_MODCOD_16APSK_2_3,
+	DVBFE_MODCOD_16APSK_3_4,
+	DVBFE_MODCOD_16APSK_4_5,
+	DVBFE_MODCOD_16APSK_5_6,
+	DVBFE_MODCOD_16APSK_8_9,
+	DVBFE_MODCOD_16APSK_9_10,
+	DVBFE_MODCOD_32APSK_3_4,
+	DVBFE_MODCOD_32APSK_4_5,
+	DVBFE_MODCOD_32APSK_5_6,
+	DVBFE_MODCOD_32APSK_8_9,
+	DVBFE_MODCOD_32APSK_9_10,
+	DVBFE_MODCOD_RESERVED_1,
+	DVBFE_MODCOD_BPSK_1_3,
+	DVBFE_MODCOD_BPSK_1_4,
+	DVBFE_MODCOD_RESERVED_2
+};
+
+enum tuner_param {
+	DVBFE_TUNER_FREQUENCY		= (1 <<  0),
+	DVBFE_TUNER_TUNERSTEP		= (1 <<  1),
+	DVBFE_TUNER_IFFREQ		= (1 <<  2),
+	DVBFE_TUNER_BANDWIDTH		= (1 <<  3),
+	DVBFE_TUNER_REFCLOCK		= (1 <<  4),
+	DVBFE_TUNER_IQSENSE		= (1 <<  5),
+	DVBFE_TUNER_DUMMY		= (1 << 31)
+};
+
+/**
+ *	ALGO_HW:	Frontend has/uses Hardware tuning algorithm
+ *	ALGO_SW:	Frontend has/uses Software tuning algorithm
+ *	ALGO_RECOVERY:	Frontend has Auto Recovery capabilities for
+ *			handling FE_HAS_LOCK failure
+ */
+enum dvbfe_algo {
+	DVBFE_ALGO_HW			= (1 <<  0),
+	DVBFE_ALGO_SW			= (1 <<  1),
+	DVBFE_ALGO_RECOVERY		= (1 <<  31)
+};
+
+struct tuner_state {
+	u32 frequency;
+	u32 tunerstep;
+	u32 ifreq;
+	u32 bandwidth;
+	u32 iqsense;
+	u32 refclock;
+};
+
 struct dvb_tuner_ops {
 
 	struct dvb_tuner_info info;
@@ -70,10 +138,12 @@ struct dvb_tuner_ops {
 	int (*sleep)(struct dvb_frontend *fe);
 
 	/** This is for simple PLLs - set all parameters in one go. */
-	int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+	int (*set_params_compat)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+	int (*set_params)(struct dvb_frontend *fe, struct dvbfe_params *p);
 
 	/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
-	int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
+	int (*calc_regs_compat)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
+	int (*calc_regs)(struct dvb_frontend *fe, struct dvbfe_params *p, u8 *buf, int buf_len);
 
 	int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
 	int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
@@ -81,10 +151,12 @@ struct dvb_tuner_ops {
 #define TUNER_STATUS_LOCKED 1
 	int (*get_status)(struct dvb_frontend *fe, u32 *status);
 
-	/** These are provided seperately from set_params in order to facilitate silicon
-	 * tuners which require sophisticated tuning loops, controlling each parameter seperately. */
-	int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
-	int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+	/**
+	 * These are provided seperately from set_params in order to facilitate silicon
+	 * tuners which require sophisticated tuning loops, controlling each parameter seperately.
+	 */
+	int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
+	int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
 };
 
 struct dvb_frontend_ops {
@@ -103,7 +175,7 @@ struct dvb_frontend_ops {
 		    int *delay,
 		    fe_status_t *status);
 	/* get frontend tuning algorithm from the module */
-	int (*get_frontend_algo)(struct dvb_frontend *fe);
+	enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
 
 	/* these two are only used for the swzigzag code */
 	int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
@@ -127,6 +199,18 @@ struct dvb_frontend_ops {
 	int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
 	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
 
+	/*	These callbacks are based on the superseding IOCTL's	*/
+	int (*set_params)(struct dvb_frontend *fe, struct dvbfe_params *fe_params);
+	int (*get_params)(struct dvb_frontend *fe, struct dvbfe_params *fe_params);
+	int (*get_info)(struct dvb_frontend *fe, struct dvbfe_info *fe_info);
+	int (*get_delsys)(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys);
+
+	/*	These callbacks are for devices that implement their own
+	 *	tuning algorithms, rather than a simple swzigzag
+	 */
+	int (*search)(struct dvb_frontend *fe, struct dvbfe_params *fe_params);
+	int (*track)(struct dvb_frontend *fe, struct dvbfe_params *fe_params);
+
 	struct dvb_tuner_ops tuner_ops;
 };
 
@@ -148,6 +232,7 @@ struct dvb_frontend {
 	void* tuner_priv;
 	void* frontend_priv;
 	void* misc_priv;
+	u32   legacy;
 };
 
 extern int dvb_register_frontend(struct dvb_adapter* dvb,
@@ -160,4 +245,8 @@ extern void dvb_frontend_reinitialise(st
 extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
 extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
 
+extern void decode_dvbs2_modcod(u32 modcod,
+				enum dvbfe_modulation *modulation,
+				enum dvbfe_fec *fec);
+
 #endif

_______________________________________________

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