V4L/DVB (3599): Implement new routing commands for wm8775 and cs53l32a.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / media / zc0301_core.c
index 238f60f7f47240f414ebedbbd575c740292ff5a7..4036c6268bff53e025ee57e066ba58a041ebd83a 100644 (file)
@@ -3,9 +3,9 @@
  *                                                                         *
  * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
  *                                                                         *
- * Informations about the chip internals to enable the I2C protocol have   *
- * been taken from the documentation of the ZC030x Video4Linux1 driver     *
- * written by Andrew Birkett <andy@nobugs.org>                             *
+ * Informations about the chip internals needed to enable the I2C protocol *
+ * have been taken from the documentation of the ZC030x Video4Linux1       *
+ * driver written by Andrew Birkett <andy@nobugs.org>                      *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
  * it under the terms of the GNU General Public License as published by    *
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/string.h>
 #include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/delay.h>
-#include <linux/stddef.h>
 #include <linux/compiler.h>
 #include <linux/ioctl.h>
 #include <linux/poll.h>
@@ -54,8 +52,8 @@
 #define ZC0301_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
 #define ZC0301_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ZC0301_MODULE_LICENSE "GPL"
-#define ZC0301_MODULE_VERSION "1:1.00"
-#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 0)
+#define ZC0301_MODULE_VERSION "1:1.03"
+#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 3)
 
 /*****************************************************************************/
 
@@ -94,6 +92,15 @@ MODULE_PARM_DESC(force_munmap,
                  "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
                  "\n");
 
+static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] =
+                                       ZC0301_FRAME_TIMEOUT};
+module_param_array(frame_timeout, uint, NULL, 0644);
+MODULE_PARM_DESC(frame_timeout,
+                 "\n<n[,...]> Timeout for a video frame in seconds."
+                 "\nThis parameter is specific for each detected camera."
+                 "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"."
+                 "\n");
+
 #ifdef ZC0301_DEBUG
 static unsigned short debug = ZC0301_DEBUG_LEVEL;
 module_param(debug, ushort, 0644);
@@ -115,8 +122,8 @@ static u32
 zc0301_request_buffers(struct zc0301_device* cam, u32 count,
                        enum zc0301_io_method io)
 {
-       struct v4l2_pix_format* p = &(cam->sensor->pix_format);
-       struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
+       struct v4l2_pix_format* p = &(cam->sensor.pix_format);
+       struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
        const size_t imagesize = cam->module_param.force_munmap ||
                                 io == IO_READ ?
                                 (p->width * p->height * p->priv) / 8 :
@@ -314,7 +321,7 @@ static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs)
                if ((*f))
                        (*f)->state = F_QUEUED;
                DBG(3, "Stream interrupted");
-               wake_up_interruptible(&cam->wait_stream);
+               wake_up(&cam->wait_stream);
        }
 
        if (cam->state & DEV_DISCONNECTED)
@@ -332,9 +339,9 @@ static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs)
                (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t,
                                  frame);
 
-       imagesize = (cam->sensor->pix_format.width *
-                    cam->sensor->pix_format.height *
-                    cam->sensor->pix_format.priv) / 8;
+       imagesize = (cam->sensor.pix_format.width *
+                    cam->sensor.pix_format.height *
+                    cam->sensor.pix_format.priv) / 8;
 
        for (i = 0; i < urb->number_of_packets; i++) {
                unsigned int len, status;
@@ -526,7 +533,7 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam)
                                     ZC0301_URB_TIMEOUT);
        if (cam->state & DEV_DISCONNECTED)
                return -ENODEV;
