V4L/DVB (8525): fix a few assorted spelling mistakes.
[safe/jmp/linux-2.6] / drivers / media / video / stk-webcam.c
index ba4fe93..ad36af3 100644 (file)
 #include <linux/kref.h>
 
 #include <linux/usb.h>
+#include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include "stk-webcam.h"
 
@@ -63,7 +65,7 @@ static struct usb_device_id stkwebcam_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, stkwebcam_table);
 
-void stk_camera_cleanup(struct kref *kref)
+static void stk_camera_cleanup(struct kref *kref)
 {
        struct stk_camera *dev = to_stk_camera(kref);
 
@@ -245,6 +247,8 @@ static int stk_initialise(struct stk_camera *dev)
                return -1;
 }
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+
 /* sysfs functions */
 /*FIXME cleanup this */
 
@@ -337,19 +341,25 @@ static int stk_create_sysfs_files(struct video_device *vdev)
 {
        int ret;
 
-       ret = video_device_create_file(vdev, &dev_attr_brightness);
-       ret += video_device_create_file(vdev, &dev_attr_hflip);
-       ret += video_device_create_file(vdev, &dev_attr_vflip);
+       ret = device_create_file(&vdev->dev, &dev_attr_brightness);
+       ret += device_create_file(&vdev->dev, &dev_attr_hflip);
+       ret += device_create_file(&vdev->dev, &dev_attr_vflip);
+       if (ret)
+               STK_WARNING("Could not create sysfs files\n");
        return ret;
 }
 
 static void stk_remove_sysfs_files(struct video_device *vdev)
 {
-       video_device_remove_file(vdev, &dev_attr_brightness);
-       video_device_remove_file(vdev, &dev_attr_hflip);
-       video_device_remove_file(vdev, &dev_attr_vflip);
+       device_remove_file(&vdev->dev, &dev_attr_brightness);
+       device_remove_file(&vdev->dev, &dev_attr_hflip);
+       device_remove_file(&vdev->dev, &dev_attr_vflip);
 }
 
+#else
+#define stk_create_sysfs_files(a)
+#define stk_remove_sysfs_files(a)
+#endif
 
 /* *********************************************** */
 /*
@@ -435,18 +445,19 @@ static void stk_isoc_handler(struct urb *urb)
                                fb->v4lbuf.bytesused = 0;
                                fill = fb->buffer;
                        } else if (fb->v4lbuf.bytesused == dev->frame_size) {
-                               list_move_tail(dev->sio_avail.next,
-                                       &dev->sio_full);
-                               wake_up(&dev->wait_frame);
-                               if (list_empty(&dev->sio_avail)) {
-                                       (void) (printk_ratelimit() &&
-                                       STK_ERROR("No buffer available\n"));
-                                       goto resubmit;
+                               if (list_is_singular(&dev->sio_avail)) {
+                                       /* Always reuse the last buffer */
+                                       fb->v4lbuf.bytesused = 0;
+                                       fill = fb->buffer;
+                               } else {
+                                       list_move_tail(dev->sio_avail.next,
+                                               &dev->sio_full);
+                                       wake_up(&dev->wait_frame);
+                                       fb = list_first_entry(&dev->sio_avail,
+                                               struct stk_sio_buffer, list);
+                                       fb->v4lbuf.bytesused = 0;
+                                       fill = fb->buffer;
                                }
-                               fb = list_first_entry(&dev->sio_avail,
-                                       struct stk_sio_buffer, list);
-                               fb->v4lbuf.bytesused = 0;
-                               fill = fb->buffer;
                        }
                } else {
                        framelen -= 4;
@@ -682,6 +693,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp)
                return -ENXIO;
        fp->private_data = vdev;
        kref_get(&dev->kref);
+       usb_autopm_get_interface(dev->interface);
 
        return 0;
 }
@@ -703,6 +715,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp)
        }
 
        if (dev->owner != fp) {
+               usb_autopm_put_interface(dev->interface);
                kref_put(&dev->kref, stk_camera_cleanup);
                return 0;
        }
@@ -713,6 +726,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp)
 
        dev->owner = NULL;
 
+       usb_autopm_put_interface(dev->interface);
        kref_put(&dev->kref, stk_camera_cleanup);
 
        return 0;
@@ -971,7 +985,7 @@ static int stk_vidioc_s_ctrl(struct file *filp,
 }
 
 
