summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-12-29 10:20:59 +0100
committerJean-Francois Moine <moinejf@free.fr>2008-12-29 10:20:59 +0100
commit91cca7cf1298d0d75c258e282c93b78e4d43c97b (patch)
treec6b4e8764a3c65c6bb78f2a4010f6cde619cbc1b /linux/drivers/media/video
parent9b4cfe3aca4123a0279d63449c540a2fdd5fddca (diff)
parent1f181a1b26f6f36b4a546e0fa57f64df8274b4b3 (diff)
downloadmediapointer-dvb-s2-91cca7cf1298d0d75c258e282c93b78e4d43c97b.tar.gz
mediapointer-dvb-s2-91cca7cf1298d0d75c258e282c93b78e4d43c97b.tar.bz2
merge: v4l-dvb
Diffstat (limited to 'linux/drivers/media/video')
-rw-r--r--linux/drivers/media/video/gspca/gspca.c18
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_bridge.h7
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_core.c100
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c135
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h14
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_ov9650.c282
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_ov9650.h164
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_po1030.c166
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_po1030.h10
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c202
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h19
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c213
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h25
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_sensor.h14
-rw-r--r--linux/drivers/media/video/gspca/ov534.c114
-rw-r--r--linux/drivers/media/video/gspca/pac207.c5
-rw-r--r--linux/drivers/media/video/gspca/pac7311.c2
-rw-r--r--linux/drivers/media/video/gspca/spca561.c531
-rw-r--r--linux/drivers/media/video/gspca/t613.c2
-rw-r--r--linux/drivers/media/video/gspca/zc3xx.c1
20 files changed, 908 insertions, 1116 deletions
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index 71e7afe1b..5adbe7301 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -785,8 +785,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv;
int mode;
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
mode = gspca_dev->curr_mode;
memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode],
sizeof fmt->fmt.pix);
@@ -798,8 +796,6 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
{
int w, h, mode, mode2;
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
w = fmt->fmt.pix.width;
h = fmt->fmt.pix.height;
@@ -1153,8 +1149,6 @@ static int vidioc_reqbufs(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv;
int i, ret = 0;
- if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
switch (rb->memory) {
case GSPCA_MEMORY_READ: /* (internal call) */
case V4L2_MEMORY_MMAP:
@@ -1219,8 +1213,7 @@ static int vidioc_querybuf(struct file *file, void *priv,
struct gspca_dev *gspca_dev = priv;
struct gspca_frame *frame;
- if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
- || v4l2_buf->index < 0
+ if (v4l2_buf->index < 0
|| v4l2_buf->index >= gspca_dev->nframes)
return -EINVAL;
@@ -1243,7 +1236,8 @@ static int vidioc_streamon(struct file *file, void *priv,
ret = -ENODEV;
goto out;
}
- if (gspca_dev->nframes == 0) {
+ if (gspca_dev->nframes == 0
+ || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) {
ret = -EINVAL;
goto out;
}
@@ -1561,8 +1555,6 @@ static int vidioc_dqbuf(struct file *file, void *priv,
int i, ret;
PDEBUG(D_FRAM, "dqbuf");
- if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
if (v4l2_buf->memory != gspca_dev->memory)
return -EINVAL;
@@ -1617,8 +1609,6 @@ static int vidioc_qbuf(struct file *file, void *priv,
int i, index, ret;
PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
- if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
@@ -1828,7 +1818,7 @@ static struct file_operations dev_fops = {
.release = dev_close,
.read = dev_read,
.mmap = dev_mmap,
- .ioctl = video_ioctl2,
+ .unlocked_ioctl = __video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
#endif
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h
index c1c7ce524..a3f3b7a0c 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h
+++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h
@@ -109,7 +109,6 @@ static const unsigned char sensor_urb_skeleton[] = {
0x13, M5602_XB_I2C_CTRL, 0x81, 0x11
};
-/* m5602 device descriptor, currently it just wraps the m5602_camera struct */
struct sd {
struct gspca_dev gspca_dev;
@@ -134,4 +133,10 @@ int m5602_read_bridge(
int m5602_write_bridge(
struct sd *sd, u8 address, u8 i2c_data);
+int m5602_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
+int m5602_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len);
+
#endif
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c
index fd6ce384b..ed906fe31 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_core.c
+++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c
@@ -24,7 +24,7 @@
/* Kernel module parameters */
int force_sensor;
-int dump_bridge;
+static int dump_bridge;
int dump_sensor;
static const __devinitdata struct usb_device_id m5602_table[] = {
@@ -80,6 +80,97 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data)
return (err < 0) ? err : 0;
}
+int m5602_read_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+
+ if (!len || len > sd->sensor->i2c_regW)
+ return -EINVAL;
+
+ do {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+ } while ((*i2c_data & I2C_BUSY) && !err);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+ sd->sensor->i2c_slave_id);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+ if (err < 0)
+ goto out;
+
+ if (sd->sensor->i2c_regW == 1) {
+ err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, len);
+ if (err < 0)
+ goto out;
+
+ err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
+ if (err < 0)
+ goto out;
+ } else {
+ err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
+ if (err < 0)
+ goto out;
+ }
+
+ for (i = 0; (i < len) && !err; i++) {
+ err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+ PDEBUG(D_CONF, "Reading sensor register "
+ "0x%x containing 0x%x ", address, *i2c_data);
+ }
+out:
+ return err;
+}
+
+int m5602_write_sensor(struct sd *sd, const u8 address,
+ u8 *i2c_data, const u8 len)
+{
+ int err, i;
+ u8 *p;
+ struct usb_device *udev = sd->gspca_dev.dev;
+ __u8 *buf = sd->gspca_dev.usb_buf;
+
+ /* No sensor with a data width larger than 16 bits has yet been seen */
+ if (len > sd->sensor->i2c_regW || !len)
+ return -EINVAL;
+
+ memcpy(buf, sensor_urb_skeleton,
+ sizeof(sensor_urb_skeleton));
+
+ buf[11] = sd->sensor->i2c_slave_id;
+ buf[15] = address;
+
+ /* Special case larger sensor writes */
+ p = buf + 16;
+
+ /* Copy a four byte write sequence for each byte to be written to */
+ for (i = 0; i < len; i++) {
+ memcpy(p, sensor_urb_skeleton + 16, 4);
+ p[3] = i2c_data[i];
+ p += 4;
+ PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
+ address, i2c_data[i]);
+ }
+
+ /* Copy the tailer */
+ memcpy(p, sensor_urb_skeleton + 20, 4);
+
+ /* Set the total length */
+ p[3] = 0x10 + len;
+
+ err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x04, 0x40, 0x19,
+ 0x0000, buf,
+ 20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+ return (err < 0) ? err : 0;
+}
+
/* Dump all the registers of the m5602 bridge,
unfortunately this breaks the camera until it's power cycled */
static void m5602_dump_bridge(struct sd *sd)
@@ -150,11 +241,15 @@ static int m5602_start_transfer(struct gspca_dev *gspca_dev)
/* Send start command to the camera */
const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01};
+
+ if (sd->sensor->start)
+ sd->sensor->start(sd);
+
memcpy(buf, buffer, sizeof(buffer));
err = usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
0x04, 0x40, 0x19, 0x0000, buf,
- 4, M5602_URB_MSG_TIMEOUT);
+ sizeof(buffer), M5602_URB_MSG_TIMEOUT);
PDEBUG(D_STREAM, "Transfer started");
return (err < 0) ? err : 0;
@@ -284,6 +379,7 @@ static int __init mod_m5602_init(void)
PDEBUG(D_PROBE, "registered");
return 0;
}
+
static void __exit mod_m5602_exit(void)
{
usb_deregister(&sd_driver);
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c
index fb700c2d0..c0e71c331 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c
+++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c
@@ -18,6 +18,8 @@
#include "m5602_mt9m111.h"
+static void mt9m111_dump_registers(struct sd *sd);
+
int mt9m111_probe(struct sd *sd)
{
u8 data[2] = {0x00, 0x00};
@@ -44,12 +46,12 @@ int mt9m111_probe(struct sd *sd)
} else {
data[0] = preinit_mt9m111[i][2];
data[1] = preinit_mt9m111[i][3];
- mt9m111_write_sensor(sd,
+ m5602_write_sensor(sd,
preinit_mt9m111[i][1], data, 2);
}
}
- if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
+ if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
return -ENODEV;
if ((data[0] == 0x14) && (data[1] == 0x3a)) {
@@ -72,7 +74,7 @@ int mt9m111_init(struct sd *sd)
int i, err = 0;
/* Init the sensor */
- for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) {
+ for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
u8 data[2];
if (init_mt9m111[i][0] == BRIDGE) {
@@ -82,7 +84,7 @@ int mt9m111_init(struct sd *sd)
} else {
data[0] = init_mt9m111[i][2];
data[1] = init_mt9m111[i][3];
- err = mt9m111_write_sensor(sd,
+ err = m5602_write_sensor(sd,
init_mt9m111[i][1], data, 2);
}
}
@@ -104,12 +106,12 @@ int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
u8 data[2] = {0x00, 0x00};
struct sd *sd = (struct sd *) gspca_dev;
- err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+ err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
data, 2);
*val = data[0] & MT9M111_RMB_MIRROR_ROWS;
PDEBUG(D_V4L2, "Read vertical flip %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -121,19 +123,19 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
/* Set the correct page map */
- err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
if (err < 0)
goto out;
- err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+ err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
if (err < 0)
goto out;
data[0] = (data[0] & 0xfe) | val;
- err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+ err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
data, 2);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -142,12 +144,12 @@ int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
u8 data[2] = {0x00, 0x00};
struct sd *sd = (struct sd *) gspca_dev;
- err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+ err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
data, 2);
*val = data[0] & MT9M111_RMB_MIRROR_COLS;
PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -159,19 +161,19 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
/* Set the correct page map */
- err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
if (err < 0)
goto out;
- err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+ err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
if (err < 0)
goto out;
data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
- err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+ err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
data, 2);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
@@ -180,7 +182,7 @@ int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
u8 data[2] = {0x00, 0x00};
struct sd *sd = (struct sd *) gspca_dev;
- err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
+ err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
tmp = ((data[1] << 8) | data[0]);
*val = ((tmp & (1 << 10)) * 2) |
@@ -190,7 +192,7 @@ int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
PDEBUG(D_V4L2, "Read gain %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -200,7 +202,7 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
/* Set the correct page map */
- err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+ err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
if (err < 0)
goto out;
@@ -225,90 +227,13 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
data[1], data[0]);
- err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
+ err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
data, 2);
out:
- return (err < 0) ? err : 0;
-}
-
-int mt9m111_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len) {
- int err, i;
-
- do {
- err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
- } while ((*i2c_data & I2C_BUSY) && !err);
- if (err < 0)
- goto out;
-
- err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
- sd->sensor->i2c_slave_id);
- if (err < 0)
- goto out;
-
- err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
- if (err < 0)
- goto out;
-
- err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a);
- if (err < 0)
- goto out;
-
- for (i = 0; i < len && !err; i++) {
- err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
-
- PDEBUG(D_CONF, "Reading sensor register "
- "0x%x contains 0x%x ", address, *i2c_data);
- }
-out:
- return (err < 0) ? err : 0;
-}
-
-int mt9m111_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len)
-{
- int err, i;
- u8 *p;
- struct usb_device *udev = sd->gspca_dev.dev;
- __u8 *buf = sd->gspca_dev.usb_buf;
-
- /* No sensor with a data width larger
- than 16 bits has yet been seen, nor with 0 :p*/
- if (len > 2 || !len)
- return -EINVAL;
-
- memcpy(buf, sensor_urb_skeleton,
- sizeof(sensor_urb_skeleton));
-
- buf[11] = sd->sensor->i2c_slave_id;
- buf[15] = address;
-
- p = buf + 16;
-
- /* Copy a four byte write sequence for each byte to be written to */
- for (i = 0; i < len; i++) {
- memcpy(p, sensor_urb_skeleton + 16, 4);
- p[3] = i2c_data[i];
- p += 4;
- PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
- address, i2c_data[i]);
- }
-
- /* Copy the tailer */
- memcpy(p, sensor_urb_skeleton + 20, 4);
-
- /* Set the total length */
- p[3] = 0x10 + len;
-
- err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- 0x04, 0x40, 0x19,
- 0x0000, buf,
- 20 + len * 4, M5602_URB_MSG_TIMEOUT);
-
- return (err < 0) ? err : 0;
+ return err;
}
-void mt9m111_dump_registers(struct sd *sd)
+static void mt9m111_dump_registers(struct sd *sd)
{
u8 address, value[2] = {0x00, 0x00};
@@ -316,27 +241,27 @@ void mt9m111_dump_registers(struct sd *sd)
info("Dumping the mt9m111 sensor core registers");
value[1] = MT9M111_SENSOR_CORE;
- mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+ m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
for (address = 0; address < 0xff; address++) {
- mt9m111_read_sensor(sd, address, value, 2);
+ m5602_read_sensor(sd, address, value, 2);
info("register 0x%x contains 0x%x%x",
address, value[0], value[1]);
}
info("Dumping the mt9m111 color pipeline registers");
value[1] = MT9M111_COLORPIPE;
- mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+ m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
for (address = 0; address < 0xff; address++) {
- mt9m111_read_sensor(sd, address, value, 2);
+ m5602_read_sensor(sd, address, value, 2);
info("register 0x%x contains 0x%x%x",
address, value[0], value[1]);
}
info("Dumping the mt9m111 camera control registers");
value[1] = MT9M111_CAMERA_CONTROL;
- mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+ m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
for (address = 0; address < 0xff; address++) {
- mt9m111_read_sensor(sd, address, value, 2);
+ m5602_read_sensor(sd, address, value, 2);
info("register 0x%x contains 0x%x%x",
address, value[0], value[1]);
}
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h
index 315209d5a..e795ab7a3 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h
+++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h
@@ -87,14 +87,6 @@ int mt9m111_probe(struct sd *sd);
int mt9m111_init(struct sd *sd);
int mt9m111_power_down(struct sd *sd);
-int mt9m111_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-
-int mt9m111_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-
-void mt9m111_dump_registers(struct sd *sd);
-
int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
@@ -106,14 +98,12 @@ static struct m5602_sensor mt9m111 = {
.name = "MT9M111",
.i2c_slave_id = 0xba,
+ .i2c_regW = 2,
.probe = mt9m111_probe,
.init = mt9m111_init,
.power_down = mt9m111_power_down,
- .read_sensor = mt9m111_read_sensor,
- .write_sensor = mt9m111_write_sensor,
-
.nctrls = 3,
.ctrls = {
{
@@ -1003,7 +993,7 @@ static const unsigned char init_mt9m111[][4] =
{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, /* 639*/
{BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c
index 07ef2b3db..dde5075ed 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c
+++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -47,86 +47,30 @@ static
}
},
{
+ .ident = "ASUS A6Ja",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
+ }
+ },
+ {
.ident = "ASUS A6Kt",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
}
},
+ {
+ .ident = "Alienware Aurora m9700",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
+ }
+ },
{ }
};
-int ov9650_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len)
-{
- int err, i;
-
- /* The ov9650 registers have a max depth of one byte */
- if (len > 1 || !len)
- return -EINVAL;
-
- do {
- err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
- } while ((*i2c_data & I2C_BUSY) && !err);
-
- m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
- ov9650.i2c_slave_id);
- m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
- m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len);
- m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
-
- for (i = 0; i < len; i++) {
- err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
-
- PDEBUG(D_CONF, "Reading sensor register "
- "0x%x containing 0x%x ", address, *i2c_data);
- }
- return (err < 0) ? err : 0;
-}
-
-int ov9650_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len)
-{
- int err, i;
- u8 *p;
- struct usb_device *udev = sd->gspca_dev.dev;
- __u8 *buf = sd->gspca_dev.usb_buf;
-
- /* The ov9650 only supports one byte writes */
- if (len > 1 || !len)
- return -EINVAL;
-
- memcpy(buf, sensor_urb_skeleton,
- sizeof(sensor_urb_skeleton));
-
- buf[11] = sd->sensor->i2c_slave_id;
- buf[15] = address;
-
- /* Special case larger sensor writes */
- p = buf + 16;
-
- /* Copy a four byte write sequence for each byte to be written to */
- for (i = 0; i < len; i++) {
- memcpy(p, sensor_urb_skeleton + 16, 4);
- p[3] = i2c_data[i];
- p += 4;
- PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
- address, i2c_data[i]);
- }
-
- /* Copy the tailer */
- memcpy(p, sensor_urb_skeleton + 20, 4);
-
- /* Set the total length */
- p[3] = 0x10 + len;
-
- err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- 0x04, 0x40, 0x19,
- 0x0000, buf,
- 20 + len * 4, M5602_URB_MSG_TIMEOUT);
-
- return (err < 0) ? err : 0;
-}
+static void ov9650_dump_registers(struct sd *sd);
int ov9650_probe(struct sd *sd)
{
@@ -148,16 +92,16 @@ int ov9650_probe(struct sd *sd)
for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) {
u8 data = preinit_ov9650[i][2];
if (preinit_ov9650[i][0] == SENSOR)
- ov9650_write_sensor(sd,
+ m5602_write_sensor(sd,
preinit_ov9650[i][1], &data, 1);
else
m5602_write_bridge(sd, preinit_ov9650[i][1], data);
}
- if (ov9650_read_sensor(sd, OV9650_PID, &prod_id, 1))
+ if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
return -ENODEV;
- if (ov9650_read_sensor(sd, OV9650_VER, &ver_id, 1))
+ if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
return -ENODEV;
if ((prod_id == 0x96) && (ver_id == 0x52)) {
@@ -186,34 +130,90 @@ int ov9650_init(struct sd *sd)
for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
data = init_ov9650[i][2];
if (init_ov9650[i][0] == SENSOR)
- err = ov9650_write_sensor(sd, init_ov9650[i][1],
+ err = m5602_write_sensor(sd, init_ov9650[i][1],
&data, 1);
else
err = m5602_write_bridge(sd, init_ov9650[i][1], data);
}
- if (!err && dmi_check_system(ov9650_flip_dmi_table)) {
+ if (dmi_check_system(ov9650_flip_dmi_table) && !err) {
info("vflip quirk active");
data = 0x30;
- err = ov9650_write_sensor(sd, OV9650_MVFP, &data, 1);
+ err = m5602_write_sensor(sd, OV9650_MVFP, &data, 1);
}
+ return err;
+}
- return (err < 0) ? err : 0;
+int ov9650_start(struct sd *sd)
+{
+ int i, err = 0;
+ struct cam *cam = &sd->gspca_dev.cam;
+
+ for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
+ u8 data = res_init_ov9650[i][1];
+ err = m5602_write_bridge(sd, res_init_ov9650[i][0], data);
+ }
+ if (err < 0)
+ return err;
+
+ switch (cam->cam_mode[sd->gspca_dev.curr_mode].width)
+ {
+ case 640:
+ PDEBUG(D_V4L2, "Configuring camera for VGA mode");
+
+ for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) {
+ u8 data = VGA_ov9650[i][2];
+ if (VGA_ov9650[i][0] == SENSOR)
+ err = m5602_write_sensor(sd,
+ VGA_ov9650[i][1], &data, 1);
+ else
+ err = m5602_write_bridge(sd, VGA_ov9650[i][1], data);
+ }
+ break;
+
+ case 352:
+ PDEBUG(D_V4L2, "Configuring camera for CIF mode");
+
+ for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) {
+ u8 data = CIF_ov9650[i][2];
+ if (CIF_ov9650[i][0] == SENSOR)
+ err = m5602_write_sensor(sd,
+ CIF_ov9650[i][1], &data, 1);
+ else
+ err = m5602_write_bridge(sd, CIF_ov9650[i][1], data);
+ }
+ break;
+
+ case 320:
+ PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
+
+ for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) {
+ u8 data = QVGA_ov9650[i][2];
+ if (QVGA_ov9650[i][0] == SENSOR)
+ err = m5602_write_sensor(sd,
+ QVGA_ov9650[i][1], &data, 1);
+ else
+ err = m5602_write_bridge(sd, QVGA_ov9650[i][1], data);
+ }
+ break;
+ }
+ return err;
}
int ov9650_power_down(struct sd *sd)
{
- int i;
- for (i = 0; i < ARRAY_SIZE(power_down_ov9650); i++) {
+ int i, err = 0;
+ for (i = 0; i < ARRAY_SIZE(power_down_ov9650) && !err; i++) {
u8 data = power_down_ov9650[i][2];
if (power_down_ov9650[i][0] == SENSOR)
- ov9650_write_sensor(sd,
+ err = m5602_write_sensor(sd,
power_down_ov9650[i][1], &data, 1);
else
- m5602_write_bridge(sd, power_down_ov9650[i][1], data);
+ err = m5602_write_bridge(sd, power_down_ov9650[i][1],
+ data);
}
- return 0;
+ return err;
}
int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
@@ -222,24 +222,24 @@ int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
int err;
- err = ov9650_read_sensor(sd, OV9650_COM1, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_COM1, &i2c_data, 1);
if (err < 0)
goto out;
*val = i2c_data & 0x03;
- err = ov9650_read_sensor(sd, OV9650_AECH, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_AECH, &i2c_data, 1);
if (err < 0)
goto out;
*val |= (i2c_data << 2);
- err = ov9650_read_sensor(sd, OV9650_AECHM, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_AECHM, &i2c_data, 1);
if (err < 0)
goto out;
*val |= (i2c_data & 0x3f) << 10;
PDEBUG(D_V4L2, "Read exposure %d", *val);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
@@ -253,24 +253,24 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
/* The 6 MSBs */
i2c_data = (val >> 10) & 0x3f;
- err = ov9650_write_sensor(sd, OV9650_AECHM,
+ err = m5602_write_sensor(sd, OV9650_AECHM,
&i2c_data, 1);
if (err < 0)
goto out;
/* The 8 middle bits */
i2c_data = (val >> 2) & 0xff;
- err = ov9650_write_sensor(sd, OV9650_AECH,
+ err = m5602_write_sensor(sd, OV9650_AECH,
&i2c_data, 1);
if (err < 0)
goto out;
/* The 2 LSBs */
i2c_data = val & 0x03;
- err = ov9650_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
@@ -279,13 +279,13 @@ int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
- ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
*val = (i2c_data & 0x03) << 8;
- err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
*val |= i2c_data;
PDEBUG(D_V4L2, "Read gain %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -297,16 +297,16 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
/* The 2 MSB */
/* Read the OV9650_VREF register first to avoid
corrupting the VREF high and low bits */
- ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
/* Mask away all uninteresting bits */
i2c_data = ((val & 0x0300) >> 2) |
(i2c_data & 0x3F);
- err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
/* The 8 LSBs */
i2c_data = val & 0xff;
- err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
- return (err < 0) ? err : 0;
+ err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+ return err;
}
int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
@@ -315,12 +315,12 @@ int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
- err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_RED, &i2c_data, 1);
*val = i2c_data;
PDEBUG(D_V4L2, "Read red gain %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
@@ -333,9 +333,9 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
val & 0xff);
i2c_data = val & 0xff;
- err = ov9650_write_sensor(sd, OV9650_RED, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
@@ -344,12 +344,12 @@ int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
- err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_BLUE, &i2c_data, 1);
*val = i2c_data;
PDEBUG(D_V4L2, "Read blue gain %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
@@ -362,9 +362,9 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
val & 0xff);
i2c_data = val & 0xff;
- err = ov9650_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -373,14 +373,14 @@ int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
- err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
if (dmi_check_system(ov9650_flip_dmi_table))
*val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1;
else
*val = (i2c_data & OV9650_HFLIP) >> 5;
PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -390,20 +390,20 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
- err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
if (err < 0)
goto out;
if (dmi_check_system(ov9650_flip_dmi_table))
i2c_data = ((i2c_data & 0xdf) |
- (((val ? 0 : 1) & 0x01) << 5));
+ (((val ? 0 : 1) & 0x01) << 5));
else
i2c_data = ((i2c_data & 0xdf) |
- ((val & 0x01) << 5));
+ ((val & 0x01) << 5));
- err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -412,14 +412,14 @@ int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
- err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
if (dmi_check_system(ov9650_flip_dmi_table))
*val = ((i2c_data & 0x10) >> 4) ? 0 : 1;
else
*val = (i2c_data & 0x10) >> 4;
PDEBUG(D_V4L2, "Read vertical flip %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -429,7 +429,7 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
- err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
if (err < 0)
goto out;
@@ -440,9 +440,9 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
i2c_data = ((i2c_data & 0xef) |
((val & 0x01) << 4));
- err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
@@ -451,16 +451,16 @@ int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
- err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
if (err < 0)
goto out;
*val = (i2c_data & 0x03) << 8;
- err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
*val |= i2c_data;
PDEBUG(D_V4L2, "Read gain %d", *val);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -473,22 +473,22 @@ int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
/* Read the OV9650_VREF register first to avoid
corrupting the VREF high and low bits */
- err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
if (err < 0)
goto out;
/* Mask away all uninteresting bits */
i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
- err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
if (err < 0)
goto out;
/* The 8 LSBs */
i2c_data = val & 0xff;
- err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
@@ -497,11 +497,11 @@ int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
- err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
*val = (i2c_data & OV9650_AWB_EN) >> 1;
PDEBUG(D_V4L2, "Read auto white balance %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
@@ -511,14 +511,14 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
PDEBUG(D_V4L2, "Set auto white balance to %d", val);
- err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
if (err < 0)
goto out;
i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
- err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
@@ -527,11 +527,11 @@ int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
struct sd *sd = (struct sd *) gspca_dev;
- err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
*val = (i2c_data & OV9650_AGC_EN) >> 2;
PDEBUG(D_V4L2, "Read auto gain control %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -541,23 +541,23 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
PDEBUG(D_V4L2, "Set auto gain control to %d", val);
- err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
if (err < 0)
goto out;
i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
- err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
+ err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
out:
- return (err < 0) ? err : 0;
+ return err;
}
-void ov9650_dump_registers(struct sd *sd)
+static void ov9650_dump_registers(struct sd *sd)
{
int address;
info("Dumping the ov9650 register state");
for (address = 0; address < 0xa9; address++) {
u8 value;
- ov9650_read_sensor(sd, address, &value, 1);
+ m5602_read_sensor(sd, address, &value, 1);
info("register 0x%x contains 0x%x",
address, value);
}
@@ -569,9 +569,9 @@ void ov9650_dump_registers(struct sd *sd)
u8 old_value, ctrl_value;
u8 test_value[2] = {0xff, 0xff};
- ov9650_read_sensor(sd, address, &old_value, 1);
- ov9650_write_sensor(sd, address, test_value, 1);
- ov9650_read_sensor(sd, address, &ctrl_value, 1);
+ m5602_read_sensor(sd, address, &old_value, 1);
+ m5602_write_sensor(sd, address, test_value, 1);
+ m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value[0])
info("register 0x%x is writeable", address);
@@ -579,6 +579,6 @@ void ov9650_dump_registers(struct sd *sd)
info("register 0x%x is read only", address);
/* Restore original value */
- ov9650_write_sensor(sd, address, &old_value, 1);
+ m5602_write_sensor(sd, address, &old_value, 1);
}
}
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h
index e0efdb930..f4b33b8e8 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h
+++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h
@@ -20,7 +20,6 @@
#define M5602_OV9650_H_
#include <linux/dmi.h>
-
#include "m5602_sensor.h"
/*****************************************************************************/
@@ -36,6 +35,7 @@
#define OV9650_PID 0x0a
#define OV9650_VER 0x0b
#define OV9650_COM3 0x0c
+#define OV9650_COM4 0x0d
#define OV9650_COM5 0x0e
#define OV9650_COM6 0x0f
#define OV9650_AECH 0x10
@@ -94,6 +94,8 @@
#define OV9650_REGISTER_RESET (1 << 7)
#define OV9650_VGA_SELECT (1 << 6)
+#define OV9650_CIF_SELECT (1 << 5)
+#define OV9650_QVGA_SELECT (1 << 4)
#define OV9650_RGB_SELECT (1 << 2)
#define OV9650_RAW_RGB_SELECT (1 << 0)
@@ -108,6 +110,8 @@
#define OV9650_SYSTEM_CLK_SEL (1 << 7)
#define OV9650_SLAM_MODE (1 << 4)
+#define OV9650_QVGA_VARIOPIXEL (1 << 7)
+
#define OV9650_VFLIP (1 << 4)
#define OV9650_HFLIP (1 << 5)
@@ -124,15 +128,9 @@ extern int dump_sensor;
int ov9650_probe(struct sd *sd);
int ov9650_init(struct sd *sd);
+int ov9650_start(struct sd *sd);
int ov9650_power_down(struct sd *sd);
-int ov9650_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-int ov9650_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-
-void ov9650_dump_registers(struct sd *sd);
-
int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
@@ -155,11 +153,11 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
static struct m5602_sensor ov9650 = {
.name = "OV9650",
.i2c_slave_id = 0x60,
+ .i2c_regW = 1,
.probe = ov9650_probe,
.init = ov9650_init,
+ .start = ov9650_start,
.power_down = ov9650_power_down,
- .read_sensor = ov9650_read_sensor,
- .write_sensor = ov9650_write_sensor,
.nctrls = 8,
.ctrls = {
@@ -264,18 +262,38 @@ static struct m5602_sensor ov9650 = {
}
},
- .nmodes = 1,
+ .nmodes = 3,
.modes = {
{
- M5602_DEFAULT_FRAME_WIDTH,
- M5602_DEFAULT_FRAME_HEIGHT,
+ 320,
+ 240,
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_FIELD_NONE,
+ .sizeimage =
+ 320 * 240,
+ .bytesperline = 320,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0
+ }, {
+ 352,
+ 288,
V4L2_PIX_FMT_SBGGR8,
V4L2_FIELD_NONE,
.sizeimage =
- M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
- .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+ 352 * 288,
+ .bytesperline = 352,
.colorspace = V4L2_COLORSPACE_SRGB,
- .priv = 1
+ .priv = 0
+ }, {
+ 640,
+ 480,
+ V4L2_PIX_FMT_SBGGR8,
+ V4L2_FIELD_NONE,
+ .sizeimage =
+ 640 * 480,
+ .bytesperline = 640,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0
}
}
};
@@ -324,6 +342,7 @@ static const unsigned char init_ov9650[][3] =
{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
{BRIDGE, M5602_XB_GPIO_DAT, 0x00},
{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
+
/* Reset chip */
{SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
/* Enable double clock */
@@ -331,8 +350,6 @@ static const unsigned char init_ov9650[][3] =
/* Do something out of spec with the power */
{SENSOR, OV9650_OFON, 0x40},
- /* Set QQVGA */
- {SENSOR, OV9650_COM1, 0x20},
/* Set fast AGC/AEC algorithm with unlimited step size */
{SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
OV9650_AEC_UNLIM_STEP_SIZE |
@@ -343,7 +360,7 @@ static const unsigned char init_ov9650[][3] =
{SENSOR, OV9650_ACOM38, 0x81},
/* Turn off color matrix coefficient double option */
{SENSOR, OV9650_COM16, 0x00},
- /* Enable color matrix for RGB/YUV, Delay Y channel,
+ /* Enable color matrix for RGB/YUV, Delay Y channel,
set output Y/UV delay to 1 */
{SENSOR, OV9650_COM13, 0x19},
/* Enable digital BLC, Set output mode to U Y V Y */
@@ -352,7 +369,7 @@ static const unsigned char init_ov9650[][3] =
{SENSOR, OV9650_COM24, 0x00},
/* Enable HREF and some out of spec things */
{SENSOR, OV9650_COM12, 0x73},
- /* Set all DBLC offset signs to positive and
+ /* Set all DBLC offset signs to positive and
do some out of spec stuff */
{SENSOR, OV9650_DBLC1, 0xdf},
{SENSOR, OV9650_COM21, 0x06},
@@ -364,7 +381,7 @@ static const unsigned char init_ov9650[][3] =
{SENSOR, OV9650_RSVD96, 0x04},
/* Enable full range output */
{SENSOR, OV9650_COM15, 0x0},
- /* Enable HREF at optical black, enable ADBLC bias,
+ /* Enable HREF at optical black, enable ADBLC bias,
enable ADBLC, reset timings at format change */
{SENSOR, OV9650_COM6, 0x4b},
/* Subtract 32 from the B channel bias */
@@ -385,7 +402,7 @@ static const unsigned char init_ov9650[][3] =
{SENSOR, OV9650_AEB, 0x5c},
/* Set the high and low limit nibbles to 3 */
{SENSOR, OV9650_VPT, 0xc3},
- /* Set the Automatic Gain Ceiling (AGC) to 128x,
+ /* Set the Automatic Gain Ceiling (AGC) to 128x,
drop VSYNC at frame drop,
limit exposure timing,
drop frame when the AEC step is larger than the exposure gap */
@@ -394,9 +411,9 @@ static const unsigned char init_ov9650[][3] =
and set PWDN to SLVS (slave mode vertical sync) */
{SENSOR, OV9650_COM10, 0x42},
/* Set horizontal column start high to default value */
- {SENSOR, OV9650_HSTART, 0x1a},
+ {SENSOR, OV9650_HSTART, 0x1a}, /* 210 */
/* Set horizontal column end */
- {SENSOR, OV9650_HSTOP, 0xbf},
+ {SENSOR, OV9650_HSTOP, 0xbf}, /* 1534 */
/* Complementing register to the two writes above */
{SENSOR, OV9650_HREF, 0xb2},
/* Set vertical row start high bits */
@@ -405,10 +422,6 @@ static const unsigned char init_ov9650[][3] =
{SENSOR, OV9650_VSTOP, 0x7e},
/* Set complementing vertical frame control */
{SENSOR, OV9650_VREF, 0x10},
- /* Set raw RGB output format with VGA resolution */
- {SENSOR, OV9650_COM7, OV9650_VGA_SELECT |
- OV9650_RGB_SELECT |
- OV9650_RAW_RGB_SELECT},
{SENSOR, OV9650_ADC, 0x04},
{SENSOR, OV9650_HV, 0x40},
/* Enable denoise, and white-pixel erase */
@@ -417,31 +430,15 @@ static const unsigned char init_ov9650[][3] =
/* Set the high bits of the exposure value */
{SENSOR, OV9650_AECH, ((EXPOSURE_DEFAULT & 0xff00) >> 8)},
+ /* Enable VARIOPIXEL */
+ {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
+ {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL},
+
/* Set the low bits of the exposure value */
{SENSOR, OV9650_COM1, (EXPOSURE_DEFAULT & 0xff)},
{SENSOR, OV9650_GAIN, GAIN_DEFAULT},
{SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT},
{SENSOR, OV9650_RED, RED_GAIN_DEFAULT},
-
- {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
- {SENSOR, OV9650_COM5, OV9650_SYSTEM_CLK_SEL},
-
- {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
- {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
- {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
- {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
- {BRIDGE, M5602_XB_SIG_INI, 0x01},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- /* Moves the view window in a vertical orientation */
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0},
- {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
- {BRIDGE, M5602_XB_HSYNC_PARA, 0xde}
};
static const unsigned char power_down_ov9650[][3] =
@@ -461,7 +458,76 @@ static const unsigned char power_down_ov9650[][3] =
{BRIDGE, M5602_XB_GPIO_EN_L, 0x06},
{BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
- {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}
+ {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+};
+
+static const unsigned char res_init_ov9650[][2] =
+{
+ {M5602_XB_LINE_OF_FRAME_H, 0x82},
+ {M5602_XB_LINE_OF_FRAME_L, 0x00},
+ {M5602_XB_PIX_OF_LINE_H, 0x82},
+ {M5602_XB_PIX_OF_LINE_L, 0x00},
+ {M5602_XB_SIG_INI, 0x01}
+};
+
+static const unsigned char VGA_ov9650[][3] =
+{
+ /* Moves the view window in a vertical orientation */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, /* 480 */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, /* 640 + 98 */
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0xe2},
+
+ {SENSOR, OV9650_COM7, OV9650_VGA_SELECT |
+ OV9650_RGB_SELECT |
+ OV9650_RAW_RGB_SELECT},
+};
+
+static const unsigned char CIF_ov9650[][3] =
+{
+ /* Moves the view window in a vertical orientation */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x20}, /* 288 */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x62}, /* 98 */
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 352 + 98 */
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0xc2},
+
+ {SENSOR, OV9650_COM7, OV9650_CIF_SELECT |
+ OV9650_RGB_SELECT |
+ OV9650_RAW_RGB_SELECT},
+};
+
+static const unsigned char QVGA_ov9650[][3] =
+{
+ /* Moves the view window in a vertical orientation */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x08},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0xf0}, /* 240 */
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x31}, /* 50 */
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x01}, /* 320 + 50 */
+ {BRIDGE, M5602_XB_HSYNC_PARA, 0x71},
+
+ {SENSOR, OV9650_COM7, OV9650_QVGA_SELECT |
+ OV9650_RGB_SELECT |
+ OV9650_RAW_RGB_SELECT},
};
#endif
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c
index d17ac5256..2e7fb9167 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c
+++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c
@@ -18,6 +18,8 @@
#include "m5602_po1030.h"
+static void po1030_dump_registers(struct sd *sd);
+
int po1030_probe(struct sd *sd)
{
u8 prod_id = 0, ver_id = 0, i;
@@ -38,16 +40,16 @@ int po1030_probe(struct sd *sd)
for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
u8 data = preinit_po1030[i][2];
if (preinit_po1030[i][0] == SENSOR)
- po1030_write_sensor(sd,
+ m5602_write_sensor(sd,
preinit_po1030[i][1], &data, 1);
else
m5602_write_bridge(sd, preinit_po1030[i][1], data);
}
- if (po1030_read_sensor(sd, 0x3, &prod_id, 1))
+ if (m5602_read_sensor(sd, 0x3, &prod_id, 1))
return -ENODEV;
- if (po1030_read_sensor(sd, 0x4, &ver_id, 1))
+ if (m5602_read_sensor(sd, 0x4, &ver_id, 1))
return -ENODEV;
if ((prod_id == 0x02) && (ver_id == 0xef)) {
@@ -64,78 +66,12 @@ sensor_found:
return 0;
}
-int po1030_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len)
-{
- int err, i;
-
- do {
- err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
- } while ((*i2c_data & I2C_BUSY) && !err);
-
- m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
- sd->sensor->i2c_slave_id);
- m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
- m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len);
- m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
-
- for (i = 0; i < len; i++) {
- err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
-
- PDEBUG(D_CONF, "Reading sensor register "
- "0x%x containing 0x%x ", address, *i2c_data);
- }
- return (err < 0) ? err : 0;
-}
-
-int po1030_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len)
-{
- int err, i;
- u8 *p;
- struct usb_device *udev = sd->gspca_dev.dev;
- __u8 *buf = sd->gspca_dev.usb_buf;
-
- /* The po1030 only supports one byte writes */
- if (len > 1 || !len)
- return -EINVAL;
-
- memcpy(buf, sensor_urb_skeleton, sizeof(sensor_urb_skeleton));
-
- buf[11] = sd->sensor->i2c_slave_id;
- buf[15] = address;
-
- p = buf + 16;
-
- /* Copy a four byte write sequence for each byte to be written to */
- for (i = 0; i < len; i++) {
- memcpy(p, sensor_urb_skeleton + 16, 4);
- p[3] = i2c_data[i];
- p += 4;
- PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
- address, i2c_data[i]);
- }
-
- /* Copy the footer */
- memcpy(p, sensor_urb_skeleton + 20, 4);
-
- /* Set the total length */
- p[3] = 0x10 + len;
-
- err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- 0x04, 0x40, 0x19,
- 0x0000, buf,
- 20 + len * 4, M5602_URB_MSG_TIMEOUT);
-
- return (err < 0) ? err : 0;
-}
-
int po1030_init(struct sd *sd)
{
int i, err = 0;
/* Init the sensor */
- for (i = 0; i < ARRAY_SIZE(init_po1030); i++) {
+ for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
u8 data[2] = {0x00, 0x00};
switch (init_po1030[i][0]) {
@@ -147,16 +83,10 @@ int po1030_init(struct sd *sd)
case SENSOR:
data[0] = init_po1030[i][2];
- err = po1030_write_sensor(sd,
+ err = m5602_write_sensor(sd,
init_po1030[i][1], data, 1);
break;
- case SENSOR_LONG:
- data[0] = init_po1030[i][2];
- data[1] = init_po1030[i][3];
- err = po1030_write_sensor(sd,
- init_po1030[i][1], data, 2);
- break;
default:
info("Invalid stream command, exiting init");
return -EINVAL;
@@ -166,7 +96,7 @@ int po1030_init(struct sd *sd)
if (dump_sensor)
po1030_dump_registers(sd);
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
@@ -175,19 +105,19 @@ int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
int err;
- err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_H,
+ err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_H,
&i2c_data, 1);
if (err < 0)
goto out;
*val = (i2c_data << 8);
- err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_M,
+ err = m5602_read_sensor(sd, PO1030_REG_INTEGLINES_M,
&i2c_data, 1);
*val |= i2c_data;
PDEBUG(D_V4L2, "Exposure read as %d", *val);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
@@ -202,7 +132,7 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
i2c_data);
- err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H,
+ err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_H,
&i2c_data, 1);
if (err < 0)
goto out;
@@ -210,11 +140,11 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
i2c_data = (val & 0xff);
PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
i2c_data);
- err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M,
+ err = m5602_write_sensor(sd, PO1030_REG_INTEGLINES_M,
&i2c_data, 1);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
@@ -223,12 +153,12 @@ int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
int err;
- err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN,
+ err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
&i2c_data, 1);
*val = i2c_data;
PDEBUG(D_V4L2, "Read global gain %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -237,14 +167,14 @@ int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
int err;
- err = po1030_read_sensor(sd, PO1030_REG_CONTROL2,
+ err = m5602_read_sensor(sd, PO1030_REG_CONTROL2,
&i2c_data, 1);
*val = (i2c_data >> 7) & 0x01 ;
PDEBUG(D_V4L2, "Read hflip %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -254,13 +184,17 @@ int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
int err;
PDEBUG(D_V4L2, "Set hflip %d", val);
+ err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
+ if (err < 0)
+ goto out;
- i2c_data = (val & 0x01) << 7;
+ i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
- err = po1030_write_sensor(sd, PO1030_REG_CONTROL2,
- &i2c_data, 1);
+ err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
+ &i2c_data, 1);
- return (err < 0) ? err : 0;
+out:
+ return err;
}
int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -269,14 +203,14 @@ int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
int err;
- err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN,
+ err = m5602_read_sensor(sd, PO1030_REG_GLOBALGAIN,
&i2c_data, 1);
*val = (i2c_data >> 6) & 0x01;
PDEBUG(D_V4L2, "Read vflip %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -286,13 +220,17 @@ int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
int err;
PDEBUG(D_V4L2, "Set vflip %d", val);
+ err = m5602_read_sensor(sd, PO1030_REG_CONTROL2, &i2c_data, 1);
+ if (err < 0)
+ goto out;
- i2c_data = (val & 0x01) << 6;
+ i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
- err = po1030_write_sensor(sd, PO1030_REG_CONTROL2,
- &i2c_data, 1);
+ err = m5602_write_sensor(sd, PO1030_REG_CONTROL2,
+ &i2c_data, 1);
- return (err < 0) ? err : 0;
+out:
+ return err;
}
int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -303,9 +241,9 @@ int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
i2c_data = val & 0xff;
PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
- err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN,
+ err = m5602_write_sensor(sd, PO1030_REG_GLOBALGAIN,
&i2c_data, 1);
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
@@ -314,11 +252,11 @@ int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
int err;
- err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN,
+ err = m5602_read_sensor(sd, PO1030_REG_RED_GAIN,
&i2c_data, 1);
*val = i2c_data;
PDEBUG(D_V4L2, "Read red gain %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
@@ -329,9 +267,9 @@ int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
i2c_data = val & 0xff;
PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
- err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN,
+ err = m5602_write_sensor(sd, PO1030_REG_RED_GAIN,
&i2c_data, 1);
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
@@ -340,12 +278,12 @@ int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
u8 i2c_data;
int err;
- err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN,
+ err = m5602_read_sensor(sd, PO1030_REG_BLUE_GAIN,
&i2c_data, 1);
*val = i2c_data;
PDEBUG(D_V4L2, "Read blue gain %d", *val);
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
@@ -355,10 +293,10 @@ int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
int err;
i2c_data = val & 0xff;
PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
- err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN,
+ err = m5602_write_sensor(sd, PO1030_REG_BLUE_GAIN,
&i2c_data, 1);
- return (err < 0) ? err : 0;
+ return err;
}
int po1030_power_down(struct sd *sd)
@@ -366,14 +304,14 @@ int po1030_power_down(struct sd *sd)
return 0;
}
-void po1030_dump_registers(struct sd *sd)
+static void po1030_dump_registers(struct sd *sd)
{
int address;
u8 value = 0;
info("Dumping the po1030 sensor core registers");
for (address = 0; address < 0x7f; address++) {
- po1030_read_sensor(sd, address, &value, 1);
+ m5602_read_sensor(sd, address, &value, 1);
info("register 0x%x contains 0x%x",
address, value);
}
@@ -385,9 +323,9 @@ void po1030_dump_registers(struct sd *sd)
u8 old_value, ctrl_value;
u8 test_value[2] = {0xff, 0xff};
- po1030_read_sensor(sd, address, &old_value, 1);
- po1030_write_sensor(sd, address, test_value, 1);
- po1030_read_sensor(sd, address, &ctrl_value, 1);
+ m5602_read_sensor(sd, address, &old_value, 1);
+ m5602_write_sensor(sd, address, test_value, 1);
+ m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value[0])
info("register 0x%x is writeable", address);
@@ -395,6 +333,6 @@ void po1030_dump_registers(struct sd *sd)
info("register 0x%x is read only", address);
/* Restore original value */
- po1030_write_sensor(sd, address, &old_value, 1);
+ m5602_write_sensor(sd, address, &old_value, 1);
}
}
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h
index a0b75ff61..def39d5bc 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h
+++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h
@@ -10,7 +10,7 @@
* v4l2 interface modeled after the V4L2 driver
* for SN9C10x PC Camera Controllers
*
- * Register defines taken from Pascal Stangs Proxycon Armlib
+ * Register defines taken from Pascal Stangs Procyon Armlib
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -128,13 +128,6 @@ int po1030_probe(struct sd *sd);
int po1030_init(struct sd *sd);
int po1030_power_down(struct sd *sd);
-void po1030_dump_registers(struct sd *sd);
-
-int po1030_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-int po1030_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-
int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
@@ -152,6 +145,7 @@ static struct m5602_sensor po1030 = {
.name = "PO1030",
.i2c_slave_id = 0xdc,
+ .i2c_regW = 1,
.probe = po1030_probe,
.init = po1030_init,
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index 1f72e7eae..2bd7d4d99 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -52,6 +52,7 @@ static
{ }
};
+static void s5k4aa_dump_registers(struct sd *sd);
int s5k4aa_probe(struct sd *sd)
{
@@ -84,7 +85,7 @@ int s5k4aa_probe(struct sd *sd)
case SENSOR:
data[0] = preinit_s5k4aa[i][2];
- err = s5k4aa_write_sensor(sd,
+ err = m5602_write_sensor(sd,
preinit_s5k4aa[i][1],
data, 1);
break;
@@ -92,7 +93,7 @@ int s5k4aa_probe(struct sd *sd)
case SENSOR_LONG:
data[0] = preinit_s5k4aa[i][2];
data[1] = preinit_s5k4aa[i][3];
- err = s5k4aa_write_sensor(sd,
+ err = m5602_write_sensor(sd,
preinit_s5k4aa[i][1],
data, 2);
break;
@@ -103,13 +104,14 @@ int s5k4aa_probe(struct sd *sd)
}
/* Test some registers, but we don't know their exact meaning yet */
- if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id)))
+ if (m5602_read_sensor(sd, 0x00, prod_id, sizeof(prod_id)))
return -ENODEV;
if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
return -ENODEV;
else
info("Detected a s5k4aa sensor");
+
sensor_found:
sd->gspca_dev.cam.cam_mode = s5k4aa.modes;
sd->gspca_dev.cam.nmodes = s5k4aa.nmodes;
@@ -119,90 +121,6 @@ sensor_found:
return 0;
}
-int s5k4aa_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len)
-{
- int err, i;
-
- do {
- err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
- } while ((*i2c_data & I2C_BUSY) && !err);
- if (err < 0)
- goto out;
-
- err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
- sd->sensor->i2c_slave_id);
- if (err < 0)
- goto out;
-
- err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
- if (err < 0)
- goto out;
-
- err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
- if (err < 0)
- goto out;
-
- do {
- err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
- } while ((*i2c_data & I2C_BUSY) && !err);
- if (err < 0)
- goto out;
-
- for (i = 0; (i < len) & !err; i++) {
- err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
-
- PDEBUG(D_CONF, "Reading sensor register "
- "0x%x containing 0x%x ", address, *i2c_data);
- }
-out:
- return (err < 0) ? err : 0;
-}
-
-int s5k4aa_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len)
-{
- int err, i;
- u8 *p;
- struct usb_device *udev = sd->gspca_dev.dev;
- __u8 *buf = sd->gspca_dev.usb_buf;
-
- /* No sensor with a data width larger than 16 bits has yet been seen */
- if (len > 2 || !len)
- return -EINVAL;
-
- memcpy(buf, sensor_urb_skeleton,
- sizeof(sensor_urb_skeleton));
-
- buf[11] = sd->sensor->i2c_slave_id;
- buf[15] = address;
-
- /* Special case larger sensor writes */
- p = buf + 16;
-
- /* Copy a four byte write sequence for each byte to be written to */
- for (i = 0; i < len; i++) {
- memcpy(p, sensor_urb_skeleton + 16, 4);
- p[3] = i2c_data[i];
- p += 4;
- PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
- address, i2c_data[i]);
- }
-
- /* Copy the tailer */
- memcpy(p, sensor_urb_skeleton + 20, 4);
-
- /* Set the total length */
- p[3] = 0x10 + len;
-
- err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- 0x04, 0x40, 0x19,
- 0x0000, buf,
- 20 + len * 4, M5602_URB_MSG_TIMEOUT);
-
- return (err < 0) ? err : 0;
-}
-
int s5k4aa_init(struct sd *sd)
{
int i, err = 0;
@@ -219,14 +137,14 @@ int s5k4aa_init(struct sd *sd)
case SENSOR:
data[0] = init_s5k4aa[i][2];
- err = s5k4aa_write_sensor(sd,
+ err = m5602_write_sensor(sd,
init_s5k4aa[i][1], data, 1);
break;
case SENSOR_LONG:
data[0] = init_s5k4aa[i][2];
data[1] = init_s5k4aa[i][3];
- err = s5k4aa_write_sensor(sd,
+ err = m5602_write_sensor(sd,
init_s5k4aa[i][1], data, 2);
break;
default:
@@ -241,21 +159,21 @@ int s5k4aa_init(struct sd *sd)
if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) {
u8 data = 0x02;
info("vertical flip quirk active");
- s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
- s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
data |= S5K4AA_RM_V_FLIP;
data &= ~S5K4AA_RM_H_FLIP;
- s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
/* Decrement COLSTART to preserve color order (BGGR) */
- s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
data--;
- s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
/* Increment ROWSTART to preserve color order (BGGR) */
- s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
data++;
- s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
}
return (err < 0) ? err : 0;
@@ -272,20 +190,20 @@ int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
u8 data = S5K4AA_PAGE_MAP_2;
int err;
- err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
goto out;
- err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
+ err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
if (err < 0)
goto out;
*val = data << 8;
- err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
+ err = m5602_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
*val |= data;
PDEBUG(D_V4L2, "Read exposure %d", *val);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
@@ -295,17 +213,17 @@ int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
int err;
PDEBUG(D_V4L2, "Set exposure to %d", val);
- err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
goto out;
data = (val >> 8) & 0xff;
- err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
if (err < 0)
goto out;
data = val & 0xff;
- err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -314,16 +232,16 @@ int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
u8 data = S5K4AA_PAGE_MAP_2;
int err;
- err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
goto out;
- err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
*val = (data & S5K4AA_RM_V_FLIP) >> 7;
PDEBUG(D_V4L2, "Read vertical flip %d", *val);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -333,35 +251,35 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
int err;
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
- err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
goto out;
- err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
if (err < 0)
goto out;
data = ((data & ~S5K4AA_RM_V_FLIP)
| ((val & 0x01) << 7));
- err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
if (err < 0)
goto out;
if (val) {
- err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
if (err < 0)
goto out;
data++;
- err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
} else {
- err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
if (err < 0)
goto out;
data--;
- err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
}
out:
- return (err < 0) ? err : 0;
+ return err;
}
int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -370,15 +288,15 @@ int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
u8 data = S5K4AA_PAGE_MAP_2;
int err;
- err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
goto out;
- err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
*val = (data & S5K4AA_RM_H_FLIP) >> 6;
PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -389,35 +307,35 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
PDEBUG(D_V4L2, "Set horizontal flip to %d",
val);
- err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
goto out;
- err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
if (err < 0)
goto out;
data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
- err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
if (err < 0)
goto out;
if (val) {
- err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
if (err < 0)
goto out;
data++;
- err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
if (err < 0)
goto out;
} else {
- err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
if (err < 0)
goto out;
data--;
- err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
}
out:
- return (err < 0) ? err : 0;
+ return err;
}
int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
@@ -426,16 +344,16 @@ int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
u8 data = S5K4AA_PAGE_MAP_2;
int err;
- err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
goto out;
- err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
+ err = m5602_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
*val = data;
PDEBUG(D_V4L2, "Read gain %d", *val);
out:
- return (err < 0) ? err : 0;
+ return err;
}
int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -445,28 +363,28 @@ int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
int err;
PDEBUG(D_V4L2, "Set gain to %d", val);
- err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
goto out;
data = val & 0xff;
- err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1);
+ err = m5602_write_sensor(sd, S5K4AA_GAIN_2, &data, 1);
out:
- return (err < 0) ? err : 0;
+ return err;
}
-void s5k4aa_dump_registers(struct sd *sd)
+static void s5k4aa_dump_registers(struct sd *sd)
{
int address;
u8 page, old_page;
- s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
+ m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
for (page = 0; page < 16; page++) {
- s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
+ m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
info("Dumping the s5k4aa register state for page 0x%x", page);
for (address = 0; address <= 0xff; address++) {
u8 value = 0;
- s5k4aa_read_sensor(sd, address, &value, 1);
+ m5602_read_sensor(sd, address, &value, 1);
info("register 0x%x contains 0x%x",
address, value);
}
@@ -474,15 +392,15 @@ void s5k4aa_dump_registers(struct sd *sd)
info("s5k4aa register state dump complete");
for (page = 0; page < 16; page++) {
- s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
+ m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
info("Probing for which registers that are "
"read/write for page 0x%x", page);
for (address = 0; address <= 0xff; address++) {
u8 old_value, ctrl_value, test_value = 0xff;
- s5k4aa_read_sensor(sd, address, &old_value, 1);
- s5k4aa_write_sensor(sd, address, &test_value, 1);
- s5k4aa_read_sensor(sd, address, &ctrl_value, 1);
+ m5602_read_sensor(sd, address, &old_value, 1);
+ m5602_write_sensor(sd, address, &test_value, 1);
+ m5602_read_sensor(sd, address, &ctrl_value, 1);
if (ctrl_value == test_value)
info("register 0x%x is writeable", address);
@@ -490,9 +408,9 @@ void s5k4aa_dump_registers(struct sd *sd)
info("register 0x%x is read only", address);
/* Restore original value */
- s5k4aa_write_sensor(sd, address, &old_value, 1);
+ m5602_write_sensor(sd, address, &old_value, 1);
}
}
info("Read/write register probing complete");
- s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
+ m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
}
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
index 151c6f530..1f88b0d04 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
+++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
@@ -41,11 +41,10 @@
#define S5K4AA_WINDOW_HEIGHT_LO 0x09
#define S5K4AA_WINDOW_WIDTH_HI 0x0a
#define S5K4AA_WINDOW_WIDTH_LO 0x0b
-#define S5K4AA_GLOBAL_GAIN__ 0x0f /* Only a guess ATM !!! */
-#define S5K4AA_H_BLANK_HI__ 0x1d /* Only a guess ATM !!! sync lost
- if too low, reduces frame rate
- if too high */
-#define S5K4AA_H_BLANK_LO__ 0x1e /* Only a guess ATM !!! */
+#define S5K4AA_GLOBAL_GAIN__ 0x0f
+/* sync lost, if too low, reduces frame rate if too high */
+#define S5K4AA_H_BLANK_HI__ 0x1d
+#define S5K4AA_H_BLANK_LO__ 0x1e
#define S5K4AA_EXPOSURE_HI 0x17
#define S5K4AA_EXPOSURE_LO 0x18
#define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */
@@ -68,13 +67,6 @@ int s5k4aa_probe(struct sd *sd);
int s5k4aa_init(struct sd *sd);
int s5k4aa_power_down(struct sd *sd);
-void s5k4aa_dump_registers(struct sd *sd);
-
-int s5k4aa_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-int s5k4aa_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-
int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
@@ -89,9 +81,8 @@ static struct m5602_sensor s5k4aa = {
.probe = s5k4aa_probe,
.init = s5k4aa_init,
.power_down = s5k4aa_power_down,
- .read_sensor = s5k4aa_read_sensor,
- .write_sensor = s5k4aa_write_sensor,
.i2c_slave_id = 0x5a,
+ .i2c_regW = 2,
.nctrls = 4,
.ctrls = {
{
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c
index 8988a728e..af3f2dc2c 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c
+++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -18,6 +18,8 @@
#include "m5602_s5k83a.h"
+static void s5k83a_dump_registers(struct sd *sd);
+
int s5k83a_probe(struct sd *sd)
{
u8 prod_id = 0, ver_id = 0;
@@ -39,7 +41,7 @@ int s5k83a_probe(struct sd *sd)
for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
if (preinit_s5k83a[i][0] == SENSOR)
- err = s5k83a_write_sensor(sd, preinit_s5k83a[i][1],
+ err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
data, 2);
else
err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
@@ -49,10 +51,10 @@ int s5k83a_probe(struct sd *sd)
/* We don't know what register (if any) that contain the product id
* Just pick the first addresses that seem to produce the same results
* on multiple machines */
- if (s5k83a_read_sensor(sd, 0x00, &prod_id, 1))
+ if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
return -ENODEV;
- if (s5k83a_read_sensor(sd, 0x01, &ver_id, 1))
+ if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
return -ENODEV;
if ((prod_id == 0xff) || (ver_id == 0xff))
@@ -68,91 +70,6 @@ sensor_found:
return 0;
}
-int s5k83a_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len)
-{
- int err, i;
-
- do {
- err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
- } while ((*i2c_data & I2C_BUSY) && !err);
- if (err < 0)
- goto out;
-
- err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
- sd->sensor->i2c_slave_id);
- if (err < 0)
- goto out;
-
- err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
- if (err < 0)
- goto out;
-
- err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
- if (err < 0)
- goto out;
-
- do {
- err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
- } while ((*i2c_data & I2C_BUSY) && !err);
-
- if (err < 0)
- goto out;
- for (i = 0; i < len && !len; i++) {
- err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
-
- PDEBUG(D_CONF, "Reading sensor register "
- "0x%x containing 0x%x ", address, *i2c_data);
- }
-
-out:
- return (err < 0) ? err : 0;
-}
-
-int s5k83a_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len)
-{
- int err, i;
- u8 *p;
- struct usb_device *udev = sd->gspca_dev.dev;
- __u8 *buf = sd->gspca_dev.usb_buf;
-
- /* No sensor with a data width larger than 16 bits has yet been seen */
- if (len > 2 || !len)
- return -EINVAL;
-
- memcpy(buf, sensor_urb_skeleton,
- sizeof(sensor_urb_skeleton));
-
- buf[11] = sd->sensor->i2c_slave_id;
- buf[15] = address;
-
- /* Special case larger sensor writes */
- p = buf + 16;
-
- /* Copy a four byte write sequence for each byte to be written to */
- for (i = 0; i < len; i++) {
- memcpy(p, sensor_urb_skeleton + 16, 4);
- p[3] = i2c_data[i];
- p += 4;
- PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
- address, i2c_data[i]);
- }
-
- /* Copy the tailer */
- memcpy(p, sensor_urb_skeleton + 20, 4);
-
- /* Set the total length */
- p[3] = 0x10 + len;
-
- err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- 0x04, 0x40, 0x19,
- 0x0000, buf,
- 20 + len * 4, M5602_URB_MSG_TIMEOUT);
-
- return (err < 0) ? err : 0;
-}
-
int s5k83a_init(struct sd *sd)
{
int i, err = 0;
@@ -169,14 +86,14 @@ int s5k83a_init(struct sd *sd)
case SENSOR:
data[0] = init_s5k83a[i][2];
- err = s5k83a_write_sensor(sd,
+ err = m5602_write_sensor(sd,
init_s5k83a[i][1], data, 1);
break;
case SENSOR_LONG:
data[0] = init_s5k83a[i][2];
data[1] = init_s5k83a[i][3];
- err = s5k83a_write_sensor(sd,
+ err = m5602_write_sensor(sd,
init_s5k83a[i][1], data, 2);
break;
default:
@@ -200,14 +117,14 @@ void s5k83a_dump_registers(struct sd *sd)
{
int address;
u8 page, old_page;
- s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+ m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
for (page = 0; page < 16; page++) {
- s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+ m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
info("Dumping the s5k83a register state for page 0x%x", page);
for (address = 0; address <= 0xff; address++) {
u8 val = 0;
- s5k83a_read_sensor(sd, address, &val, 1);
+ m5602_read_sensor(sd, address, &val, 1);
info("register 0x%x contains 0x%x",
address, val);
}
@@ -215,15 +132,15 @@ void s5k83a_dump_registers(struct sd *sd)
info("s5k83a register state dump complete");
for (page = 0; page < 16; page++) {
- s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+ m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
info("Probing for which registers that are read/write "
"for page 0x%x", page);
for (address = 0; address <= 0xff; address++) {
u8 old_val, ctrl_val, test_val = 0xff;
- s5k83a_read_sensor(sd, address, &old_val, 1);
- s5k83a_write_sensor(sd, address, &test_val, 1);
- s5k83a_read_sensor(sd, address, &ctrl_val, 1);
+ m5602_read_sensor(sd, address, &old_val, 1);
+ m5602_write_sensor(sd, address, &test_val, 1);
+ m5602_read_sensor(sd, address, &ctrl_val, 1);
if (ctrl_val == test_val)
info("register 0x%x is writeable", address);
@@ -231,11 +148,11 @@ void s5k83a_dump_registers(struct sd *sd)
info("register 0x%x is read only", address);
/* Restore original val */
- s5k83a_write_sensor(sd, address, &old_val, 1);
+ m5602_write_sensor(sd, address, &old_val, 1);
}
}
info("Read/write register probing complete");
- s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+ m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
}
int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
@@ -244,11 +161,15 @@ int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
u8 data[2];
struct sd *sd = (struct sd *) gspca_dev;
- err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
+ err = m5602_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
+ if (err < 0)
+ goto out;
+
data[1] = data[1] << 1;
*val = data[1];
- return (err < 0) ? err : 0;
+out:
+ return err;
}
int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -259,23 +180,24 @@ int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
data[0] = 0x00;
data[1] = 0x20;
- err = s5k83a_write_sensor(sd, 0x14, data, 2);
+ err = m5602_write_sensor(sd, 0x14, data, 2);
if (err < 0)
- return err;
+ goto out;
data[0] = 0x01;
data[1] = 0x00;
- err = s5k83a_write_sensor(sd, 0x0d, data, 2);
+ err = m5602_write_sensor(sd, 0x0d, data, 2);
if (err < 0)
- return err;
+ goto out;
/* FIXME: This is not sane, we need to figure out the composition
of these registers */
data[0] = val >> 3; /* brightness, high 5 bits */
data[1] = val >> 1; /* brightness, high 7 bits */
- err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
+ err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
- return (err < 0) ? err : 0;
+out:
+ return err;
}
int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val)
@@ -284,10 +206,14 @@ int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val)
u8 data;
struct sd *sd = (struct sd *) gspca_dev;
- err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1);
+ err = m5602_read_sensor(sd, S5K83A_WHITENESS, &data, 1);
+ if (err < 0)
+ goto out;
*val = data;
- return (err < 0) ? err : 0;
+
+out:
+ return err;
}
int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val)
@@ -297,9 +223,9 @@ int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
data[0] = val;
- err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1);
+ err = m5602_write_sensor(sd, S5K83A_WHITENESS, data, 1);
- return (err < 0) ? err : 0;
+ return err;
}
int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
@@ -308,7 +234,9 @@ int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
u8 data[2];
struct sd *sd = (struct sd *) gspca_dev;
- err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2);
+ err = m5602_read_sensor(sd, S5K83A_GAIN, data, 2);
+ if (err < 0)
+ goto out;
data[1] = data[1] & 0x3f;
if (data[1] > S5K83A_MAXIMUM_GAIN)
@@ -316,7 +244,8 @@ int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
*val = data[1];
- return (err < 0) ? err : 0;
+out:
+ return err;
}
int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -327,9 +256,8 @@ int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
data[0] = 0;
data[1] = val;
- err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2);
-
- return (err < 0) ? err : 0;
+ err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
+ return err;
}
int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -339,14 +267,15 @@ int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
struct sd *sd = (struct sd *) gspca_dev;
data[0] = 0x05;
- err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+ err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
if (err < 0)
- return err;
+ goto out;
- err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+ err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
*val = (data[0] | 0x40) ? 1 : 0;
- return (err < 0) ? err : 0;
+out:
+ return err;
}
int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -356,25 +285,26 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
data[0] = 0x05;
- err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+ err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
if (err < 0)
- return err;
+ goto out;
- err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+ err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
if (err < 0)
- return err;
+ goto out;
/* set or zero six bit, seven is hflip */
data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK
: (data[0] & 0x80) | S5K83A_FLIP_MASK;
- err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1);
+ err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
if (err < 0)
- return err;
+ goto out;
data[0] = (val) ? 0x0b : 0x0a;
- err = s5k83a_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
+ err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
- return (err < 0) ? err : 0;
+out:
+ return err;
}
int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -384,14 +314,15 @@ int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
struct sd *sd = (struct sd *) gspca_dev;
data[0] = 0x05;
- err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+ err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
if (err < 0)
- return err;
+ goto out;
- err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+ err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
*val = (data[0] | 0x80) ? 1 : 0;
- return (err < 0) ? err : 0;
+out:
+ return err;
}
int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -401,23 +332,23 @@ int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
data[0] = 0x05;
- err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+ err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
if (err < 0)
- return err;
+ goto out;
- err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+ err = m5602_read_sensor(sd, S5K83A_FLIP, data, 1);
if (err < 0)
- return err;
+ goto out;
/* set or zero seven bit, six is vflip */
data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK
: (data[0] & 0x40) | S5K83A_FLIP_MASK;
- err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1);
+ err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
if (err < 0)
- return err;
+ goto out;
data[0] = (val) ? 0x0a : 0x0b;
- err = s5k83a_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
-
- return (err < 0) ? err : 0;
+ err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
+out:
+ return err;
}
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h
index ee3ee9cfc..05ccb5b57 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h
+++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h
@@ -22,15 +22,15 @@
#include "m5602_sensor.h"
#define S5K83A_FLIP 0x01
-#define S5K83A_HFLIP_TUNE 0x03
-#define S5K83A_VFLIP_TUNE 0x05
-#define S5K83A_WHITENESS 0x0a
+#define S5K83A_HFLIP_TUNE 0x03
+#define S5K83A_VFLIP_TUNE 0x05
+#define S5K83A_WHITENESS 0x0a
#define S5K83A_GAIN 0x18
-#define S5K83A_BRIGHTNESS 0x1b
-#define S5K83A_PAGE_MAP 0xec
+#define S5K83A_BRIGHTNESS 0x1b
+#define S5K83A_PAGE_MAP 0xec
-#define S5K83A_DEFAULT_BRIGHTNESS 0x71
-#define S5K83A_DEFAULT_WHITENESS 0x7e
+#define S5K83A_DEFAULT_BRIGHTNESS 0x71
+#define S5K83A_DEFAULT_WHITENESS 0x7e
#define S5K83A_DEFAULT_GAIN 0x00
#define S5K83A_MAXIMUM_GAIN 0x3c
#define S5K83A_FLIP_MASK 0x10
@@ -46,13 +46,6 @@ int s5k83a_probe(struct sd *sd);
int s5k83a_init(struct sd *sd);
int s5k83a_power_down(struct sd *sd);
-void s5k83a_dump_registers(struct sd *sd);
-
-int s5k83a_read_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-int s5k83a_write_sensor(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-
int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val);
@@ -64,15 +57,13 @@ int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-
static struct m5602_sensor s5k83a = {
.name = "S5K83A",
.probe = s5k83a_probe,
.init = s5k83a_init,
.power_down = s5k83a_power_down,
- .read_sensor = s5k83a_read_sensor,
- .write_sensor = s5k83a_write_sensor,
.i2c_slave_id = 0x5a,
+ .i2c_regW = 2,
.nctrls = 5,
.ctrls = {
{
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h
index 60c9a48e0..261623f0d 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h
+++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h
@@ -49,23 +49,21 @@ struct m5602_sensor {
/* What i2c address the sensor is connected to */
u8 i2c_slave_id;
+ /* Width of each i2c register (in bytes) */
+ u8 i2c_regW;
+
/* Probes if the sensor is connected */
int (*probe)(struct sd *sd);
/* Performs a initialization sequence */
int (*init)(struct sd *sd);
+ /* Executed when the camera starts to send data */
+ int (*start)(struct sd *sd);
+
/* Performs a power down sequence */
int (*power_down)(struct sd *sd);
- /* Reads a sensor register */
- int (*read_sensor)(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-
- /* Writes to a sensor register */
- int (*write_sensor)(struct sd *sd, const u8 address,
- u8 *i2c_data, const u8 len);
-
int nctrls;
struct ctrl ctrls[M5602_MAX_CTRLS];
diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c
index 7332947cb..406f6bc12 100644
--- a/linux/drivers/media/video/gspca/ov534.c
+++ b/linux/drivers/media/video/gspca/ov534.c
@@ -63,65 +63,66 @@ static struct v4l2_pix_format vga_mode[] = {
.priv = 0},
};
-static void ov534_reg_write(struct usb_device *udev, u16 reg, u8 val)
+static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
{
- u8 data = val;
+ struct usb_device *udev = gspca_dev->dev;
int ret;
PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val);
+ gspca_dev->usb_buf[0] = val;
ret = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
0x1,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0, reg, &data, 1, CTRL_TIMEOUT);
+ 0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
if (ret < 0)
PDEBUG(D_ERR, "write failed");
}
-static u8 ov534_reg_read(struct usb_device *udev, u16 reg)
+static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
{
- u8 data;
+ struct usb_device *udev = gspca_dev->dev;
int ret;
ret = usb_control_msg(udev,
usb_rcvctrlpipe(udev, 0),
0x1,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0x0, reg, &data, 1, CTRL_TIMEOUT);
- PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, data);
+ 0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
+ PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]);
if (ret < 0)
PDEBUG(D_ERR, "read failed");
- return data;
+ return gspca_dev->usb_buf[0];
}
/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
* (direction and output)? */
-static void ov534_set_led(struct usb_device *udev, int status)
+static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
{
u8 data;
PDEBUG(D_CONF, "led status: %d", status);
- data = ov534_reg_read(udev, 0x21);
+ data = ov534_reg_read(gspca_dev, 0x21);
data |= 0x80;
- ov534_reg_write(udev, 0x21, data);
+ ov534_reg_write(gspca_dev, 0x21, data);
- data = ov534_reg_read(udev, 0x23);
+ data = ov534_reg_read(gspca_dev, 0x23);
if (status)
data |= 0x80;
else
data &= ~(0x80);
- ov534_reg_write(udev, 0x23, data);
+ ov534_reg_write(gspca_dev, 0x23, data);
}
-static int sccb_check_status(struct usb_device *udev)
+static int sccb_check_status(struct gspca_dev *gspca_dev)
{
u8 data;
int i;
for (i = 0; i < 5; i++) {
- data = ov534_reg_read(udev, OV534_REG_STATUS);
+ data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
switch (data) {
case 0x00:
@@ -131,37 +132,37 @@ static int sccb_check_status(struct usb_device *udev)
case 0x03:
break;
default:
- PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5\n",
+ PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
data, i + 1);
}
}
return 0;
}
-static void sccb_reg_write(struct usb_device *udev, u16 reg, u8 val)
+static void sccb_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
{
PDEBUG(D_USBO, "reg: 0x%04x, val: 0x%02x", reg, val);
- ov534_reg_write(udev, OV534_REG_SUBADDR, reg);
- ov534_reg_write(udev, OV534_REG_WRITE, val);
- ov534_reg_write(udev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
+ ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
+ ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
+ ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
- if (!sccb_check_status(udev))
+ if (!sccb_check_status(gspca_dev))
PDEBUG(D_ERR, "sccb_reg_write failed");
}
#ifdef GSPCA_DEBUG
-static u8 sccb_reg_read(struct usb_device *udev, u16 reg)
+static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
{
- ov534_reg_write(udev, OV534_REG_SUBADDR, reg);
- ov534_reg_write(udev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
- if (!sccb_check_status(udev))
+ ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
+ ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
+ if (!sccb_check_status(gspca_dev))
PDEBUG(D_ERR, "sccb_reg_read failed 1");
- ov534_reg_write(udev, OV534_REG_OPERATION, OV534_OP_READ_2);
- if (!sccb_check_status(udev))
+ ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
+ if (!sccb_check_status(gspca_dev))
PDEBUG(D_ERR, "sccb_reg_read failed 2");
- return ov534_reg_read(udev, OV534_REG_READ);
+ return ov534_reg_read(gspca_dev, OV534_REG_READ);
}
#endif
@@ -318,26 +319,26 @@ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev)
switch (fr) {
case 50:
- sccb_reg_write(gspca_dev->dev, 0x11, 0x01);
- sccb_reg_write(gspca_dev->dev, 0x0d, 0x41);
- ov534_reg_write(gspca_dev->dev, 0xe5, 0x02);
+ sccb_reg_write(gspca_dev, 0x11, 0x01);
+ sccb_reg_write(gspca_dev, 0x0d, 0x41);
+ ov534_reg_write(gspca_dev, 0xe5, 0x02);
break;
case 40:
- sccb_reg_write(gspca_dev->dev, 0x11, 0x02);
- sccb_reg_write(gspca_dev->dev, 0x0d, 0xc1);
- ov534_reg_write(gspca_dev->dev, 0xe5, 0x04);
+ sccb_reg_write(gspca_dev, 0x11, 0x02);
+ sccb_reg_write(gspca_dev, 0x0d, 0xc1);
+ ov534_reg_write(gspca_dev, 0xe5, 0x04);
break;
/* case 30: */
default:
fr = 30;
- sccb_reg_write(gspca_dev->dev, 0x11, 0x04);
- sccb_reg_write(gspca_dev->dev, 0x0d, 0x81);
- ov534_reg_write(gspca_dev->dev, 0xe5, 0x02);
+ sccb_reg_write(gspca_dev, 0x11, 0x04);
+ sccb_reg_write(gspca_dev, 0x0d, 0x81);
+ ov534_reg_write(gspca_dev, 0xe5, 0x02);
break;
case 15:
- sccb_reg_write(gspca_dev->dev, 0x11, 0x03);
- sccb_reg_write(gspca_dev->dev, 0x0d, 0x41);
- ov534_reg_write(gspca_dev->dev, 0xe5, 0x04);
+ sccb_reg_write(gspca_dev, 0x11, 0x03);
+ sccb_reg_write(gspca_dev, 0x0d, 0x41);
+ ov534_reg_write(gspca_dev, 0xe5, 0x04);
break;
}
@@ -346,27 +347,28 @@ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev)
}
/* setup method */
-static void ov534_setup(struct usb_device *udev)
+static void ov534_setup(struct gspca_dev *gspca_dev)
{
int i;
/* Initialize bridge chip */
for (i = 0; i < ARRAY_SIZE(ov534_reg_initdata); i++)
- ov534_reg_write(udev, ov534_reg_initdata[i][0],
+ ov534_reg_write(gspca_dev, ov534_reg_initdata[i][0],
ov534_reg_initdata[i][1]);
PDEBUG(D_PROBE, "sensor is ov%02x%02x",
- sccb_reg_read(udev, 0x0a), sccb_reg_read(udev, 0x0b));
+ sccb_reg_read(gspca_dev, 0x0a),
+ sccb_reg_read(gspca_dev, 0x0b));
- ov534_set_led(udev, 1);
+ ov534_set_led(gspca_dev, 1);
/* Initialize sensor */
for (i = 0; i < ARRAY_SIZE(ov772x_reg_initdata); i++)
- sccb_reg_write(udev, ov772x_reg_initdata[i][0],
+ sccb_reg_write(gspca_dev, ov772x_reg_initdata[i][0],
ov772x_reg_initdata[i][1]);
- ov534_reg_write(udev, 0xe0, 0x09);
- ov534_set_led(udev, 0);
+ ov534_reg_write(gspca_dev, 0xe0, 0x09);
+ ov534_set_led(gspca_dev, 0);
}
/* this function is called at probe time */
@@ -390,7 +392,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
/* this function is called at probe and resume time */
static int sd_init(struct gspca_dev *gspca_dev)
{
- ov534_setup(gspca_dev->dev);
+ ov534_setup(gspca_dev);
ov534_set_frame_rate(gspca_dev);
return 0;
@@ -399,8 +401,8 @@ static int sd_init(struct gspca_dev *gspca_dev)
static int sd_start(struct gspca_dev *gspca_dev)
{
/* start streaming data */
- ov534_set_led(gspca_dev->dev, 1);
- ov534_reg_write(gspca_dev->dev, 0xe0, 0x00);
+ ov534_set_led(gspca_dev, 1);
+ ov534_reg_write(gspca_dev, 0xe0, 0x00);
return 0;
}
@@ -408,8 +410,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
static void sd_stopN(struct gspca_dev *gspca_dev)
{
/* stop streaming data */
- ov534_reg_write(gspca_dev->dev, 0xe0, 0x09);
- ov534_set_led(gspca_dev->dev, 0);
+ ov534_reg_write(gspca_dev, 0xe0, 0x09);
+ ov534_set_led(gspca_dev, 0);
}
/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
@@ -499,8 +501,8 @@ discard:
}
/* get stream parameters (framerate) */
-int sd_get_streamparm(struct gspca_dev *gspca_dev,
- struct v4l2_streamparm *parm)
+static int sd_get_streamparm(struct gspca_dev *gspca_dev,
+ struct v4l2_streamparm *parm)
{
struct v4l2_captureparm *cp = &parm->parm.capture;
struct v4l2_fract *tpf = &cp->timeperframe;
@@ -517,8 +519,8 @@ int sd_get_streamparm(struct gspca_dev *gspca_dev,
}
/* set stream parameters (framerate) */
-int sd_set_streamparm(struct gspca_dev *gspca_dev,
- struct v4l2_streamparm *parm)
+static int sd_set_streamparm(struct gspca_dev *gspca_dev,
+ struct v4l2_streamparm *parm)
{
struct v4l2_captureparm *cp = &parm->parm.capture;
struct v4l2_fract *tpf = &cp->timeperframe;
diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c
index 39473e6b9..e46b8e8f0 100644
--- a/linux/drivers/media/video/gspca/pac207.c
+++ b/linux/drivers/media/video/gspca/pac207.c
@@ -1,7 +1,7 @@
/*
* Pixart PAC207BCA library
*
- * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+ * Copyright (C) 2008 Hans de Goede <hdgoede@redhat.com>
* Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
* Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
*
@@ -27,7 +27,7 @@
#include "gspca.h"
-MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>");
MODULE_DESCRIPTION("Pixart PAC207");
MODULE_LICENSE("GPL");
@@ -529,6 +529,7 @@ static const struct sd_desc sd_desc = {
static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x041e, 0x4028)},
{USB_DEVICE(0x093a, 0x2460)},
+ {USB_DEVICE(0x093a, 0x2461)},
{USB_DEVICE(0x093a, 0x2463)},
{USB_DEVICE(0x093a, 0x2464)},
{USB_DEVICE(0x093a, 0x2468)},
diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c
index b0a9d0687..0a3c91301 100644
--- a/linux/drivers/media/video/gspca/pac7311.c
+++ b/linux/drivers/media/video/gspca/pac7311.c
@@ -1078,11 +1078,13 @@ static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
{USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
{USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
+ {USB_DEVICE(0x093a, 0x2620), .driver_info = SENSOR_PAC7302},
{USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
{USB_DEVICE(0x093a, 0x2622), .driver_info = SENSOR_PAC7302},
{USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
{USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302},
{USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302},
+ {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c
index 4c0046cc7..f518bb02f 100644
--- a/linux/drivers/media/video/gspca/spca561.c
+++ b/linux/drivers/media/video/gspca/spca561.c
@@ -32,22 +32,22 @@ MODULE_LICENSE("GPL");
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
- __u16 contrast; /* rev72a only */
-#define CONTRAST_MIN 0x0000
-#define CONTRAST_DEF 0x2000
-#define CONTRAST_MAX 0x3fff
-
__u16 exposure; /* rev12a only */
#define EXPOSURE_MIN 1
#define EXPOSURE_DEF 200
#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */
+ __u8 contrast; /* rev72a only */
+#define CONTRAST_MIN 0x00
+#define CONTRAST_DEF 0x20
+#define CONTRAST_MAX 0x3f
+
__u8 brightness; /* rev72a only */
#define BRIGHTNESS_MIN 0
-#define BRIGHTNESS_DEF 32
-#define BRIGHTNESS_MAX 63
+#define BRIGHTNESS_DEF 0x20
+#define BRIGHTNESS_MAX 0x3f
- __u8 white; /* rev12a only */
+ __u8 white;
#define WHITE_MIN 1
#define WHITE_DEF 0x40
#define WHITE_MAX 0x7f
@@ -146,98 +146,7 @@ static struct v4l2_pix_format sif_072a_mode[] = {
#define SPCA561_SNAPBIT 0x20
#define SPCA561_SNAPCTRL 0x40
-static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
-{
- int ret;
-
- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- 0, /* request */
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value, index, NULL, 0, 500);
- PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
- if (ret < 0)
- PDEBUG(D_ERR, "reg write: error %d", ret);
-}
-
-static void write_vector(struct gspca_dev *gspca_dev,
- const __u16 data[][2])
-{
- struct usb_device *dev = gspca_dev->dev;
- int i;
-
- i = 0;
- while (data[i][1] != 0) {
- reg_w_val(dev, data[i][1], data[i][0]);
- i++;
- }
-}
-
-/* read 'len' bytes to gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
- __u16 index, __u16 length)
-{
- usb_control_msg(gspca_dev->dev,
- usb_rcvctrlpipe(gspca_dev->dev, 0),
- 0, /* request */
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, /* value */
- index, gspca_dev->usb_buf, length, 500);
-}
-
-static void reg_w_buf(struct gspca_dev *gspca_dev,
- __u16 index, const __u8 *buffer, __u16 len)
-{
- memcpy(gspca_dev->usb_buf, buffer, len);
- usb_control_msg(gspca_dev->dev,
- usb_sndctrlpipe(gspca_dev->dev, 0),
- 0, /* request */
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, /* value */
- index, gspca_dev->usb_buf, len, 500);
-}
-
-static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
-{
- int retry = 60;
- __u8 DataLow;
- __u8 DataHight;
-
- DataLow = valeur;
- DataHight = valeur >> 8;
- reg_w_val(gspca_dev->dev, 0x8801, reg);
- reg_w_val(gspca_dev->dev, 0x8805, DataLow);
- reg_w_val(gspca_dev->dev, 0x8800, DataHight);
- while (retry--) {
- reg_r(gspca_dev, 0x8803, 1);
- if (!gspca_dev->usb_buf[0])
- break;
- }
-}
-
-static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
-{
- int retry = 60;
- __u8 value;
- __u8 vallsb;
-
- reg_w_val(gspca_dev->dev, 0x8804, 0x92);
- reg_w_val(gspca_dev->dev, 0x8801, reg);
- reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01));
- do {
- reg_r(gspca_dev, 0x8803, 1);
- if (!gspca_dev->usb_buf[0])
- break;
- } while (--retry);
- if (retry == 0)
- return -1;
- reg_r(gspca_dev, 0x8800, 1);
- value = gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8805, 1);
- vallsb = gspca_dev->usb_buf[0];
- return ((int) value << 8) | vallsb;
-}
-
-static const __u16 spca561_init_data[][2] = {
+static const __u16 rev72a_init_data1[][2] = {
{0x0000, 0x8114}, /* Software GPIO output data */
{0x0001, 0x8114}, /* Software GPIO output data */
{0x0000, 0x8112}, /* Some kind of reset */
@@ -247,44 +156,26 @@ static const __u16 spca561_init_data[][2] = {
{0x0001, 0x8118}, /* Conf sensor */
{0x0092, 0x8804}, /* I know nothing about these */
{0x0010, 0x8802}, /* 0x88xx registers, so I won't */
- /***************/
{0x000d, 0x8805}, /* sensor default setting */
- {0x0001, 0x8801}, /* 1 <- 0x0d */
- {0x0000, 0x8800},
- {0x0018, 0x8805},
- {0x0002, 0x8801}, /* 2 <- 0x18 */
- {0x0000, 0x8800},
- {0x0065, 0x8805},
- {0x0004, 0x8801}, /* 4 <- 0x01 0x65 */
- {0x0001, 0x8800},
- {0x0021, 0x8805},
- {0x0005, 0x8801}, /* 5 <- 0x21 */
- {0x0000, 0x8800},
- {0x00aa, 0x8805},
- {0x0007, 0x8801}, /* 7 <- 0xaa */
- {0x0000, 0x8800},
- {0x0004, 0x8805},
- {0x0020, 0x8801}, /* 0x20 <- 0x15 0x04 */
- {0x0015, 0x8800},
- {0x0002, 0x8805},
- {0x0039, 0x8801}, /* 0x39 <- 0x02 */
- {0x0000, 0x8800},
- {0x0010, 0x8805},
- {0x0035, 0x8801}, /* 0x35 <- 0x10 */
- {0x0000, 0x8800},
- {0x0049, 0x8805},
- {0x0009, 0x8801}, /* 0x09 <- 0x10 0x49 */
- {0x0010, 0x8800},
- {0x000b, 0x8805},
- {0x0028, 0x8801}, /* 0x28 <- 0x0b */
- {0x0000, 0x8800},
- {0x000f, 0x8805},
- {0x003b, 0x8801}, /* 0x3b <- 0x0f */
- {0x0000, 0x8800},
- {0x0000, 0x8805},
- {0x003c, 0x8801}, /* 0x3c <- 0x00 */
- {0x0000, 0x8800},
- /***************/
+ {}
+};
+static const __u16 rev72a_init_sensor1[][2] = {
+ /* ms-win values */
+ {0x0001, 0x0018}, /* 0x01 <- 0x0d */
+ {0x0002, 0x0065}, /* 0x02 <- 0x18 */
+ {0x0004, 0x0121}, /* 0x04 <- 0x0165 */
+ {0x0005, 0x00aa}, /* 0x05 <- 0x21 */
+ {0x0007, 0x0004}, /* 0x07 <- 0xaa */
+ {0x0020, 0x1502}, /* 0x20 <- 0x1504 */
+ {0x0039, 0x0010}, /* 0x39 <- 0x02 */
+ {0x0035, 0x0049}, /* 0x35 <- 0x10 */
+ {0x0009, 0x100b}, /* 0x09 <- 0x1049 */
+ {0x0028, 0x000f}, /* 0x28 <- 0x0b */
+ {0x003b, 0x003c}, /* 0x3b <- 0x0f */
+ {0x003c, 0x0000}, /* 0x3c <- 0x00 */
+ {}
+};
+static const __u16 rev72a_init_data2[][2] = {
{0x0018, 0x8601}, /* Pixel/line selection for color separation */
{0x0000, 0x8602}, /* Optical black level for user setting */
{0x0060, 0x8604}, /* Optical black horizontal offset */
@@ -309,10 +200,18 @@ static const __u16 spca561_init_data[][2] = {
{0x0004, 0x8612}, /* Gr offset for white balance */
{0x0007, 0x8613}, /* B offset for white balance */
{0x0000, 0x8614}, /* Gb offset for white balance */
+#if 1
+/* from ms-win */
+ {0x0035, 0x8651}, /* R gain for white balance */
+ {0x0040, 0x8652}, /* Gr gain for white balance */
+ {0x005f, 0x8653}, /* B gain for white balance */
+ {0x0040, 0x8654}, /* Gb gain for white balance */
+#else
{0x008c, 0x8651}, /* R gain for white balance */
{0x008c, 0x8652}, /* Gr gain for white balance */
{0x00b5, 0x8653}, /* B gain for white balance */
{0x008c, 0x8654}, /* Gb gain for white balance */
+#endif
{0x0002, 0x8502}, /* Maximum average bit rate stuff */
{0x0011, 0x8802},
@@ -324,29 +223,22 @@ static const __u16 spca561_init_data[][2] = {
{0x0002, 0x865b}, /* Horizontal offset for valid pixels */
{0x0003, 0x865c}, /* Vertical offset for valid lines */
- /***************//* sensor active */
- {0x0003, 0x8801}, /* 0x03 <- 0x01 0x21 //289 */
- {0x0021, 0x8805},
- {0x0001, 0x8800},
- {0x0004, 0x8801}, /* 0x04 <- 0x01 0x65 //357 */
- {0x0065, 0x8805},
- {0x0001, 0x8800},
- {0x0005, 0x8801}, /* 0x05 <- 0x2f */
- {0x002f, 0x8805},
- {0x0000, 0x8800},
- {0x0006, 0x8801}, /* 0x06 <- 0 */
- {0x0000, 0x8805},
- {0x0000, 0x8800},
- {0x000a, 0x8801}, /* 0x0a <- 2 */
- {0x0002, 0x8805},
- {0x0000, 0x8800},
- {0x0009, 0x8801}, /* 0x09 <- 0x1061 */
- {0x0061, 0x8805},
- {0x0010, 0x8800},
- {0x0035, 0x8801}, /* 0x35 <-0x14 */
- {0x0014, 0x8805},
- {0x0000, 0x8800},
+ {}
+};
+static const __u16 rev72a_init_sensor2[][2] = {
+ /* ms-win values */
+ {0x0003, 0x0121}, /* 0x03 <- 0x01 0x21 //289 */
+ {0x0004, 0x0165}, /* 0x04 <- 0x01 0x65 //357 */
+ {0x0005, 0x002f}, /* 0x05 <- 0x2f */
+ {0x0006, 0x0000}, /* 0x06 <- 0 */
+ {0x000a, 0x0002}, /* 0x0a <- 2 */
+ {0x0009, 0x1061}, /* 0x09 <- 0x1061 */
+ {0x0035, 0x0014}, /* 0x35 <- 0x14 */
+ {}
+};
+static const __u16 rev72a_init_data3[][2] = {
{0x0030, 0x8112}, /* ISO and drop packet enable */
+/*fixme: should stop here*/
{0x0000, 0x8112}, /* Some kind of reset ???? */
{0x0009, 0x8118}, /* Enable sensor and set standby */
{0x0000, 0x8114}, /* Software GPIO output data */
@@ -434,21 +326,6 @@ static const __u16 spca561_init_data[][2] = {
{}
};
-#if 0
-static void sensor_reset(struct gspca_dev *gspca_dev)
-{
- reg_w_val(gspca_dev->dev, 0x8631, 0xc8);
- reg_w_val(gspca_dev->dev, 0x8634, 0xc8);
- reg_w_val(gspca_dev->dev, 0x8112, 0x00);
- reg_w_val(gspca_dev->dev, 0x8114, 0x00);
- reg_w_val(gspca_dev->dev, 0x8118, 0x21);
- reg_w_val(gspca_dev->dev, 0x8804, 0x92); /* i2c init */
- reg_w_val(gspca_dev->dev, 0x8802, 0x14);
- i2c_write(gspca_dev, 0x0001, 0x0d);
- i2c_write(gspca_dev, 0x0000, 0x0d);
-}
-#endif
-
/******************** QC Express etch2 stuff ********************/
static const __u16 Pb100_1map8300[][2] = {
/* reg, value */
@@ -529,22 +406,112 @@ static const __u16 spca561_161rev12A_data2[][2] = {
{}
};
-static void sensor_mapwrite(struct gspca_dev *gspca_dev,
- const __u16 sensormap[][2])
+static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
+{
+ int ret;
+
+ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 0, /* request */
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, NULL, 0, 500);
+ PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
+ if (ret < 0)
+ PDEBUG(D_ERR, "reg write: error %d", ret);
+}
+
+static void write_vector(struct gspca_dev *gspca_dev,
+ const __u16 data[][2])
{
- int i = 0;
- __u8 usbval[2];
+ struct usb_device *dev = gspca_dev->dev;
+ int i;
- while (sensormap[i][0]) {
- usbval[0] = sensormap[i][1];
- usbval[1] = sensormap[i][1] >> 8;
- reg_w_buf(gspca_dev, sensormap[i][0], usbval, 2);
+ i = 0;
+ while (data[i][1] != 0) {
+ reg_w_val(dev, data[i][1], data[i][0]);
i++;
}
}
+
+/* read 'len' bytes to gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+ __u16 index, __u16 length)
+{
+ usb_control_msg(gspca_dev->dev,
+ usb_rcvctrlpipe(gspca_dev->dev, 0),
+ 0, /* request */
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, /* value */
+ index, gspca_dev->usb_buf, length, 500);
+}
+
+/* write 'len' bytes from gspca_dev->usb_buf */
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+ __u16 index, __u16 len)
+{
+ usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ 0, /* request */
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, /* value */
+ index, gspca_dev->usb_buf, len, 500);
+}
+
+static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
+{
+ int retry = 60;
+
+ reg_w_val(gspca_dev->dev, 0x8801, reg);
+ reg_w_val(gspca_dev->dev, 0x8805, value);
+ reg_w_val(gspca_dev->dev, 0x8800, value >> 8);
+ do {
+ reg_r(gspca_dev, 0x8803, 1);
+ if (!gspca_dev->usb_buf[0])
+ return;
+ } while (--retry);
+}
+
+static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
+{
+ int retry = 60;
+ __u8 value;
+
+ reg_w_val(gspca_dev->dev, 0x8804, 0x92);
+ reg_w_val(gspca_dev->dev, 0x8801, reg);
+ reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01);
+ do {
+ reg_r(gspca_dev, 0x8803, 1);
+ if (!gspca_dev->usb_buf[0]) {
+ reg_r(gspca_dev, 0x8800, 1);
+ value = gspca_dev->usb_buf[0];
+ reg_r(gspca_dev, 0x8805, 1);
+ return ((int) value << 8) | gspca_dev->usb_buf[0];
+ }
+ } while (--retry);
+ return -1;
+}
+
+static void sensor_mapwrite(struct gspca_dev *gspca_dev,
+ const __u16 (*sensormap)[2])
+{
+ while ((*sensormap)[0]) {
+ gspca_dev->usb_buf[0] = (*sensormap)[1];
+ gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;
+ reg_w_buf(gspca_dev, (*sensormap)[0], 2);
+ sensormap++;
+ }
+}
+
+static void write_sensor_72a(struct gspca_dev *gspca_dev,
+ const __u16 (*sensor)[2])
+{
+ while ((*sensor)[0]) {
+ i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);
+ sensor++;
+ }
+}
+
static void init_161rev12A(struct gspca_dev *gspca_dev)
{
-/* sensor_reset(gspca_dev); (not in win) */
write_vector(gspca_dev, spca561_161rev12A_data1);
sensor_mapwrite(gspca_dev, Pb100_1map8300);
/*fixme: should be in sd_start*/
@@ -612,49 +579,68 @@ static int sd_init_12a(struct gspca_dev *gspca_dev)
static int sd_init_72a(struct gspca_dev *gspca_dev)
{
PDEBUG(D_STREAM, "Chip revision: 072a");
- write_vector(gspca_dev, spca561_init_data);
+ write_vector(gspca_dev, rev72a_init_data1);
+ write_sensor_72a(gspca_dev, rev72a_init_sensor1);
+ write_vector(gspca_dev, rev72a_init_data2);
+ write_sensor_72a(gspca_dev, rev72a_init_sensor2);
+ write_vector(gspca_dev, rev72a_init_data3);
return 0;
}
-static void setcontrast(struct gspca_dev *gspca_dev)
+/* rev 72a only */
+static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
- __u8 lowb;
+ __u8 value;
- switch (sd->chip_revision) {
- case Rev072A:
- lowb = sd->contrast >> 8;
- reg_w_val(dev, 0x8651, lowb);
- reg_w_val(dev, 0x8652, lowb);
- reg_w_val(dev, 0x8653, lowb);
- reg_w_val(dev, 0x8654, lowb);
- break;
- default: {
-/* case Rev012A: { */
- static const __u8 Reg8391[] =
- { 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 };
+ value = sd->brightness;
- reg_w_buf(gspca_dev, 0x8391, Reg8391, 8);
- reg_w_buf(gspca_dev, 0x8390, Reg8391, 8);
- break;
- }
- }
+ /* offsets for white balance */
+ reg_w_val(dev, 0x8611, value); /* R */
+ reg_w_val(dev, 0x8612, value); /* Gr */
+ reg_w_val(dev, 0x8613, value); /* B */
+ reg_w_val(dev, 0x8614, value); /* Gb */
}
-/* rev12a only */
static void setwhite(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
__u16 white;
- __u8 reg8614, reg8616;
+ __u8 blue, red;
+ __u16 reg;
- white = sd->white;
/* try to emulate MS-win as possible */
- reg8616 = 0x90 - white * 5 / 8;
- reg_w_val(gspca_dev->dev, 0x8616, reg8616);
- reg8614 = 0x20 + white * 3 / 8;
- reg_w_val(gspca_dev->dev, 0x8614, reg8614);
+ white = sd->white;
+ red = 0x20 + white * 3 / 8;
+ blue = 0x90 - white * 5 / 8;
+ if (sd->chip_revision == Rev012A) {
+ reg = 0x8614;
+ } else {
+ reg = 0x8651;
+ red += sd->contrast - 0x20;
+ blue += sd->contrast - 0x20;
+ }
+ reg_w_val(gspca_dev->dev, reg, red);
+ reg_w_val(gspca_dev->dev, reg + 2, blue);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ __u8 value;
+
+ if (sd->chip_revision != Rev072A)
+ return;
+ value = sd->contrast + 0x20;
+
+ /* gains for white balance */
+ setwhite(gspca_dev);
+/* reg_w_val(dev, 0x8651, value); * R - done by setwhite */
+ reg_w_val(dev, 0x8652, value); /* Gr */
+/* reg_w_val(dev, 0x8653, value); * B - done by setwhite */
+ reg_w_val(dev, 0x8654, value); /* Gb */
}
/* rev 12a only */
@@ -663,7 +649,6 @@ static void setexposure(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
int expo;
int clock_divider;
- __u8 data[2];
/* Register 0x8309 controls exposure for the spca561,
the basic exposure setting goes from 1-2047, where 1 is completely
@@ -687,20 +672,19 @@ static void setexposure(struct gspca_dev *gspca_dev)
clock_divider = 3;
}
expo |= clock_divider << 11;
- data[0] = expo;
- data[1] = expo >> 8;
- reg_w_buf(gspca_dev, 0x8309, data, 2);
+ gspca_dev->usb_buf[0] = expo;
+ gspca_dev->usb_buf[1] = expo >> 8;
+ reg_w_buf(gspca_dev, 0x8309, 2);
}
/* rev 12a only */
static void setgain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- __u8 data[2];
- data[0] = sd->gain;
- data[1] = 0;
- reg_w_buf(gspca_dev, 0x8335, data, 2);
+ gspca_dev->usb_buf[0] = sd->gain;
+ gspca_dev->usb_buf[1] = 0;
+ reg_w_buf(gspca_dev, 0x8335, 2);
}
static void setautogain(struct gspca_dev *gspca_dev)
@@ -716,9 +700,9 @@ static void setautogain(struct gspca_dev *gspca_dev)
static int sd_start_12a(struct gspca_dev *gspca_dev)
{
struct usb_device *dev = gspca_dev->dev;
- int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */
- __u8 Reg8307[] = { 0xaa, 0x00 };
int mode;
+ static const __u8 Reg8391[8] =
+ {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
if (mode <= 1) {
@@ -730,14 +714,21 @@ static int sd_start_12a(struct gspca_dev *gspca_dev)
* is sufficient to push raw frames at ~20fps */
reg_w_val(dev, 0x8500, mode);
} /* -- qq@kuku.eu.org */
- reg_w_buf(gspca_dev, 0x8307, Reg8307, 2);
- reg_w_val(gspca_dev->dev, 0x8700, Clck);
+
+ gspca_dev->usb_buf[0] = 0xaa;
+ gspca_dev->usb_buf[1] = 0x00;
+ reg_w_buf(gspca_dev, 0x8307, 2);
+ /* clock - lower 0x8X values lead to fps > 30 */
+ reg_w_val(gspca_dev->dev, 0x8700, 0x8a);
/* 0x8f 0x85 0x27 clock */
reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
reg_w_val(gspca_dev->dev, 0x850b, 0x03);
- setcontrast(gspca_dev);
+ memcpy(gspca_dev->usb_buf, Reg8391, 8);
+ reg_w_buf(gspca_dev, 0x8391, 8);
+ reg_w_buf(gspca_dev, 0x8390, 8);
setwhite(gspca_dev);
setautogain(gspca_dev);
+/* setgain(gspca_dev); */
setexposure(gspca_dev);
return 0;
}
@@ -764,6 +755,9 @@ static int sd_start_72a(struct gspca_dev *gspca_dev)
reg_w_val(dev, 0x8500, mode); /* mode */
reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
reg_w_val(dev, 0x8112, 0x10 | 0x20);
+ setcontrast(gspca_dev);
+/* setbrightness(gspca_dev); * fixme: bad values */
+ setwhite(gspca_dev);
setautogain(gspca_dev);
return 0;
}
@@ -805,7 +799,6 @@ static void do_autogain(struct gspca_dev *gspca_dev)
__u8 luma_mean = 110;
__u8 luma_delta = 20;
__u8 spring = 4;
- __u8 reg8339[2];
if (sd->ag_cnt < 0)
return;
@@ -848,13 +841,13 @@ static void do_autogain(struct gspca_dev *gspca_dev)
if (gainG > 0x3f)
gainG = 0x3f;
- else if (gainG < 4)
+ else if (gainG < 3)
gainG = 3;
i2c_write(gspca_dev, gainG, 0x35);
- if (expotimes >= 0x0256)
+ if (expotimes > 0x0256)
expotimes = 0x0256;
- else if (expotimes < 4)
+ else if (expotimes < 3)
expotimes = 3;
i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
}
@@ -862,13 +855,13 @@ static void do_autogain(struct gspca_dev *gspca_dev)
case Rev012A:
reg_r(gspca_dev, 0x8330, 2);
if (gspca_dev->usb_buf[1] > 0x08) {
- reg8339[0] = ++sd->expo12a;
- reg8339[1] = 0;
- reg_w_buf(gspca_dev, 0x8339, reg8339, 2);
+ gspca_dev->usb_buf[0] = ++sd->expo12a;
+ gspca_dev->usb_buf[1] = 0;
+ reg_w_buf(gspca_dev, 0x8339, 2);
} else if (gspca_dev->usb_buf[1] < 0x02) {
- reg8339[0] = --sd->expo12a;
- reg8339[1] = 0;
- reg_w_buf(gspca_dev, 0x8339, reg8339, 2);
+ gspca_dev->usb_buf[0] = --sd->expo12a;
+ gspca_dev->usb_buf[1] = 0;
+ reg_w_buf(gspca_dev, 0x8339, 2);
}
break;
}
@@ -881,8 +874,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
{
struct sd *sd = (struct sd *) gspca_dev;
- switch (data[0]) {
- case 0: /* start of frame */
+ switch (data[0]) { /* sequence number */
+ case 0: /* start of frame */
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
data, 0);
data += SPCA561_OFFSET_DATA;
@@ -904,8 +897,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
frame, data, len);
}
return;
- case 0xff: /* drop */
-/* gspca_dev->last_packet_type = DISCARD_PACKET; */
+ case 0xff: /* drop (empty mpackets) */
return;
}
data++;
@@ -914,55 +906,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
}
/* rev 72a only */
-static void setbrightness(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- __u8 value;
-
- value = sd->brightness;
- reg_w_val(gspca_dev->dev, 0x8611, value);
- reg_w_val(gspca_dev->dev, 0x8612, value);
- reg_w_val(gspca_dev->dev, 0x8613, value);
- reg_w_val(gspca_dev->dev, 0x8614, value);
-}
-
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- __u16 tot;
-
- tot = 0;
- reg_r(gspca_dev, 0x8611, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8612, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8613, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8614, 1);
- tot += gspca_dev->usb_buf[0];
- sd->brightness = tot >> 2;
-}
-
-/* rev72a only */
-static void getcontrast(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- __u16 tot;
-
- tot = 0;
- reg_r(gspca_dev, 0x8651, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8652, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8653, 1);
- tot += gspca_dev->usb_buf[0];
- reg_r(gspca_dev, 0x8654, 1);
- tot += gspca_dev->usb_buf[0];
- sd->contrast = tot << 6;
- PDEBUG(D_CONF, "get contrast %d", sd->contrast);
-}
-
-/* rev 72a only */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -977,7 +920,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- getbrightness(gspca_dev);
*val = sd->brightness;
return 0;
}
@@ -997,7 +939,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- getcontrast(gspca_dev);
*val = sd->contrast;
return 0;
}
@@ -1020,7 +961,6 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
-/* rev12a only */
static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -1135,6 +1075,19 @@ static struct ctrl sd_ctrls_12a[] = {
static struct ctrl sd_ctrls_72a[] = {
{
+ {
+ .id = V4L2_CID_DO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "White Balance",
+ .minimum = WHITE_MIN,
+ .maximum = WHITE_MAX,
+ .step = 1,
+ .default_value = WHITE_DEF,
+ },
+ .set = sd_setwhite,
+ .get = sd_getwhite,
+ },
+ {
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c
index d2d6ad9d1..452ca1d16 100644
--- a/linux/drivers/media/video/gspca/t613.c
+++ b/linux/drivers/media/video/gspca/t613.c
@@ -499,7 +499,7 @@ static void om6802_sensor_init(struct gspca_dev *gspca_dev)
reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
msleep(5);
i = 4;
- while (--i < 0) {
+ while (--i > 0) {
byte = reg_r(gspca_dev, 0x0060);
if (!(byte & 0x01))
break;
diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c
index 678070b93..13e34fc7b 100644
--- a/linux/drivers/media/video/gspca/zc3xx.c
+++ b/linux/drivers/media/video/gspca/zc3xx.c
@@ -7542,6 +7542,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0458, 0x700c)},
{USB_DEVICE(0x0458, 0x700f)},
{USB_DEVICE(0x0461, 0x0a00)},
+ {USB_DEVICE(0x046d, 0x089d), .driver_info = SENSOR_MC501CB},
{USB_DEVICE(0x046d, 0x08a0)},
{USB_DEVICE(0x046d, 0x08a1)},
{USB_DEVICE(0x046d, 0x08a2)},