-       else if (!timeout) {
+       else if (cam->stream != STREAM_OFF) {
                cam->state |= DEV_MISCONFIGURED;
                DBG(1, "URB timeout reached. The camera is misconfigured. To "
                       "use it, close and open /dev/video%d again.",
@@ -547,8 +554,7 @@ zc0301_set_compression(struct zc0301_device* cam,
 
        if ((r = zc0301_read_reg(cam, 0x0008)) < 0)
                err += r;
-       err += zc0301_write_reg(cam, 0x0008,
-                               r | 0x11 | (compression->quality >> 1));
+       err += zc0301_write_reg(cam, 0x0008, r | 0x11 | compression->quality);
 
        return err ? -EIO : 0;
 }
@@ -556,7 +562,7 @@ zc0301_set_compression(struct zc0301_device* cam,
 
 static int zc0301_init(struct zc0301_device* cam)
 {
-       struct zc0301_sensor* s = cam->sensor;
+       struct zc0301_sensor* s = &cam->sensor;
        struct v4l2_control ctrl;
        struct v4l2_queryctrl *qctrl;
        struct v4l2_rect* rect;
@@ -720,6 +726,7 @@ static int zc0301_release(struct inode* inode, struct file* filp)
 
        if (cam->state & DEV_DISCONNECTED) {
                zc0301_release_resources(cam);
+               usb_put_dev(cam->usbdev);
                mutex_unlock(&cam->dev_mutex);
                kfree(cam);
                return 0;
@@ -737,8 +744,7 @@ static int zc0301_release(struct inode* inode, struct file* filp)
 
 
 static ssize_t
-zc0301_read(struct file* filp, char __user * buf,
-              size_t count, loff_t* f_pos)
+zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
 {
        struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
        struct zc0301_frame_t* f, * i;
@@ -800,7 +806,8 @@ zc0301_read(struct file* filp, char __user * buf,
                            (!list_empty(&cam->outqueue)) ||
                            (cam->state & DEV_DISCONNECTED) ||
                            (cam->state & DEV_MISCONFIGURED),
-                           ZC0301_FRAME_TIMEOUT );
+                           cam->module_param.frame_timeout *
+                           1000 * msecs_to_jiffies(1) );
                if (timeout < 0) {
                        mutex_unlock(&cam->fileop_mutex);
                        return timeout;
@@ -1019,6 +1026,7 @@ zc0301_vidioc_enuminput(struct zc0301_device* cam, void __user * arg)
 
        memset(&i, 0, sizeof(i));
        strcpy(i.name, "Camera");
+       i.type = V4L2_INPUT_TYPE_CAMERA;
 
        if (copy_to_user(arg, &i, sizeof(i)))
                return -EFAULT;
@@ -1028,7 +1036,19 @@ zc0301_vidioc_enuminput(struct zc0301_device* cam, void __user * arg)
 
 
 static int
-zc0301_vidioc_gs_input(struct zc0301_device* cam, void __user * arg)
+zc0301_vidioc_g_input(struct zc0301_device* cam, void __user * arg)
+{
+       int index = 0;
+
+       if (copy_to_user(arg, &index, sizeof(index)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+zc0301_vidioc_s_input(struct zc0301_device* cam, void __user * arg)
 {
        int index;
 
@@ -1045,7 +1065,7 @@ zc0301_vidioc_gs_input(struct zc0301_device* cam, void __user * arg)
 static int
 zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg)
 {
-       struct zc0301_sensor* s = cam->sensor;
+       struct zc0301_sensor* s = &cam->sensor;
        struct v4l2_queryctrl qc;
        u8 i;
 
@@ -1067,7 +1087,7 @@ zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg)
 static int
 zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg)
 {
-       struct zc0301_sensor* s = cam->sensor;
+       struct zc0301_sensor* s = &cam->sensor;
        struct v4l2_control ctrl;
        int err = 0;
        u8 i;
@@ -1099,7 +1119,7 @@ exit:
 static int
 zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
 {
-       struct zc0301_sensor* s = cam->sensor;
+       struct zc0301_sensor* s = &cam->sensor;
        struct v4l2_control ctrl;
        u8 i;
        int err = 0;
@@ -1112,6 +1132,8 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
 
        for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
                if (ctrl.id == s->qctrl[i].id) {
+                       if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
+                               return -EINVAL;
                        if (ctrl.value < s->qctrl[i].minimum ||
                            ctrl.value > s->qctrl[i].maximum)
                                return -ERANGE;
@@ -1131,7 +1153,7 @@ zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg)
 static int
 zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg)
 {
-       struct v4l2_cropcap* cc = &(cam->sensor->cropcap);
+       struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
 
        cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        cc->pixelaspect.numerator = 1;
@@ -1147,7 +1169,7 @@ zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg)
 static int
 zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg)
 {
-       struct zc0301_sensor* s = cam->sensor;
+       struct zc0301_sensor* s = &cam->sensor;
        struct v4l2_crop crop = {
                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
        };
@@ -1164,7 +1186,7 @@ zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg)
 static int
 zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg)
 {
-       struct zc0301_sensor* s = cam->sensor;
+       struct zc0301_sensor* s = &cam->sensor;
        struct v4l2_crop crop;
        struct v4l2_rect* rect;
        struct v4l2_rect* bounds = &(s->cropcap.bounds);
@@ -1293,7 +1315,7 @@ static int
 zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg)
 {
        struct v4l2_format format;
-       struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);
+       struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
 
        if (copy_from_user(&format, arg, sizeof(format)))
                return -EFAULT;
@@ -1317,7 +1339,7 @@ static int
 zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd,
                         void __user * arg)
 {
-       struct zc0301_sensor* s = cam->sensor;
+       struct zc0301_sensor* s = &cam->sensor;
        struct v4l2_format format;
        struct v4l2_pix_format* pix;
        struct v4l2_pix_format* pfmt = &(s->pix_format);
@@ -1446,7 +1468,7 @@ zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg)
        if (copy_from_user(&jc, arg, sizeof(jc)))
                return -EFAULT;
 
-       if (jc.quality < 0 || jc.quality > 3)
+       if (jc.quality != 0)
                return -EINVAL;
 
        if (cam->stream == STREAM_ON)
@@ -1601,7 +1623,8 @@ zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp,
                            (!list_empty(&cam->outqueue)) ||
                            (cam->state & DEV_DISCONNECTED) ||
                            (cam->state & DEV_MISCONFIGURED),
-                           ZC0301_FRAME_TIMEOUT );
+                           cam->module_param.frame_timeout *
+                           1000 * msecs_to_jiffies(1) );
                if (timeout < 0)
                        return timeout;
                if (cam->state & DEV_DISCONNECTED)
@@ -1738,8 +1761,10 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
                return zc0301_vidioc_enuminput(cam, arg);
 
        case VIDIOC_G_INPUT:
+               return zc0301_vidioc_g_input(cam, arg);
+
        case VIDIOC_S_INPUT:
-               return zc0301_vidioc_gs_input(cam, arg);
+               return zc0301_vidioc_s_input(cam, arg);
 
        case VIDIOC_QUERYCTRL:
                return zc0301_vidioc_query_ctrl(cam, arg);
@@ -1898,8 +1923,8 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
                        break;
        }
 
-       if (!err && cam->sensor)
-               DBG(2, "%s image sensor detected", cam->sensor->name);
+       if (!err)
+               DBG(2, "%s image sensor detected", cam->sensor.name);
        else {
                DBG(1, "No supported image sensor detected");
                err = -ENODEV;
@@ -1937,6 +1962,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
 
        cam->module_param.force_munmap = force_munmap[dev_nr];
+       cam->module_param.frame_timeout = frame_timeout[dev_nr];
 
        dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0;
 
@@ -1980,7 +2006,8 @@ static void zc0301_usb_disconnect(struct usb_interface* intf)
                zc0301_stop_transfer(cam);
                cam->state |= DEV_DISCONNECTED;
                wake_up_interruptible(&cam->wait_frame);
-               wake_up_interruptible(&cam->wait_stream);
+               wake_up(&cam->wait_stream);
+               usb_get_dev(cam->usbdev);
        } else {
                cam->state |= DEV_DISCONNECTED;
                zc0301_release_resources(cam);