ath: fix WARN_ON with Polish (Poland) Contry code
[safe/jmp/linux-2.6] / drivers / media / video / c-qcam.c
index 75442ec..85cf177 100644 (file)
@@ -16,7 +16,7 @@
  *
  * The parport parameter controls which parports will be scanned.
  * Scanning all parports causes some printers to print a garbage page.
- *       -- March 14, 1999  Billy Donahue <billy@escape.com> 
+ *       -- March 14, 1999  Billy Donahue <billy@escape.com>
  *
  * Fixed data format to BGR, added force_rgb parameter. Added missing
  * parport_unregister_driver() on module removal.
 #include <linux/parport.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
-#include <asm/semaphore.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/mutex.h>
+#include <linux/jiffies.h>
+
 #include <asm/uaccess.h>
 
 struct qcam_device {
@@ -47,7 +51,8 @@ struct qcam_device {
        int contrast, brightness, whitebal;
        int top, left;
        unsigned int bidirectional;
-       struct semaphore lock;
+       unsigned long in_use;
+       struct mutex lock;
 };
 
 /* cameras maximum */
@@ -67,7 +72,7 @@ struct qcam_device {
 
 static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
 static int probe = 2;
-static int force_rgb = 0;
+static int force_rgb;
 static int video_nr = -1;
 
 static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
@@ -87,17 +92,18 @@ static inline unsigned int qcam_ready2(struct qcam_device *qcam)
        return (parport_read_data(qcam->pport) & 0x1)?1:0;
 }
 
-static unsigned int qcam_await_ready1(struct qcam_device *qcam, 
+static unsigned int qcam_await_ready1(struct qcam_device *qcam,
                                             int value)
 {
        unsigned long oldjiffies = jiffies;
        unsigned int i;
 
-       for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
+       for (oldjiffies = jiffies;
+            time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
                if (qcam_ready1(qcam) == value)
                        return 0;
 
-       /* If the camera didn't respond within 1/25 second, poll slowly 
+       /* If the camera didn't respond within 1/25 second, poll slowly
           for a while. */
        for (i = 0; i < 50; i++)
        {
@@ -118,11 +124,12 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
        unsigned long oldjiffies = jiffies;
        unsigned int i;
 
-       for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); )
+       for (oldjiffies = jiffies;
+            time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
                if (qcam_ready2(qcam) == value)
                        return 0;
 
-       /* If the camera didn't respond within 1/25 second, poll slowly 
+       /* If the camera didn't respond within 1/25 second, poll slowly
           for a while. */
        for (i = 0; i < 50; i++)
        {
@@ -156,12 +163,12 @@ static int qcam_write_data(struct qcam_device *qcam, unsigned int data)
        unsigned int idata;
        parport_write_data(qcam->pport, data);
        idata = qcam_read_data(qcam);
-       if (data != idata) 
+       if (data != idata)
        {
-               printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, 
+               printk(KERN_WARNING "cqcam: sent %x but received %x\n", data,
                       idata);
                return 1;
-       } 
+       }
        return 0;
 }
 
@@ -192,12 +199,12 @@ static int qc_detect(struct qcam_device *qcam)
           no device was found".  Fix this one day. */
        if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
            && qcam->pport->probe_info[0].model
-           && !strcmp(qcam->pdev->port->probe_info[0].model, 
+           && !strcmp(qcam->pdev->port->probe_info[0].model,
                       "Color QuickCam 2.0")) {
                printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
                return 1;
        }
-       
+
        if (probe < 2)
                return 0;
 
@@ -205,11 +212,11 @@ static int qc_detect(struct qcam_device *qcam)
 
        /* look for a heartbeat */
        ostat = stat = parport_read_status(qcam->pport);
-       for (i=0; i<250; i++) 
+       for (i=0; i<250; i++)
        {
                mdelay(1);
                stat = parport_read_status(qcam->pport);
-               if (ostat != stat) 
+               if (ostat != stat)
                {
                        if (++count >= 3) return 1;
                        ostat = stat;
@@ -225,11 +232,11 @@ static int qc_detect(struct qcam_device *qcam)
        count = 0;
 
        ostat = stat = parport_read_status(qcam->pport);
-       for (i=0; i<250; i++) 
+       for (i=0; i<250; i++)
        {
                mdelay(1);
                stat = parport_read_status(qcam->pport);
-               if (ostat != stat) 
+               if (ostat != stat)
                {
                        if (++count >= 3) return 1;
                        ostat = stat;
@@ -246,7 +253,7 @@ static void qc_reset(struct qcam_device *qcam)
        parport_write_control(qcam->pport, 0x8);
        mdelay(1);
        parport_write_control(qcam->pport, 0xc);
-       mdelay(1);          
+       mdelay(1);
 }
 
 /* Reset the QuickCam and program for brightness, contrast,
@@ -257,7 +264,7 @@ static void qc_setup(struct qcam_device *q)
        qc_reset(q);
 
        /* Set the brightness.  */
-               qcam_set(q, 11, q->brightness);
+       qcam_set(q, 11, q->brightness);
 
        /* Set the height and width.  These refer to the actual
           CCD area *before* applying the selected decimation.  */
@@ -271,12 +278,12 @@ static void qc_setup(struct qcam_device *q)
        /* Set contrast and white balance.  */
        qcam_set(q, 0x19, q->contrast);
        qcam_set(q, 0x1f, q->whitebal);
-       
+
        /* Set the speed.  */
        qcam_set(q, 45, 2);
 }
 
-/* Read some bytes from the camera and put them in the buffer. 
+/* Read some bytes from the camera and put them in the buffer.
    nbytes should be a multiple of 3, because bidirectional mode gives
    us three bytes at a time.  */
 
@@ -382,7 +389,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
 
        if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1))
                return -EIO;
-       
+
        lines = q->height;
        pixelsperline = q->width;
        bitsperxfer = (is_bi_dir) ? 24 : 8;
@@ -493,12 +500,11 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
  *     Video4linux interfacing
  */
 
-static int qcam_do_ioctl(struct inode *inode, struct file *file,
-                        unsigned int cmd, void *arg)
+static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
        struct video_device *dev = video_devdata(file);
        struct qcam_device *qcam=(struct qcam_device *)dev;
-       
+
        switch(cmd)
        {
                case VIDIOCGCAP:
@@ -573,7 +579,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
                         */
                        if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
                                return -EINVAL;
-                       
+
                        /*
                         *      Now load the camera.
                         */
@@ -581,11 +587,11 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
                        qcam->contrast = p->contrast>>8;
                        qcam->whitebal = p->whiteness>>8;
 
-                       down(&qcam->lock);                      
+                       mutex_lock(&qcam->lock);
                        parport_claim_or_block(qcam->pdev);
-                       qc_setup(qcam); 
+                       qc_setup(qcam);
                        parport_release(qcam->pdev);
-                       up(&qcam->lock);
+                       mutex_unlock(&qcam->lock);
                        return 0;
                }
                case VIDIOCSWIN:
@@ -600,11 +606,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 = 80;
                        qcam->height = 60;
                        qcam->mode = QC_DECIMATION_4;
-                       
+
                        if(vw->width>=160 && vw->height>=120)
                        {
                                qcam->width = 160;
@@ -626,13 +632,13 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
                                qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
                        }
 #endif
-                       /* Ok we figured out what to use from our 
+                       /* Ok we figured out what to use from our
                           wide choice */
-                       down(&qcam->lock);
+                       mutex_lock(&qcam->lock);
                        parport_claim_or_block(qcam->pdev);
                        qc_setup(qcam);
                        parport_release(qcam->pdev);
-                       up(&qcam->lock);
+                       mutex_unlock(&qcam->lock);
                        return 0;
                }
                case VIDIOCGWIN:
@@ -659,10 +665,10 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
        return 0;
 }
 
-static int qcam_ioctl(struct inode *inode, struct file *file,
-                    unsigned int cmd, unsigned long arg)
+static long qcam_ioctl(struct file *file,
+                     unsigned int cmd, unsigned long arg)
 {
-       return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
+       return video_usercopy(file, cmd, arg, qcam_do_ioctl);
 }
 
 static ssize_t qcam_read(struct file *file, char __user *buf,
@@ -672,32 +678,46 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
        struct qcam_device *qcam=(struct qcam_device *)v;
        int len;
 
-       down(&qcam->lock);
+       mutex_lock(&qcam->lock);
        parport_claim_or_block(qcam->pdev);
        /* Probably should have a semaphore against multiple users */
-       len = qc_capture(qcam, buf,count); 
+       len = qc_capture(qcam, buf,count);
        parport_release(qcam->pdev);
-       up(&qcam->lock);
+       mutex_unlock(&qcam->lock);
        return len;
 }
 
+static int qcam_exclusive_open(struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct qcam_device *qcam = (struct qcam_device *)dev;
+
+       return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
+}
+
+static int qcam_exclusive_release(struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct qcam_device *qcam = (struct qcam_device *)dev;
+
+       clear_bit(0, &qcam->in_use);
+       return 0;
+}
+
 /* video device template */
-static struct file_operations qcam_fops = {
+static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = qcam_exclusive_open,
+       .release        = qcam_exclusive_release,
        .ioctl          = qcam_ioctl,
        .read           = qcam_read,
-       .llseek         = no_llseek,
 };
 
 static struct video_device qcam_template=
 {
-       .owner          = THIS_MODULE,
        .name           = "Colour QuickCam",
-       .type           = VID_TYPE_CAPTURE,
-       .hardware       = VID_HARDWARE_QCAM_C,
        .fops           = &qcam_fops,
+       .release        = video_device_release_empty,
 };
 
 /* Initialize the QuickCam driver control structure. */
@@ -705,7 +725,7 @@ static struct video_device qcam_template=
 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;
@@ -716,17 +736,17 @@ static struct qcam_device *qcam_init(struct parport *port)
 
        q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE)?1:0;
 
