Merge tag 'v2.6.39-rc7'
[pandora-kernel.git] / drivers / media / video / vivi.c
index 9ed3831..2238a61 100644 (file)
@@ -30,6 +30,8 @@
 #include <media/videobuf2-vmalloc.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
 #include <media/v4l2-common.h>
 
 #define VIVI_MODULE_NAME "vivi"
@@ -158,13 +160,20 @@ static LIST_HEAD(vivi_devlist);
 struct vivi_dev {
        struct list_head           vivi_devlist;
        struct v4l2_device         v4l2_dev;
+       struct v4l2_ctrl_handler   ctrl_handler;
 
        /* controls */
-       int                        brightness;
-       int                        contrast;
-       int                        saturation;
-       int                        hue;
-       int                        volume;
+       struct v4l2_ctrl           *brightness;
+       struct v4l2_ctrl           *contrast;
+       struct v4l2_ctrl           *saturation;
+       struct v4l2_ctrl           *hue;
+       struct v4l2_ctrl           *volume;
+       struct v4l2_ctrl           *button;
+       struct v4l2_ctrl           *boolean;
+       struct v4l2_ctrl           *int32;
+       struct v4l2_ctrl           *int64;
+       struct v4l2_ctrl           *menu;
+       struct v4l2_ctrl           *string;
 
        spinlock_t                 slock;
        struct mutex               mutex;
@@ -177,6 +186,7 @@ struct vivi_dev {
        /* Several counters */
        unsigned                   ms;
        unsigned long              jiffies;
+       unsigned                   button_pressed;
 
        int                        mv_count;    /* Controls bars movement */
 
@@ -190,7 +200,6 @@ struct vivi_dev {
        enum v4l2_field            field;
        unsigned int               field_count;
 
-       unsigned int               open_count;
        u8                         bars[9][3];
        u8                         line[MAX_WIDTH * 4];
 };
@@ -470,14 +479,30 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
                        dev->width, dev->height, dev->input);
        gen_text(dev, vbuf, line++ * 16, 16, str);
 
+       mutex_lock(&dev->ctrl_handler.lock);
        snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
-                       dev->brightness,
-                       dev->contrast,
-                       dev->saturation,
-                       dev->hue);
+                       dev->brightness->cur.val,
+                       dev->contrast->cur.val,
+                       dev->saturation->cur.val,
+                       dev->hue->cur.val);
        gen_text(dev, vbuf, line++ * 16, 16, str);
-       snprintf(str, sizeof(str), " volume %3d ", dev->volume);
+       snprintf(str, sizeof(str), " volume %3d ", dev->volume->cur.val);
        gen_text(dev, vbuf, line++ * 16, 16, str);
+       snprintf(str, sizeof(str), " int32 %d, int64 %lld ",
+                       dev->int32->cur.val,
+                       dev->int64->cur.val64);
+       gen_text(dev, vbuf, line++ * 16, 16, str);
+       snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
+                       dev->boolean->cur.val,
+                       dev->menu->qmenu[dev->menu->cur.val],
+                       dev->string->cur.string);
+       mutex_unlock(&dev->ctrl_handler.lock);
+       gen_text(dev, vbuf, line++ * 16, 16, str);
+       if (dev->button_pressed) {
+               dev->button_pressed--;
+               snprintf(str, sizeof(str), " button pressed!");
+               gen_text(dev, vbuf, line++ * 16, 16, str);
+       }
 
        dev->mv_count += 2;
 
@@ -957,95 +982,20 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 }
 
 /* --- controls ---------------------------------------------- */
