]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/dvb/dvb-core/dvb_frontend.c
Merge branch 'nfs-server-stable' of git://linux-nfs.org/~bfields/linux
[linux-2.6-omap-h63xx.git] / drivers / media / dvb / dvb-core / dvb_frontend.c
index afe797b75de4cfcd65b6046ffb7b59155e30da1e..b203640ef1c587e7c4f294a7b0be8f2bd9f923a8 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/list.h>
 #include <linux/freezer.h>
 #include <linux/jiffies.h>
@@ -43,7 +42,7 @@
 #include "dvbdev.h"
 
 static int dvb_frontend_debug;
-static int dvb_shutdown_timeout = 5;
+static int dvb_shutdown_timeout;
 static int dvb_force_auto_inversion;
 static int dvb_override_tune_delay;
 static int dvb_powerdown_on_sleep = 1;
@@ -574,10 +573,9 @@ restart:
                        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 (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)
@@ -697,17 +695,35 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
        return 0;
 }
 
+static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe,
+                                       u32 *freq_min, u32 *freq_max)
+{
+       *freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min);
+
+       if (fe->ops.info.frequency_max == 0)
+               *freq_max = fe->ops.tuner_ops.info.frequency_max;
+       else if (fe->ops.tuner_ops.info.frequency_max == 0)
+               *freq_max = fe->ops.info.frequency_max;
+       else
+               *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);
+}
+
 static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
                                struct dvb_frontend_parameters *parms)
 {
+       u32 freq_min;
+       u32 freq_max;
+
        /* range check: frequency */
-       if ((fe->ops.info.frequency_min &&
-            parms->frequency < fe->ops.info.frequency_min) ||
-           (fe->ops.info.frequency_max &&
-            parms->frequency > fe->ops.info.frequency_max)) {
+       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,
-                      fe->ops.info.frequency_min, fe->ops.info.frequency_max);
+                      fe->dvb->num, parms->frequency, freq_min, freq_max);
                return -EINVAL;
        }
 
@@ -748,7 +764,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 
        dprintk ("%s\n", __FUNCTION__);
 
-       if (!fe || fepriv->exit)
+       if (fepriv->exit)
                return -ENODEV;
 
        if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
@@ -763,6 +779,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
        case FE_GET_INFO: {
                struct dvb_frontend_info* info = parg;
                memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
+               dvb_frontend_get_frequeny_limits(fe, &info->frequency_min, &info->frequency_max);
 
                /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
                 * do it, it is done for it. */
@@ -1038,18 +1055,15 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
 
        dprintk ("%s\n", __FUNCTION__);
 
-       if ((ret = dvb_generic_open (inode, file)) < 0)
-               return ret;
-
-       if (fe->ops.ts_bus_ctrl) {
-               if ((ret = fe->ops.ts_bus_ctrl (fe, 1)) < 0) {
-                       dvb_generic_release (inode, file);
+       if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
+               if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
                        return ret;
-               }
        }
 
-       if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+       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;
@@ -1057,13 +1071,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
 
                ret = dvb_frontend_start (fe);
                if (ret)
-                       dvb_generic_release (inode, file);
+                       goto err2;
 
                /*  empty event queue */
                fepriv->events.eventr = fepriv->events.eventw = 0;
        }
 
        return ret;
+
+err2:
+       dvb_generic_release(inode, file);
+err1:
+       if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
+               fe->ops.ts_bus_ctrl(fe, 0);
+       return ret;
 }
 
 static int dvb_frontend_release(struct inode *inode, struct file *file)
@@ -1078,16 +1099,18 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
        if ((file->f_flags & O_ACCMODE) != O_RDONLY)
                fepriv->release_jiffies = jiffies;
 
-       if (fe->ops.ts_bus_ctrl)
-               fe->ops.ts_bus_ctrl (fe, 0);
-
        ret = dvb_generic_release (inode, file);
 
-       if (dvbdev->users==-1 && fepriv->exit==1) {
-               fops_put(file->f_op);
-               file->f_op = NULL;
-               wake_up(&dvbdev->wait_queue);
+       if (dvbdev->users == -1) {
+               if (fepriv->exit == 1) {
+                       fops_put(file->f_op);
+                       file->f_op = NULL;
+                       wake_up(&dvbdev->wait_queue);
+               }
+               if (fe->ops.ts_bus_ctrl)
+                       fe->ops.ts_bus_ctrl(fe, 0);
        }
+
        return ret;
 }