Changes: - Delete the correct entry in the outgoing queue during DQBUF - Implement correct image downscaling selection through VIDIOC_S_[CROP|FTM] - Replace darkness controls with brightness (simple swapping) for PAS106B and PAS202BCB - Implement gain control for TAS5110C1B and TAS5130D1B - Add a note to the documentation about correct image downscaling selection
Signed-off-by: Luca Risolia <[EMAIL PROTECTED]>
Greg, please apply.
Thanks,
Luca
diff -uprN -X dontdiff linux-2.6.7/Documentation/usb/sn9c102.txt
devel-2.6.7/Documentation/usb/sn9c102.txt
--- linux-2.6.7/Documentation/usb/sn9c102.txt 2004-08-12 04:03:13.000000000 +0200
+++ devel-2.6.7/Documentation/usb/sn9c102.txt 2004-08-12 04:25:22.000000000 +0200
@@ -14,10 +14,10 @@ Index
4. Module dependencies
5. Module loading
6. Module parameters
-7. Device control through "sysfs"
+7. Optional device control through "sysfs"
8. Supported devices
9. How to add support for new image sensors
-10. Note for V4L2 developers
+10. Notes for V4L2 application developers
11. Contact information
12. Credits
@@ -148,8 +148,8 @@ Default: 2
-------------------------------------------------------------------------------
-7. Device control through "sysfs"
-=================================
+7. Optional device control through "sysfs"
+==========================================
It is possible to read and write both the SN9C10[12] and the image sensor
registers by using the "sysfs" filesystem interface.
@@ -206,7 +206,7 @@ Vendor ID Product ID
0xc45 0x6029
0xc45 0x602a
0xc45 0x602c
-0xc45 0x8001
+0xc45 0x6030
The list above does NOT imply that all those devices work with this driver: up
until now only the ones that mount the following image sensors are supported.
@@ -242,19 +242,27 @@ At the moment, not yet supported image s
MI03 (VGA), OV7620 (VGA).
-10. Note for V4L2 developers
-============================
+10. Notes for V4L2 application developers
+=========================================
This driver follows the V4L2 API specifications. In particular, it enforces two
rules:
-1) Exactly one I/O method, either "mmap" or "read", is associated with each
+- exactly one I/O method, either "mmap" or "read", is associated with each
file descriptor. Once it is selected, the application must close and reopen the
-device to switch to the other I/O method.
+device to switch to the other I/O method;
-2) Previously mapped buffer memory must always be unmapped before calling any
-of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. In case,
-the same number of buffers as before will be allocated again to match the size
-of the new video frames, so you have to map them again before any I/O attempts.
+- previously mapped buffer memory must always be unmapped before calling any
+of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. The same
+number of buffers as before will be allocated again to match the size of the
+new video frames, so you have to map them again before any I/O attempts.
+
+Consistently with the hardware limits, this driver also supports image
+downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
+However the V4L2 API specifications don't correctly define how the scaling
+factor can be choosen arbitrarily by the "negotiation" of the "source" and
+"target" rectangles. To work around this flaw, we have added the convention
+that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
+scaling factor is restored to 1.
11. Contact information
diff -uprN -X dontdiff linux-2.6.7/drivers/usb/media/sn9c102_core.c
devel-2.6.7/drivers/usb/media/sn9c102_core.c
--- linux-2.6.7/drivers/usb/media/sn9c102_core.c 2004-08-12 04:04:08.000000000
+0200
+++ devel-2.6.7/drivers/usb/media/sn9c102_core.c 2004-08-12 04:15:32.000000000
+0200
@@ -31,6 +31,7 @@
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/stddef.h>
+#include <linux/compiler.h>
#include <linux/ioctl.h>
#include <linux/poll.h>
#include <linux/stat.h>
@@ -1731,13 +1732,15 @@ static int sn9c102_v4l2_ioctl(struct ino
rect->width &= ~15L;
rect->height &= ~15L;
- { /* calculate the actual scaling factor */
+ if (SN9C102_PRESERVE_IMGSCALE) {
+ /* Calculate the actual scaling factor */
u32 a, b;
a = rect->width * rect->height;
b = pix_format->width * pix_format->height;
scale = b ? (u8)((a / b) < 4 ? 1 :
((a / b) < 16 ? 2 : 4)) : 1;
- }
+ } else
+ scale = 1;
if (cam->stream == STREAM_ON) {
cam->stream = STREAM_INTERRUPT;
@@ -2111,7 +2114,7 @@ static int sn9c102_v4l2_ioctl(struct ino
spin_lock_irqsave(&cam->queue_lock, lock_flags);
f = list_entry(cam->outqueue.next, struct sn9c102_frame_t,
frame);
- list_del(&cam->outqueue);
+ list_del(cam->outqueue.next);
spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
f->state = F_UNUSED;
diff -uprN -X dontdiff linux-2.6.7/drivers/usb/media/sn9c102.h
devel-2.6.7/drivers/usb/media/sn9c102.h
--- linux-2.6.7/drivers/usb/media/sn9c102.h 2004-08-12 04:04:08.000000000 +0200
+++ devel-2.6.7/drivers/usb/media/sn9c102.h 2004-08-12 04:16:47.000000000 +0200
@@ -40,6 +40,7 @@
#define SN9C102_DEBUG
#define SN9C102_DEBUG_LEVEL 2
#define SN9C102_MAX_DEVICES 64
+#define SN9C102_PRESERVE_IMGSCALE 0
#define SN9C102_MAX_FRAMES 32
#define SN9C102_URBS 2
#define SN9C102_ISO_PACKETS 7
@@ -52,8 +53,8 @@
#define SN9C102_MODULE_AUTHOR "(C) 2004 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<[EMAIL PROTECTED]>"
#define SN9C102_MODULE_LICENSE "GPL"
-#define SN9C102_MODULE_VERSION "1:1.07"
-#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 7)
+#define SN9C102_MODULE_VERSION "1:1.08"
+#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 8)
SN9C102_ID_TABLE;
SN9C102_SENSOR_TABLE;
diff -uprN -X dontdiff linux-2.6.7/drivers/usb/media/sn9c102_pas106b.c
devel-2.6.7/drivers/usb/media/sn9c102_pas106b.c
--- linux-2.6.7/drivers/usb/media/sn9c102_pas106b.c 2004-08-12 04:04:08.000000000
+0200
+++ devel-2.6.7/drivers/usb/media/sn9c102_pas106b.c 2004-08-12 04:15:47.000000000
+0200
@@ -109,7 +109,7 @@ static int pas106b_set_ctrl(struct sn9c1
err += sn9c102_i2c_write(cam, 0x0e, ctrl->value & 0x1f);
break;
case V4L2_CID_BRIGHTNESS:
- err += sn9c102_i2c_write(cam, 0x0d, ctrl->value & 0x1f);
+ err += sn9c102_i2c_write(cam, 0x0d, 0x1f-(ctrl->value & 0x1f));
break;
case V4L2_CID_CONTRAST:
err += sn9c102_i2c_write(cam, 0x0f, ctrl->value & 0x03);
@@ -180,11 +180,11 @@ static struct sn9c102_sensor pas106b = {
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "darkness",
+ .name = "brightness",
.minimum = 0x00,
.maximum = 0x1f,
.step = 0x01,
- .default_value = 0x00,
+ .default_value = 0x1f,
.flags = 0,
},
{
diff -uprN -X dontdiff linux-2.6.7/drivers/usb/media/sn9c102_pas202bcb.c
devel-2.6.7/drivers/usb/media/sn9c102_pas202bcb.c
--- linux-2.6.7/drivers/usb/media/sn9c102_pas202bcb.c 2004-08-12 04:04:08.000000000
+0200
+++ devel-2.6.7/drivers/usb/media/sn9c102_pas202bcb.c 2004-08-12 04:15:54.000000000
+0200
@@ -104,7 +104,7 @@ static int pas202bcb_set_ctrl(struct sn9
err += sn9c102_i2c_write(cam, 0x10, ctrl->value & 0x1f);
break;
case V4L2_CID_BRIGHTNESS:
- err += sn9c102_i2c_write(cam, 0x06, ctrl->value & 0x0f);
+ err += sn9c102_i2c_write(cam, 0x06, 0x0f-(ctrl->value & 0x0f));
break;
default:
return -EINVAL;
@@ -173,11 +173,11 @@ static struct sn9c102_sensor pas202bcb =
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "darkness",
+ .name = "brightness",
.minimum = 0x00,
.maximum = 0x0f,
.step = 0x01,
- .default_value = 0x00,
+ .default_value = 0x0f,
.flags = 0,
},
},
diff -uprN -X dontdiff linux-2.6.7/drivers/usb/media/sn9c102_tas5110c1b.c
devel-2.6.7/drivers/usb/media/sn9c102_tas5110c1b.c
--- linux-2.6.7/drivers/usb/media/sn9c102_tas5110c1b.c 2004-08-12 04:04:08.000000000
+0200
+++ devel-2.6.7/drivers/usb/media/sn9c102_tas5110c1b.c 2004-08-12 04:16:12.000000000
+0200
@@ -27,7 +27,6 @@ static struct sn9c102_sensor tas5110c1b;
static int tas5110c1b_init(struct sn9c102_device* cam)
{
- const u8 DARKNESS = 0xb7;
int err = 0;
err += sn9c102_write_reg(cam, 0x01, 0x01);
@@ -41,13 +40,26 @@ static int tas5110c1b_init(struct sn9c10
err += sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11, 0x00, 0xc0,
0x80, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11, 0x02, 0x20,
- DARKNESS, 0, 0);
return err;
}
+static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ return sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11,
+ 0x02, 0x20,
+ 0xff - (ctrl->value & 0xff),
+ 0, 0);
+ default:
+ return -EINVAL;
+ }
+}
+
+
static int tas5110c1b_set_crop(struct sn9c102_device* cam,
const struct v4l2_rect* rect)
{
@@ -74,6 +86,19 @@ static struct sn9c102_sensor tas5110c1b
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES,
.init = &tas5110c1b_init,
+ .qctrl = {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "global gain",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x01,
+ .default_value = 0x48,
+ .flags = 0,
+ },
+ },
+ .set_ctrl = &tas5110c1b_set_ctrl,
.cropcap = {
.bounds = {
.left = 0,
diff -uprN -X dontdiff linux-2.6.7/drivers/usb/media/sn9c102_tas5130d1b.c
devel-2.6.7/drivers/usb/media/sn9c102_tas5130d1b.c
--- linux-2.6.7/drivers/usb/media/sn9c102_tas5130d1b.c 2004-08-12 04:04:08.000000000
+0200
+++ devel-2.6.7/drivers/usb/media/sn9c102_tas5130d1b.c 2004-08-12 04:16:20.000000000
+0200
@@ -27,7 +27,6 @@ static struct sn9c102_sensor tas5130d1b;
static int tas5130d1b_init(struct sn9c102_device* cam)
{
- const u8 DARKNESS = 0xff, CONTRAST = 0xb0, GAIN = 0x08;
int err = 0;
err += sn9c102_write_reg(cam, 0x01, 0x01);
@@ -39,19 +38,28 @@ static int tas5130d1b_init(struct sn9c10
err += sn9c102_write_reg(cam, 0x60, 0x17);
err += sn9c102_write_reg(cam, 0x07, 0x18);
- err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x80,
- 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0xc0,
- GAIN, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x40,
- CONTRAST, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x02, 0x20,
- DARKNESS, 0, 0);
+ 0x47, 0, 0);
return err;
}
+static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ return sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11,
+ 0x02, 0x20,
+ 0xff - (ctrl->value & 0xff),
+ 0, 0);
+ default:
+ return -EINVAL;
+ }
+}
+
+
static int tas5130d1b_set_crop(struct sn9c102_device* cam,
const struct v4l2_rect* rect)
{
@@ -78,6 +86,19 @@ static struct sn9c102_sensor tas5130d1b
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES,
.init = &tas5130d1b_init,
+ .qctrl = {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "global gain",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x01,
+ .default_value = 0x00,
+ .flags = 0,
+ },
+ },
+ .set_ctrl = &tas5130d1b_set_ctrl,
.cropcap = {
.bounds = {
.left = 0,
pgpWOxetUI8yD.pgp
Description: PGP signature