-static int stk_vidioc_enum_fmt_cap(struct file *filp,
+static int stk_vidioc_enum_fmt_vid_cap(struct file *filp,
                void *priv, struct v4l2_fmtdesc *fmtd)
 {
        fmtd->flags = 0;
@@ -1015,7 +1029,7 @@ static struct stk_size {
        { .w = 176,  .h = 144,  .m = MODE_QCIF, },
 };
 
-static int stk_vidioc_g_fmt_cap(struct file *filp,
+static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
                void *priv, struct v4l2_format *f)
 {
        struct v4l2_pix_format *pix_format = &f->fmt.pix;
@@ -1044,7 +1058,7 @@ static int stk_vidioc_g_fmt_cap(struct file *filp,
        return 0;
 }
 
-static int stk_vidioc_try_fmt_cap(struct file *filp,
+static int stk_vidioc_try_fmt_vid_cap(struct file *filp,
                void *priv, struct v4l2_format *fmtd)
 {
        int i;
@@ -1085,7 +1099,43 @@ static int stk_vidioc_try_fmt_cap(struct file *filp,
        return 0;
 }
 
-static int stk_vidioc_s_fmt_cap(struct file *filp,
+static int stk_setup_format(struct stk_camera *dev)
+{
+       int i = 0;
+       int depth;
+       if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)
+               depth = 1;
+       else
+               depth = 2;
+       while (stk_sizes[i].m != dev->vsettings.mode
+                       && i < ARRAY_SIZE(stk_sizes))
+               i++;
+       if (i == ARRAY_SIZE(stk_sizes)) {
+               STK_ERROR("Something is broken in %s\n", __func__);
+               return -EFAULT;
+       }
+       /* This registers controls some timings, not sure of what. */
+       stk_camera_write_reg(dev, 0x001b, 0x0e);
+       if (dev->vsettings.mode == MODE_SXGA)
+               stk_camera_write_reg(dev, 0x001c, 0x0e);
+       else
+               stk_camera_write_reg(dev, 0x001c, 0x46);
+       /*
+        * Registers 0x0115 0x0114 are the size of each line (bytes),
+        * regs 0x0117 0x0116 are the heigth of the image.
+        */
+       stk_camera_write_reg(dev, 0x0115,
+               ((stk_sizes[i].w * depth) >> 8) & 0xff);
+       stk_camera_write_reg(dev, 0x0114,
+               (stk_sizes[i].w * depth) & 0xff);
+       stk_camera_write_reg(dev, 0x0117,
+               (stk_sizes[i].h >> 8) & 0xff);
+       stk_camera_write_reg(dev, 0x0116,
+               stk_sizes[i].h & 0xff);
+       return stk_sensor_configure(dev);
+}
+
+static int stk_vidioc_s_fmt_vid_cap(struct file *filp,
                void *priv, struct v4l2_format *fmtd)
 {
        int ret;
@@ -1099,10 +1149,10 @@ static int stk_vidioc_s_fmt_cap(struct file *filp,
                return -EBUSY;
        if (dev->owner && dev->owner != filp)
                return -EBUSY;
-       dev->owner = filp;
-       ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd);
+       ret = stk_vidioc_try_fmt_vid_cap(filp, priv, fmtd);
        if (ret)
                return ret;
+       dev->owner = filp;
 
        dev->vsettings.palette = fmtd->fmt.pix.pixelformat;
        stk_free_buffers(dev);
@@ -1110,25 +1160,7 @@ static int stk_vidioc_s_fmt_cap(struct file *filp,
        dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m;
 
        stk_initialise(dev);
-       /* This registers controls some timings, not sure of what. */
-       stk_camera_write_reg(dev, 0x001b, 0x0e);
-       if (dev->vsettings.mode == MODE_SXGA)
-               stk_camera_write_reg(dev, 0x001c, 0x0e);
-       else
-               stk_camera_write_reg(dev, 0x001c, 0x46);
-       /*
-        * Registers 0x0115 0x0114 are the size of each line (bytes),
-        * regs 0x0117 0x0116 are the heigth of the image.
-        */
-       stk_camera_write_reg(dev, 0x0115,
-               (fmtd->fmt.pix.bytesperline >> 8) & 0xff);
-       stk_camera_write_reg(dev, 0x0114,
-               fmtd->fmt.pix.bytesperline & 0xff);
-       stk_camera_write_reg(dev, 0x0117,
-               (fmtd->fmt.pix.height >> 8) & 0xff);
-       stk_camera_write_reg(dev, 0x0116,
-               fmtd->fmt.pix.height & 0xff);
-       return stk_sensor_configure(dev);
+       return stk_setup_format(dev);
 }
 
 static int stk_vidioc_reqbufs(struct file *filp,
@@ -1293,28 +1325,18 @@ static struct file_operations v4l_stk_fops = {
        .poll = v4l_stk_poll,
        .mmap = v4l_stk_mmap,
        .ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = v4l_compat_ioctl32,
+#endif
        .llseek = no_llseek
 };
 
-static void stk_v4l_dev_release(struct video_device *vd)
-{
-}
-
-static struct video_device stk_v4l_data = {
-       .name = "stkwebcam",
-       .type = VFL_TYPE_GRABBER,
-       .type2 = VID_TYPE_CAPTURE,
-       .minor = -1,
-       .tvnorms = V4L2_STD_UNKNOWN,
-       .current_norm = V4L2_STD_UNKNOWN,
-       .fops = &v4l_stk_fops,
-       .release = stk_v4l_dev_release,
-
+static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
        .vidioc_querycap = stk_vidioc_querycap,
-       .vidioc_enum_fmt_cap = stk_vidioc_enum_fmt_cap,
-       .vidioc_try_fmt_cap = stk_vidioc_try_fmt_cap,
-       .vidioc_s_fmt_cap = stk_vidioc_s_fmt_cap,
-       .vidioc_g_fmt_cap = stk_vidioc_g_fmt_cap,
+       .vidioc_enum_fmt_vid_cap = stk_vidioc_enum_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = stk_vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap = stk_vidioc_s_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap = stk_vidioc_g_fmt_vid_cap,
        .vidioc_enum_input = stk_vidioc_enum_input,
        .vidioc_s_input = stk_vidioc_s_input,
        .vidioc_g_input = stk_vidioc_g_input,
@@ -1331,6 +1353,20 @@ static struct video_device stk_v4l_data = {
        .vidioc_g_parm = stk_vidioc_g_parm,
 };
 
+static void stk_v4l_dev_release(struct video_device *vd)
+{
+}
+
+static struct video_device stk_v4l_data = {
+       .name = "stkwebcam",
+       .minor = -1,
+       .tvnorms = V4L2_STD_UNKNOWN,
+       .current_norm = V4L2_STD_UNKNOWN,
+       .fops = &v4l_stk_fops,
+       .ioctl_ops = &v4l_stk_ioctl_ops,
+       .release = stk_v4l_dev_release,
+};
+
 
 static int stk_register_video_device(struct stk_camera *dev)
 {
@@ -1338,7 +1374,7 @@ static int stk_register_video_device(struct stk_camera *dev)
 
        dev->vdev = stk_v4l_data;
        dev->vdev.debug = debug;
-       dev->vdev.dev = &dev->interface->dev;
+       dev->vdev.parent = &dev->interface->dev;
        dev->vdev.priv = dev;
        err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
        if (err)
@@ -1422,6 +1458,7 @@ static int stk_camera_probe(struct usb_interface *interface,
        }
 
        stk_create_sysfs_files(&dev->vdev);
+       usb_autopm_enable(dev->interface);
 
        return 0;
 }
@@ -1439,11 +1476,41 @@ static void stk_camera_disconnect(struct usb_interface *interface)
        kref_put(&dev->kref, stk_camera_cleanup);
 }
 
+#ifdef CONFIG_PM
+static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct stk_camera *dev = usb_get_intfdata(intf);
+       if (is_streaming(dev)) {
+               stk_stop_stream(dev);
+               /* yes, this is ugly */
+               set_streaming(dev);
+       }
+       return 0;
+}
+
+static int stk_camera_resume(struct usb_interface *intf)
+{
+       struct stk_camera *dev = usb_get_intfdata(intf);
+       if (!is_initialised(dev))
+               return 0;
+       unset_initialised(dev);
+       stk_initialise(dev);
+       stk_setup_format(dev);
+       if (is_streaming(dev))
+               stk_start_stream(dev);
+       return 0;
+}
+#endif
+
 static struct usb_driver stk_camera_driver = {
        .name = "stkwebcam",
        .probe = stk_camera_probe,
        .disconnect = stk_camera_disconnect,
        .id_table = stkwebcam_table,
+#ifdef CONFIG_PM
+       .suspend = stk_camera_suspend,
+       .resume = stk_camera_resume,
+#endif
 };