diff options
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_frontend.c | 67 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_frontend.h | 1 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvbdev.c | 3 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvbdev.h | 4 |
4 files changed, 63 insertions, 12 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index c07c14ba0..51fb82edc 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -52,6 +52,7 @@ static int dvb_shutdown_timeout; static int dvb_force_auto_inversion; static int dvb_override_tune_delay; static int dvb_powerdown_on_sleep = 1; +static int dvb_mfe_wait_time = 5; module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off)."); @@ -63,6 +64,8 @@ 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)"); #define dprintk if (dvb_frontend_debug) printk @@ -217,8 +220,9 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe, static void dvb_frontend_init(struct dvb_frontend *fe) { - dprintk ("DVB: initialising frontend %i (%s)...\n", + dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n", fe->dvb->num, + fe->id, fe->ops.info.name); if (fe->ops.init) @@ -697,7 +701,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe) mb(); fe_thread = kthread_run(dvb_frontend_thread, fe, - "kdvb-fe-%i", fe->dvb->num); + "kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id); if (IS_ERR(fe_thread)) { ret = PTR_ERR(fe_thread); printk("dvb_frontend_start: failed to start kthread (%d)\n", ret); @@ -721,8 +725,8 @@ static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe, *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); if (*freq_min == 0 || *freq_max == 0) - printk(KERN_WARNING "DVB: frontend %u frequency limits undefined - fix the driver\n", - fe->dvb->num); + printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", + fe->dvb->num,fe->id); } static int dvb_frontend_check_parameters(struct dvb_frontend *fe, @@ -735,8 +739,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max); if ((freq_min && parms->frequency < freq_min) || (freq_max && parms->frequency > freq_max)) { - printk(KERN_WARNING "DVB: frontend %u frequency %u out of range (%u..%u)\n", - fe->dvb->num, parms->frequency, freq_min, freq_max); + printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, parms->frequency, freq_min, freq_max); return -EINVAL; } @@ -746,8 +750,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) || (fe->ops.info.symbol_rate_max && parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) { - printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n", - fe->dvb->num, parms->u.qpsk.symbol_rate, + printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, parms->u.qpsk.symbol_rate, fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); return -EINVAL; } @@ -757,8 +761,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) || (fe->ops.info.symbol_rate_max && parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) { - printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n", - fe->dvb->num, parms->u.qam.symbol_rate, + printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, parms->u.qam.symbol_rate, fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); return -EINVAL; } @@ -1820,13 +1824,46 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; + struct dvb_adapter *adapter = fe->dvb; + struct dvb_device *mfedev; + struct dvb_frontend *mfe; + struct dvb_frontend_private *mfepriv; + int mferetry; int ret; dprintk ("%s\n", __func__); + if (adapter->mfe_shared) { + mutex_lock (&adapter->mfe_lock); + if (adapter->mfe_dvbdev != dvbdev) { + if (adapter->mfe_dvbdev) { + mfedev = adapter->mfe_dvbdev; + mfe = mfedev->priv; + mfepriv = mfe->frontend_priv; + mutex_unlock (&adapter->mfe_lock); + mferetry = (dvb_mfe_wait_time << 1); + while (mferetry-- && (mfedev->users != -1 || mfepriv->thread != NULL)) { + if(msleep_interruptible(500)) { + if(signal_pending(current)) + return -EINTR; + } + } + mutex_lock (&adapter->mfe_lock); + mfedev = adapter->mfe_dvbdev; + mfe = mfedev->priv; + mfepriv = mfe->frontend_priv; + if (mfedev->users != -1 || mfepriv->thread != NULL) { + ret = -EBUSY; + goto err0; + } + } + adapter->mfe_dvbdev = dvbdev; + } + } + if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) - return ret; + goto err0; } if ((ret = dvb_generic_open (inode, file)) < 0) @@ -1846,6 +1883,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) fepriv->events.eventr = fepriv->events.eventw = 0; } + if (adapter->mfe_shared) + mutex_unlock (&adapter->mfe_lock); return ret; err2: @@ -1853,6 +1892,9 @@ err2: err1: if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) fe->ops.ts_bus_ctrl(fe, 0); +err0: + if (adapter->mfe_shared) + mutex_unlock (&adapter->mfe_lock); return ret; } @@ -1922,8 +1964,9 @@ int dvb_register_frontend(struct dvb_adapter* dvb, fe->dvb = dvb; fepriv->inversion = INVERSION_OFF; - printk ("DVB: registering frontend %i (%s)...\n", + printk ("DVB: registering adapter %i frontend %i (%s)...\n", fe->dvb->num, + fe->id, fe->ops.info.name); dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h index a0c591b3b..569b72a96 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -236,6 +236,7 @@ struct dvb_frontend { struct dtv_frontend_properties dtv_property_cache; #define DVB_FRONTEND_COMPONENT_TUNER 0 int (*callback)(void *adapter_priv, int component, int cmd, int arg); + int id; }; extern int dvb_register_frontend(struct dvb_adapter *dvb, diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c index 0820da504..422af5a0d 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.c +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c @@ -341,6 +341,9 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, adap->name = name; adap->module = module; adap->device = device; + adap->mfe_shared = 0; + adap->mfe_dvbdev = NULL; + mutex_init (&adap->mfe_lock); list_add_tail (&adap->list_head, &dvb_adapter_list); diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h index 89d12dc47..574e336ba 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.h +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h @@ -62,6 +62,10 @@ struct dvb_adapter { struct device *device; struct module *module; + + int mfe_shared; /* indicates mutually exclusive frontends */ + struct dvb_device *mfe_dvbdev; /* frontend device in use */ + struct mutex mfe_lock; /* access lock for thread creation */ }; |