summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/dvb-core
diff options
context:
space:
mode:
authorAndrew de Quincy <devnull@localhost>2004-03-11 18:40:44 +0000
committerAndrew de Quincy <devnull@localhost>2004-03-11 18:40:44 +0000
commit4881f248a09885725d1ad51ec35339ff4db2d81c (patch)
treef28e1ee6e7e472092c1a2a5e9ea55825c61f7c04 /linux/drivers/media/dvb/dvb-core
parent455c6bb685dcf96d46dc80361513fc6476d541e7 (diff)
downloadmediapointer-dvb-s2-4881f248a09885725d1ad51ec35339ff4db2d81c.tar.gz
mediapointer-dvb-s2-4881f248a09885725d1ad51ec35339ff4db2d81c.tar.bz2
Checked in experimental frontend patch
Also some minimal budget-ci CI support implemented (just detection+IRQs)
Diffstat (limited to 'linux/drivers/media/dvb/dvb-core')
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.c227
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.h14
2 files changed, 132 insertions, 109 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
index 07be5e758..84e9627aa 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -46,8 +46,8 @@
#define FESTATE_TUNED 16
#define FESTATE_ZIGZAG_FAST 32
#define FESTATE_ZIGZAG_SLOW 64
-#define FESTATE_CLEAN_SETUP 128
-#define FESTATE_SEARCHING (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
+#define FESTATE_DISEQC 128
+#define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC)
#define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
#define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
@@ -59,8 +59,8 @@
* FESTATE_TUNED. The frontend has successfully locked on.
* FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it.
* FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower.
- * FESTATE_CLEAN_SETUP. Used for certain dodgy tuners which need special massaging to lock.
- * FESTATE_SEARCHING. When we're searching for a signal using a zigzag scan of any sort.
+ * FESTATE_DISEQC. A DISEQC command has just been issued.
+ * FESTATE_WAITFORLOCK. When we're waiting for a lock.
* FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan.
* FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan.
* FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
@@ -69,7 +69,10 @@
static int dvb_frontend_debug = 0;
static int dvb_shutdown_timeout = 5;
-static int dvb_frequency_bending = 1;
+static int dvb_override_frequency_bending = 0;
+static int dvb_force_auto_inversion = 0;
+
+static int do_frequency_bending = 0;
#define dprintk if (dvb_frontend_debug) printk
@@ -100,9 +103,12 @@ struct dvb_frontend_data {
int bending;
int lnb_drift;
int inversion;
- int auto_count;
- int started_auto_count;
+ int auto_step;
+ int auto_sub_step;
+ int started_auto_step;
int min_delay;
+ int max_drift;
+ int step_size;
int exit;
fe_status_t status;
};
@@ -353,78 +359,50 @@ static void update_delay (int *quality, int *delay, int min_delay, int locked)
* Performs automatic twiddling of frontend parameters.
*
* @param fe The frontend concerned.
+ * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
* @returns Number of complete iterations that have been performed.
*/
-static int dvb_frontend_autotune(struct dvb_frontend_data *fe)
+static int dvb_frontend_autotune(struct dvb_frontend_data *fe, int check_wrapped)
{
- int stepsize;
- int maxdrift;
int autoinversion;
int ready = 0;
- int wrapped = 0;
int original_inversion = fe->parameters.inversion;
u32 original_frequency = fe->parameters.frequency;
dprintk ("%s\n", __FUNCTION__);
- // choose step size for zigzag scan
- switch(fe->info->type) {
- case FE_QPSK:
- if (fe->parameters.u.qpsk.symbol_rate < 10000000) {
- stepsize = fe->parameters.u.qpsk.symbol_rate / 32000;
- maxdrift = 5000;
- } else {
- stepsize = fe->parameters.u.qpsk.symbol_rate / 16000;
- maxdrift = fe->parameters.u.qpsk.symbol_rate / 2000;
- }
- break;
-
- case FE_QAM:
- stepsize = 1;
- maxdrift = 0; // don't want any zigzagging under DVB-C frontends
- break;
-
- case FE_OFDM:
- stepsize = fe->info->frequency_stepsize * 2;
- maxdrift = (fe->info->frequency_stepsize * 2) + 1;
- break;
-
- default:
- printk("Unknown frontend type %i\n", fe->info->type);
- return 0;
- }
-
// are we using autoinversion?
autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO));
// setup parameters correctly
while(!ready) {
- // wrap the count if we've reached the maximum drift
- fe->lnb_drift = (fe->auto_count / 4) * stepsize;
- if (fe->lnb_drift >= maxdrift) {
- fe->auto_count = 0;
+ // calculate the lnb_drift
+ fe->lnb_drift = fe->auto_step * fe->step_size;
+
+ // wrap the auto_step if we've exceeded the maximum drift
+ if (fe->lnb_drift > fe->max_drift) {
+ fe->auto_step = 0;
+ fe->auto_sub_step = 0;
fe->lnb_drift = 0;
- wrapped = 1;
}
-
+
// perform inversion and +/- zigzag
- switch(fe->auto_count % 4) {
+ switch(fe->auto_sub_step) {
case 0:
- fe->inversion = INVERSION_OFF;
+ // try with the current inversion and current drift setting
ready = 1;
break;
case 1:
if (!autoinversion) break;
- fe->inversion = INVERSION_ON;
+ fe->inversion = (fe->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
ready = 1;
break;
case 2:
if (fe->lnb_drift == 0) break;
- fe->inversion = INVERSION_OFF;
fe->lnb_drift = -fe->lnb_drift;
ready = 1;
break;
@@ -433,32 +411,38 @@ static int dvb_frontend_autotune(struct dvb_frontend_data *fe)
if (fe->lnb_drift == 0) break;
if (!autoinversion) break;
- fe->inversion = INVERSION_ON;
+ fe->inversion = (fe->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
fe->lnb_drift = -fe->lnb_drift;
ready = 1;
break;
+
+ default:
+ fe->auto_step++;
+ fe->auto_sub_step = -1; // it'll be incremented to 0 in a moment
+ break;
}
- if (!ready) fe->auto_count++;
+ if (!ready) fe->auto_sub_step++;
+ }
+
+ // if this attempt would hit where we started, indicate a complete iteration has occurred
+ if ((fe->auto_step == fe->started_auto_step) && (fe->auto_sub_step == 0) && check_wrapped) {
+ return 1;
}
-
- // perform frequency bending if enabled
- if (dvb_frequency_bending)
+
+ // perform frequency bending if necessary
+ if ((dvb_override_frequency_bending != 1) && do_frequency_bending)
dvb_bend_frequency(fe, 0);
-
+
// set the frontend itself
fe->parameters.frequency += fe->lnb_drift + fe->bending;
if (autoinversion) fe->parameters.inversion = fe->inversion;
dvb_frontend_internal_ioctl (&fe->frontend, FE_SET_FRONTEND, &fe->parameters);
fe->parameters.frequency = original_frequency;
fe->parameters.inversion = original_inversion;
-
- // reset frontend IRQ bits to clean error stats
- dvb_frontend_internal_ioctl (&fe->frontend, FE_RESET, NULL);
- // if we've hit where we started from, indicate a complete iteration has occurred
- fe->auto_count++;
- if ((fe->auto_count == fe->started_auto_count) || (fe->started_auto_count==0 && wrapped)) return 1;
+ // normal return
+ fe->auto_sub_step++;
return 0;
}
@@ -483,8 +467,8 @@ static int dvb_frontend_thread (void *data)
unsigned long timeout;
char name [15];
int quality = 0, delay = 3*HZ;
- int clean_setup_count = 0;
fe_status_t s;
+ int check_wrapped = 0;
dprintk ("%s\n", __FUNCTION__);
@@ -521,17 +505,17 @@ static int dvb_frontend_thread (void *data)
dvb_frontend_add_event (fe, s);
// if we're not tuned, and we have a lock, move to the TUNED state
- if ((fe->state & FESTATE_SEARCHING) && (s & FE_HAS_LOCK)) {
+ if ((fe->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
fe->state = FESTATE_TUNED;
-
+
// if we're tuned, then we have determined the correct inversion
if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)) {
fe->parameters.inversion = fe->inversion;
}
continue;
}
-
+
// if we are tuned already, check we're still locked
if (fe->state & FESTATE_TUNED) {
update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
@@ -542,46 +526,56 @@ static int dvb_frontend_thread (void *data)
} else {
// if we _WERE_ tuned, but now don't have a lock, need to zigzag
fe->state = FESTATE_ZIGZAG_FAST;
- fe->started_auto_count = fe->auto_count;
+ fe->started_auto_step = fe->auto_step;
+ check_wrapped = 0;
// fallthrough
}
}
- // don't actually do anything if we're in the LOSTLOCK state
- // and the frontend can recover automatically
- if ((fe->state & FESTATE_LOSTLOCK) && (fe->info->caps & FE_CAN_RECOVER)) {
+ // 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 ((fe->state & FESTATE_LOSTLOCK) &&
+ (fe->info->caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) {
+ update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
+ continue;
+ }
+
+ // 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 (fe->state & FESTATE_DISEQC) {
update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
continue;
}
-
- // if we're in the RETUNE state, set everything up for a brand new scan
+
+ // if we're in the RETUNE state, set everything up for a brand new scan,
+ // keeping the current inversion setting, as the next tune is _very_ likely
+ // to require the same
if (fe->state & FESTATE_RETUNE) {
fe->lnb_drift = 0;
- fe->inversion = INVERSION_OFF;
- fe->auto_count = 0;
- fe->started_auto_count = 0;
- clean_setup_count = 0;
+ fe->auto_step = 0;
+ fe->auto_sub_step = 0;
+ fe->started_auto_step = 0;
+ check_wrapped = 0;
}
-
+
// fast zigzag.
if ((fe->state & FESTATE_SEARCHING_FAST) || (fe->state & FESTATE_RETUNE)) {
delay = fe->min_delay;
-
- // OK, if we've run out of trials at the fast speed. Drop back to
- // slow for the _next_ attempt
- if (dvb_frontend_autotune(fe)) {
+
+ // peform a tune
+ if (dvb_frontend_autotune(fe, check_wrapped)) {
+ // OK, if we've run out of trials at the fast speed. Drop back to
+ // slow for the _next_ attempt
fe->state = FESTATE_SEARCHING_SLOW;
- fe->started_auto_count = fe->auto_count;
+ fe->started_auto_step = fe->auto_step;
continue;
}
+ check_wrapped = 1;
- // enter clean setup state after the first tune if necessary. yeuch
- if ((!(fe->info->caps & FE_CAN_CLEAN_SETUP)) && (clean_setup_count == 0)) {
- fe->state = FESTATE_CLEAN_SETUP;
- }
-
// if we've just retuned, enter the ZIGZAG_FAST state. This ensures
- // we cannot return from an FE_SET_FRONTEND before the retune occurs.
+ // we cannot return from an FE_SET_FRONTEND ioctl before the first frontend
+ // tune occurs
if (fe->state & FESTATE_RETUNE) {
fe->state = FESTATE_TUNING_FAST;
}
@@ -590,18 +584,10 @@ static int dvb_frontend_thread (void *data)
// slow zigzag
if (fe->state & FESTATE_SEARCHING_SLOW) {
update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
- dvb_frontend_autotune(fe);
- }
-
- // clean setup
- if (fe->state & FESTATE_CLEAN_SETUP) {
- if ((clean_setup_count < 10) && (!(s & FE_HAS_LOCK))) {
- dvb_frontend_internal_ioctl(&fe->frontend, FE_RESET, NULL);
- } else {
- // return to tuning state
- fe->state = FESTATE_TUNING_FAST;
- }
- clean_setup_count++;
+
+ // Note: don't bother checking for wrapping; we stay in this state
+ // until we get a lock
+ dvb_frontend_autotune(fe, 0);
}
};
@@ -713,8 +699,8 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend_data *fe = dvbdev->priv;
+ struct dvb_frontend_tune_settings fetunesettings;
int err = 0;
- int delay_ms;
dprintk ("%s\n", __FUNCTION__);
@@ -731,7 +717,7 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
if (fe->status)
dvb_call_frontend_notifiers (fe, 0);
dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg);
- fe->state = FESTATE_IDLE;
+ fe->state = FESTATE_DISEQC;
break;
case FE_SET_FRONTEND:
@@ -740,20 +726,40 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
memcpy (&fe->parameters, parg,
sizeof (struct dvb_frontend_parameters));
- delay_ms = dvb_frontend_internal_ioctl(&fe->frontend, FE_GETMINDELAY, &fe->parameters);
- if (delay_ms >= 0) fe->min_delay = (delay_ms * HZ) / 1000;
- else {
+ memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
+ memcpy(&fetunesettings.parameters, parg,
+ sizeof (struct dvb_frontend_parameters));
+
+ // force auto frequency inversion if requested
+ if (dvb_force_auto_inversion) {
+ fe->parameters.inversion = INVERSION_AUTO;
+ fetunesettings.parameters.inversion = INVERSION_AUTO;
+ }
+
+ // get frontend-specific tuning settings
+ if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS, &fetunesettings) == 0) {
+ fe->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+ fe->max_drift = fetunesettings.max_drift;
+ fe->step_size = fetunesettings.step_size;
+ } else {
+ // default values
switch(fe->info->type) {
case FE_QPSK:
fe->min_delay = HZ/20; // default mindelay of 50ms
+ fe->step_size = fe->parameters.u.qpsk.symbol_rate / 16000;
+ fe->max_drift = fe->parameters.u.qpsk.symbol_rate / 2000;
break;
case FE_QAM:
fe->min_delay = HZ/20; // default mindelay of 50ms
+ fe->step_size = 0;
+ fe->max_drift = 0; // don't want any zigzagging under DVB-C frontends
break;
case FE_OFDM:
- fe->min_delay = HZ/10; // default mindelay of 100ms
+ fe->min_delay = HZ/20; // default mindelay of 50ms
+ fe->step_size = fe->info->frequency_stepsize * 2;
+ fe->max_drift = (fe->info->frequency_stepsize * 2) + 1;
break;
}
}
@@ -764,7 +770,7 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
case FE_GET_EVENT:
err = dvb_frontend_get_event (fe, parg, file->f_flags);
break;
-
+
case FE_GET_FRONTEND:
memcpy (parg, &fe->parameters,
sizeof (struct dvb_frontend_parameters));
@@ -1089,6 +1095,7 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
fe->frontend.i2c = i2c;
fe->frontend.data = data;
fe->info = info;
+ fe->inversion = INVERSION_OFF;
list_for_each (entry, &frontend_ioctl_list) {
struct dvb_frontend_ioctl_data *ioctl;
@@ -1128,6 +1135,9 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
dvb_register_device (i2c->adapter, &fe->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND);
+ if ((info->caps & FE_NEEDS_BENDING) || (dvb_override_frequency_bending == 2))
+ do_frequency_bending = 1;
+
up (&frontend_mutex);
return 0;
@@ -1165,7 +1175,10 @@ int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
MODULE_PARM(dvb_frontend_debug,"i");
MODULE_PARM(dvb_shutdown_timeout,"i");
-MODULE_PARM(dvb_frequency_bending,"i");
+MODULE_PARM(dvb_override_frequency_bending,"i");
+MODULE_PARM(dvb_force_auto_inversion,"i");
+
MODULE_PARM_DESC(dvb_frontend_debug, "enable verbose debug messages");
MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
-MODULE_PARM_DESC(dvb_frequency_bending, "0: disable frequency bending, 1: enable (default)");
+MODULE_PARM_DESC(dvb_override_frequency_bending, "0: normal (default), 1: never use frequency bending, 2: always use frequency bending");
+MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
index 4ab2f6b0c..affabab88 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -56,15 +56,25 @@ struct dvb_frontend {
void *data; /* can be used by hardware module... */
};
+struct dvb_frontend_tune_settings {
+ int min_delay_ms;
+ int step_size;
+ int max_drift;
+ struct dvb_frontend_parameters parameters;
+};
+
/**
* private frontend command ioctl's.
* keep them in sync with the public ones defined in linux/dvb/frontend.h
+ *
+ * FE_SLEEP. Ioctl used to put frontend into a low power mode.
+ * FE_INIT. Ioctl used to initialise the frontend.
+ * FE_GET_TUNE_SETTINGS. Get the frontend-specific tuning loop settings for the supplied set of parameters.
*/
#define FE_SLEEP _IO('v', 80)
#define FE_INIT _IO('v', 81)
-#define FE_RESET _IO('v', 82)
-#define FE_GETMINDELAY _IOW('v', 83, struct dvb_frontend_parameters)
+#define FE_GET_TUNE_SETTINGS _IOWR('v', 83, struct dvb_frontend_tune_settings)
extern int