-       if (q->pdev == NULL) 
+       if (q->pdev == NULL)
        {
                printk(KERN_ERR "c-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->width = q->ccd_width = 320;
        q->height = q->ccd_height = 240;
        q->mode = QC_MILLIONS | QC_DECIMATION_1;
@@ -739,7 +759,7 @@ static struct qcam_device *qcam_init(struct parport *port)
 }
 
 static struct qcam_device *qcams[MAX_CAMS];
-static unsigned int num_cams = 0;
+static unsigned int num_cams;
 
 static int init_cqcam(struct parport *port)
 {
@@ -764,11 +784,11 @@ static int init_cqcam(struct parport *port)
        qcam = qcam_init(port);
        if (qcam==NULL)
                return -ENODEV;
-               
+
        parport_claim_or_block(qcam->pdev);
 
        qc_reset(qcam);
-       
+
        if (probe && qc_detect(qcam)==0)
        {
                parport_release(qcam->pdev);
@@ -780,9 +800,8 @@ static int init_cqcam(struct parport *port)
        qc_setup(qcam);
 
        parport_release(qcam->pdev);
-       
-       if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1)
-       {
+
+       if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
                printk(KERN_ERR "Unable to register Colour QuickCam on %s\n",
                       qcam->pport->name);
                parport_unregister_device(qcam->pdev);
@@ -790,9 +809,9 @@ static int init_cqcam(struct parport *port)
                return -ENODEV;
        }
 
-       printk(KERN_INFO "video%d: Colour QuickCam found on %s\n", 
-              qcam->vdev.minor, qcam->pport->name);
-       
+       printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
+              qcam->vdev.num, qcam->pport->name);
+
        qcams[num_cams++] = qcam;
 
        return 0;