diff options
author | Andrew de Quincy <devnull@localhost> | 2004-03-11 18:40:44 +0000 |
---|---|---|
committer | Andrew de Quincy <devnull@localhost> | 2004-03-11 18:40:44 +0000 |
commit | 4881f248a09885725d1ad51ec35339ff4db2d81c (patch) | |
tree | f28e1ee6e7e472092c1a2a5e9ea55825c61f7c04 /linux/drivers/media/dvb/dvb-core | |
parent | 455c6bb685dcf96d46dc80361513fc6476d541e7 (diff) | |
download | mediapointer-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.c | 227 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_frontend.h | 14 |
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 |