Prechádzať zdrojové kódy

V4L/DVB (9344): DVB-Core update

Signed-off-by: Manu Abraham <manu@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Manu Abraham 16 rokov pred
rodič
commit
c59e7870fd

+ 59 - 7
drivers/media/dvb/dvb-core/dvb_frontend.c

@@ -128,6 +128,7 @@ struct dvb_frontend_private {
 	unsigned int step_size;
 	int quality;
 	unsigned int check_wrapped;
+	enum dvbfe_search algo_status;
 };
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -516,6 +517,8 @@ static int dvb_frontend_thread(void *data)
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	unsigned long timeout;
 	fe_status_t s;
+	enum dvbfe_algo algo;
+
 	struct dvb_frontend_parameters *params;
 
 	dprintk("%s\n", __func__);
@@ -562,23 +565,72 @@ restart:
 
 		/* do an iteration of the tuning loop */
 		if (fe->ops.get_frontend_algo) {
-			if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
-				/* have we been asked to retune? */
-				params = NULL;
+			algo = fe->ops.get_frontend_algo(fe);
+			switch (algo) {
+			case DVBFE_ALGO_HW:
+				dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
+				params = NULL; /* have we been asked to RETUNE ? */
+
 				if (fepriv->state & FESTATE_RETUNE) {
-					params = &fepriv->parameters;
+					dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
 					fepriv->state = FESTATE_TUNED;
 				}
 
-				fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+				if (fe->ops.tune)
+					fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+
 				if (s != fepriv->status) {
+					dprintk("%s: state changed, adding current state\n", __func__);
 					dvb_frontend_add_event(fe, s);
 					fepriv->status = s;
 				}
-			} else
+				break;
+			case DVBFE_ALGO_SW:
+				dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
 				dvb_frontend_swzigzag(fe);
-		} else
+				break;
+			case DVBFE_ALGO_CUSTOM:
+				params = NULL; /* have we been asked to RETUNE ?	*/
+				dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
+				if (fepriv->state & FESTATE_RETUNE) {
+					dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
+					fepriv->state = FESTATE_TUNED;
+				}
+				/* Case where we are going to search for a carrier
+				 * User asked us to retune again for some reason, possibly
+				 * requesting a search with a new set of parameters
+				 */
+				if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
+					if (fe->ops.search)
+						fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters);
+						/* We did do a search as was requested, the flags are
+						 * now unset as well and has the flags wrt to search.
+						 */
+
+					fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN;
+				}
+				/* Track the carrier if the search was successful */
+				if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
+					if (fepriv->algo_status & DVBFE_ALGO_SEARCH_SUCCESS)
+						dprintk("%s: status = DVBFE_ALGO_SEARCH_SUCCESS\n", __func__);
+					if (fepriv->algo_status & DVBFE_ALGO_SEARCH_FAILED)
+						fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
+					fe->ops.read_status(fe, &s);
+					dvb_frontend_add_event(fe, s); /* update event list */
+					fepriv->status = s;
+					if (fe->ops.track)
+						fe->ops.track(fe, &fepriv->parameters);
+
+				}
+				break;
+			default:
+				dprintk("%s: UNDEFINED ALGO !\n", __func__);
+				break;
+			}
+		} else {
 			dvb_frontend_swzigzag(fe);
+		}
 	}
 
 	if (dvb_powerdown_on_sleep) {

+ 133 - 1
drivers/media/dvb/dvb-core/dvb_frontend.h

@@ -69,6 +69,125 @@ struct analog_parameters {
 	u64 std;
 };
 
+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: (Hardware Algorithm)
+ * ----------------------------------------------------------------
+ * Devices that support this algorithm do everything in hardware
+ * and no software support is needed to handle them.
+ * Requesting these devices to LOCK is the only thing required,
+ * device is supposed to do everything in the hardware.
+ *
+ * ALGO_SW: (Software Algorithm)
+ * ----------------------------------------------------------------
+ * These are dumb devices, that require software to do everything
+ *
+ * ALGO_CUSTOM: (Customizable Agorithm)
+ * ----------------------------------------------------------------
+ * Devices having this algorithm can be customized to have specific
+ * algorithms in the frontend driver, rather than simply doing a
+ * software zig-zag. In this case the zigzag maybe hardware assisted
+ * or it maybe completely done in hardware. In all cases, usage of
+ * this algorithm, in conjunction with the search and track
+ * callbacks, utilizes the driver specific algorithm.
+ *
+ * ALGO_RECOVERY: (Recovery Algorithm)
+ * ----------------------------------------------------------------
+ * These devices have AUTO recovery capabilities from LOCK failure
+ */
+enum dvbfe_algo {
+	DVBFE_ALGO_HW			= (1 <<  0),
+	DVBFE_ALGO_SW			= (1 <<  1),
+	DVBFE_ALGO_CUSTOM		= (1 <<  2),
+	DVBFE_ALGO_RECOVERY		= (1 << 31)
+};
+
+struct tuner_state {
+	u32 frequency;
+	u32 tunerstep;
+	u32 ifreq;
+	u32 bandwidth;
+	u32 iqsense;
+	u32 refclock;
+};
+
+/*
+ * search callback possible return status
+ *
+ * DVBFE_ALGO_SEARCH_SUCCESS
+ * The frontend search algorithm completed and returned succesfully
+ *
+ * DVBFE_ALGO_SEARCH_ASLEEP
+ * The frontend search algorithm is sleeping
+ *
+ * DVBFE_ALGO_SEARCH_FAILED
+ * The frontend search for a signal failed
+ *
+ * DVBFE_ALGO_SEARCH_INVALID
+ * The frontend search algorith was probably supplied with invalid
+ * parameters and the search is an invalid one
+ *
+ * DVBFE_ALGO_SEARCH_ERROR
+ * The frontend search algorithm failed due to some error
+ *
+ * DVBFE_ALGO_SEARCH_AGAIN
+ * The frontend search algorithm was requested to search again
+ */
+enum dvbfe_search {
+	DVBFE_ALGO_SEARCH_SUCCESS	= (1 <<  0),
+	DVBFE_ALGO_SEARCH_ASLEEP	= (1 <<  1),
+	DVBFE_ALGO_SEARCH_FAILED	= (1 <<  2),
+	DVBFE_ALGO_SEARCH_INVALID	= (1 <<  3),
+	DVBFE_ALGO_SEARCH_AGAIN		= (1 <<  4),
+	DVBFE_ALGO_SEARCH_ERROR		= (1 << 31),
+};
+
+
 struct dvb_tuner_ops {
 
 	struct dvb_tuner_info info;
@@ -99,6 +218,13 @@ struct dvb_tuner_ops {
 	 * 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 analog_demod_info {
@@ -142,7 +268,7 @@ struct dvb_frontend_ops {
 		    unsigned 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);
@@ -167,6 +293,12 @@ struct dvb_frontend_ops {
 	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
 	int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
 
+	/* These callbacks are for devices that implement their own
+	 * tuning algorithms, rather than a simple swzigzag
+	 */
+	enum dvbfe_search (*search)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+	int (*track)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+
 	struct dvb_tuner_ops tuner_ops;
 	struct analog_demod_ops analog_ops;