fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / media / video / bw-qcam.c
index c90ec3b..7d0b6e5 100644 (file)
@@ -73,7 +73,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <linux/parport.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
-#include <asm/semaphore.h>
+#include <media/v4l2-common.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
 #include "bw-qcam.h"
@@ -82,20 +83,15 @@ static unsigned int maxpoll=250;   /* Maximum busy-loop count for qcam I/O */
 static unsigned int yieldlines=4;  /* Yield after this many during capture */
 static int video_nr = -1;
 
-MODULE_PARM(maxpoll,"i");
-MODULE_PARM(yieldlines,"i");   
-MODULE_PARM(video_nr,"i");
+module_param(maxpoll, int, 0);
+module_param(yieldlines, int, 0);
+module_param(video_nr, int, 0);
 
 static inline int read_lpstatus(struct qcam_device *q)
 {
        return parport_read_status(q->pport);
 }
 
-static inline int read_lpcontrol(struct qcam_device *q)
-{
-       return parport_read_control(q->pport);
-}
-
 static inline int read_lpdata(struct qcam_device *q)
 {
        return parport_read_data(q->pport);
@@ -155,7 +151,7 @@ static int qc_calibrate(struct qcam_device *q)
 static struct qcam_device *qcam_init(struct parport *port)
 {
        struct qcam_device *q;
-       
+
        q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
        if(q==NULL)
                return NULL;
@@ -163,17 +159,17 @@ static struct qcam_device *qcam_init(struct parport *port)
        q->pport = port;
        q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
                                          NULL, 0, NULL);
-       if (q->pdev == NULL) 
+       if (q->pdev == NULL)
        {
                printk(KERN_ERR "bw-qcam: couldn't register for %s.\n",
                       port->name);
                kfree(q);
                return NULL;
        }
-       
+
        memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
-       
-       init_MUTEX(&q->lock);
+
+       mutex_init(&q->lock);
 
        q->port_mode = (QC_ANY | QC_NOTSET);
        q->width = 320;
@@ -241,16 +237,15 @@ static int qc_waithand(struct qcam_device *q, int val)
                while (!((status = read_lpstatus(q)) & 8))
                {
                        /* 1000 is enough spins on the I/O for all normal
-                          cases, at that point we start to poll slowly 
+                          cases, at that point we start to poll slowly
                           until the camera wakes up. However, we are
                           busy blocked until the camera responds, so
                           setting it lower is much better for interactive
                           response. */
-                          
+
                        if(runs++>maxpoll)
                        {
-                               current->state=TASK_INTERRUPTIBLE;
-                               schedule_timeout(HZ/200);
+                               msleep_interruptible(5);
                        }
                        if(runs>(maxpoll+1000)) /* 5 seconds */
                                return -1;
@@ -261,16 +256,15 @@ static int qc_waithand(struct qcam_device *q, int val)
                while (((status = read_lpstatus(q)) & 8))
                {
                        /* 1000 is enough spins on the I/O for all normal
-                          cases, at that point we start to poll slowly 
+                          cases, at that point we start to poll slowly
                           until the camera wakes up. However, we are
                           busy blocked until the camera responds, so
                           setting it lower is much better for interactive
                           response. */
-                          
+
                        if(runs++>maxpoll)
                        {
-                               current->state=TASK_INTERRUPTIBLE;
-                               schedule_timeout(HZ/200);
+                               msleep_interruptible(5);
                        }
                        if(runs++>(maxpoll+1000)) /* 5 seconds */
                                return -1;
@@ -289,21 +283,20 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val)
 {
        unsigned int status;
        int runs=0;
-       
-       do 
+
+       do
        {
                status = read_lpdata(q);
                /* 1000 is enough spins on the I/O for all normal
-                  cases, at that point we start to poll slowly 
+                  cases, at that point we start to poll slowly
                   until the camera wakes up. However, we are
                   busy blocked until the camera responds, so
                   setting it lower is much better for interactive
                   response. */
-                  
+
                if(runs++>maxpoll)
                {
-                       current->state=TASK_INTERRUPTIBLE;
-                       schedule_timeout(HZ/200);
+                       msleep_interruptible(5);
                }
                if(runs++>(maxpoll+1000)) /* 5 seconds */
                        return 0;
@@ -329,7 +322,7 @@ static int qc_detect(struct qcam_device *q)
 
        lastreg = reg = read_lpstatus(q) & 0xf0;
 
-       for (i = 0; i < 500; i++) 
+       for (i = 0; i < 500; i++)
        {
                reg = read_lpstatus(q) & 0xf0;
                if (reg != lastreg)
@@ -365,7 +358,7 @@ static int qc_detect(struct qcam_device *q)
 
 static void qc_reset(struct qcam_device *q)
 {
-       switch (q->port_mode & QC_FORCE_MASK) 
+       switch (q->port_mode & QC_FORCE_MASK)
        {
                case QC_FORCE_UNIDIR:
                        q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
@@ -378,7 +371,7 @@ static void qc_reset(struct qcam_device *q)
                case QC_ANY:
                        write_lpcontrol(q, 0x20);
                        write_lpdata(q, 0x75);
-       
+
                        if (read_lpdata(q) != 0x75) {
                                q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
                        } else {
@@ -406,8 +399,8 @@ static void qc_reset(struct qcam_device *q)
 static int qc_setscanmode(struct qcam_device *q)
 {
        int old_mode = q->mode;
-       
-       switch (q->transfer_scale) 
+
+       switch (q->transfer_scale)
        {
                case 1:
                        q->mode = 0;
@@ -420,7 +413,7 @@ static int qc_setscanmode(struct qcam_device *q)
                        break;
        }
 
-       switch (q->bpp) 
+       switch (q->bpp)
        {
                case 4:
                        break;
@@ -429,7 +422,7 @@ static int qc_setscanmode(struct qcam_device *q)
                        break;
        }
 
-       switch (q->port_mode & QC_MODE_MASK) 
+       switch (q->port_mode & QC_MODE_MASK)
        {
                case QC_BIDIR:
                        q->mode += 1;
@@ -438,10 +431,10 @@ static int qc_setscanmode(struct qcam_device *q)
                case QC_UNIDIR:
                        break;
        }
-       
+
        if (q->mode != old_mode)
                q->status |= QC_PARAM_CHANGE;
-       
+
        return 0;
 }
 
@@ -449,7 +442,7 @@ static int qc_setscanmode(struct qcam_device *q)
 /* Reset the QuickCam and program for brightness, contrast,
  * white-balance, and resolution. */
 
-void qc_set(struct qcam_device *q)
+static void qc_set(struct qcam_device *q)
 {
        int val;
        int val2;
@@ -459,7 +452,7 @@ void qc_set(struct qcam_device *q)
        /* Set the brightness.  Yes, this is repetitive, but it works.
         * Shorter versions seem to fail subtly.  Feel free to try :-). */
        /* I think the problem was in qc_command, not here -- bls */
-       
+
        qc_command(q, 0xb);
        qc_command(q, q->brightness);
 
@@ -510,13 +503,13 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
        unsigned int hi2, lo2;
        static int state = 0;
 
-       if (buffer == NULL) 
+       if (buffer == NULL)
        {
                state = 0;
                return 0;
        }
-       
-       switch (q->port_mode & QC_MODE_MASK) 
+
+       switch (q->port_mode & QC_MODE_MASK)
        {
                case QC_BIDIR:          /* Bi-directional Port */
                        write_lpcontrol(q, 0x26);
@@ -525,7 +518,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
                        write_lpcontrol(q, 0x2e);
                        lo2 = (qc_waithand2(q, 0) >> 1);
                        hi2 = (read_lpstatus(q) >> 3) & 0x1f;
-                       switch (q->bpp) 
+                       switch (q->bpp)
                        {
                                case 4:
                                        buffer[0] = lo & 0xf;
@@ -552,7 +545,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
                        write_lpcontrol(q, 0xe);
                        hi = (qc_waithand(q, 0) & 0xf0) >> 4;
 
-                       switch (q->bpp) 
+                       switch (q->bpp)
                        {
                                case 4:
                                        buffer[0] = lo;
@@ -560,7 +553,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
                                        ret = 2;
                                        break;
                                case 6:
-                                       switch (state) 
+                                       switch (state)
                                        {
                                                case 0:
                                                        buffer[0] = (lo << 2) | ((hi & 0xc) >> 2);
@@ -599,7 +592,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
  * n=2^(bit depth)-1.  Ask me for more details if you don't understand
  * this. */
 
-long qc_capture(struct qcam_device * q, char *buf, unsigned long len)
+static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long len)
 {
        int i, j, k, yield;
        int bytes;
@@ -612,13 +605,13 @@ long qc_capture(struct qcam_device * q, char *buf, unsigned long len)
        int  shift=8-q->bpp;
        char invert;
 
-       if (q->mode == -1) 
+       if (q->mode == -1)
                return -ENXIO;
 
        qc_command(q, 0x7);
        qc_command(q, q->mode);
 
-       if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) 
+       if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
        {
                write_lpcontrol(q, 0x2e);       /* turn port around */
                write_lpcontrol(q, 0x26);
@@ -626,7 +619,7 @@ long qc_capture(struct qcam_device * q, char *buf, unsigned long len)
                write_lpcontrol(q, 0x2e);
                (void) qc_waithand(q, 0);
        }
-       
+
        /* strange -- should be 15:63 below, but 4bpp is odd */
        invert = (q->bpp == 4) ? 16 : 63;
 
@@ -637,15 +630,15 @@ long qc_capture(struct qcam_device * q, char *buf, unsigned long len)
            q->transfer_scale;
        transperline = (transperline + divisor - 1) / divisor;
 
-       for (i = 0, yield = yieldlines; i < linestotrans; i++) 
+       for (i = 0, yield = yieldlines; i < linestotrans; i++)
        {
-               for (pixels_read = j = 0; j < transperline; j++) 
+               for (pixels_read = j = 0; j < transperline; j++)
                {
                        bytes = qc_readbytes(q, buffer);
-                       for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) 
+                       for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++)
                        {
                                int o;
-                               if (buffer[k] == 0 && invert == 16) 
+                               if (buffer[k] == 0 && invert == 16)
                                {
                                        /* 4bpp is odd (again) -- inverter is 16, not 15, but output
                                           must be 0-15 -- bls */
@@ -660,8 +653,8 @@ long qc_capture(struct qcam_device * q, char *buf, unsigned long len)
                        }
                        pixels_read += bytes;
                }
-               (void) qc_readbytes(q, 0);      /* reset state machine */
-               
+               (void) qc_readbytes(q, NULL);   /* reset state machine */
+
                /* Grabbing an entire frame from the quickcam is a lengthy
                   process. We don't (usually) want to busy-block the
                   processor for the entire frame. yieldlines is a module
@@ -669,13 +662,12 @@ long qc_capture(struct qcam_device * q, char *buf, unsigned long len)
                   time will be 240 / 200 = 1.2 seconds. The compile-time
                   default is to yield every 4 lines. */
                if (i >= yield) {
-                       current->state=TASK_INTERRUPTIBLE;
-                       schedule_timeout(HZ/200);
+                       msleep_interruptible(5);
                        yield = i + yieldlines;
                }
        }
 
-       if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) 
+       if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
        {
                write_lpcontrol(q, 2);
                write_lpcontrol(q, 6);
@@ -696,7 +688,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
 {
        struct video_device *dev = video_devdata(file);
        struct qcam_device *qcam=(struct qcam_device *)dev;
-       
+
        switch(cmd)
        {
                case VIDIOCGCAP:
@@ -768,10 +760,10 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
                {
                        struct video_picture *p = arg;
                        if(p->palette!=VIDEO_PALETTE_GREY)
-                               return -EINVAL;
+                               return -EINVAL;
                        if(p->depth!=4 && p->depth!=6)
                                return -EINVAL;
-                       
+
                        /*
                         *      Now load the camera.
                         */
@@ -781,9 +773,9 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
                        qcam->whitebal = p->whiteness>>8;
                        qcam->bpp = p->depth;
 
-                       down(&qcam->lock);                      
+                       mutex_lock(&qcam->lock);
                        qc_setscanmode(qcam);
-                       up(&qcam->lock);
+                       mutex_unlock(&qcam->lock);
                        qcam->status |= QC_PARAM_CHANGE;
 
                        return 0;
@@ -799,11 +791,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
                                return -EINVAL;
                        if(vw->width<80||vw->width>320)
                                return -EINVAL;
-                               
+
                        qcam->width = 320;
                        qcam->height = 240;
                        qcam->transfer_scale = 4;
-                       
+
                        if(vw->width>=160 && vw->height>=120)
                        {
                                qcam->transfer_scale = 2;
@@ -814,14 +806,14 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
                                qcam->height = 240;
                                qcam->transfer_scale = 1;
                        }
-                       down(&qcam->lock);
+                       mutex_lock(&qcam->lock);
                        qc_setscanmode(qcam);
-                       up(&qcam->lock);
-                       
+                       mutex_unlock(&qcam->lock);
+
                        /* We must update the camera before we grab. We could
                           just have changed the grab size */
                        qcam->status |= QC_PARAM_CHANGE;
-                       
+
                        /* Ok we figured out what to use from our wide choice */
                        return 0;
                }
@@ -855,16 +847,16 @@ static int qcam_ioctl(struct inode *inode, struct file *file,
        return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
 }
 
-static ssize_t qcam_read(struct file *file, char *buf,
+static ssize_t qcam_read(struct file *file, char __user *buf,
                         size_t count, loff_t *ppos)
 {
        struct video_device *v = video_devdata(file);
        struct qcam_device *qcam=(struct qcam_device *)v;
        int len;
        parport_claim_or_block(qcam->pdev);
-       
-       down(&qcam->lock);
-       
+
+       mutex_lock(&qcam->lock);
+
        qc_reset(qcam);
 
        /* Update the camera parameters if we need to */
@@ -872,18 +864,19 @@ static ssize_t qcam_read(struct file *file, char *buf,
                qc_set(qcam);
 
        len=qc_capture(qcam, buf,count);
-       
-       up(&qcam->lock);
-       
+
+       mutex_unlock(&qcam->lock);
+
        parport_release(qcam->pdev);
        return len;
 }
+
 static struct file_operations qcam_fops = {
        .owner          = THIS_MODULE,
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
        .ioctl          = qcam_ioctl,
+       .compat_ioctl   = v4l_compat_ioctl32,
        .read           = qcam_read,
        .llseek         = no_llseek,
 };
@@ -900,7 +893,7 @@ static struct video_device qcam_template=
 static struct qcam_device *qcams[MAX_CAMS];
 static unsigned int num_cams = 0;
 
-int init_bwqcam(struct parport *port)
+static int init_bwqcam(struct parport *port)
 {
        struct qcam_device *qcam;
 
@@ -913,11 +906,11 @@ int init_bwqcam(struct parport *port)
        qcam=qcam_init(port);
        if(qcam==NULL)
                return -ENODEV;
-               
+
        parport_claim_or_block(qcam->pdev);
 
        qc_reset(qcam);
-       
+
        if(qc_detect(qcam)==0)
        {
                parport_release(qcam->pdev);
@@ -928,9 +921,9 @@ int init_bwqcam(struct parport *port)
        qc_calibrate(qcam);
 
        parport_release(qcam->pdev);
-       
+
        printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
-       
+
        if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
        {
                parport_unregister_device(qcam->pdev);
@@ -943,7 +936,7 @@ int init_bwqcam(struct parport *port)
        return 0;
 }
 
-void close_bwqcam(struct qcam_device *qcam)
+static void close_bwqcam(struct qcam_device *qcam)
 {
        video_unregister_device(&qcam->vdev);
        parport_unregister_device(qcam->pdev);
@@ -955,7 +948,7 @@ void close_bwqcam(struct qcam_device *qcam)
  *       -- March 14, 1999  Billy Donahue <billy@escape.com> */
 #ifdef MODULE
 static char *parport[MAX_CAMS] = { NULL, };
-MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "s");
+module_param_array(parport, charp, NULL, 0);
 #endif
 
 static int accept_bwqcam(struct parport *port)
@@ -1021,7 +1014,7 @@ static int __init init_bw_qcams(void)
                printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n");
                maxpoll = 5000;
        }
-       
+
        if (yieldlines < 1) {
                printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n");
                yieldlines = 1;