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