module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off).");
module_param(dvb_shutdown_timeout, int, 0644);
MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
module_param(dvb_force_auto_inversion, int, 0644);
MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
module_param(dvb_override_tune_delay, int, 0644);
MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
module_param(dvb_powerdown_on_sleep, int, 0644);
MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
module_param(dvb_mfe_wait_time, int, 0644);
MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)");
staticenum dvbv3_emulation_type dvbv3_type(u32 delivery_system)
{ switch (delivery_system) { case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: return DVBV3_QAM; case SYS_DVBS: case SYS_DVBS2: case SYS_TURBO: case SYS_ISDBS: case SYS_DSS: return DVBV3_QPSK; case SYS_DVBT: case SYS_DVBT2: case SYS_ISDBT: case SYS_DTMB: return DVBV3_OFDM; case SYS_ATSC: case SYS_ATSCMH: case SYS_DVBC_ANNEX_B: return DVBV3_ATSC; case SYS_UNDEFINED: case SYS_ISDBC: case SYS_DVBH: case SYS_DAB: default: /* *Doesn'tknowhowtoemulatethosetypesand/or *there'snofrontenddriverfromthistypeyet *withsomeemulationcode,so,we'renotsureyethow *tohandlethem,orthey'renotcompatiblewithaDVBv3call.
*/ return DVBV3_UNKNOWN;
}
}
if (fe->ops.init)
fe->ops.init(fe); if (fe->ops.tuner_ops.init) { if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.init(fe); if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
}
/** *dvb_frontend_swzigzag_autotune-Performsautomatictwiddlingoffrontend *parameters. * *@fe:Thefrontendconcerned. *@check_wrapped:Checksifaniterationhascompleted. *DONOTSETONTHEFIRSTATTEMPT. * *return:Numberofcompleteiterationsthathavebeenperformed.
*/ staticint dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
{ int autoinversion; int ready = 0; int fe_set_err = 0; struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp; int original_inversion = c->inversion;
u32 original_frequency = c->frequency;
/* are we using autoinversion? */
autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
(c->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;
fepriv->auto_sub_step = 0;
fepriv->lnb_drift = 0;
}
/* perform inversion and +/- zigzag */ switch (fepriv->auto_sub_step) { case0: /* try with the current inversion and current drift setting */
ready = 1; break;
/* if this attempt would hit where we started, indicate a complete
* iteration has occurred */ if ((fepriv->auto_step == fepriv->started_auto_step) &&
(fepriv->auto_sub_step == 0) && check_wrapped) { return1;
}
if (fepriv->max_drift)
dev_warn_once(fe->dvb->device, "Frontend requested software zigzag, but didn't set the frequency step size\n");
/* if we've got no parameters, just keep idling */ if (fepriv->state & FESTATE_IDLE) {
fepriv->delay = 3 * HZ;
fepriv->quality = 0; return;
}
/* 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) {
tmp = *c; if (fe->ops.set_frontend)
retval = fe->ops.set_frontend(fe);
*c = tmp; if (retval < 0)
fepriv->state = FESTATE_ERROR; else
fepriv->state = FESTATE_TUNED;
}
fepriv->delay = 3 * HZ;
fepriv->quality = 0; return;
}
/* get the frontend status */ if (fepriv->state & FESTATE_RETUNE) {
s = 0;
} else { if (fe->ops.read_status)
fe->ops.read_status(fe, &s); if (s != fepriv->status) {
dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
}
/* if we're not tuned, and we have a lock, move to the TUNED state */ if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
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)) &&
(c->inversion == INVERSION_AUTO)) {
c->inversion = fepriv->inversion;
} return;
}
/* if we are tuned already, check we're still locked */ if (fepriv->state & FESTATE_TUNED) {
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
/* we're tuned, and the lock is still good... */ if (s & FE_HAS_LOCK) { return;
} else { /* if we _WERE_ tuned, but now don't have a lock */
fepriv->state = FESTATE_ZIGZAG_FAST;
fepriv->started_auto_step = fepriv->auto_step;
fepriv->check_wrapped = 0;
}
}
/* 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;
}
/* don't do anything if we're in the DISEQC state, since this *mightbesomeonewithamotorizeddishcontrolledbyDISEQC.
* 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;
}
/* if we're in the RETUNE state, set everything up for a brand *newscan,keepingthecurrentinversionsetting,asthenext
* tune is _very_ likely to require the same */ if (fepriv->state & FESTATE_RETUNE) {
fepriv->lnb_drift = 0;
fepriv->auto_step = 0;
fepriv->auto_sub_step = 0;
fepriv->started_auto_step = 0;
fepriv->check_wrapped = 0;
}
/* fast zigzag. */ if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
fepriv->delay = fepriv->min_delay;
/* perform a tune */
retval = dvb_frontend_swzigzag_autotune(fe,
fepriv->check_wrapped); if (retval < 0) { return;
} elseif (retval) { /* OK, if we've run out of trials at the fast speed.
* Drop back to slow for the _next_ attempt */
fepriv->state = FESTATE_SEARCHING_SLOW;
fepriv->started_auto_step = fepriv->auto_step; return;
}
fepriv->check_wrapped = 1;
/* if we've just re-tuned, enter the ZIGZAG_FAST state. *Thisensureswecannotreturnfroman *FE_SET_FRONTENDioctlbeforethefirstfrontendtune
* occurs */ if (fepriv->state & FESTATE_RETUNE) {
fepriv->state = FESTATE_TUNING_FAST;
}
}
/* slow zigzag */ if (fepriv->state & FESTATE_SEARCHING_SLOW) {
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
/* Note: don't bother checking for wrapping; we stay in this
* state until we get a lock */
dvb_frontend_swzigzag_autotune(fe, 0);
}
}
set_freezable(); while (1) {
up(&fepriv->sem); /* is locked when we enter the thread... */
wait_event_freezable_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe) ||
kthread_should_stop(),
fepriv->delay);
if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { /* got signal or quitting */ if (!down_interruptible(&fepriv->sem))
semheld = true;
fe->exit = DVB_FE_NORMAL_EXIT; break;
}
if (down_interruptible(&fepriv->sem)) break;
if (fepriv->reinitialise) {
dvb_frontend_init(fe); if (fe->ops.set_tone && fepriv->tone != -1)
fe->ops.set_tone(fe, fepriv->tone); if (fe->ops.set_voltage && fepriv->voltage != -1)
fe->ops.set_voltage(fe, fepriv->voltage);
fepriv->reinitialise = 0;
}
/* do an iteration of the tuning loop */ if (fe->ops.get_frontend_algo) {
algo = fe->ops.get_frontend_algo(fe); switch (algo) { case DVBFE_ALGO_HW:
dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
if (fe->ops.tune)
fe->ops.tune(fe, re_tune, fepriv->tune_mode_flags, &fepriv->delay, &s);
if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) {
dev_dbg(fe->dvb->device, "%s: state changed, adding current state\n", __func__);
dvb_frontend_add_event(fe, s);
fepriv->status = s;
} break; case DVBFE_ALGO_SW:
dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
dvb_frontend_swzigzag(fe); break; case DVBFE_ALGO_CUSTOM:
dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); if (fepriv->state & FESTATE_RETUNE) {
dev_dbg(fe->dvb->device, "%s: Retune requested, FESTAT_RETUNE\n", __func__);
fepriv->state = FESTATE_TUNED;
} /* Case where we are going to search for a carrier *Useraskedustoretuneagainforsomereason,possibly *requestingasearchwithanewsetofparameters
*/ if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { if (fe->ops.search) {
fepriv->algo_status = fe->ops.search(fe); /* We did do a search as was requested, the flags are *nowunsetaswellandhastheflagswrttosearch.
*/
} else {
fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN;
}
} /* Track the carrier if the search was successful */ if (fepriv->algo_status != DVBFE_ALGO_SEARCH_SUCCESS) {
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
fepriv->delay = HZ / 2;
}
dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out);
fe->ops.read_status(fe, &s); if (s != fepriv->status) {
dvb_frontend_add_event(fe, s); /* update event list */
fepriv->status = s; if (!(s & FE_HAS_LOCK)) {
fepriv->delay = HZ / 10;
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
} else {
fepriv->delay = 60 * HZ;
}
} break; default:
dev_dbg(fe->dvb->device, "%s: UNDEFINED ALGO !\n", __func__); break;
}
} else {
dvb_frontend_swzigzag(fe);
}
}
if (dvb_powerdown_on_sleep) { if (fe->ops.set_voltage)
fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); if (fe->ops.tuner_ops.sleep) { if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.sleep(fe); if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
} if (fe->ops.sleep)
fe->ops.sleep(fe);
}
/* paranoia check in case a signal arrived */ if (fepriv->thread)
dev_warn(fe->dvb->device, "dvb_frontend_stop: warning: thread %p won't exit\n",
fepriv->thread);
}
/* If the standard is for satellite, convert frequencies to kHz */ switch (c->delivery_system) { case SYS_DSS: case SYS_DVBS: case SYS_DVBS2: case SYS_TURBO: case SYS_ISDBS:
*freq_min /= kHz;
*freq_max /= kHz; if (tolerance)
*tolerance = fe->ops.info.frequency_tolerance_hz / kHz;
break; default: if (tolerance)
*tolerance = fe->ops.info.frequency_tolerance_hz; break;
}
}
/* range check: frequency */
dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max, NULL); if ((freq_min && c->frequency < freq_min) ||
(freq_max && c->frequency > freq_max)) {
dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
fe->dvb->num, fe->id, c->frequency,
freq_min, freq_max); return -EINVAL;
}
/* range check: symbol rate */ switch (c->delivery_system) { case SYS_DSS: case SYS_DVBS: case SYS_DVBS2: case SYS_TURBO: case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: if ((fe->ops.info.symbol_rate_min &&
c->symbol_rate < fe->ops.info.symbol_rate_min) ||
(fe->ops.info.symbol_rate_max &&
c->symbol_rate > fe->ops.info.symbol_rate_max)) {
dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
fe->dvb->num, fe->id, c->symbol_rate,
fe->ops.info.symbol_rate_min,
fe->ops.info.symbol_rate_max); return -EINVAL;
} break; default: break;
}
if (fe->ops.get_frontend) {
r = fe->ops.get_frontend(fe, c); if (unlikely(r < 0)) return r; if (p_out)
dtv_property_legacy_params_sync(fe, c, p_out); return0;
}
/* As everything is in cache, get_frontend fops are always supported */ return0;
}
/* *IfthecallisforISDB-T,putitintofull-seg,automode,TV
*/ if (c->delivery_system == SYS_ISDBT) {
dev_dbg(fe->dvb->device, "%s: Using defaults for SYS_ISDBT\n",
__func__);
if (!c->bandwidth_hz)
c->bandwidth_hz = 6000000;
c->isdbt_partial_reception = 0;
c->isdbt_sb_mode = 0;
c->isdbt_sb_subchannel = 0;
c->isdbt_sb_segment_idx = 0;
c->isdbt_sb_segment_count = 0;
c->isdbt_layer_enabled = 7; for (i = 0; i < 3; i++) {
c->layer[i].fec = FEC_AUTO;
c->layer[i].modulation = QAM_AUTO;
c->layer[i].interleaving = 0;
c->layer[i].segment_count = 0;
}
}
dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
__func__, c->delivery_system);
/* There's nothing compatible with the desired delivery system */ if (delsys == SYS_UNDEFINED) {
dev_dbg(fe->dvb->device, "%s: Delivery system %d not supported on emulation mode.\n",
__func__, desired_system); return -EINVAL;
}
dev_dbg(fe->dvb->device, "%s: Using delivery system %d emulated as if it were %d\n",
__func__, delsys, desired_system);
/* If not set yet, defaults to the first supported delivery system */ if (c->delivery_system == SYS_UNDEFINED)
c->delivery_system = fe->ops.delsys[0];
/* *Trivialcase:justusethecurrentone,ifitalreadyaDVBv3 *deliverysystem
*/ if (is_dvbv3_delsys(c->delivery_system)) {
dev_dbg(fe->dvb->device, "%s: Using delivery system to %d\n",
__func__, c->delivery_system); return0;
}
/* *Seekforthefirstdeliverysystemthatitiscompatiblewitha *DVBv3standard
*/
ncaps = 0; while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) { if (dvbv3_type(fe->ops.delsys[ncaps]) != DVBV3_UNKNOWN) {
delsys = fe->ops.delsys[ncaps]; break;
}
ncaps++;
} if (delsys == SYS_UNDEFINED) {
dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that works with FE_SET_FRONTEND\n",
__func__); return -EINVAL;
} return emulate_delivery_system(fe, delsys);
}
/* *Associatethe4deliverysystemssupportedbyDVBv3 *APIwiththeirDVBv5counterpart.Fortheotherstandards, *usetheclosesttype,assumingthatitwouldhopefully *workwithaDVBv3application. *Itshouldbenoticedthat,onmulti-frontenddeviceswith *differenttypes(terrestrialandcable,forexample), *apureDVBv3applicationwon'tbeabletousealldelivery *systems.Yet,changingtheDVBv5cachetotheotherdelivery *systemshouldbeenoughformakingitwork.
*/ switch (dvbv3_type(c->delivery_system)) { case DVBV3_QPSK:
info->type = FE_QPSK; break; case DVBV3_ATSC:
info->type = FE_ATSC; break; case DVBV3_QAM:
info->type = FE_QAM; break; case DVBV3_OFDM:
info->type = FE_OFDM; break; default:
dev_err(fe->dvb->device, "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
__func__, c->delivery_system);
info->type = FE_OFDM;
}
dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n",
__func__, c->delivery_system, info->type);
/* Set CAN_INVERSION_AUTO bit on in other than oneshot mode */ if (!(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT))
info->caps |= FE_CAN_INVERSION_AUTO;
err = 0; break;
}
case FE_READ_STATUS: { enum fe_status *status = parg;
/* if retune was requested but hasn't occurred yet, prevent
* that user get signal state from previous tuning */ if (fepriv->state == FESTATE_RETUNE ||
fepriv->state == FESTATE_ERROR) {
err = 0;
*status = 0; break;
}
if (fe->ops.read_status)
err = fe->ops.read_status(fe, status); break;
}
case FE_DISEQC_RESET_OVERLOAD: if (fe->ops.diseqc_reset_overload) {
err = fe->ops.diseqc_reset_overload(fe);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
} break;
case FE_DISEQC_SEND_MASTER_CMD: if (fe->ops.diseqc_send_master_cmd) { struct dvb_diseqc_master_cmd *cmd = parg;
case FE_DISEQC_SEND_BURST: if (fe->ops.diseqc_send_burst) {
err = fe->ops.diseqc_send_burst(fe, (long)parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
} break;
case FE_SET_TONE: if (fe->ops.set_tone) {
fepriv->tone = (long)parg;
err = fe->ops.set_tone(fe, fepriv->tone);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
} break;
case FE_SET_VOLTAGE: if (fe->ops.set_voltage) {
fepriv->voltage = (long)parg;
err = fe->ops.set_voltage(fe, fepriv->voltage);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
} break;
case FE_DISEQC_RECV_SLAVE_REPLY: if (fe->ops.diseqc_recv_slave_reply)
err = fe->ops.diseqc_recv_slave_reply(fe, parg); break;
case FE_ENABLE_HIGH_LNB_VOLTAGE:
if (fe->ops.enable_high_lnb_voltage)
err = fe->ops.enable_high_lnb_voltage(fe, (long)parg);
break;
case FE_SET_FRONTEND_TUNE_MODE:
fepriv->tune_mode_flags = (unsigned long)parg;
err = 0;
break;
/* DEPRECATED dish control ioctls */
case FE_DISHNETWORK_SEND_LEGACY_CMD:
if (fe->ops.dishnetwork_send_legacy_command) {
err = fe->ops.dishnetwork_send_legacy_command(fe,
(unsigned long)parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
} else if (fe->ops.set_voltage) {
/*
* NOTE: This is a fallback condition. Some frontends
* (stv0299 for instance) take longer than 8msec to
* respond to a set_voltage command. Those switches
* need custom routines to switch properly. For all
* other frontends, the following should work ok.
* Dish network legacy switches (as used by Dish500)
* are controlled by sending 9-bit command words
* spaced 8msec apart.
* the actual command word is switch/port dependent
* so it is up to the userspace application to send
* the right command.
* The command must always start with a '0' after
* initialization, so parg is 8 bits and does not
* include the initialization or start bit
*/
unsigned long swcmd = ((unsigned long)parg) << 1;
ktime_t nexttime;
ktime_t tv[10];
int i;
u8 last = 1;
if (dvb_frontend_debug)
dprintk("switch command: 0x%04lx\n",
swcmd);
nexttime = ktime_get_boottime();
if (dvb_frontend_debug)
tv[0] = nexttime;
/* before sending a command, initialize by sending
* a 32ms 18V to the switch
*/
fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
dvb_frontend_sleep_until(&nexttime, 32000);
for (i = 0; i < 9; i++) {
if (dvb_frontend_debug)
tv[i + 1] = ktime_get_boottime();
if ((swcmd & 0x01) != last) {
/* set voltage to (last ? 13V : 18V) */
fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
last = (last) ? 0 : 1;
}
swcmd = swcmd >> 1;
if (i != 8)
dvb_frontend_sleep_until(&nexttime, 8000);
}
if (dvb_frontend_debug) {
dprintk("(adapter %d): switch delay (should be 32k followed by all 8k)\n",
fe->dvb->num);
for (i = 1; i < 10; i++)
pr_info("%d: %d\n", i,
(int)ktime_us_delta(tv[i], tv[i - 1]));
}
err = 0;
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
break;
/* DEPRECATED statistics ioctls */
case FE_READ_BER:
if (fe->ops.read_ber) {
if (fepriv->thread)
err = fe->ops.read_ber(fe, parg);
else
err = -EAGAIN;
}
break;
case FE_READ_SIGNAL_STRENGTH:
if (fe->ops.read_signal_strength) {
if (fepriv->thread)
err = fe->ops.read_signal_strength(fe, parg);
else
err = -EAGAIN;
}
break;
case FE_READ_SNR:
if (fe->ops.read_snr) {
if (fepriv->thread)
err = fe->ops.read_snr(fe, parg);
else
err = -EAGAIN;
}
break;
case FE_READ_UNCORRECTED_BLOCKS:
if (fe->ops.read_ucblocks) {
if (fepriv->thread)
err = fe->ops.read_ucblocks(fe, parg);
else
err = -EAGAIN;
}
break;
/* DEPRECATED DVBv3 ioctls */
case FE_SET_FRONTEND:
err = dvbv3_set_delivery_system(fe);
if (err)
break;
if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
goto err0;
/* If we took control of the bus, we need to force
reinitialization. This is because many ts_bus_ctrl()
functions strobe the RESET pin on the demod, and if the
frontend thread already exists then the dvb_init() routine
won't get called (which is what usually does initial
register configuration). */
fepriv->reinitialise = 1;
}
if ((ret = dvb_generic_open(inode, file)) < 0)
goto err1;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
/* normal tune mode when opened R/W */
fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
fepriv->tone = -1;
fepriv->voltage = -1;
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
mutex_lock(&fe->dvb->mdev_lock);
if (fe->dvb->mdev) {
mutex_lock(&fe->dvb->mdev->graph_mutex);
if (fe->dvb->mdev->enable_source)
ret = fe->dvb->mdev->enable_source(
dvbdev->entity,
&fepriv->pipe);
mutex_unlock(&fe->dvb->mdev->graph_mutex);
if (ret) {
mutex_unlock(&fe->dvb->mdev_lock);
dev_err(fe->dvb->device,
"Tuner is busy. Error %d\n", ret);
goto err2;
}
}
mutex_unlock(&fe->dvb->mdev_lock);
#endif
ret = dvb_frontend_start(fe);
if (ret)
goto err3;
/*
* After initialization, there need to be two references: one
* for dvb_unregister_frontend(), and another one for
* dvb_frontend_detach().
*/
dvb_frontend_get(fe);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.