Commit 26563127 authored by Luca Risolia's avatar Luca Risolia Committed by Mauro Carvalho Chehab

V4L/DVB (5064): ET61X251 driver updates.

- Implement audio ioctl's and VIDIOC_ENUM_FRAMESIZES
- Documentation updates
- Generic improvements
Signed-off-by: default avatarLuca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 7e3a0660
...@@ -23,7 +23,7 @@ Index ...@@ -23,7 +23,7 @@ Index
1. Copyright 1. Copyright
============ ============
Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
2. Disclaimer 2. Disclaimer
...@@ -135,8 +135,9 @@ And finally: ...@@ -135,8 +135,9 @@ And finally:
6. Module loading 6. Module loading
================= =================
To use the driver, it is necessary to load the "et61x251" module into memory To use the driver, it is necessary to load the "et61x251" module into memory
after every other module required: "videodev", "usbcore" and, depending on after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd". "usbcore" and, depending on the USB host controller you have, "ehci-hcd",
"uhci-hcd" or "ohci-hcd".
Loading can be done as shown below: Loading can be done as shown below:
......
...@@ -171,10 +171,7 @@ struct et61x251_device { ...@@ -171,10 +171,7 @@ struct et61x251_device {
struct et61x251_device* struct et61x251_device*
et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id)
{ {
if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
return cam;
return NULL;
} }
......
/*************************************************************************** /***************************************************************************
* V4L2 driver for ET61X[12]51 PC Camera Controllers * * V4L2 driver for ET61X[12]51 PC Camera Controllers *
* * * *
* Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
* * * *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
...@@ -48,8 +48,8 @@ ...@@ -48,8 +48,8 @@
#define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia"
#define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define ET61X251_MODULE_LICENSE "GPL" #define ET61X251_MODULE_LICENSE "GPL"
#define ET61X251_MODULE_VERSION "1:1.02" #define ET61X251_MODULE_VERSION "1:1.04"
#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) #define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 4)
/*****************************************************************************/ /*****************************************************************************/
...@@ -85,7 +85,7 @@ MODULE_PARM_DESC(force_munmap, ...@@ -85,7 +85,7 @@ MODULE_PARM_DESC(force_munmap,
"\ndetected camera." "\ndetected camera."
"\n 0 = do not force memory unmapping" "\n 0 = do not force memory unmapping"
"\n 1 = force memory unmapping (save memory)" "\n 1 = force memory unmapping (save memory)"
"\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." "\nDefault value is "__MODULE_STRING(ET61X251_FORCE_MUNMAP)"."
"\n"); "\n");
static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] =
...@@ -133,7 +133,8 @@ et61x251_request_buffers(struct et61x251_device* cam, u32 count, ...@@ -133,7 +133,8 @@ et61x251_request_buffers(struct et61x251_device* cam, u32 count,
cam->nbuffers = count; cam->nbuffers = count;
while (cam->nbuffers > 0) { while (cam->nbuffers > 0) {
if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) if ((buff = vmalloc_32_user(cam->nbuffers *
PAGE_ALIGN(imagesize))))
break; break;
cam->nbuffers--; cam->nbuffers--;
} }
...@@ -543,10 +544,11 @@ static int et61x251_start_transfer(struct et61x251_device* cam) ...@@ -543,10 +544,11 @@ static int et61x251_start_transfer(struct et61x251_device* cam)
{ {
struct usb_device *udev = cam->usbdev; struct usb_device *udev = cam->usbdev;
struct urb* urb; struct urb* urb;
const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832, struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
864, 896, 920, 956, 980, 1000, usb_ifnum_to_if(udev, 0),
1022}; ET61X251_ALTERNATE_SETTING);
const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING]; const unsigned int psz = le16_to_cpu(altsetting->
endpoint[0].desc.wMaxPacketSize);
s8 i, j; s8 i, j;
int err = 0; int err = 0;
...@@ -976,29 +978,31 @@ static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, ...@@ -976,29 +978,31 @@ static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
static int et61x251_create_sysfs(struct et61x251_device* cam) static int et61x251_create_sysfs(struct et61x251_device* cam)
{ {
struct video_device *v4ldev = cam->v4ldev; struct video_device *v4ldev = cam->v4ldev;
int rc; int err = 0;
if ((err = video_device_create_file(v4ldev, &class_device_attr_reg)))
goto err_out;
if ((err = video_device_create_file(v4ldev, &class_device_attr_val)))
goto err_reg;
rc = video_device_create_file(v4ldev, &class_device_attr_reg);
if (rc) goto err;
rc = video_device_create_file(v4ldev, &class_device_attr_val);
if (rc) goto err_reg;
if (cam->sensor.sysfs_ops) { if (cam->sensor.sysfs_ops) {
rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg); if ((err = video_device_create_file(v4ldev,
if (rc) goto err_val; &class_device_attr_i2c_reg)))
rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val); goto err_val;
if (rc) goto err_i2c_reg; if ((err = video_device_create_file(v4ldev,
&class_device_attr_i2c_val)))
goto err_i2c_reg;
} }
return 0;
err_i2c_reg: err_i2c_reg:
if (cam->sensor.sysfs_ops)
video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
err_val: err_val:
video_device_remove_file(v4ldev, &class_device_attr_val); video_device_remove_file(v4ldev, &class_device_attr_val);
err_reg: err_reg:
video_device_remove_file(v4ldev, &class_device_attr_reg); video_device_remove_file(v4ldev, &class_device_attr_reg);
err: err_out:
return rc; return err;
} }
#endif /* CONFIG_VIDEO_ADV_DEBUG */ #endif /* CONFIG_VIDEO_ADV_DEBUG */
...@@ -1767,10 +1771,10 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) ...@@ -1767,10 +1771,10 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
if (rect->width < 4) if (rect->width < 16)
rect->width = 4; rect->width = 16;
if (rect->height < 4) if (rect->height < 16)
rect->height = 4; rect->height = 16;
if (rect->width > bounds->width) if (rect->width > bounds->width)
rect->width = bounds->width; rect->width = bounds->width;
if (rect->height > bounds->height) if (rect->height > bounds->height)
...@@ -1784,8 +1788,8 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) ...@@ -1784,8 +1788,8 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
if (rect->top + rect->height > bounds->top + bounds->height) if (rect->top + rect->height > bounds->top + bounds->height)
rect->top = bounds->top+bounds->height - rect->height; rect->top = bounds->top+bounds->height - rect->height;
rect->width &= ~3L; rect->width &= ~15L;
rect->height &= ~3L; rect->height &= ~15L;
if (ET61X251_PRESERVE_IMGSCALE) { if (ET61X251_PRESERVE_IMGSCALE) {
/* Calculate the actual scaling factor */ /* Calculate the actual scaling factor */
...@@ -1845,6 +1849,35 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) ...@@ -1845,6 +1849,35 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg)
} }
static int
et61x251_vidioc_enum_framesizes(struct et61x251_device* cam, void __user * arg)
{
struct v4l2_frmsizeenum frmsize;
if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
return -EFAULT;
if (frmsize.index != 0)
return -EINVAL;
if (frmsize.pixel_format != V4L2_PIX_FMT_ET61X251 &&
frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
return -EINVAL;
frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
return -EFAULT;
return 0;
}
static int static int
et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg)
{ {
...@@ -1853,6 +1886,9 @@ et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) ...@@ -1853,6 +1886,9 @@ et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg)
if (copy_from_user(&fmtd, arg, sizeof(fmtd))) if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
return -EFAULT; return -EFAULT;
if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
if (fmtd.index == 0) { if (fmtd.index == 0) {
strcpy(fmtd.description, "bayer rgb"); strcpy(fmtd.description, "bayer rgb");
fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
...@@ -1934,17 +1970,17 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, ...@@ -1934,17 +1970,17 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd,
rect.width = scale * pix->width; rect.width = scale * pix->width;
rect.height = scale * pix->height; rect.height = scale * pix->height;
if (rect.width < 4) if (rect.width < 16)
rect.width = 4; rect.width = 16;
if (rect.height < 4) if (rect.height < 16)
rect.height = 4; rect.height = 16;
if (rect.width > bounds->left + bounds->width - rect.left) if (rect.width > bounds->left + bounds->width - rect.left)
rect.width = bounds->left + bounds->width - rect.left; rect.width = bounds->left + bounds->width - rect.left;
if (rect.height > bounds->top + bounds->height - rect.top) if (rect.height > bounds->top + bounds->height - rect.top)
rect.height = bounds->top + bounds->height - rect.top; rect.height = bounds->top + bounds->height - rect.top;
rect.width &= ~3L; rect.width &= ~15L;
rect.height &= ~3L; rect.height &= ~15L;
{ /* adjust the scaling factor */ { /* adjust the scaling factor */
u32 a, b; u32 a, b;
...@@ -2378,6 +2414,9 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, ...@@ -2378,6 +2414,9 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
case VIDIOC_S_FMT: case VIDIOC_S_FMT:
return et61x251_vidioc_try_s_fmt(cam, cmd, arg); return et61x251_vidioc_try_s_fmt(cam, cmd, arg);
case VIDIOC_ENUM_FRAMESIZES:
return et61x251_vidioc_enum_framesizes(cam, arg);
case VIDIOC_G_JPEGCOMP: case VIDIOC_G_JPEGCOMP:
return et61x251_vidioc_g_jpegcomp(cam, arg); return et61x251_vidioc_g_jpegcomp(cam, arg);
...@@ -2413,6 +2452,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, ...@@ -2413,6 +2452,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
case VIDIOC_QUERYSTD: case VIDIOC_QUERYSTD:
case VIDIOC_ENUMSTD: case VIDIOC_ENUMSTD:
case VIDIOC_QUERYMENU: case VIDIOC_QUERYMENU:
case VIDIOC_ENUM_FRAMEINTERVALS:
return -EINVAL; return -EINVAL;
default: default:
...@@ -2459,6 +2499,7 @@ static const struct file_operations et61x251_fops = { ...@@ -2459,6 +2499,7 @@ static const struct file_operations et61x251_fops = {
.open = et61x251_open, .open = et61x251_open,
.release = et61x251_release, .release = et61x251_release,
.ioctl = et61x251_ioctl, .ioctl = et61x251_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.read = et61x251_read, .read = et61x251_read,
.poll = et61x251_poll, .poll = et61x251_poll,
.mmap = et61x251_mmap, .mmap = et61x251_mmap,
...@@ -2497,7 +2538,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) ...@@ -2497,7 +2538,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
mutex_init(&cam->dev_mutex); mutex_init(&cam->dev_mutex);
DBG(2, "ET61X[12]51 PC Camera Controller detected " DBG(2, "ET61X[12]51 PC Camera Controller detected "
"(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct);
for (i = 0; et61x251_sensor_table[i]; i++) { for (i = 0; et61x251_sensor_table[i]; i++) {
err = et61x251_sensor_table[i](cam); err = et61x251_sensor_table[i](cam);
...@@ -2550,9 +2591,14 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) ...@@ -2550,9 +2591,14 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
err = et61x251_create_sysfs(cam); err = et61x251_create_sysfs(cam);
if (err) if (!err)
goto fail2; DBG(2, "Optional device control through 'sysfs' "
DBG(2, "Optional device control through 'sysfs' interface ready"); "interface ready");
else
DBG(2, "Failed to create 'sysfs' interface for optional "
"device controlling. Error #%d", err);
#else
DBG(2, "Optional device control through 'sysfs' interface disabled");
#endif #endif
usb_set_intfdata(intf, cam); usb_set_intfdata(intf, cam);
...@@ -2561,13 +2607,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) ...@@ -2561,13 +2607,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
return 0; return 0;
#ifdef CONFIG_VIDEO_ADV_DEBUG
fail2:
video_nr[dev_nr] = -1;
dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0;
mutex_unlock(&cam->dev_mutex);
video_unregister_device(cam->v4ldev);
#endif
fail: fail:
if (cam) { if (cam) {
kfree(cam->control_buffer); kfree(cam->control_buffer);
......
/*************************************************************************** /***************************************************************************
* API for image sensors connected to ET61X[12]51 PC Camera Controllers * * API for image sensors connected to ET61X[12]51 PC Camera Controllers *
* * * *
* Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
* * * *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
...@@ -82,7 +82,7 @@ enum et61x251_i2c_rsta { ...@@ -82,7 +82,7 @@ enum et61x251_i2c_rsta {
ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */ ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */
}; };
#define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 #define ET61X251_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
struct et61x251_sensor { struct et61x251_sensor {
char name[32]; char name[32];
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 * * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 *
* PC Camera Controllers * * PC Camera Controllers *
* * * *
* Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
* * * *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment