X-Git-Url: http://git.onelab.eu/?p=linux-2.6.git;a=blobdiff_plain;f=drivers%2Fmedia%2Fdvb%2Fdvb-core%2Fdvb_frontend.c;fp=drivers%2Fmedia%2Fdvb%2Fdvb-core%2Fdvb_frontend.c;h=771f32d889e6261de8b8c77d10fad85b55da20a4;hp=57b34cda99f5a6f598b9786d42af22d58a19f70d;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 57b34cda9..771f32d88 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "dvb_frontend.h" #include "dvbdev.h" @@ -49,14 +50,14 @@ static int dvb_powerdown_on_sleep = 1; 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_param(dvb_shutdown_timeout, int, 0444); MODULE_PARM_DESC(dvb_shutdown_timeout, "wait seconds after close() before suspending hardware"); -module_param(dvb_force_auto_inversion, int, 0644); +module_param(dvb_force_auto_inversion, int, 0444); MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always"); -module_param(dvb_override_tune_delay, int, 0644); +module_param(dvb_override_tune_delay, int, 0444); 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_powerdown_on_sleep, int, 0444); +MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)"); #define dprintk if (dvb_frontend_debug) printk @@ -72,8 +73,6 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volt #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) - -#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. @@ -89,7 +88,7 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volt * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again. */ -static DEFINE_MUTEX(frontend_mutex); +static DECLARE_MUTEX(frontend_mutex); struct dvb_frontend_private { @@ -107,9 +106,6 @@ struct dvb_frontend_private { fe_status_t status; unsigned long tune_mode_flags; unsigned int delay; - unsigned int reinitialise; - int tone; - int voltage; /* swzigzag values */ unsigned int state; @@ -126,7 +122,6 @@ struct dvb_frontend_private { unsigned int check_wrapped; }; -static void dvb_frontend_wakeup(struct dvb_frontend *fe); static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) { @@ -153,8 +148,8 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) sizeof (struct dvb_frontend_parameters)); if (status & FE_HAS_LOCK) - if (fe->ops.get_frontend) - fe->ops.get_frontend(fe, &e->parameters); + if (fe->ops->get_frontend) + fe->ops->get_frontend(fe, &e->parameters); events->eventw = wp; @@ -213,25 +208,11 @@ static void dvb_frontend_init(struct dvb_frontend *fe) { dprintk ("DVB: initialising frontend %i (%s)...\n", fe->dvb->num, - fe->ops.info.name); - - if (fe->ops.init) - fe->ops.init(fe); - if (fe->ops.tuner_ops.init) { - fe->ops.tuner_ops.init(fe); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - } -} - -void dvb_frontend_reinitialise(struct dvb_frontend *fe) -{ - struct dvb_frontend_private *fepriv = fe->frontend_priv; + fe->ops->info.name); - fepriv->reinitialise = 1; - dvb_frontend_wakeup(fe); + if (fe->ops->init) + fe->ops->init(fe); } -EXPORT_SYMBOL(dvb_frontend_reinitialise); static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked) { @@ -266,7 +247,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra u32 original_frequency = fepriv->parameters.frequency; /* are we using autoinversion? */ - autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && + autoinversion = ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && (fepriv->parameters.inversion == INVERSION_AUTO)); /* setup parameters correctly */ @@ -336,8 +317,8 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra 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); + if (fe->ops->set_frontend) + fe->ops->set_frontend(fe, &fepriv->parameters); fepriv->parameters.frequency = original_frequency; fepriv->parameters.inversion = original_inversion; @@ -361,8 +342,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) /* 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->ops->set_frontend) + fe->ops->set_frontend(fe, &fepriv->parameters); fepriv->state = FESTATE_TUNED; } fepriv->delay = 3*HZ; @@ -374,8 +355,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) if (fepriv->state & FESTATE_RETUNE) { s = 0; } else { - if (fe->ops.read_status) - fe->ops.read_status(fe, &s); + if (fe->ops->read_status) + fe->ops->read_status(fe, &s); if (s != fepriv->status) { dvb_frontend_add_event(fe, s); fepriv->status = s; @@ -388,7 +369,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) fepriv->state = FESTATE_TUNED; /* if we're tuned, then we have determined the correct inversion */ - if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && + if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && (fepriv->parameters.inversion == INVERSION_AUTO)) { fepriv->parameters.inversion = fepriv->inversion; } @@ -412,7 +393,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) /* 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)) { + (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); return; } @@ -525,10 +506,8 @@ static int dvb_frontend_thread(void *data) fepriv->quality = 0; fepriv->delay = 3*HZ; fepriv->status = 0; - fepriv->wakeup = 0; - fepriv->reinitialise = 0; - dvb_frontend_init(fe); + fepriv->wakeup = 0; while (1) { up(&fepriv->sem); /* is locked when we enter the thread... */ @@ -546,49 +525,31 @@ static int dvb_frontend_thread(void *data) if (down_interruptible(&fepriv->sem)) break; - if (fepriv->reinitialise) { - dvb_frontend_init(fe); - if (fepriv->tone != -1) { - fe->ops.set_tone(fe, fepriv->tone); - } - if (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) { - if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) { - /* have we been asked to retune? */ - params = NULL; - if (fepriv->state & FESTATE_RETUNE) { - params = &fepriv->parameters; - fepriv->state = FESTATE_TUNED; - } + if (fe->ops->tune) { + /* have we been asked to retune? */ + params = NULL; + if (fepriv->state & FESTATE_RETUNE) { + params = &fepriv->parameters; + fepriv->state = FESTATE_TUNED; + } - fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); - if (s != fepriv->status) { - dvb_frontend_add_event(fe, s); - fepriv->status = s; - } - } else - dvb_frontend_swzigzag(fe); - } else + fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); + if (s != fepriv->status) { + dvb_frontend_add_event(fe, s); + fepriv->status = s; + } + } else { dvb_frontend_swzigzag(fe); + } } if (dvb_shutdown_timeout) { if (dvb_powerdown_on_sleep) - if (fe->ops.set_voltage) - fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); - if (fe->ops.tuner_ops.sleep) { - 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); + if (fe->ops->set_voltage) + fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF); + if (fe->ops->sleep) + fe->ops->sleep(fe); } fepriv->thread_pid = 0; @@ -740,7 +701,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, switch (cmd) { case FE_GET_INFO: { struct dvb_frontend_info* info = parg; - memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); + memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info)); /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't * do it, it is done for it. */ @@ -760,79 +721,77 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, break; } - if (fe->ops.read_status) - err = fe->ops.read_status(fe, status); + if (fe->ops->read_status) + err = fe->ops->read_status(fe, status); break; } case FE_READ_BER: - if (fe->ops.read_ber) - err = fe->ops.read_ber(fe, (__u32*) parg); + if (fe->ops->read_ber) + err = fe->ops->read_ber(fe, (__u32*) parg); break; case FE_READ_SIGNAL_STRENGTH: - if (fe->ops.read_signal_strength) - err = fe->ops.read_signal_strength(fe, (__u16*) parg); + if (fe->ops->read_signal_strength) + err = fe->ops->read_signal_strength(fe, (__u16*) parg); break; case FE_READ_SNR: - if (fe->ops.read_snr) - err = fe->ops.read_snr(fe, (__u16*) parg); + if (fe->ops->read_snr) + err = fe->ops->read_snr(fe, (__u16*) parg); break; case FE_READ_UNCORRECTED_BLOCKS: - if (fe->ops.read_ucblocks) - err = fe->ops.read_ucblocks(fe, (__u32*) parg); + if (fe->ops->read_ucblocks) + err = fe->ops->read_ucblocks(fe, (__u32*) parg); break; case FE_DISEQC_RESET_OVERLOAD: - if (fe->ops.diseqc_reset_overload) { - err = fe->ops.diseqc_reset_overload(fe); + 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) { - err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); + if (fe->ops->diseqc_send_master_cmd) { + err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } break; case FE_DISEQC_SEND_BURST: - if (fe->ops.diseqc_send_burst) { - err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); + if (fe->ops->diseqc_send_burst) { + err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } break; case FE_SET_TONE: - if (fe->ops.set_tone) { - err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg); - fepriv->tone = (fe_sec_tone_mode_t) parg; + if (fe->ops->set_tone) { + err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } break; case FE_SET_VOLTAGE: - if (fe->ops.set_voltage) { - err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg); - fepriv->voltage = (fe_sec_voltage_t) parg; + if (fe->ops->set_voltage) { + err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } break; case FE_DISHNETWORK_SEND_LEGACY_CMD: - if (fe->ops.dishnetwork_send_legacy_command) { - err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg); + 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) { + } else if (fe->ops->set_voltage) { /* * NOTE: This is a fallback condition. Some frontends * (stv0299 for instance) take longer than 8msec to @@ -862,7 +821,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, /* before sending a command, initialize by sending * a 32ms 18V to the switch */ - fe->ops.set_voltage(fe, SEC_VOLTAGE_18); + fe->ops->set_voltage(fe, SEC_VOLTAGE_18); dvb_frontend_sleep_until(&nexttime, 32000); for (i = 0; i < 9; i++) { @@ -870,7 +829,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, do_gettimeofday(&tv[i + 1]); if ((cmd & 0x01) != last) { /* set voltage to (last ? 13V : 18V) */ - fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); + fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); last = (last) ? 0 : 1; } cmd = cmd >> 1; @@ -890,13 +849,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, break; case FE_DISEQC_RECV_SLAVE_REPLY: - if (fe->ops.diseqc_recv_slave_reply) - err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); + if (fe->ops->diseqc_recv_slave_reply) + err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) 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); + if (fe->ops->enable_high_lnb_voltage) + err = fe->ops->enable_high_lnb_voltage(fe, (long) parg); break; case FE_SET_FRONTEND: { @@ -914,7 +873,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, fepriv->parameters.inversion = INVERSION_AUTO; fetunesettings.parameters.inversion = INVERSION_AUTO; } - if (fe->ops.info.type == FE_OFDM) { + 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 && @@ -923,13 +882,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, } /* get frontend-specific tuning settings */ - if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) { + 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(fe->ops.info.type) { + switch(fe->ops->info.type) { case FE_QPSK: fepriv->min_delay = HZ/20; fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000; @@ -944,13 +903,11 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, case FE_OFDM: fepriv->min_delay = HZ/20; - fepriv->step_size = fe->ops.info.frequency_stepsize * 2; - fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; + fepriv->step_size = fe->ops->info.frequency_stepsize * 2; + fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1; break; case FE_ATSC: - fepriv->min_delay = HZ/20; - fepriv->step_size = 0; - fepriv->max_drift = 0; + printk("dvb-core: FE_ATSC not handled yet.\n"); break; } } @@ -970,15 +927,14 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, break; case FE_GET_FRONTEND: - if (fe->ops.get_frontend) { + 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); + err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg); } break; case FE_SET_FRONTEND_TUNE_MODE: fepriv->tune_mode_flags = (unsigned long) parg; - err = 0; break; }; @@ -1015,18 +971,15 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) return ret; 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; - ret = dvb_frontend_start (fe); if (ret) dvb_generic_release (inode, file); /* empty event queue */ fepriv->events.eventr = fepriv->events.eventw = 0; + + /* normal tune mode when opened R/W */ + fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; } return ret; @@ -1068,12 +1021,12 @@ int dvb_register_frontend(struct dvb_adapter* dvb, dprintk ("%s\n", __FUNCTION__); - if (mutex_lock_interruptible(&frontend_mutex)) + if (down_interruptible (&frontend_mutex)) return -ERESTARTSYS; fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL); if (fe->frontend_priv == NULL) { - mutex_unlock(&frontend_mutex); + up(&frontend_mutex); return -ENOMEM; } fepriv = fe->frontend_priv; @@ -1087,12 +1040,12 @@ int dvb_register_frontend(struct dvb_adapter* dvb, printk ("DVB: registering frontend %i (%s)...\n", fe->dvb->num, - fe->ops.info.name); + fe->ops->info.name); dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, fe, DVB_DEVICE_FRONTEND); - mutex_unlock(&frontend_mutex); + up (&frontend_mutex); return 0; } EXPORT_SYMBOL(dvb_register_frontend); @@ -1102,21 +1055,16 @@ int dvb_unregister_frontend(struct dvb_frontend* fe) struct dvb_frontend_private *fepriv = fe->frontend_priv; dprintk ("%s\n", __FUNCTION__); - mutex_lock(&frontend_mutex); + down (&frontend_mutex); dvb_unregister_device (fepriv->dvbdev); dvb_frontend_stop (fe); - if (fe->ops.tuner_ops.release) { - fe->ops.tuner_ops.release(fe); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - } - if (fe->ops.release) - fe->ops.release(fe); + if (fe->ops->release) + fe->ops->release(fe); else - printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name); + printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name); /* fe is invalid now */ kfree(fepriv); - mutex_unlock(&frontend_mutex); + up (&frontend_mutex); return 0; } EXPORT_SYMBOL(dvb_unregister_frontend);