-static int vidioc_queryctrl(struct file *file, void *priv,
-                           struct v4l2_queryctrl *qc)
-{
-       switch (qc->id) {
-       case V4L2_CID_AUDIO_VOLUME:
-               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 200);
-       case V4L2_CID_BRIGHTNESS:
-               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
-       case V4L2_CID_CONTRAST:
-               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 16);
-       case V4L2_CID_SATURATION:
-               return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
-       case V4L2_CID_HUE:
-               return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
-       }
-       return -EINVAL;
-}
 
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
+static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-       struct vivi_dev *dev = video_drvdata(file);
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUDIO_VOLUME:
-               ctrl->value = dev->volume;
-               return 0;
-       case V4L2_CID_BRIGHTNESS:
-               ctrl->value = dev->brightness;
-               return 0;
-       case V4L2_CID_CONTRAST:
-               ctrl->value = dev->contrast;
-               return 0;
-       case V4L2_CID_SATURATION:
-               ctrl->value = dev->saturation;
-               return 0;
-       case V4L2_CID_HUE:
-               ctrl->value = dev->hue;
-               return 0;
-       }
-       return -EINVAL;
-}
+       struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
 
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct vivi_dev *dev = video_drvdata(file);
-       struct v4l2_queryctrl qc;
-       int err;
-
-       qc.id = ctrl->id;
-       err = vidioc_queryctrl(file, priv, &qc);
-       if (err < 0)
-               return err;
-       if (ctrl->value < qc.minimum || ctrl->value > qc.maximum)
-               return -ERANGE;
-       switch (ctrl->id) {
-       case V4L2_CID_AUDIO_VOLUME:
-               dev->volume = ctrl->value;
-               return 0;
-       case V4L2_CID_BRIGHTNESS:
-               dev->brightness = ctrl->value;
-               return 0;
-       case V4L2_CID_CONTRAST:
-               dev->contrast = ctrl->value;
-               return 0;
-       case V4L2_CID_SATURATION:
-               dev->saturation = ctrl->value;
-               return 0;
-       case V4L2_CID_HUE:
-               dev->hue = ctrl->value;
-               return 0;
-       }
-       return -EINVAL;
+       if (ctrl == dev->button)
+               dev->button_pressed = 30;
+       return 0;
 }
 
 /* ------------------------------------------------------------------
        File operations for the device
    ------------------------------------------------------------------*/
 
-static int vivi_open(struct file *file)
-{
-       struct vivi_dev *dev = video_drvdata(file);
-
-       dprintk(dev, 1, "%s, %p\n", __func__, file);
-       dev->open_count++;
-       return 0;
-}
-
 static ssize_t
 vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
@@ -1074,9 +1024,9 @@ static int vivi_close(struct file *file)
        dprintk(dev, 1, "close called (dev=%s), file %p\n",
                video_device_node_name(vdev), file);
 
-       if (--dev->open_count == 0)
+       if (v4l2_fh_is_singular_file(file))
                vb2_queue_release(&dev->vb_vidq);
-       return 0;
+       return v4l2_fh_release(file);
 }
 
 static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
@@ -1094,9 +1044,82 @@ static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
        return ret;
 }
 
