|
@@ -39,15 +39,15 @@
|
|
|
#include <linux/videodev2.h>
|
|
|
#include <linux/stringify.h>
|
|
|
#include <media/v4l2-ioctl.h>
|
|
|
+#include <media/v4l2-event.h>
|
|
|
|
|
|
#include "cpia2.h"
|
|
|
-#include "cpia2dev.h"
|
|
|
|
|
|
static int video_nr = -1;
|
|
|
module_param(video_nr, int, 0);
|
|
|
-MODULE_PARM_DESC(video_nr,"video device to register (0=/dev/video0, etc)");
|
|
|
+MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)");
|
|
|
|
|
|
-static int buffer_size = 68*1024;
|
|
|
+static int buffer_size = 68 * 1024;
|
|
|
module_param(buffer_size, int, 0);
|
|
|
MODULE_PARM_DESC(buffer_size, "Size for each frame buffer in bytes (default 68k)");
|
|
|
|
|
@@ -62,18 +62,10 @@ MODULE_PARM_DESC(alternate, "USB Alternate (" __stringify(USBIF_ISO_1) "-"
|
|
|
__stringify(USBIF_ISO_6) ", default "
|
|
|
__stringify(DEFAULT_ALT) ")");
|
|
|
|
|
|
-static int flicker_freq = 60;
|
|
|
-module_param(flicker_freq, int, 0);
|
|
|
-MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" __stringify(50) "or"
|
|
|
- __stringify(60) ", default "
|
|
|
- __stringify(60) ")");
|
|
|
-
|
|
|
-static int flicker_mode = NEVER_FLICKER;
|
|
|
+static int flicker_mode;
|
|
|
module_param(flicker_mode, int, 0);
|
|
|
-MODULE_PARM_DESC(flicker_mode,
|
|
|
- "Flicker supression (" __stringify(NEVER_FLICKER) "or"
|
|
|
- __stringify(ANTI_FLICKER_ON) ", default "
|
|
|
- __stringify(NEVER_FLICKER) ")");
|
|
|
+MODULE_PARM_DESC(flicker_mode, "Flicker frequency (0 (disabled), " __stringify(50) " or "
|
|
|
+ __stringify(60) ", default 0)");
|
|
|
|
|
|
MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>");
|
|
|
MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras");
|
|
@@ -82,153 +74,7 @@ MODULE_LICENSE("GPL");
|
|
|
MODULE_VERSION(CPIA_VERSION);
|
|
|
|
|
|
#define ABOUT "V4L-Driver for Vision CPiA2 based cameras"
|
|
|
-
|
|
|
-struct control_menu_info {
|
|
|
- int value;
|
|
|
- char name[32];
|
|
|
-};
|
|
|
-
|
|
|
-static struct control_menu_info framerate_controls[] =
|
|
|
-{
|
|
|
- { CPIA2_VP_FRAMERATE_6_25, "6.25 fps" },
|
|
|
- { CPIA2_VP_FRAMERATE_7_5, "7.5 fps" },
|
|
|
- { CPIA2_VP_FRAMERATE_12_5, "12.5 fps" },
|
|
|
- { CPIA2_VP_FRAMERATE_15, "15 fps" },
|
|
|
- { CPIA2_VP_FRAMERATE_25, "25 fps" },
|
|
|
- { CPIA2_VP_FRAMERATE_30, "30 fps" },
|
|
|
-};
|
|
|
-#define NUM_FRAMERATE_CONTROLS (ARRAY_SIZE(framerate_controls))
|
|
|
-
|
|
|
-static struct control_menu_info flicker_controls[] =
|
|
|
-{
|
|
|
- { NEVER_FLICKER, "Off" },
|
|
|
- { FLICKER_50, "50 Hz" },
|
|
|
- { FLICKER_60, "60 Hz" },
|
|
|
-};
|
|
|
-#define NUM_FLICKER_CONTROLS (ARRAY_SIZE(flicker_controls))
|
|
|
-
|
|
|
-static struct control_menu_info lights_controls[] =
|
|
|
-{
|
|
|
- { 0, "Off" },
|
|
|
- { 64, "Top" },
|
|
|
- { 128, "Bottom" },
|
|
|
- { 192, "Both" },
|
|
|
-};
|
|
|
-#define NUM_LIGHTS_CONTROLS (ARRAY_SIZE(lights_controls))
|
|
|
-#define GPIO_LIGHTS_MASK 192
|
|
|
-
|
|
|
-static struct v4l2_queryctrl controls[] = {
|
|
|
- {
|
|
|
- .id = V4L2_CID_BRIGHTNESS,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Brightness",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 255,
|
|
|
- .step = 1,
|
|
|
- .default_value = DEFAULT_BRIGHTNESS,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = V4L2_CID_CONTRAST,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Contrast",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 255,
|
|
|
- .step = 1,
|
|
|
- .default_value = DEFAULT_CONTRAST,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = V4L2_CID_SATURATION,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Saturation",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 255,
|
|
|
- .step = 1,
|
|
|
- .default_value = DEFAULT_SATURATION,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = V4L2_CID_HFLIP,
|
|
|
- .type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
|
- .name = "Mirror Horizontally",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 1,
|
|
|
- .step = 1,
|
|
|
- .default_value = 0,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = V4L2_CID_VFLIP,
|
|
|
- .type = V4L2_CTRL_TYPE_BOOLEAN,
|
|
|
- .name = "Flip Vertically",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 1,
|
|
|
- .step = 1,
|
|
|
- .default_value = 0,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = CPIA2_CID_TARGET_KB,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "Target KB",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 255,
|
|
|
- .step = 1,
|
|
|
- .default_value = DEFAULT_TARGET_KB,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = CPIA2_CID_GPIO,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "GPIO",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 255,
|
|
|
- .step = 1,
|
|
|
- .default_value = 0,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = CPIA2_CID_FLICKER_MODE,
|
|
|
- .type = V4L2_CTRL_TYPE_MENU,
|
|
|
- .name = "Flicker Reduction",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = NUM_FLICKER_CONTROLS-1,
|
|
|
- .step = 1,
|
|
|
- .default_value = 0,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = CPIA2_CID_FRAMERATE,
|
|
|
- .type = V4L2_CTRL_TYPE_MENU,
|
|
|
- .name = "Framerate",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = NUM_FRAMERATE_CONTROLS-1,
|
|
|
- .step = 1,
|
|
|
- .default_value = NUM_FRAMERATE_CONTROLS-1,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = CPIA2_CID_USB_ALT,
|
|
|
- .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
- .name = "USB Alternate",
|
|
|
- .minimum = USBIF_ISO_1,
|
|
|
- .maximum = USBIF_ISO_6,
|
|
|
- .step = 1,
|
|
|
- .default_value = DEFAULT_ALT,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = CPIA2_CID_LIGHTS,
|
|
|
- .type = V4L2_CTRL_TYPE_MENU,
|
|
|
- .name = "Lights",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = NUM_LIGHTS_CONTROLS-1,
|
|
|
- .step = 1,
|
|
|
- .default_value = 0,
|
|
|
- },
|
|
|
- {
|
|
|
- .id = CPIA2_CID_RESET_CAMERA,
|
|
|
- .type = V4L2_CTRL_TYPE_BUTTON,
|
|
|
- .name = "Reset Camera",
|
|
|
- .minimum = 0,
|
|
|
- .maximum = 0,
|
|
|
- .step = 0,
|
|
|
- .default_value = 0,
|
|
|
- },
|
|
|
-};
|
|
|
-#define NUM_CONTROLS (ARRAY_SIZE(controls))
|
|
|
-
|
|
|
+#define CPIA2_CID_USB_ALT (V4L2_CID_USER_BASE | 0xf000)
|
|
|
|
|
|
/******************************************************************************
|
|
|
*
|
|
@@ -238,38 +84,27 @@ static struct v4l2_queryctrl controls[] = {
|
|
|
static int cpia2_open(struct file *file)
|
|
|
{
|
|
|
struct camera_data *cam = video_drvdata(file);
|
|
|
- struct cpia2_fh *fh;
|
|
|
-
|
|
|
- if (!cam) {
|
|
|
- ERR("Internal error, camera_data not found!\n");
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
+ int retval = v4l2_fh_open(file);
|
|
|
|
|
|
- if (!cam->present)
|
|
|
- return -ENODEV;
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
|
|
|
- if (cam->open_count == 0) {
|
|
|
- if (cpia2_allocate_buffers(cam))
|
|
|
+ if (v4l2_fh_is_singular_file(file)) {
|
|
|
+ if (cpia2_allocate_buffers(cam)) {
|
|
|
+ v4l2_fh_release(file);
|
|
|
return -ENOMEM;
|
|
|
+ }
|
|
|
|
|
|
/* reset the camera */
|
|
|
- if (cpia2_reset_camera(cam) < 0)
|
|
|
+ if (cpia2_reset_camera(cam) < 0) {
|
|
|
+ v4l2_fh_release(file);
|
|
|
return -EIO;
|
|
|
+ }
|
|
|
|
|
|
cam->APP_len = 0;
|
|
|
cam->COM_len = 0;
|
|
|
}
|
|
|
|
|
|
- fh = kmalloc(sizeof(*fh), GFP_KERNEL);
|
|
|
- if (!fh)
|
|
|
- return -ENOMEM;
|
|
|
- file->private_data = fh;
|
|
|
- fh->prio = V4L2_PRIORITY_UNSET;
|
|
|
- v4l2_prio_open(&cam->prio, &fh->prio);
|
|
|
- fh->mmapped = 0;
|
|
|
-
|
|
|
- ++cam->open_count;
|
|
|
-
|
|
|
cpia2_dbg_dump_registers(cam);
|
|
|
return 0;
|
|
|
}
|
|
@@ -283,37 +118,22 @@ static int cpia2_close(struct file *file)
|
|
|
{
|
|
|
struct video_device *dev = video_devdata(file);
|
|
|
struct camera_data *cam = video_get_drvdata(dev);
|
|
|
- struct cpia2_fh *fh = file->private_data;
|
|
|
|
|
|
- if (cam->present &&
|
|
|
- (cam->open_count == 1 || fh->prio == V4L2_PRIORITY_RECORD)) {
|
|
|
+ if (video_is_registered(&cam->vdev) && v4l2_fh_is_singular_file(file)) {
|
|
|
cpia2_usb_stream_stop(cam);
|
|
|
|
|
|
- if (cam->open_count == 1) {
|
|
|
- /* save camera state for later open */
|
|
|
- cpia2_save_camera_state(cam);
|
|
|
+ /* save camera state for later open */
|
|
|
+ cpia2_save_camera_state(cam);
|
|
|
|
|
|
- cpia2_set_low_power(cam);
|
|
|
- cpia2_free_buffers(cam);
|
|
|
- }
|
|
|
+ cpia2_set_low_power(cam);
|
|
|
+ cpia2_free_buffers(cam);
|
|
|
}
|
|
|
|
|
|
- if (fh->mmapped)
|
|
|
+ if (cam->stream_fh == file->private_data) {
|
|
|
+ cam->stream_fh = NULL;
|
|
|
cam->mmapped = 0;
|
|
|
- v4l2_prio_close(&cam->prio, fh->prio);
|
|
|
- file->private_data = NULL;
|
|
|
- kfree(fh);
|
|
|
-
|
|
|
- if (--cam->open_count == 0) {
|
|
|
- cpia2_free_buffers(cam);
|
|
|
- if (!cam->present) {
|
|
|
- video_unregister_device(dev);
|
|
|
- kfree(cam);
|
|
|
- return 0;
|
|
|
- }
|
|
|
}
|
|
|
-
|
|
|
- return 0;
|
|
|
+ return v4l2_fh_release(file);
|
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
@@ -327,16 +147,9 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
|
|
|
struct camera_data *cam = video_drvdata(file);
|
|
|
int noblock = file->f_flags&O_NONBLOCK;
|
|
|
|
|
|
- struct cpia2_fh *fh = file->private_data;
|
|
|
-
|
|
|
if(!cam)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- /* Priority check */
|
|
|
- if(fh->prio != V4L2_PRIORITY_RECORD) {
|
|
|
- return -EBUSY;
|
|
|
- }
|
|
|
-
|
|
|
return cpia2_read(cam, buf, count, noblock);
|
|
|
}
|
|
|
|
|
@@ -349,15 +162,6 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
|
|
|
static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait)
|
|
|
{
|
|
|
struct camera_data *cam = video_drvdata(filp);
|
|
|
- struct cpia2_fh *fh = filp->private_data;
|
|
|
-
|
|
|
- if(!cam)
|
|
|
- return POLLERR;
|
|
|
-
|
|
|
- /* Priority check */
|
|
|
- if(fh->prio != V4L2_PRIORITY_RECORD) {
|
|
|
- return POLLERR;
|
|
|
- }
|
|
|
|
|
|
return cpia2_poll(cam, filp, wait);
|
|
|
}
|
|
@@ -384,34 +188,11 @@ static int sync(struct camera_data *cam, int frame_nr)
|
|
|
mutex_lock(&cam->v4l2_lock);
|
|
|
if (signal_pending(current))
|
|
|
return -ERESTARTSYS;
|
|
|
- if(!cam->present)
|
|
|
+ if (!video_is_registered(&cam->vdev))
|
|
|
return -ENOTTY;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/******************************************************************************
|
|
|
- *
|
|
|
- * ioctl_set_gpio
|
|
|
- *
|
|
|
- *****************************************************************************/
|
|
|
-
|
|
|
-static long cpia2_default(struct file *file, void *fh, bool valid_prio,
|
|
|
- int cmd, void *arg)
|
|
|
-{
|
|
|
- struct camera_data *cam = video_drvdata(file);
|
|
|
- __u32 gpio_val;
|
|
|
-
|
|
|
- if (cmd != CPIA2_CID_GPIO)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- gpio_val = *(__u32*) arg;
|
|
|
-
|
|
|
- if (gpio_val &~ 0xFFU)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- return cpia2_set_gpio(cam, (unsigned char)gpio_val);
|
|
|
-}
|
|
|
-
|
|
|
/******************************************************************************
|
|
|
*
|
|
|
* ioctl_querycap
|
|
@@ -465,9 +246,11 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v
|
|
|
if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0)
|
|
|
memset(vc->bus_info,0, sizeof(vc->bus_info));
|
|
|
|
|
|
- vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
|
|
|
+ vc->device_caps = V4L2_CAP_VIDEO_CAPTURE |
|
|
|
V4L2_CAP_READWRITE |
|
|
|
V4L2_CAP_STREAMING;
|
|
|
+ vc->capabilities = vc->device_caps |
|
|
|
+ V4L2_CAP_DEVICE_CAPS;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -610,22 +393,12 @@ static int cpia2_s_fmt_vid_cap(struct file *file, void *_fh,
|
|
|
struct v4l2_format *f)
|
|
|
{
|
|
|
struct camera_data *cam = video_drvdata(file);
|
|
|
- struct cpia2_fh *fh = _fh;
|
|
|
int err, frame;
|
|
|
|
|
|
- err = v4l2_prio_check(&cam->prio, fh->prio);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
err = cpia2_try_fmt_vid_cap(file, _fh, f);
|
|
|
if(err != 0)
|
|
|
return err;
|
|
|
|
|
|
- /* Ensure that only this process can change the format. */
|
|
|
- err = v4l2_prio_change(&cam->prio, &fh->prio, V4L2_PRIORITY_RECORD);
|
|
|
- if(err != 0) {
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
cam->pixelformat = f->fmt.pix.pixelformat;
|
|
|
|
|
|
/* NOTE: This should be set to 1 for MJPEG, but some apps don't handle
|
|
@@ -713,240 +486,126 @@ static int cpia2_cropcap(struct file *file, void *fh, struct v4l2_cropcap *c)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/******************************************************************************
|
|
|
- *
|
|
|
- * ioctl_queryctrl
|
|
|
- *
|
|
|
- * V4L2 query possible control variables
|
|
|
- *
|
|
|
- *****************************************************************************/
|
|
|
+struct framerate_info {
|
|
|
+ int value;
|
|
|
+ struct v4l2_fract period;
|
|
|
+};
|
|
|
|
|
|
-static int cpia2_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c)
|
|
|
+static const struct framerate_info framerate_controls[] = {
|
|
|
+ { CPIA2_VP_FRAMERATE_6_25, { 4, 25 } },
|
|
|
+ { CPIA2_VP_FRAMERATE_7_5, { 2, 15 } },
|
|
|
+ { CPIA2_VP_FRAMERATE_12_5, { 2, 25 } },
|
|
|
+ { CPIA2_VP_FRAMERATE_15, { 1, 15 } },
|
|
|
+ { CPIA2_VP_FRAMERATE_25, { 1, 25 } },
|
|
|
+ { CPIA2_VP_FRAMERATE_30, { 1, 30 } },
|
|
|
+};
|
|
|
+
|
|
|
+static int cpia2_g_parm(struct file *file, void *fh, struct v4l2_streamparm *p)
|
|
|
{
|
|
|
struct camera_data *cam = video_drvdata(file);
|
|
|
+ struct v4l2_captureparm *cap = &p->parm.capture;
|
|
|
int i;
|
|
|
|
|
|
- for(i=0; i<NUM_CONTROLS; ++i) {
|
|
|
- if(c->id == controls[i].id) {
|
|
|
- memcpy(c, controls+i, sizeof(*c));
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(i == NUM_CONTROLS)
|
|
|
+ if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- /* Some devices have additional limitations */
|
|
|
- switch(c->id) {
|
|
|
- case V4L2_CID_BRIGHTNESS:
|
|
|
- /***
|
|
|
- * Don't let the register be set to zero - bug in VP4
|
|
|
- * flash of full brightness
|
|
|
- ***/
|
|
|
- if (cam->params.pnp_id.device_type == DEVICE_STV_672)
|
|
|
- c->minimum = 1;
|
|
|
- break;
|
|
|
- case V4L2_CID_VFLIP:
|
|
|
- // VP5 Only
|
|
|
- if(cam->params.pnp_id.device_type == DEVICE_STV_672)
|
|
|
- c->flags |= V4L2_CTRL_FLAG_DISABLED;
|
|
|
- break;
|
|
|
- case CPIA2_CID_FRAMERATE:
|
|
|
- if(cam->params.pnp_id.device_type == DEVICE_STV_672 &&
|
|
|
- cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){
|
|
|
- // Maximum 15fps
|
|
|
- for(i=0; i<c->maximum; ++i) {
|
|
|
- if(framerate_controls[i].value ==
|
|
|
- CPIA2_VP_FRAMERATE_15) {
|
|
|
- c->maximum = i;
|
|
|
- c->default_value = i;
|
|
|
- }
|
|
|
- }
|
|
|
+ cap->capability = V4L2_CAP_TIMEPERFRAME;
|
|
|
+ cap->readbuffers = cam->num_frames;
|
|
|
+ for (i = 0; i < ARRAY_SIZE(framerate_controls); i++)
|
|
|
+ if (cam->params.vp_params.frame_rate == framerate_controls[i].value) {
|
|
|
+ cap->timeperframe = framerate_controls[i].period;
|
|
|
+ break;
|
|
|
}
|
|
|
- break;
|
|
|
- case CPIA2_CID_FLICKER_MODE:
|
|
|
- // Flicker control only valid for 672.
|
|
|
- if(cam->params.pnp_id.device_type != DEVICE_STV_672)
|
|
|
- c->flags |= V4L2_CTRL_FLAG_DISABLED;
|
|
|
- break;
|
|
|
- case CPIA2_CID_LIGHTS:
|
|
|
- // Light control only valid for the QX5 Microscope.
|
|
|
- if(cam->params.pnp_id.product != 0x151)
|
|
|
- c->flags |= V4L2_CTRL_FLAG_DISABLED;
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/******************************************************************************
|
|
|
- *
|
|
|
- * ioctl_querymenu
|
|
|
- *
|
|
|
- * V4L2 query possible control variables
|
|
|
- *
|
|
|
- *****************************************************************************/
|
|
|
-
|
|
|
-static int cpia2_querymenu(struct file *file, void *fh, struct v4l2_querymenu *m)
|
|
|
+static int cpia2_s_parm(struct file *file, void *fh, struct v4l2_streamparm *p)
|
|
|
{
|
|
|
struct camera_data *cam = video_drvdata(file);
|
|
|
+ struct v4l2_captureparm *cap = &p->parm.capture;
|
|
|
+ struct v4l2_fract tpf = cap->timeperframe;
|
|
|
+ int max = ARRAY_SIZE(framerate_controls) - 1;
|
|
|
+ int ret;
|
|
|
+ int i;
|
|
|
|
|
|
- switch(m->id) {
|
|
|
- case CPIA2_CID_FLICKER_MODE:
|
|
|
- if (m->index >= NUM_FLICKER_CONTROLS)
|
|
|
- return -EINVAL;
|
|
|
+ ret = cpia2_g_parm(file, fh, p);
|
|
|
+ if (ret || !tpf.denominator || !tpf.numerator)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ /* Maximum 15 fps for this model */
|
|
|
+ if (cam->params.pnp_id.device_type == DEVICE_STV_672 &&
|
|
|
+ cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500)
|
|
|
+ max -= 2;
|
|
|
+ for (i = 0; i <= max; i++) {
|
|
|
+ struct v4l2_fract f1 = tpf;
|
|
|
+ struct v4l2_fract f2 = framerate_controls[i].period;
|
|
|
+
|
|
|
+ f1.numerator *= f2.denominator;
|
|
|
+ f2.numerator *= f1.denominator;
|
|
|
+ if (f1.numerator >= f2.numerator)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (i > max)
|
|
|
+ i = max;
|
|
|
+ cap->timeperframe = framerate_controls[i].period;
|
|
|
+ return cpia2_set_fps(cam, framerate_controls[i].value);
|
|
|
+}
|
|
|
|
|
|
- strcpy(m->name, flicker_controls[m->index].name);
|
|
|
- break;
|
|
|
- case CPIA2_CID_FRAMERATE:
|
|
|
- {
|
|
|
- int maximum = NUM_FRAMERATE_CONTROLS - 1;
|
|
|
- if(cam->params.pnp_id.device_type == DEVICE_STV_672 &&
|
|
|
- cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){
|
|
|
- // Maximum 15fps
|
|
|
- int i;
|
|
|
- for(i=0; i<maximum; ++i) {
|
|
|
- if(framerate_controls[i].value ==
|
|
|
- CPIA2_VP_FRAMERATE_15)
|
|
|
- maximum = i;
|
|
|
- }
|
|
|
- }
|
|
|
- if (m->index > maximum)
|
|
|
- return -EINVAL;
|
|
|
+static const struct {
|
|
|
+ u32 width;
|
|
|
+ u32 height;
|
|
|
+} cpia2_framesizes[] = {
|
|
|
+ { 640, 480 },
|
|
|
+ { 352, 288 },
|
|
|
+ { 320, 240 },
|
|
|
+ { 288, 216 },
|
|
|
+ { 256, 192 },
|
|
|
+ { 224, 168 },
|
|
|
+ { 192, 144 },
|
|
|
+ { 176, 144 },
|
|
|
+};
|
|
|
|
|
|
- strcpy(m->name, framerate_controls[m->index].name);
|
|
|
- break;
|
|
|
- }
|
|
|
- case CPIA2_CID_LIGHTS:
|
|
|
- if (m->index >= NUM_LIGHTS_CONTROLS)
|
|
|
- return -EINVAL;
|
|
|
+static int cpia2_enum_framesizes(struct file *file, void *fh,
|
|
|
+ struct v4l2_frmsizeenum *fsize)
|
|
|
+{
|
|
|
|
|
|
- strcpy(m->name, lights_controls[m->index].name);
|
|
|
- break;
|
|
|
- default:
|
|
|
+ if (fsize->pixel_format != V4L2_PIX_FMT_MJPEG &&
|
|
|
+ fsize->pixel_format != V4L2_PIX_FMT_JPEG)
|
|
|
return -EINVAL;
|
|
|
- }
|
|
|
+ if (fsize->index >= ARRAY_SIZE(cpia2_framesizes))
|
|
|
+ return -EINVAL;
|
|
|
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
|
|
+ fsize->discrete.width = cpia2_framesizes[fsize->index].width;
|
|
|
+ fsize->discrete.height = cpia2_framesizes[fsize->index].height;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/******************************************************************************
|
|
|
- *
|
|
|
- * ioctl_g_ctrl
|
|
|
- *
|
|
|
- * V4L2 get the value of a control variable
|
|
|
- *
|
|
|
- *****************************************************************************/
|
|
|
-
|
|
|
-static int cpia2_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
|
|
|
+static int cpia2_enum_frameintervals(struct file *file, void *fh,
|
|
|
+ struct v4l2_frmivalenum *fival)
|
|
|
{
|
|
|
struct camera_data *cam = video_drvdata(file);
|
|
|
+ int max = ARRAY_SIZE(framerate_controls) - 1;
|
|
|
+ int i;
|
|
|
|
|
|
- switch(c->id) {
|
|
|
- case V4L2_CID_BRIGHTNESS:
|
|
|
- cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS,
|
|
|
- TRANSFER_READ, 0);
|
|
|
- c->value = cam->params.color_params.brightness;
|
|
|
- break;
|
|
|
- case V4L2_CID_CONTRAST:
|
|
|
- cpia2_do_command(cam, CPIA2_CMD_GET_CONTRAST,
|
|
|
- TRANSFER_READ, 0);
|
|
|
- c->value = cam->params.color_params.contrast;
|
|
|
- break;
|
|
|
- case V4L2_CID_SATURATION:
|
|
|
- cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION,
|
|
|
- TRANSFER_READ, 0);
|
|
|
- c->value = cam->params.color_params.saturation;
|
|
|
- break;
|
|
|
- case V4L2_CID_HFLIP:
|
|
|
- cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS,
|
|
|
- TRANSFER_READ, 0);
|
|
|
- c->value = (cam->params.vp_params.user_effects &
|
|
|
- CPIA2_VP_USER_EFFECTS_MIRROR) != 0;
|
|
|
- break;
|
|
|
- case V4L2_CID_VFLIP:
|
|
|
- cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS,
|
|
|
- TRANSFER_READ, 0);
|
|
|
- c->value = (cam->params.vp_params.user_effects &
|
|
|
- CPIA2_VP_USER_EFFECTS_FLIP) != 0;
|
|
|
- break;
|
|
|
- case CPIA2_CID_TARGET_KB:
|
|
|
- c->value = cam->params.vc_params.target_kb;
|
|
|
- break;
|
|
|
- case CPIA2_CID_GPIO:
|
|
|
- cpia2_do_command(cam, CPIA2_CMD_GET_VP_GPIO_DATA,
|
|
|
- TRANSFER_READ, 0);
|
|
|
- c->value = cam->params.vp_params.gpio_data;
|
|
|
- break;
|
|
|
- case CPIA2_CID_FLICKER_MODE:
|
|
|
- {
|
|
|
- int i, mode;
|
|
|
- cpia2_do_command(cam, CPIA2_CMD_GET_FLICKER_MODES,
|
|
|
- TRANSFER_READ, 0);
|
|
|
- if(cam->params.flicker_control.cam_register &
|
|
|
- CPIA2_VP_FLICKER_MODES_NEVER_FLICKER) {
|
|
|
- mode = NEVER_FLICKER;
|
|
|
- } else {
|
|
|
- if(cam->params.flicker_control.cam_register &
|
|
|
- CPIA2_VP_FLICKER_MODES_50HZ) {
|
|
|
- mode = FLICKER_50;
|
|
|
- } else {
|
|
|
- mode = FLICKER_60;
|
|
|
- }
|
|
|
- }
|
|
|
- for(i=0; i<NUM_FLICKER_CONTROLS; i++) {
|
|
|
- if(flicker_controls[i].value == mode) {
|
|
|
- c->value = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if(i == NUM_FLICKER_CONTROLS)
|
|
|
- return -EINVAL;
|
|
|
- break;
|
|
|
- }
|
|
|
- case CPIA2_CID_FRAMERATE:
|
|
|
- {
|
|
|
- int maximum = NUM_FRAMERATE_CONTROLS - 1;
|
|
|
- int i;
|
|
|
- for(i=0; i<= maximum; i++) {
|
|
|
- if(cam->params.vp_params.frame_rate ==
|
|
|
- framerate_controls[i].value)
|
|
|
- break;
|
|
|
- }
|
|
|
- if(i > maximum)
|
|
|
- return -EINVAL;
|
|
|
- c->value = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- case CPIA2_CID_USB_ALT:
|
|
|
- c->value = cam->params.camera_state.stream_mode;
|
|
|
- break;
|
|
|
- case CPIA2_CID_LIGHTS:
|
|
|
- {
|
|
|
- int i;
|
|
|
- cpia2_do_command(cam, CPIA2_CMD_GET_VP_GPIO_DATA,
|
|
|
- TRANSFER_READ, 0);
|
|
|
- for(i=0; i<NUM_LIGHTS_CONTROLS; i++) {
|
|
|
- if((cam->params.vp_params.gpio_data&GPIO_LIGHTS_MASK) ==
|
|
|
- lights_controls[i].value) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if(i == NUM_LIGHTS_CONTROLS)
|
|
|
- return -EINVAL;
|
|
|
- c->value = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- case CPIA2_CID_RESET_CAMERA:
|
|
|
+ if (fival->pixel_format != V4L2_PIX_FMT_MJPEG &&
|
|
|
+ fival->pixel_format != V4L2_PIX_FMT_JPEG)
|
|
|
return -EINVAL;
|
|
|
- default:
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- DBG("Get control id:%d, value:%d\n", c->id, c->value);
|
|
|
|
|
|
+ /* Maximum 15 fps for this model */
|
|
|
+ if (cam->params.pnp_id.device_type == DEVICE_STV_672 &&
|
|
|
+ cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500)
|
|
|
+ max -= 2;
|
|
|
+ if (fival->index > max)
|
|
|
+ return -EINVAL;
|
|
|
+ for (i = 0; i < ARRAY_SIZE(cpia2_framesizes); i++)
|
|
|
+ if (fival->width == cpia2_framesizes[i].width &&
|
|
|
+ fival->height == cpia2_framesizes[i].height)
|
|
|
+ break;
|
|
|
+ if (i == ARRAY_SIZE(cpia2_framesizes))
|
|
|
+ return -EINVAL;
|
|
|
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
|
|
|
+ fival->discrete = framerate_controls[fival->index].period;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -958,72 +617,54 @@ static int cpia2_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
|
|
|
*
|
|
|
*****************************************************************************/
|
|
|
|
|
|
-static int cpia2_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
|
|
|
+static int cpia2_s_ctrl(struct v4l2_ctrl *ctrl)
|
|
|
{
|
|
|
- struct camera_data *cam = video_drvdata(file);
|
|
|
- int i;
|
|
|
- int retval = 0;
|
|
|
+ struct camera_data *cam =
|
|
|
+ container_of(ctrl->handler, struct camera_data, hdl);
|
|
|
+ static const int flicker_table[] = {
|
|
|
+ NEVER_FLICKER,
|
|
|
+ FLICKER_50,
|
|
|
+ FLICKER_60,
|
|
|
+ };
|
|
|
|
|
|
- DBG("Set control id:%d, value:%d\n", c->id, c->value);
|
|
|
-
|
|
|
- /* Check that the value is in range */
|
|
|
- for(i=0; i<NUM_CONTROLS; i++) {
|
|
|
- if(c->id == controls[i].id) {
|
|
|
- if(c->value < controls[i].minimum ||
|
|
|
- c->value > controls[i].maximum) {
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if(i == NUM_CONTROLS)
|
|
|
- return -EINVAL;
|
|
|
+ DBG("Set control id:%d, value:%d\n", ctrl->id, ctrl->val);
|
|
|
|
|
|
- switch(c->id) {
|
|
|
+ switch (ctrl->id) {
|
|
|
case V4L2_CID_BRIGHTNESS:
|
|
|
- cpia2_set_brightness(cam, c->value);
|
|
|
+ cpia2_set_brightness(cam, ctrl->val);
|
|
|
break;
|
|
|
case V4L2_CID_CONTRAST:
|
|
|
- cpia2_set_contrast(cam, c->value);
|
|
|
+ cpia2_set_contrast(cam, ctrl->val);
|
|
|
break;
|
|
|
case V4L2_CID_SATURATION:
|
|
|
- cpia2_set_saturation(cam, c->value);
|
|
|
+ cpia2_set_saturation(cam, ctrl->val);
|
|
|
break;
|
|
|
case V4L2_CID_HFLIP:
|
|
|
- cpia2_set_property_mirror(cam, c->value);
|
|
|
+ cpia2_set_property_mirror(cam, ctrl->val);
|
|
|
break;
|
|
|
case V4L2_CID_VFLIP:
|
|
|
- cpia2_set_property_flip(cam, c->value);
|
|
|
+ cpia2_set_property_flip(cam, ctrl->val);
|
|
|
break;
|
|
|
- case CPIA2_CID_TARGET_KB:
|
|
|
- retval = cpia2_set_target_kb(cam, c->value);
|
|
|
+ case V4L2_CID_POWER_LINE_FREQUENCY:
|
|
|
+ return cpia2_set_flicker_mode(cam, flicker_table[ctrl->val]);
|
|
|
+ case V4L2_CID_ILLUMINATORS_1:
|
|
|
+ return cpia2_set_gpio(cam, (cam->top_light->val << 6) |
|
|
|
+ (cam->bottom_light->val << 7));
|
|
|
+ case V4L2_CID_JPEG_ACTIVE_MARKER:
|
|
|
+ cam->params.compression.inhibit_htables =
|
|
|
+ !(ctrl->val & V4L2_JPEG_ACTIVE_MARKER_DHT);
|
|
|
break;
|
|
|
- case CPIA2_CID_GPIO:
|
|
|
- retval = cpia2_set_gpio(cam, c->value);
|
|
|
- break;
|
|
|
- case CPIA2_CID_FLICKER_MODE:
|
|
|
- retval = cpia2_set_flicker_mode(cam,
|
|
|
- flicker_controls[c->value].value);
|
|
|
- break;
|
|
|
- case CPIA2_CID_FRAMERATE:
|
|
|
- retval = cpia2_set_fps(cam, framerate_controls[c->value].value);
|
|
|
+ case V4L2_CID_JPEG_COMPRESSION_QUALITY:
|
|
|
+ cam->params.vc_params.quality = ctrl->val;
|
|
|
break;
|
|
|
case CPIA2_CID_USB_ALT:
|
|
|
- retval = cpia2_usb_change_streaming_alternate(cam, c->value);
|
|
|
- break;
|
|
|
- case CPIA2_CID_LIGHTS:
|
|
|
- retval = cpia2_set_gpio(cam, lights_controls[c->value].value);
|
|
|
- break;
|
|
|
- case CPIA2_CID_RESET_CAMERA:
|
|
|
- cpia2_usb_stream_pause(cam);
|
|
|
- cpia2_reset_camera(cam);
|
|
|
- cpia2_usb_stream_resume(cam);
|
|
|
+ cam->params.camera_state.stream_mode = ctrl->val;
|
|
|
break;
|
|
|
default:
|
|
|
- retval = -EINVAL;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- return retval;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
@@ -1084,6 +725,8 @@ static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompres
|
|
|
|
|
|
cam->params.compression.inhibit_htables =
|
|
|
!(parms->jpeg_markers & V4L2_JPEG_MARKER_DHT);
|
|
|
+ parms->jpeg_markers &= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI |
|
|
|
+ V4L2_JPEG_MARKER_DHT;
|
|
|
|
|
|
if(parms->APP_len != 0) {
|
|
|
if(parms->APP_len > 0 &&
|
|
@@ -1270,12 +913,12 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
|
|
|
struct framebuf *cb=cam->curbuff;
|
|
|
mutex_unlock(&cam->v4l2_lock);
|
|
|
wait_event_interruptible(cam->wq_stream,
|
|
|
- !cam->present ||
|
|
|
+ !video_is_registered(&cam->vdev) ||
|
|
|
(cb=cam->curbuff)->status == FRAME_READY);
|
|
|
mutex_lock(&cam->v4l2_lock);
|
|
|
if (signal_pending(current))
|
|
|
return -ERESTARTSYS;
|
|
|
- if(!cam->present)
|
|
|
+ if (!video_is_registered(&cam->vdev))
|
|
|
return -ENOTTY;
|
|
|
frame = cb->num;
|
|
|
}
|
|
@@ -1299,56 +942,39 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int cpia2_g_priority(struct file *file, void *_fh, enum v4l2_priority *p)
|
|
|
-{
|
|
|
- struct cpia2_fh *fh = _fh;
|
|
|
-
|
|
|
- *p = fh->prio;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int cpia2_s_priority(struct file *file, void *_fh, enum v4l2_priority prio)
|
|
|
-{
|
|
|
- struct camera_data *cam = video_drvdata(file);
|
|
|
- struct cpia2_fh *fh = _fh;
|
|
|
-
|
|
|
- if (cam->streaming && prio != fh->prio &&
|
|
|
- fh->prio == V4L2_PRIORITY_RECORD)
|
|
|
- /* Can't drop record priority while streaming */
|
|
|
- return -EBUSY;
|
|
|
-
|
|
|
- if (prio == V4L2_PRIORITY_RECORD && prio != fh->prio &&
|
|
|
- v4l2_prio_max(&cam->prio) == V4L2_PRIORITY_RECORD)
|
|
|
- /* Only one program can record at a time */
|
|
|
- return -EBUSY;
|
|
|
- return v4l2_prio_change(&cam->prio, &fh->prio, prio);
|
|
|
-}
|
|
|
-
|
|
|
static int cpia2_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
|
|
|
{
|
|
|
struct camera_data *cam = video_drvdata(file);
|
|
|
+ int ret = -EINVAL;
|
|
|
|
|
|
DBG("VIDIOC_STREAMON, streaming=%d\n", cam->streaming);
|
|
|
if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- if (!cam->streaming)
|
|
|
- return cpia2_usb_stream_start(cam,
|
|
|
+ if (!cam->streaming) {
|
|
|
+ ret = cpia2_usb_stream_start(cam,
|
|
|
cam->params.camera_state.stream_mode);
|
|
|
- return -EINVAL;
|
|
|
+ if (!ret)
|
|
|
+ v4l2_ctrl_grab(cam->usb_alt, true);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int cpia2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
|
|
|
{
|
|
|
struct camera_data *cam = video_drvdata(file);
|
|
|
+ int ret = -EINVAL;
|
|
|
|
|
|
DBG("VIDIOC_STREAMOFF, streaming=%d\n", cam->streaming);
|
|
|
if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- if (cam->streaming)
|
|
|
- return cpia2_usb_stream_stop(cam);
|
|
|
- return -EINVAL;
|
|
|
+ if (cam->streaming) {
|
|
|
+ ret = cpia2_usb_stream_stop(cam);
|
|
|
+ if (!ret)
|
|
|
+ v4l2_ctrl_grab(cam->usb_alt, false);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
@@ -1361,16 +987,10 @@ static int cpia2_mmap(struct file *file, struct vm_area_struct *area)
|
|
|
struct camera_data *cam = video_drvdata(file);
|
|
|
int retval;
|
|
|
|
|
|
- /* Priority check */
|
|
|
- struct cpia2_fh *fh = file->private_data;
|
|
|
- if(fh->prio != V4L2_PRIORITY_RECORD) {
|
|
|
- return -EBUSY;
|
|
|
- }
|
|
|
-
|
|
|
retval = cpia2_remap_buffer(cam, area);
|
|
|
|
|
|
if(!retval)
|
|
|
- fh->mmapped = 1;
|
|
|
+ cam->stream_fh = file->private_data;
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
@@ -1388,15 +1008,13 @@ static void reset_camera_struct_v4l(struct camera_data *cam)
|
|
|
cam->frame_size = buffer_size;
|
|
|
cam->num_frames = num_buffers;
|
|
|
|
|
|
- /* FlickerModes */
|
|
|
+ /* Flicker modes */
|
|
|
cam->params.flicker_control.flicker_mode_req = flicker_mode;
|
|
|
- cam->params.flicker_control.mains_frequency = flicker_freq;
|
|
|
|
|
|
- /* streamMode */
|
|
|
+ /* stream modes */
|
|
|
cam->params.camera_state.stream_mode = alternate;
|
|
|
|
|
|
cam->pixelformat = V4L2_PIX_FMT_JPEG;
|
|
|
- v4l2_prio_init(&cam->prio);
|
|
|
}
|
|
|
|
|
|
static const struct v4l2_ioctl_ops cpia2_ioctl_ops = {
|
|
@@ -1408,10 +1026,6 @@ static const struct v4l2_ioctl_ops cpia2_ioctl_ops = {
|
|
|
.vidioc_g_fmt_vid_cap = cpia2_g_fmt_vid_cap,
|
|
|
.vidioc_s_fmt_vid_cap = cpia2_s_fmt_vid_cap,
|
|
|
.vidioc_try_fmt_vid_cap = cpia2_try_fmt_vid_cap,
|
|
|
- .vidioc_queryctrl = cpia2_queryctrl,
|
|
|
- .vidioc_querymenu = cpia2_querymenu,
|
|
|
- .vidioc_g_ctrl = cpia2_g_ctrl,
|
|
|
- .vidioc_s_ctrl = cpia2_s_ctrl,
|
|
|
.vidioc_g_jpegcomp = cpia2_g_jpegcomp,
|
|
|
.vidioc_s_jpegcomp = cpia2_s_jpegcomp,
|
|
|
.vidioc_cropcap = cpia2_cropcap,
|
|
@@ -1421,9 +1035,12 @@ static const struct v4l2_ioctl_ops cpia2_ioctl_ops = {
|
|
|
.vidioc_dqbuf = cpia2_dqbuf,
|
|
|
.vidioc_streamon = cpia2_streamon,
|
|
|
.vidioc_streamoff = cpia2_streamoff,
|
|
|
- .vidioc_g_priority = cpia2_g_priority,
|
|
|
- .vidioc_s_priority = cpia2_s_priority,
|
|
|
- .vidioc_default = cpia2_default,
|
|
|
+ .vidioc_s_parm = cpia2_s_parm,
|
|
|
+ .vidioc_g_parm = cpia2_g_parm,
|
|
|
+ .vidioc_enum_framesizes = cpia2_enum_framesizes,
|
|
|
+ .vidioc_enum_frameintervals = cpia2_enum_frameintervals,
|
|
|
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
|
|
|
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
|
|
};
|
|
|
|
|
|
/***
|
|
@@ -1444,7 +1061,21 @@ static struct video_device cpia2_template = {
|
|
|
.name = "CPiA2 Camera",
|
|
|
.fops = &cpia2_fops,
|
|
|
.ioctl_ops = &cpia2_ioctl_ops,
|
|
|
- .release = video_device_release,
|
|
|
+ .release = video_device_release_empty,
|
|
|
+};
|
|
|
+
|
|
|
+void cpia2_camera_release(struct v4l2_device *v4l2_dev)
|
|
|
+{
|
|
|
+ struct camera_data *cam =
|
|
|
+ container_of(v4l2_dev, struct camera_data, v4l2_dev);
|
|
|
+
|
|
|
+ v4l2_ctrl_handler_free(&cam->hdl);
|
|
|
+ v4l2_device_unregister(&cam->v4l2_dev);
|
|
|
+ kfree(cam);
|
|
|
+}
|
|
|
+
|
|
|
+static const struct v4l2_ctrl_ops cpia2_ctrl_ops = {
|
|
|
+ .s_ctrl = cpia2_s_ctrl,
|
|
|
};
|
|
|
|
|
|
/******************************************************************************
|
|
@@ -1454,20 +1085,74 @@ static struct video_device cpia2_template = {
|
|
|
*****************************************************************************/
|
|
|
int cpia2_register_camera(struct camera_data *cam)
|
|
|
{
|
|
|
- cam->vdev = video_device_alloc();
|
|
|
- if(!cam->vdev)
|
|
|
- return -ENOMEM;
|
|
|
+ struct v4l2_ctrl_handler *hdl = &cam->hdl;
|
|
|
+ struct v4l2_ctrl_config cpia2_usb_alt = {
|
|
|
+ .ops = &cpia2_ctrl_ops,
|
|
|
+ .id = CPIA2_CID_USB_ALT,
|
|
|
+ .name = "USB Alternate",
|
|
|
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
|
|
+ .min = USBIF_ISO_1,
|
|
|
+ .max = USBIF_ISO_6,
|
|
|
+ .step = 1,
|
|
|
+ };
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ v4l2_ctrl_handler_init(hdl, 12);
|
|
|
+ v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_BRIGHTNESS,
|
|
|
+ cam->params.pnp_id.device_type == DEVICE_STV_672 ? 1 : 0,
|
|
|
+ 255, 1, DEFAULT_BRIGHTNESS);
|
|
|
+ v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_CONTRAST, 0, 255, 1, DEFAULT_CONTRAST);
|
|
|
+ v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_SATURATION, 0, 255, 1, DEFAULT_SATURATION);
|
|
|
+ v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
|
|
|
+ v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_JPEG_ACTIVE_MARKER, 0,
|
|
|
+ V4L2_JPEG_ACTIVE_MARKER_DHT, 0,
|
|
|
+ V4L2_JPEG_ACTIVE_MARKER_DHT);
|
|
|
+ v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_JPEG_COMPRESSION_QUALITY, 1,
|
|
|
+ 100, 1, 100);
|
|
|
+ cpia2_usb_alt.def = alternate;
|
|
|
+ cam->usb_alt = v4l2_ctrl_new_custom(hdl, &cpia2_usb_alt, NULL);
|
|
|
+ /* VP5 Only */
|
|
|
+ if (cam->params.pnp_id.device_type != DEVICE_STV_672)
|
|
|
+ v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
|
|
|
+ /* Flicker control only valid for 672 */
|
|
|
+ if (cam->params.pnp_id.device_type == DEVICE_STV_672)
|
|
|
+ v4l2_ctrl_new_std_menu(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_POWER_LINE_FREQUENCY,
|
|
|
+ V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
|
|
|
+ /* Light control only valid for the QX5 Microscope */
|
|
|
+ if (cam->params.pnp_id.product == 0x151) {
|
|
|
+ cam->top_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
|
|
|
+ cam->bottom_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
|
|
|
+ V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
|
|
|
+ v4l2_ctrl_cluster(2, &cam->top_light);
|
|
|
+ }
|
|
|
|
|
|
- memcpy(cam->vdev, &cpia2_template, sizeof(cpia2_template));
|
|
|
- video_set_drvdata(cam->vdev, cam);
|
|
|
- cam->vdev->lock = &cam->v4l2_lock;
|
|
|
+ if (hdl->error) {
|
|
|
+ ret = hdl->error;
|
|
|
+ v4l2_ctrl_handler_free(hdl);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ cam->vdev = cpia2_template;
|
|
|
+ video_set_drvdata(&cam->vdev, cam);
|
|
|
+ cam->vdev.lock = &cam->v4l2_lock;
|
|
|
+ cam->vdev.ctrl_handler = hdl;
|
|
|
+ cam->vdev.v4l2_dev = &cam->v4l2_dev;
|
|
|
+ set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
|
|
|
|
|
|
reset_camera_struct_v4l(cam);
|
|
|
|
|
|
/* register v4l device */
|
|
|
- if (video_register_device(cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
|
|
|
+ if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
|
|
|
ERR("video_register_device failed\n");
|
|
|
- video_device_release(cam->vdev);
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
|
|
@@ -1481,13 +1166,7 @@ int cpia2_register_camera(struct camera_data *cam)
|
|
|
*****************************************************************************/
|
|
|
void cpia2_unregister_camera(struct camera_data *cam)
|
|
|
{
|
|
|
- if (!cam->open_count) {
|
|
|
- video_unregister_device(cam->vdev);
|
|
|
- } else {
|
|
|
- LOG("%s removed while open, deferring "
|
|
|
- "video_unregister_device\n",
|
|
|
- video_device_node_name(cam->vdev));
|
|
|
- }
|
|
|
+ video_unregister_device(&cam->vdev);
|
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
@@ -1524,23 +1203,12 @@ static void __init check_parameters(void)
|
|
|
LOG("alternate specified is invalid, using %d\n", alternate);
|
|
|
}
|
|
|
|
|
|
- if (flicker_mode != NEVER_FLICKER && flicker_mode != ANTI_FLICKER_ON) {
|
|
|
- flicker_mode = NEVER_FLICKER;
|
|
|
+ if (flicker_mode != 0 && flicker_mode != FLICKER_50 && flicker_mode != FLICKER_60) {
|
|
|
+ flicker_mode = 0;
|
|
|
LOG("Flicker mode specified is invalid, using %d\n",
|
|
|
flicker_mode);
|
|
|
}
|
|
|
|
|
|
- if (flicker_freq != FLICKER_50 && flicker_freq != FLICKER_60) {
|
|
|
- flicker_freq = FLICKER_60;
|
|
|
- LOG("Flicker mode specified is invalid, using %d\n",
|
|
|
- flicker_freq);
|
|
|
- }
|
|
|
-
|
|
|
- if(video_nr < -1 || video_nr > 64) {
|
|
|
- video_nr = -1;
|
|
|
- LOG("invalid video_nr specified, must be -1 to 64\n");
|
|
|
- }
|
|
|
-
|
|
|
DBG("Using %d buffers, each %d bytes, alternate=%d\n",
|
|
|
num_buffers, buffer_size, alternate);
|
|
|
}
|