[media] gspca: Allow subdrivers to use the control framework
authorHans Verkuil <hans.verkuil@cisco.com>
Sun, 6 May 2012 12:28:17 +0000 (09:28 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 14 May 2012 12:22:50 +0000 (09:22 -0300)
Make the necessary changes to allow subdrivers to use the control framework.
This does not add control event support, that comes later.

It add a init_control cam_op that is called after init in probe that allows
the subdriver to set up the controls.

HdG: Call v4l2_ctrl_handler_setup from resume instead of
gspca_set_default_mode, as we just want to resend the current ctrl values to
the device.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/gspca.h

index ca5a2b139d0b739f8d5aa149785d95c60d674a4a..d85c30dd37ad74a211da7b433eb3bf3eff9ffce2 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/uaccess.h>
 #include <linux/ktime.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
 
 #include "gspca.h"
 
@@ -1006,6 +1007,8 @@ static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
 
        /* set the current control values to their default values
         * which may have changed in sd_init() */
+       /* does nothing if ctrl_handler == NULL */
+       v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
        ctrl = gspca_dev->cam.ctrls;
        if (ctrl != NULL) {
                for (i = 0;
@@ -1323,6 +1326,7 @@ static void gspca_release(struct video_device *vfd)
        PDEBUG(D_PROBE, "%s released",
                video_device_node_name(&gspca_dev->vdev));
 
+       v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
        kfree(gspca_dev->usb_buf);
        kfree(gspca_dev);
 }
@@ -2347,6 +2351,14 @@ int gspca_dev_probe2(struct usb_interface *intf,
        gspca_dev->sd_desc = sd_desc;
        gspca_dev->nbufread = 2;
        gspca_dev->empty_packet = -1;   /* don't check the empty packets */
+       gspca_dev->vdev = gspca_template;
+       gspca_dev->vdev.parent = &intf->dev;
+       gspca_dev->module = module;
+       gspca_dev->present = 1;
+
+       mutex_init(&gspca_dev->usb_lock);
+       mutex_init(&gspca_dev->queue_lock);
+       init_waitqueue_head(&gspca_dev->wq);
 
        /* configure the subdriver and initialize the USB device */
        ret = sd_desc->config(gspca_dev, id);
@@ -2355,6 +2367,10 @@ int gspca_dev_probe2(struct usb_interface *intf,
        if (gspca_dev->cam.ctrls != NULL)
                ctrls_init(gspca_dev);
        ret = sd_desc->init(gspca_dev);
+       if (ret < 0)
+               goto out;
+       if (sd_desc->init_controls)
+               ret = sd_desc->init_controls(gspca_dev);
        if (ret < 0)
                goto out;
        gspca_set_default_mode(gspca_dev);
@@ -2363,15 +2379,7 @@ int gspca_dev_probe2(struct usb_interface *intf,
        if (ret)
                goto out;
 
-       mutex_init(&gspca_dev->usb_lock);
-       mutex_init(&gspca_dev->queue_lock);
-       init_waitqueue_head(&gspca_dev->wq);
-
        /* init video stuff */
-       memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
-       gspca_dev->vdev.parent = &intf->dev;
-       gspca_dev->module = module;
-       gspca_dev->present = 1;
        ret = video_register_device(&gspca_dev->vdev,
                                  VFL_TYPE_GRABBER,
                                  -1);
@@ -2391,6 +2399,7 @@ out:
        if (gspca_dev->input_dev)
                input_unregister_device(gspca_dev->input_dev);
 #endif
+       v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
        kfree(gspca_dev->usb_buf);
        kfree(gspca_dev);
        return ret;
@@ -2489,11 +2498,20 @@ EXPORT_SYMBOL(gspca_suspend);
 int gspca_resume(struct usb_interface *intf)
 {
        struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+       int streaming;
 
        gspca_dev->frozen = 0;
        gspca_dev->sd_desc->init(gspca_dev);
        gspca_input_create_urb(gspca_dev);
-       if (gspca_dev->streaming)
+       /*
+        * Most subdrivers send all ctrl values on sd_start and thus
+        * only write to the device registers on s_ctrl when streaming ->
+        * Clear streaming to avoid setting all ctrls twice.
+        */
+       streaming = gspca_dev->streaming;
+       gspca_dev->streaming = 0;
+       v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
+       if (streaming)
                return gspca_init_transfer(gspca_dev);
        return 0;
 }
index 589009f4496fcfc2599bed9709f214cc082780f3..81404160ca43f8f49940d5cf34fc83bbef63efd3 100644 (file)
@@ -115,6 +115,7 @@ struct sd_desc {
 /* mandatory operations */
        cam_cf_op config;       /* called on probe */
        cam_op init;            /* called on probe and resume */
+       cam_op init_controls;   /* called on probe */
        cam_op start;           /* called on stream on after URBs creation */
        cam_pkt_op pkt_scan;
 /* optional operations */