V4L/DVB (9344): DVB-Core update
authorManu Abraham <abraham.manu@gmail.com>
Tue, 14 Oct 2008 19:34:07 +0000 (16:34 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 29 Dec 2008 19:53:12 +0000 (17:53 -0200)
Signed-off-by: Manu Abraham <manu@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.h

index 7a421e9..d006f04 100644 (file)
@@ -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) {
index db4a63b..e176da4 100644 (file)
@@ -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;