+static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
+       .s_ctrl = vivi_s_ctrl,
+};
+
+#define VIVI_CID_CUSTOM_BASE   (V4L2_CID_USER_BASE | 0xf000)
+
+static const struct v4l2_ctrl_config vivi_ctrl_button = {
+       .ops = &vivi_ctrl_ops,
+       .id = VIVI_CID_CUSTOM_BASE + 0,
+       .name = "Button",
+       .type = V4L2_CTRL_TYPE_BUTTON,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
+       .ops = &vivi_ctrl_ops,
+       .id = VIVI_CID_CUSTOM_BASE + 1,
+       .name = "Boolean",
+       .type = V4L2_CTRL_TYPE_BOOLEAN,
+       .min = 0,
+       .max = 1,
+       .step = 1,
+       .def = 1,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
+       .ops = &vivi_ctrl_ops,
+       .id = VIVI_CID_CUSTOM_BASE + 2,
+       .name = "Integer 32 Bits",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0x80000000,
+       .max = 0x7fffffff,
+       .step = 1,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
+       .ops = &vivi_ctrl_ops,
+       .id = VIVI_CID_CUSTOM_BASE + 3,
+       .name = "Integer 64 Bits",
+       .type = V4L2_CTRL_TYPE_INTEGER64,
+};
+
+static const char * const vivi_ctrl_menu_strings[] = {
+       "Menu Item 0 (Skipped)",
+       "Menu Item 1",
+       "Menu Item 2 (Skipped)",
+       "Menu Item 3",
+       "Menu Item 4",
+       "Menu Item 5 (Skipped)",
+       NULL,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_menu = {
+       .ops = &vivi_ctrl_ops,
+       .id = VIVI_CID_CUSTOM_BASE + 4,
+       .name = "Menu",
+       .type = V4L2_CTRL_TYPE_MENU,
+       .min = 1,
+       .max = 4,
+       .def = 3,
+       .menu_skip_mask = 0x04,
+       .qmenu = vivi_ctrl_menu_strings,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_string = {
+       .ops = &vivi_ctrl_ops,
+       .id = VIVI_CID_CUSTOM_BASE + 5,
+       .name = "String",
+       .type = V4L2_CTRL_TYPE_STRING,
+       .min = 2,
+       .max = 4,
+       .step = 1,
+};
+
 static const struct v4l2_file_operations vivi_fops = {
        .owner          = THIS_MODULE,
-       .open           = vivi_open,
+       .open           = v4l2_fh_open,
        .release        = vivi_close,
        .read           = vivi_read,
        .poll           = vivi_poll,
@@ -1120,9 +1143,6 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
        .vidioc_s_input       = vidioc_s_input,
        .vidioc_streamon      = vidioc_streamon,
        .vidioc_streamoff     = vidioc_streamoff,
-       .vidioc_queryctrl     = vidioc_queryctrl,
-       .vidioc_g_ctrl        = vidioc_g_ctrl,
-       .vidioc_s_ctrl        = vidioc_s_ctrl,
 };
 
 static struct video_device vivi_template = {
@@ -1153,6 +1173,7 @@ static int vivi_release(void)
                        video_device_node_name(dev->vfd));
                video_unregister_device(dev->vfd);
                v4l2_device_unregister(&dev->v4l2_dev);
+               v4l2_ctrl_handler_free(&dev->ctrl_handler);
                kfree(dev);
        }
 
@@ -1163,6 +1184,7 @@ static int __init vivi_create_instance(int inst)
 {
        struct vivi_dev *dev;
        struct video_device *vfd;
+       struct v4l2_ctrl_handler *hdl;
        struct vb2_queue *q;
        int ret;
 
@@ -1179,11 +1201,29 @@ static int __init vivi_create_instance(int inst)
        dev->fmt = &formats[0];
        dev->width = 640;
        dev->height = 480;
-       dev->volume = 200;
-       dev->brightness = 127;
-       dev->contrast = 16;
-       dev->saturation = 127;
-       dev->hue = 0;
+       hdl = &dev->ctrl_handler;
+       v4l2_ctrl_handler_init(hdl, 11);
+       dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+                       V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
+       dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+       dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, 16);
+       dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 255, 1, 127);
+       dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+                       V4L2_CID_HUE, -128, 127, 1, 0);
+       dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
+       dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
+       dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
+       dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
+       dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
+       dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
+       if (hdl->error) {
+               ret = hdl->error;
+               goto unreg_dev;
+       }
+       dev->v4l2_dev.ctrl_handler = hdl;
 
        /* initialize locks */
        spin_lock_init(&dev->slock);
@@ -1214,6 +1254,7 @@ static int __init vivi_create_instance(int inst)
        *vfd = vivi_template;
        vfd->debug = debug;
        vfd->v4l2_dev = &dev->v4l2_dev;
+       set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
 
        /*
         * Provide a mutex to v4l2 core. It will be used to protect
@@ -1241,6 +1282,7 @@ static int __init vivi_create_instance(int inst)
 rel_vdev:
        video_device_release(vfd);
 unreg_dev:
+       v4l2_ctrl_handler_free(hdl);
        v4l2_device_unregister(&dev->v4l2_dev);
 free_dev:
        kfree(dev);