summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/gspca
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-09-15 13:56:01 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-15 13:56:01 -0300
commit136a9b83fb4cb819c2f27cbb5948d26cec0e7934 (patch)
tree397919f977ae7937aa60a5001f62f0ba3faef2db /linux/drivers/media/video/gspca
parentfdafaa4f7e2ea516dbd7791f362f05273aaaa6cc (diff)
parentc5d1ee111d9e00f9ce75e48e5e3806fdcd681a83 (diff)
downloadmediapointer-dvb-s2-136a9b83fb4cb819c2f27cbb5948d26cec0e7934.tar.gz
mediapointer-dvb-s2-136a9b83fb4cb819c2f27cbb5948d26cec0e7934.tar.bz2
merge: http://kernellabs.com/hg/~mkrufky/tda18271-merge
From: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux/drivers/media/video/gspca')
-rw-r--r--linux/drivers/media/video/gspca/Kconfig23
-rw-r--r--linux/drivers/media/video/gspca/Makefile2
-rw-r--r--linux/drivers/media/video/gspca/conex.c2
-rw-r--r--linux/drivers/media/video/gspca/etoms.c4
-rw-r--r--linux/drivers/media/video/gspca/gspca.c7
-rw-r--r--linux/drivers/media/video/gspca/jeilinj.c388
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c4
-rw-r--r--linux/drivers/media/video/gspca/mr97310a.c853
-rw-r--r--linux/drivers/media/video/gspca/pac207.c37
-rw-r--r--linux/drivers/media/video/gspca/pac7311.c1
-rw-r--r--linux/drivers/media/video/gspca/sn9c20x.c197
-rw-r--r--linux/drivers/media/video/gspca/sonixj.c24
-rw-r--r--linux/drivers/media/video/gspca/spca501.c2
-rw-r--r--linux/drivers/media/video/gspca/spca506.c2
-rw-r--r--linux/drivers/media/video/gspca/stv06xx/stv06xx.c4
-rw-r--r--linux/drivers/media/video/gspca/sunplus.c380
-rw-r--r--linux/drivers/media/video/gspca/vc032x.c272
-rw-r--r--linux/drivers/media/video/gspca/zc3xx.c2
18 files changed, 1666 insertions, 538 deletions
diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig
index 34f46f2bc..8897283b0 100644
--- a/linux/drivers/media/video/gspca/Kconfig
+++ b/linux/drivers/media/video/gspca/Kconfig
@@ -47,6 +47,15 @@ config USB_GSPCA_FINEPIX
To compile this driver as a module, choose M here: the
module will be called gspca_finepix.
+config USB_GSPCA_JEILINJ
+ tristate "Jeilin JPEG USB V4L2 driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on this Jeilin chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_jeilinj.
+
config USB_GSPCA_MARS
tristate "Mars USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
@@ -103,9 +112,9 @@ config USB_GSPCA_PAC7311
module will be called gspca_pac7311.
config USB_GSPCA_SN9C20X
- tristate "SN9C20X USB Camera Driver"
- depends on VIDEO_V4L2 && USB_GSPCA
- help
+ tristate "SN9C20X USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
Say Y here if you want support for cameras based on the
sn9c20x chips (SN9C201 and SN9C202).
@@ -113,10 +122,10 @@ config USB_GSPCA_SN9C20X
module will be called gspca_sn9c20x.
config USB_GSPCA_SN9C20X_EVDEV
- bool "Enable evdev support"
- depends on USB_GSPCA_SN9C20X
- ---help---
- Say Y here in order to enable evdev support for sn9c20x webcam button.
+ bool "Enable evdev support"
+ depends on USB_GSPCA_SN9C20X && INPUT
+ ---help---
+ Say Y here in order to enable evdev support for sn9c20x webcam button.
config USB_GSPCA_SONIXB
tristate "SONIX Bayer USB Camera Driver"
diff --git a/linux/drivers/media/video/gspca/Makefile b/linux/drivers/media/video/gspca/Makefile
index f6d3b86e9..035616b5e 100644
--- a/linux/drivers/media/video/gspca/Makefile
+++ b/linux/drivers/media/video/gspca/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_USB_GSPCA) += gspca_main.o
obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o
obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o
obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o
+obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o
obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o
obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o
@@ -30,6 +31,7 @@ gspca_main-objs := gspca.o
gspca_conex-objs := conex.o
gspca_etoms-objs := etoms.o
gspca_finepix-objs := finepix.o
+gspca_jeilinj-objs := jeilinj.o
gspca_mars-objs := mars.o
gspca_mr97310a-objs := mr97310a.o
gspca_ov519-objs := ov519.o
diff --git a/linux/drivers/media/video/gspca/conex.c b/linux/drivers/media/video/gspca/conex.c
index 8d48ea174..eca003566 100644
--- a/linux/drivers/media/video/gspca/conex.c
+++ b/linux/drivers/media/video/gspca/conex.c
@@ -820,7 +820,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam = &gspca_dev->cam;
cam->cam_mode = vga_mode;
- cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ cam->nmodes = ARRAY_SIZE(vga_mode);
sd->brightness = BRIGHTNESS_DEF;
sd->contrast = CONTRAST_DEF;
diff --git a/linux/drivers/media/video/gspca/etoms.c b/linux/drivers/media/video/gspca/etoms.c
index 84f3a5eb8..42b36b8b7 100644
--- a/linux/drivers/media/video/gspca/etoms.c
+++ b/linux/drivers/media/video/gspca/etoms.c
@@ -635,10 +635,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->sensor = id->driver_info;
if (sd->sensor == SENSOR_PAS106) {
cam->cam_mode = sif_mode;
- cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
+ cam->nmodes = ARRAY_SIZE(sif_mode);
} else {
cam->cam_mode = vga_mode;
- cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ cam->nmodes = ARRAY_SIZE(vga_mode);
gspca_dev->ctrl_dis = (1 << COLOR_IDX);
}
sd->brightness = BRIGHTNESS_DEF;
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index 2e5197073..670091e42 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -1504,12 +1504,6 @@ static int vidioc_s_parm(struct file *filp, void *priv,
return 0;
}
-static int vidioc_s_std(struct file *filp, void *priv,
- v4l2_std_id *parm)
-{
- return 0;
-}
-
#ifdef CONFIG_VIDEO_V4L1_COMPAT
static int vidiocgmbuf(struct file *file, void *priv,
struct video_mbuf *mbuf)
@@ -1980,7 +1974,6 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = {
.vidioc_s_jpegcomp = vidioc_s_jpegcomp,
.vidioc_g_parm = vidioc_g_parm,
.vidioc_s_parm = vidioc_s_parm,
- .vidioc_s_std = vidioc_s_std,
.vidioc_enum_framesizes = vidioc_enum_framesizes,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.vidioc_g_register = vidioc_g_register,
diff --git a/linux/drivers/media/video/gspca/jeilinj.c b/linux/drivers/media/video/gspca/jeilinj.c
new file mode 100644
index 000000000..dbfa3ed6e
--- /dev/null
+++ b/linux/drivers/media/video/gspca/jeilinj.c
@@ -0,0 +1,388 @@
+/*
+ * Jeilinj subdriver
+ *
+ * Supports some Jeilin dual-mode cameras which use bulk transport and
+ * download raw JPEG data.
+ *
+ * Copyright (C) 2009 Theodore Kilgore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define MODULE_NAME "jeilinj"
+
+#include <linux/workqueue.h>
+#include "gspca.h"
+#include "jpeg.h"
+
+MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define JEILINJ_CMD_TIMEOUT 500
+#define JEILINJ_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define JEILINJ_MAX_TRANSFER 0x200
+
+#define FRAME_HEADER_LEN 0x10
+
+/* Structure to hold all of our device specific stuff */
+struct sd {
+ struct gspca_dev gspca_dev; /* !! must be the first item */
+ const struct v4l2_pix_format *cap_mode;
+ /* Driver stuff */
+ struct work_struct work_struct;
+ struct workqueue_struct *work_thread;
+ u8 quality; /* image quality */
+ u8 jpegqual; /* webcam quality */
+ u8 *jpeg_hdr;
+};
+
+ struct jlj_command {
+ unsigned char instruction[2];
+ unsigned char ack_wanted;
+ };
+
+/* AFAICT these cameras will only do 320x240. */
+static struct v4l2_pix_format jlj_mode[] = {
+ { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 0}
+};
+
+/*
+ * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
+ * and 0x82 for bulk transfer.
+ */
+
+/* All commands are two bytes only */
+static int jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
+{
+ int retval;
+
+ memcpy(gspca_dev->usb_buf, command, 2);
+ retval = usb_bulk_msg(gspca_dev->dev,
+ usb_sndbulkpipe(gspca_dev->dev, 3),
+ gspca_dev->usb_buf, 2, NULL, 500);
+ if (retval < 0)
+ PDEBUG(D_ERR, "command write [%02x] error %d",
+ gspca_dev->usb_buf[0], retval);
+ return retval;
+}
+
+/* Responses are one byte only */
+static int jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
+{
+ int retval;
+
+ retval = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x84),
+ gspca_dev->usb_buf, 1, NULL, 500);
+ response = gspca_dev->usb_buf[0];
+ if (retval < 0)
+ PDEBUG(D_ERR, "read command [%02x] error %d",
+ gspca_dev->usb_buf[0], retval);
+ return retval;
+}
+
+static int jlj_start(struct gspca_dev *gspca_dev)
+{
+ int i;
+ int retval = -1;
+ u8 response = 0xff;
+ struct jlj_command start_commands[] = {
+ {{0x71, 0x81}, 0},
+ {{0x70, 0x05}, 0},
+ {{0x95, 0x70}, 1},
+ {{0x71, 0x81}, 0},
+ {{0x70, 0x04}, 0},
+ {{0x95, 0x70}, 1},
+ {{0x71, 0x00}, 0},
+ {{0x70, 0x08}, 0},
+ {{0x95, 0x70}, 1},
+ {{0x94, 0x02}, 0},
+ {{0xde, 0x24}, 0},
+ {{0x94, 0x02}, 0},
+ {{0xdd, 0xf0}, 0},
+ {{0x94, 0x02}, 0},
+ {{0xe3, 0x2c}, 0},
+ {{0x94, 0x02}, 0},
+ {{0xe4, 0x00}, 0},
+ {{0x94, 0x02}, 0},
+ {{0xe5, 0x00}, 0},
+ {{0x94, 0x02}, 0},
+ {{0xe6, 0x2c}, 0},
+ {{0x94, 0x03}, 0},
+ {{0xaa, 0x00}, 0},
+ {{0x71, 0x1e}, 0},
+ {{0x70, 0x06}, 0},
+ {{0x71, 0x80}, 0},
+ {{0x70, 0x07}, 0}
+ };
+ for (i = 0; i < ARRAY_SIZE(start_commands); i++) {
+ retval = jlj_write2(gspca_dev, start_commands[i].instruction);
+ if (retval < 0)
+ return retval;
+ if (start_commands[i].ack_wanted)
+ retval = jlj_read1(gspca_dev, response);
+ if (retval < 0)
+ return retval;
+ }
+ PDEBUG(D_ERR, "jlj_start retval is %d", retval);
+ return retval;
+}
+
+static int jlj_stop(struct gspca_dev *gspca_dev)
+{
+ int i;
+ int retval;
+ struct jlj_command stop_commands[] = {
+ {{0x71, 0x00}, 0},
+ {{0x70, 0x09}, 0},
+ {{0x71, 0x80}, 0},
+ {{0x70, 0x05}, 0}
+ };
+ for (i = 0; i < ARRAY_SIZE(stop_commands); i++) {
+ retval = jlj_write2(gspca_dev, stop_commands[i].instruction);
+ if (retval < 0)
+ return retval;
+ }
+ return retval;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface the gspca usb_lock is
+ * used when performing the one USB control operation inside the workqueue,
+ * which tells the camera to close the stream. In practice the only thing
+ * which needs to be protected against is the usb_set_interface call that
+ * gspca makes during stream_off. Otherwise the camera doesn't provide any
+ * controls that the user could try to change.
+ */
+
+static void jlj_dostream(struct work_struct *work)
+{
+ struct sd *dev = container_of(work, struct sd, work_struct);
+ struct gspca_dev *gspca_dev = &dev->gspca_dev;
+ struct gspca_frame *frame;
+ int blocks_left; /* 0x200-sized blocks remaining in current frame. */
+ int size_in_blocks;
+ int act_len;
+ int discarding = 0; /* true if we failed to get space for frame. */
+ int packet_type;
+ int ret;
+ u8 *buffer;
+
+ buffer = kmalloc(JEILINJ_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+ if (!buffer) {
+ PDEBUG(D_ERR, "Couldn't allocate USB buffer");
+ goto quit_stream;
+ }
+ while (gspca_dev->present && gspca_dev->streaming) {
+ if (!gspca_dev->present)
+ goto quit_stream;
+ /* Start a new frame, and add the JPEG header, first thing */
+ frame = gspca_get_i_frame(gspca_dev);
+ if (frame && !discarding)
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+ dev->jpeg_hdr, JPEG_HDR_SZ);
+ else
+ discarding = 1;
+ /*
+ * Now request data block 0. Line 0 reports the size
+ * to download, in blocks of size 0x200, and also tells the
+ * "actual" data size, in bytes, which seems best to ignore.
+ */
+ ret = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x82),
+ buffer, JEILINJ_MAX_TRANSFER, &act_len,
+ JEILINJ_DATA_TIMEOUT);
+ PDEBUG(D_STREAM,
+ "Got %d bytes out of %d for Block 0",
+ act_len, JEILINJ_MAX_TRANSFER);
+ if (ret < 0 || act_len < FRAME_HEADER_LEN)
+ goto quit_stream;
+ size_in_blocks = buffer[0x0a];
+ blocks_left = buffer[0x0a] - 1;
+ PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left);
+ packet_type = INTER_PACKET;
+ if (frame && !discarding)
+ /* Toss line 0 of data block 0, keep the rest. */
+ gspca_frame_add(gspca_dev, packet_type,
+ frame, buffer + FRAME_HEADER_LEN,
+ JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);
+ else
+ discarding = 1;
+ while (blocks_left > 0) {
+ if (!gspca_dev->present)
+ goto quit_stream;
+ ret = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x82),
+ buffer, JEILINJ_MAX_TRANSFER, &act_len,
+ JEILINJ_DATA_TIMEOUT);
+ if (ret < 0 || act_len < JEILINJ_MAX_TRANSFER)
+ goto quit_stream;
+ PDEBUG(D_STREAM,
+ "%d blocks remaining for frame", blocks_left);
+ blocks_left -= 1;
+ if (blocks_left == 0)
+ packet_type = LAST_PACKET;
+ else
+ packet_type = INTER_PACKET;
+ if (frame && !discarding)
+ gspca_frame_add(gspca_dev, packet_type,
+ frame, buffer,
+ JEILINJ_MAX_TRANSFER);
+ else
+ discarding = 1;
+ }
+ }
+quit_stream:
+ mutex_lock(&gspca_dev->usb_lock);
+ if (gspca_dev->present)
+ jlj_stop(gspca_dev);
+ mutex_unlock(&gspca_dev->usb_lock);
+ kfree(buffer);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id)
+{
+ struct cam *cam = &gspca_dev->cam;
+ struct sd *dev = (struct sd *) gspca_dev;
+
+ dev->quality = 85;
+ dev->jpegqual = 85;
+ PDEBUG(D_PROBE,
+ "JEILINJ camera detected"
+ " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ cam->cam_mode = jlj_mode;
+ cam->nmodes = 1;
+ cam->bulk = 1;
+ /* We don't use the buffer gspca allocates so make it small. */
+ cam->bulk_size = 32;
+ INIT_WORK(&dev->work_struct, jlj_dostream);
+ return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+ struct sd *dev = (struct sd *) gspca_dev;
+
+ /* wait for the work queue to terminate */
+ mutex_unlock(&gspca_dev->usb_lock);
+ /* This waits for jlj_dostream to finish */
+ destroy_workqueue(dev->work_thread);
+ dev->work_thread = NULL;
+ mutex_lock(&gspca_dev->usb_lock);
+ kfree(dev->jpeg_hdr);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+ return 0;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+ struct sd *dev = (struct sd *) gspca_dev;
+ int ret;
+
+ /* create the JPEG header */
+ dev->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+ jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ 0x21); /* JPEG 422 */
+ jpeg_set_qual(dev->jpeg_hdr, dev->quality);
+ PDEBUG(D_STREAM, "Start streaming at 320x240");
+ ret = jlj_start(gspca_dev);
+ if (ret < 0) {
+ PDEBUG(D_ERR, "Start streaming command failed");
+ return ret;
+ }
+ /* Start the workqueue function to do the streaming */
+ dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
+ queue_work(dev->work_thread, &dev->work_struct);
+
+ return 0;
+}
+
+/* Table of supported USB devices */
+static const __devinitdata struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x0979, 0x0280)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+ .name = MODULE_NAME,
+ .config = sd_config,
+ .init = sd_init,
+ .start = sd_start,
+ .stop0 = sd_stop0,
+};
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return gspca_dev_probe(intf, id,
+ &sd_desc,
+ sizeof(struct sd),
+ THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+ .name = MODULE_NAME,
+ .id_table = device_table,
+ .probe = sd_probe,
+ .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+ int ret;
+
+ ret = usb_register(&sd_driver);
+ if (ret < 0)
+ return ret;
+ PDEBUG(D_PROBE, "registered");
+ return 0;
+}
+
+static void __exit sd_mod_exit(void)
+{
+ usb_deregister(&sd_driver);
+ PDEBUG(D_PROBE, "deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c
index 7127321ac..6b89f33a4 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c
+++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -178,8 +178,10 @@ sensor_found:
sens_priv->settings =
kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
- if (!sens_priv->settings)
+ if (!sens_priv->settings) {
+ kfree(sens_priv);
return -ENOMEM;
+ }
sd->gspca_dev.cam.cam_mode = s5k83a_modes;
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c
index 301325134..140c8f320 100644
--- a/linux/drivers/media/video/gspca/mr97310a.c
+++ b/linux/drivers/media/video/gspca/mr97310a.c
@@ -3,6 +3,21 @@
*
* Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com>
*
+ * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+
+ * and for the routines for detecting and classifying these various cameras,
+ *
+ * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
+ *
+ * Acknowledgements:
+ *
+ * The MR97311A support in gspca/mars.c has been helpful in understanding some
+ * of the registers in these cameras.
+ *
+ * Hans de Goede <hdgoede@redhat.com> and
+ * Thomas Kaiser <thomas@kaiser-linux.li>
+ * have assisted with their experience. Each of them has also helped by
+ * testing a previously unsupported camera.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -22,18 +37,108 @@
#include "gspca.h"
-MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>");
+#define CAM_TYPE_CIF 0
+#define CAM_TYPE_VGA 1
+
+#define MR97310A_BRIGHTNESS_MIN -254
+#define MR97310A_BRIGHTNESS_MAX 255
+#define MR97310A_BRIGHTNESS_DEFAULT 0
+
+#define MR97310A_EXPOSURE_MIN 300
+#define MR97310A_EXPOSURE_MAX 4095
+#define MR97310A_EXPOSURE_DEFAULT 1000
+
+#define MR97310A_GAIN_MIN 0
+#define MR97310A_GAIN_MAX 31
+#define MR97310A_GAIN_DEFAULT 25
+
+MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,"
+ "Theodore Kilgore <kilgota@auburn.edu>");
MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
MODULE_LICENSE("GPL");
+/* global parameters */
+int force_sensor_type = -1;
+module_param(force_sensor_type, int, 0644);
+MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");
+
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
u8 sof_read;
+ u8 cam_type; /* 0 is CIF and 1 is VGA */
+ u8 sensor_type; /* We use 0 and 1 here, too. */
+ u8 do_lcd_stop;
+
+ int brightness;
+ u16 exposure;
+ u8 gain;
+};
+
+struct sensor_w_data {
+ u8 reg;
+ u8 flags;
+ u8 data[16];
+ int len;
};
+static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
+static void setbrightness(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
+static void setgain(struct gspca_dev *gspca_dev);
+
/* V4L2 controls supported by the driver */
static struct ctrl sd_ctrls[] = {
+ {
+#define BRIGHTNESS_IDX 0
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = MR97310A_BRIGHTNESS_MIN,
+ .maximum = MR97310A_BRIGHTNESS_MAX,
+ .step = 1,
+ .default_value = MR97310A_BRIGHTNESS_DEFAULT,
+ .flags = 0,
+ },
+ .set = sd_setbrightness,
+ .get = sd_getbrightness,
+ },
+ {
+#define EXPOSURE_IDX 1
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure",
+ .minimum = MR97310A_EXPOSURE_MIN,
+ .maximum = MR97310A_EXPOSURE_MAX,
+ .step = 1,
+ .default_value = MR97310A_EXPOSURE_DEFAULT,
+ .flags = 0,
+ },
+ .set = sd_setexposure,
+ .get = sd_getexposure,
+ },
+ {
+#define GAIN_IDX 2
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = MR97310A_GAIN_MIN,
+ .maximum = MR97310A_GAIN_MAX,
+ .step = 1,
+ .default_value = MR97310A_GAIN_DEFAULT,
+ .flags = 0,
+ },
+ .set = sd_setgain,
+ .get = sd_getgain,
+ },
};
static const struct v4l2_pix_format vga_mode[] = {
@@ -65,7 +170,7 @@ static const struct v4l2_pix_format vga_mode[] = {
};
/* the bytes to write are in gspca_dev->usb_buf */
-static int reg_w(struct gspca_dev *gspca_dev, int len)
+static int mr_write(struct gspca_dev *gspca_dev, int len)
{
int rc;
@@ -78,15 +183,249 @@ static int reg_w(struct gspca_dev *gspca_dev, int len)
return rc;
}
+/* the bytes are read into gspca_dev->usb_buf */
+static int mr_read(struct gspca_dev *gspca_dev, int len)
+{
+ int rc;
+
+ rc = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 3),
+ gspca_dev->usb_buf, len, NULL, 500);
+ if (rc < 0)
+ PDEBUG(D_ERR, "reg read [%02x] error %d",
+ gspca_dev->usb_buf[0], rc);
+ return rc;
+}
+
+static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,
+ const u8 *data, int len)
+{
+ gspca_dev->usb_buf[0] = 0x1f;
+ gspca_dev->usb_buf[1] = flags;
+ gspca_dev->usb_buf[2] = reg;
+ memcpy(gspca_dev->usb_buf + 3, data, len);
+
+ return mr_write(gspca_dev, len + 3);
+}
+
+static int sensor_write_regs(struct gspca_dev *gspca_dev,
+ const struct sensor_w_data *data, int len)
+{
+ int i, rc;
+
+ for (i = 0; i < len; i++) {
+ rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,
+ data[i].data, data[i].len);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 buf, confirm_reg;
+ int rc;
+
+ buf = data;
+ rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
+ if (rc < 0)
+ return rc;
+
+ buf = 0x01;
+ confirm_reg = sd->sensor_type ? 0x13 : 0x11;
+ rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int cam_get_response16(struct gspca_dev *gspca_dev)
+{
+ __u8 *data = gspca_dev->usb_buf;
+ int err_code;
+
+ data[0] = 0x21;
+ err_code = mr_write(gspca_dev, 1);
+ if (err_code < 0)
+ return err_code;
+
+ err_code = mr_read(gspca_dev, 16);
+ return err_code;
+}
+
+static int zero_the_pointer(struct gspca_dev *gspca_dev)
+{
+ __u8 *data = gspca_dev->usb_buf;
+ int err_code;
+ u8 status = 0;
+ int tries = 0;
+
+ err_code = cam_get_response16(gspca_dev);
+ if (err_code < 0)
+ return err_code;
+
+ err_code = mr_write(gspca_dev, 1);
+ data[0] = 0x19;
+ data[1] = 0x51;
+ err_code = mr_write(gspca_dev, 2);
+ if (err_code < 0)
+ return err_code;
+
+ err_code = cam_get_response16(gspca_dev);
+ if (err_code < 0)
+ return err_code;
+
+ data[0] = 0x19;
+ data[1] = 0xba;
+ err_code = mr_write(gspca_dev, 2);
+ if (err_code < 0)
+ return err_code;
+
+ err_code = cam_get_response16(gspca_dev);
+ if (err_code < 0)
+ return err_code;
+
+ data[0] = 0x19;
+ data[1] = 0x00;
+ err_code = mr_write(gspca_dev, 2);
+ if (err_code < 0)
+ return err_code;
+
+ err_code = cam_get_response16(gspca_dev);
+ if (err_code < 0)
+ return err_code;
+
+ data[0] = 0x19;
+ data[1] = 0x00;
+ err_code = mr_write(gspca_dev, 2);
+ if (err_code < 0)
+ return err_code;
+
+ while (status != 0x0a && tries < 256) {
+ err_code = cam_get_response16(gspca_dev);
+ status = data[0];
+ tries++;
+ if (err_code < 0)
+ return err_code;
+ }
+ if (status != 0x0a)
+ PDEBUG(D_ERR, "status is %02x", status);
+
+ tries = 0;
+ while (tries < 4) {
+ data[0] = 0x19;
+ data[1] = 0x00;
+ err_code = mr_write(gspca_dev, 2);
+ if (err_code < 0)
+ return err_code;
+
+ err_code = cam_get_response16(gspca_dev);
+ status = data[0];
+ tries++;
+ if (err_code < 0)
+ return err_code;
+ }
+
+ data[0] = 0x19;
+ err_code = mr_write(gspca_dev, 1);
+ if (err_code < 0)
+ return err_code;
+
+ err_code = mr_read(gspca_dev, 16);
+ if (err_code < 0)
+ return err_code;
+
+ return 0;
+}
+
+static u8 get_sensor_id(struct gspca_dev *gspca_dev)
+{
+ int err_code;
+
+ gspca_dev->usb_buf[0] = 0x1e;
+ err_code = mr_write(gspca_dev, 1);
+ if (err_code < 0)
+ return err_code;
+
+ err_code = mr_read(gspca_dev, 16);
+ if (err_code < 0)
+ return err_code;
+
+ PDEBUG(D_PROBE, "Byte zero reported is %01x", gspca_dev->usb_buf[0]);
+
+ return gspca_dev->usb_buf[0];
+}
+
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
+ struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
+ __u8 *data = gspca_dev->usb_buf;
+ int err_code;
cam = &gspca_dev->cam;
cam->cam_mode = vga_mode;
cam->nmodes = ARRAY_SIZE(vga_mode);
+
+ if (id->idProduct == 0x010e) {
+ sd->cam_type = CAM_TYPE_CIF;
+ cam->nmodes--;
+
+ data[0] = 0x01;
+ data[1] = 0x01;
+ err_code = mr_write(gspca_dev, 2);
+ if (err_code < 0)
+ return err_code;
+
+ msleep(200);
+ data[0] = get_sensor_id(gspca_dev);
+ /*
+ * Known CIF cameras. If you have another to report, please do
+ *
+ * Name byte just read sd->sensor_type
+ * reported by
+ * Sakar Spy-shot 0x28 T. Kilgore 0
+ * Innovage 0xf5 (unstable) T. Kilgore 0
+ * Vivitar Mini 0x53 H. De Goede 0
+ * Vivitar Mini 0x04 / 0x24 E. Rodriguez 0
+ * Vivitar Mini 0x08 T. Kilgore 1
+ * Elta-Media 8212dc 0x23 T. Kaiser 1
+ * Philips dig. keych. 0x37 T. Kilgore 1
+ */
+ if ((data[0] & 0x78) == 8 ||
+ ((data[0] & 0x2) == 0x2 && data[0] != 0x53))
+ sd->sensor_type = 1;
+ else
+ sd->sensor_type = 0;
+
+ PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d",
+ sd->sensor_type);
+
+ if (force_sensor_type != -1) {
+ sd->sensor_type = !! force_sensor_type;
+ PDEBUG(D_PROBE, "Forcing sensor type to: %d",
+ sd->sensor_type);
+ }
+
+ if (sd->sensor_type == 0)
+ gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX);
+ } else {
+ sd->cam_type = CAM_TYPE_VGA;
+ PDEBUG(D_PROBE, "MR97310A VGA camera detected");
+ gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) |
+ (1 << EXPOSURE_IDX) | (1 << GAIN_IDX);
+ }
+
+ sd->brightness = MR97310A_BRIGHTNESS_DEFAULT;
+ sd->exposure = MR97310A_EXPOSURE_DEFAULT;
+ sd->gain = MR97310A_GAIN_DEFAULT;
+
return 0;
}
@@ -96,183 +435,462 @@ static int sd_init(struct gspca_dev *gspca_dev)
return 0;
}
-static int sd_start(struct gspca_dev *gspca_dev)
+static int start_cif_cam(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
__u8 *data = gspca_dev->usb_buf;
int err_code;
-
- sd->sof_read = 0;
-
- /* Note: register descriptions guessed from MR97113A driver */
-
+ const __u8 startup_string[] = {
+ 0x00,
+ 0x0d,
+ 0x01,
+ 0x00, /* Hsize/8 for 352 or 320 */
+ 0x00, /* Vsize/4 for 288 or 240 */
+ 0x13, /* or 0xbb, depends on sensor */
+ 0x00, /* Hstart, depends on res. */
+ 0x00, /* reserved ? */
+ 0x00, /* Vstart, depends on res. and sensor */
+ 0x50, /* 0x54 to get 176 or 160 */
+ 0xc0
+ };
+
+ /* Note: Some of the above descriptions guessed from MR97113A driver */
data[0] = 0x01;
data[1] = 0x01;
- err_code = reg_w(gspca_dev, 2);
+ err_code = mr_write(gspca_dev, 2);
if (err_code < 0)
return err_code;
- data[0] = 0x00;
- data[1] = 0x0d;
- data[2] = 0x01;
- data[5] = 0x2b;
- data[7] = 0x00;
- data[9] = 0x50; /* reg 8, no scale down */
- data[10] = 0xc0;
+ memcpy(data, startup_string, 11);
+ if (sd->sensor_type)
+ data[5] = 0xbb;
switch (gspca_dev->width) {
case 160:
- data[9] |= 0x0c; /* reg 8, 4:1 scale down */
+ data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */
/* fall thru */
case 320:
- data[9] |= 0x04; /* reg 8, 2:1 scale down */
- /* fall thru */
- case 640:
default:
- data[3] = 0x50; /* reg 2, H size */
- data[4] = 0x78; /* reg 3, V size */
- data[6] = 0x04; /* reg 5, H start */
- data[8] = 0x03; /* reg 7, V start */
+ data[3] = 0x28; /* reg 2, H size/8 */
+ data[4] = 0x3c; /* reg 3, V size/4 */
+ data[6] = 0x14; /* reg 5, H start */
+ data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */
break;
-
case 176:
- data[9] |= 0x04; /* reg 8, 2:1 scale down */
+ data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */
/* fall thru */
case 352:
- data[3] = 0x2c; /* reg 2, H size */
- data[4] = 0x48; /* reg 3, V size */
- data[6] = 0x94; /* reg 5, H start */
- data[8] = 0x63; /* reg 7, V start */
+ data[3] = 0x2c; /* reg 2, H size/8 */
+ data[4] = 0x48; /* reg 3, V size/4 */
+ data[6] = 0x06; /* reg 5, H start */
+ data[8] = 0x06 + sd->sensor_type; /* reg 7, V start */
break;
}
-
- err_code = reg_w(gspca_dev, 11);
+ err_code = mr_write(gspca_dev, 11);
if (err_code < 0)
return err_code;
- data[0] = 0x0a;
- data[1] = 0x80;
- err_code = reg_w(gspca_dev, 2);
+ if (!sd->sensor_type) {
+ const struct sensor_w_data cif_sensor0_init_data[] = {
+ {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,
+ 0x0f, 0x14, 0x0f, 0x10}, 8},
+ {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},
+ {0x12, 0x00, {0x07}, 1},
+ {0x1f, 0x00, {0x06}, 1},
+ {0x27, 0x00, {0x04}, 1},
+ {0x29, 0x00, {0x0c}, 1},
+ {0x40, 0x00, {0x40, 0x00, 0x04}, 3},
+ {0x50, 0x00, {0x60}, 1},
+ {0x60, 0x00, {0x06}, 1},
+ {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},
+ {0x72, 0x00, {0x1e, 0x56}, 2},
+ {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,
+ 0x31, 0x80, 0x00}, 9},
+ {0x11, 0x00, {0x01}, 1},
+ {0, 0, {0}, 0}
+ };
+ err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,
+ ARRAY_SIZE(cif_sensor0_init_data));
+ } else { /* sd->sensor_type = 1 */
+ const struct sensor_w_data cif_sensor1_init_data[] = {
+ /* Reg 3,4, 7,8 get set by the controls */
+ {0x02, 0x00, {0x10}, 1},
+ {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */
+ {0x06, 0x01, {0x00}, 1},
+ {0x09, 0x02, {0x0e}, 1},
+ {0x0a, 0x02, {0x05}, 1},
+ {0x0b, 0x02, {0x05}, 1},
+ {0x0c, 0x02, {0x0f}, 1},
+ {0x0d, 0x02, {0x07}, 1},
+ {0x0e, 0x02, {0x0c}, 1},
+ {0x0f, 0x00, {0x00}, 1},
+ {0x10, 0x00, {0x06}, 1},
+ {0x11, 0x00, {0x07}, 1},
+ {0x12, 0x00, {0x00}, 1},
+ {0x13, 0x00, {0x01}, 1},
+ {0, 0, {0}, 0}
+ };
+ err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
+ ARRAY_SIZE(cif_sensor1_init_data));
+ }
if (err_code < 0)
return err_code;
- data[0] = 0x14;
- data[1] = 0x0a;
- err_code = reg_w(gspca_dev, 2);
- if (err_code < 0)
- return err_code;
+ setbrightness(gspca_dev);
+ setexposure(gspca_dev);
+ setgain(gspca_dev);
- data[0] = 0x1b;
- data[1] = 0x00;
- err_code = reg_w(gspca_dev, 2);
- if (err_code < 0)
- return err_code;
+ msleep(200);
- data[0] = 0x15;
- data[1] = 0x16;
- err_code = reg_w(gspca_dev, 2);
+ data[0] = 0x00;
+ data[1] = 0x4d; /* ISOC transfering enable... */
+ err_code = mr_write(gspca_dev, 2);
if (err_code < 0)
return err_code;
- data[0] = 0x16;
- data[1] = 0x10;
- err_code = reg_w(gspca_dev, 2);
- if (err_code < 0)
- return err_code;
+ return 0;
+}
- data[0] = 0x17;
- data[1] = 0x3a;
- err_code = reg_w(gspca_dev, 2);
- if (err_code < 0)
- return err_code;
+static int start_vga_cam(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ __u8 *data = gspca_dev->usb_buf;
+ int err_code;
+ const __u8 startup_string[] = {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b,
+ 0x00, 0x00, 0x00, 0x50, 0xc0};
- data[0] = 0x18;
- data[1] = 0x68;
- err_code = reg_w(gspca_dev, 2);
- if (err_code < 0)
- return err_code;
+ /* What some of these mean is explained in start_cif_cam(), above */
+ sd->sof_read = 0;
- data[0] = 0x1f;
- data[1] = 0x00;
- data[2] = 0x02;
- data[3] = 0x06;
- data[4] = 0x59;
- data[5] = 0x0c;
- data[6] = 0x16;
- data[7] = 0x00;
- data[8] = 0x07;
- data[9] = 0x00;
- data[10] = 0x01;
- err_code = reg_w(gspca_dev, 11);
+ /*
+ * We have to know which camera we have, because the register writes
+ * depend upon the camera. This test, run before we actually enter
+ * the initialization routine, distinguishes most of the cameras, If
+ * needed, another routine is done later, too.
+ */
+ memset(data, 0, 16);
+ data[0] = 0x20;
+ err_code = mr_write(gspca_dev, 1);
if (err_code < 0)
return err_code;
- data[0] = 0x1f;
- data[1] = 0x04;
- data[2] = 0x11;
- data[3] = 0x01;
- err_code = reg_w(gspca_dev, 4);
+ err_code = mr_read(gspca_dev, 16);
if (err_code < 0)
return err_code;
- data[0] = 0x1f;
- data[1] = 0x00;
- data[2] = 0x0a;
- data[3] = 0x00;
- data[4] = 0x01;
- data[5] = 0x00;
- data[6] = 0x00;
- data[7] = 0x01;
- data[8] = 0x00;
- data[9] = 0x0a;
- err_code = reg_w(gspca_dev, 10);
- if (err_code < 0)
- return err_code;
+ PDEBUG(D_PROBE, "Byte reported is %02x", data[0]);
+
+ msleep(200);
+ /*
+ * Known VGA cameras. If you have another to report, please do
+ *
+ * Name byte just read sd->sensor_type
+ * sd->do_lcd_stop
+ * Aiptek Pencam VGA+ 0x31 0 1
+ * ION digital 0x31 0 1
+ * Argus DC-1620 0x30 1 0
+ * Argus QuickClix 0x30 1 1 (not caught here)
+ */
+ sd->sensor_type = data[0] & 1;
+ sd->do_lcd_stop = (~data[0]) & 1;
+
+
- data[0] = 0x1f;
- data[1] = 0x04;
- data[2] = 0x11;
- data[3] = 0x01;
- err_code = reg_w(gspca_dev, 4);
+ /* Streaming setup begins here. */
+
+
+ data[0] = 0x01;
+ data[1] = 0x01;
+ err_code = mr_write(gspca_dev, 2);
if (err_code < 0)
return err_code;
- data[0] = 0x1f;
- data[1] = 0x00;
- data[2] = 0x12;
- data[3] = 0x00;
- data[4] = 0x63;
- data[5] = 0x00;
- data[6] = 0x70;
- data[7] = 0x00;
- data[8] = 0x00;
- err_code = reg_w(gspca_dev, 9);
+ /*
+ * A second test can now resolve any remaining ambiguity in the
+ * identification of the camera type,
+ */
+ if (!sd->sensor_type) {
+ data[0] = get_sensor_id(gspca_dev);
+ if (data[0] == 0x7f) {
+ sd->sensor_type = 1;
+ PDEBUG(D_PROBE, "sensor_type corrected to 1");
+ }
+ msleep(200);
+ }
+
+ if (force_sensor_type != -1) {
+ sd->sensor_type = !! force_sensor_type;
+ PDEBUG(D_PROBE, "Forcing sensor type to: %d",
+ sd->sensor_type);
+ }
+
+ /*
+ * Known VGA cameras.
+ * This test is only run if the previous test returned 0x30, but
+ * here is the information for all others, too, just for reference.
+ *
+ * Name byte just read sd->sensor_type
+ *
+ * Aiptek Pencam VGA+ 0xfb (this test not run) 1
+ * ION digital 0xbd (this test not run) 1
+ * Argus DC-1620 0xe5 (no change) 0
+ * Argus QuickClix 0x7f (reclassified) 1
+ */
+ memcpy(data, startup_string, 11);
+ if (!sd->sensor_type) {
+ data[5] = 0x00;
+ data[10] = 0x91;
+ }
+
+ switch (gspca_dev->width) {
+ case 160:
+ data[9] |= 0x0c; /* reg 8, 4:1 scale down */
+ /* fall thru */
+ case 320:
+ data[9] |= 0x04; /* reg 8, 2:1 scale down */
+ /* fall thru */
+ case 640:
+ default:
+ data[3] = 0x50; /* reg 2, H size/8 */
+ data[4] = 0x78; /* reg 3, V size/4 */
+ data[6] = 0x04; /* reg 5, H start */
+ data[8] = 0x03; /* reg 7, V start */
+ if (sd->do_lcd_stop)
+ data[8] = 0x04; /* Bayer tile shifted */
+ break;
+
+ case 176:
+ data[9] |= 0x04; /* reg 8, 2:1 scale down */
+ /* fall thru */
+ case 352:
+ data[3] = 0x2c; /* reg 2, H size */
+ data[4] = 0x48; /* reg 3, V size */
+ data[6] = 0x94; /* reg 5, H start */
+ data[8] = 0x63; /* reg 7, V start */
+ if (sd->do_lcd_stop)
+ data[8] = 0x64; /* Bayer tile shifted */
+ break;
+ }
+
+ err_code = mr_write(gspca_dev, 11);
if (err_code < 0)
return err_code;
- data[0] = 0x1f;
- data[1] = 0x04;
- data[2] = 0x11;
- data[3] = 0x01;
- err_code = reg_w(gspca_dev, 4);
+ if (!sd->sensor_type) {
+ /* The only known sensor_type 0 cam is the Argus DC-1620 */
+ const struct sensor_w_data vga_sensor0_init_data[] = {
+ {0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
+ {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
+ {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},
+ {0x25, 0x00, {0x03, 0xa9, 0x80}, 3},
+ {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},
+ {0, 0, {0}, 0}
+ };
+ err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
+ ARRAY_SIZE(vga_sensor0_init_data));
+ } else { /* sd->sensor_type = 1 */
+ const struct sensor_w_data vga_sensor1_init_data[] = {
+ {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
+ 0x07, 0x00, 0x01}, 8},
+ {0x11, 0x04, {0x01}, 1},
+ /*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */
+ {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01,
+ 0x00, 0x0a}, 7},
+ {0x11, 0x04, {0x01}, 1},
+ {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},
+ {0x11, 0x04, {0x01}, 1},
+ {0, 0, {0}, 0}
+ };
+ err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
+ ARRAY_SIZE(vga_sensor1_init_data));
+ }
if (err_code < 0)
return err_code;
+ msleep(200);
data[0] = 0x00;
data[1] = 0x4d; /* ISOC transfering enable... */
- err_code = reg_w(gspca_dev, 2);
+ err_code = mr_write(gspca_dev, 2);
+
+ return err_code;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int err_code;
+ struct cam *cam;
+
+ cam = &gspca_dev->cam;
+ sd->sof_read = 0;
+ /*
+ * Some of the supported cameras require the memory pointer to be
+ * set to 0, or else they will not stream.
+ */
+ zero_the_pointer(gspca_dev);
+ msleep(200);
+ if (sd->cam_type == CAM_TYPE_CIF) {
+ err_code = start_cif_cam(gspca_dev);
+ } else {
+ err_code = start_vga_cam(gspca_dev);
+ }
return err_code;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
int result;
gspca_dev->usb_buf[0] = 1;
gspca_dev->usb_buf[1] = 0;
- result = reg_w(gspca_dev, 2);
+ result = mr_write(gspca_dev, 2);
if (result < 0)
PDEBUG(D_ERR, "Camera Stop failed");
+
+ /* Not all the cams need this, but even if not, probably a good idea */
+ zero_the_pointer(gspca_dev);
+ if (sd->do_lcd_stop) {
+ gspca_dev->usb_buf[0] = 0x19;
+ gspca_dev->usb_buf[1] = 0x54;
+ result = mr_write(gspca_dev, 2);
+ if (result < 0)
+ PDEBUG(D_ERR, "Camera Stop failed");
+ }
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 val;
+
+ if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX))
+ return;
+
+ /* Note register 7 is also seen as 0x8x or 0xCx in dumps */
+ if (sd->brightness > 0) {
+ sensor_write1(gspca_dev, 7, 0x00);
+ val = sd->brightness;
+ } else {
+ sensor_write1(gspca_dev, 7, 0x01);
+ val = 257 - sd->brightness;
+ }
+ sensor_write1(gspca_dev, 8, val);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ u8 val;
+
+ if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
+ return;
+
+ if (sd->sensor_type) {
+ val = sd->exposure >> 4;
+ sensor_write1(gspca_dev, 3, val);
+ val = sd->exposure & 0xf;
+ sensor_write1(gspca_dev, 4, val);
+ } else {
+ u8 clockdiv;
+ int exposure;
+
+ /* We have both a clock divider and an exposure register.
+ We first calculate the clock divider, as that determines
+ the maximum exposure and then we calculayte the exposure
+ register setting (which goes from 0 - 511).
+
+ Note our 0 - 4095 exposure is mapped to 0 - 511
+ milliseconds exposure time */
+ clockdiv = (60 * sd->exposure + 7999) / 8000;
+
+ /* Limit framerate to not exceed usb bandwidth */
+ if (clockdiv < 3 && gspca_dev->width >= 320)
+ clockdiv = 3;
+ else if (clockdiv < 2)
+ clockdiv = 2;
+
+ /* Frame exposure time in ms = 1000 * clockdiv / 60 ->
+ exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */
+ exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv);
+ if (exposure > 511)
+ exposure = 511;
+
+ /* exposure register value is reversed! */
+ exposure = 511 - exposure;
+
+ sensor_write1(gspca_dev, 0x02, clockdiv);
+ sensor_write1(gspca_dev, 0x0e, exposure & 0xff);
+ sensor_write1(gspca_dev, 0x0f, exposure >> 8);
+ }
+}
+
+static void setgain(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (gspca_dev->ctrl_dis & (1 << GAIN_IDX))
+ return;
+
+ if (sd->sensor_type) {
+ sensor_write1(gspca_dev, 0x0e, sd->gain);
+ } else {
+ sensor_write1(gspca_dev, 0x10, sd->gain);
+ }
+}
+
+static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->brightness = val;
+ if (gspca_dev->streaming)
+ setbrightness(gspca_dev);
+ return 0;
+}
+
+static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->brightness;
+ return 0;
+}
+
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->exposure = val;
+ if (gspca_dev->streaming)
+ setexposure(gspca_dev);
+ return 0;
+}
+
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->exposure;
+ return 0;
+}
+
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->gain = val;
+ if (gspca_dev->streaming)
+ setgain(gspca_dev);
+ return 0;
+}
+
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->gain;
+ return 0;
}
/* Include pac common sof detection functions */
@@ -320,8 +938,9 @@ static const struct sd_desc sd_desc = {
/* -- module initialisation -- */
static const __devinitdata struct usb_device_id device_table[] = {
- {USB_DEVICE(0x08ca, 0x0111)},
- {USB_DEVICE(0x093a, 0x010f)},
+ {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */
+ {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */
+ {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c
index 95a97ab68..96659433d 100644
--- a/linux/drivers/media/video/gspca/pac207.c
+++ b/linux/drivers/media/video/gspca/pac207.c
@@ -35,25 +35,17 @@ MODULE_LICENSE("GPL");
#define PAC207_BRIGHTNESS_MIN 0
#define PAC207_BRIGHTNESS_MAX 255
-#define PAC207_BRIGHTNESS_DEFAULT 4 /* power on default: 4 */
-
-/* An exposure value of 4 also works (3 does not) but then we need to lower
- the compression balance setting when in 352x288 mode, otherwise the usb
- bandwidth is not enough and packets get dropped resulting in corrupt
- frames. The problem with this is that when the compression balance gets
- lowered below 0x80, the pac207 starts using a different compression
- algorithm for some lines, these lines get prefixed with a 0x2dd2 prefix
- and currently we do not know how to decompress these lines, so for now
- we use a minimum exposure value of 5 */
-#define PAC207_EXPOSURE_MIN 5
+#define PAC207_BRIGHTNESS_DEFAULT 46
+
+#define PAC207_EXPOSURE_MIN 3
#define PAC207_EXPOSURE_MAX 26
-#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 ?? */
-#define PAC207_EXPOSURE_KNEE 11 /* 4 = 30 fps, 11 = 8, 15 = 6 */
+#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 */
+#define PAC207_EXPOSURE_KNEE 8 /* 4 = 30 fps, 11 = 8, 15 = 6 */
#define PAC207_GAIN_MIN 0
#define PAC207_GAIN_MAX 31
#define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */
-#define PAC207_GAIN_KNEE 20
+#define PAC207_GAIN_KNEE 31
#define PAC207_AUTOGAIN_DEADZONE 30
@@ -166,16 +158,12 @@ static const struct v4l2_pix_format sif_mode[] = {
};
static const __u8 pac207_sensor_init[][8] = {
- {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0},
- {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
+ {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84},
+ {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
{0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
- {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02},
{0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
};
- /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
-static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
-
static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
const u8 *buffer, u16 length)
{
@@ -274,7 +262,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
* Bit_1=LED,
* Bit_2=Compression test mode enable */
pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
- pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
return 0;
}
@@ -289,15 +276,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
- pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
- pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
- pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
+ pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8);
/* Compression Balance */
if (gspca_dev->width == 176)
pac207_write_reg(gspca_dev, 0x4a, 0xff);
else
- pac207_write_reg(gspca_dev, 0x4a, 0x88);
+ pac207_write_reg(gspca_dev, 0x4a, 0x30);
pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
pac207_write_reg(gspca_dev, 0x08, sd->brightness);
@@ -346,7 +331,7 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
if (sd->autogain_ignore_frames > 0)
sd->autogain_ignore_frames--;
else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
- 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
+ 100, PAC207_AUTOGAIN_DEADZONE,
PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
}
diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c
index ed10134c9..356111956 100644
--- a/linux/drivers/media/video/gspca/pac7311.c
+++ b/linux/drivers/media/video/gspca/pac7311.c
@@ -1071,6 +1071,7 @@ static struct sd_desc sd_desc = {
/* -- module initialisation -- */
static __devinitdata struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x06f8, 0x3009), .driver_info = SENSOR_PAC7302},
{USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
{USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
{USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
diff --git a/linux/drivers/media/video/gspca/sn9c20x.c b/linux/drivers/media/video/gspca/sn9c20x.c
index fc47f978e..99632a7d6 100644
--- a/linux/drivers/media/video/gspca/sn9c20x.c
+++ b/linux/drivers/media/video/gspca/sn9c20x.c
@@ -97,6 +97,16 @@ struct sd {
#endif
};
+struct i2c_reg_u8 {
+ u8 reg;
+ u8 val;
+};
+
+struct i2c_reg_u16 {
+ u8 reg;
+ u16 val;
+};
+
static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
@@ -406,7 +416,7 @@ static const struct v4l2_pix_format sxga_mode[] = {
.priv = 3 | MODE_RAW | MODE_SXGA},
};
-static const int hsv_red_x[] = {
+static const s16 hsv_red_x[] = {
41, 44, 46, 48, 50, 52, 54, 56,
58, 60, 62, 64, 66, 68, 70, 72,
74, 76, 78, 80, 81, 83, 85, 87,
@@ -454,7 +464,7 @@ static const int hsv_red_x[] = {
24, 26, 28, 30, 33, 35, 37, 39, 41
};
-static const int hsv_red_y[] = {
+static const s16 hsv_red_y[] = {
82, 80, 78, 76, 74, 73, 71, 69,
67, 65, 63, 61, 58, 56, 54, 52,
50, 48, 46, 44, 41, 39, 37, 35,
@@ -502,7 +512,7 @@ static const int hsv_red_y[] = {
96, 94, 92, 91, 89, 87, 85, 84, 82
};
-static const int hsv_green_x[] = {
+static const s16 hsv_green_x[] = {
-124, -124, -125, -125, -125, -125, -125, -125,
-125, -126, -126, -125, -125, -125, -125, -125,
-125, -124, -124, -124, -123, -123, -122, -122,
@@ -550,7 +560,7 @@ static const int hsv_green_x[] = {
-120, -120, -121, -122, -122, -123, -123, -124, -124
};
-static const int hsv_green_y[] = {
+static const s16 hsv_green_y[] = {
-100, -99, -98, -97, -95, -94, -93, -91,
-90, -89, -87, -86, -84, -83, -81, -80,
-78, -76, -75, -73, -71, -70, -68, -66,
@@ -598,7 +608,7 @@ static const int hsv_green_y[] = {
-109, -108, -107, -106, -105, -104, -103, -102, -100
};
-static const int hsv_blue_x[] = {
+static const s16 hsv_blue_x[] = {
112, 113, 114, 114, 115, 116, 117, 117,
118, 118, 119, 119, 120, 120, 120, 121,
121, 121, 122, 122, 122, 122, 122, 122,
@@ -646,7 +656,7 @@ static const int hsv_blue_x[] = {
104, 105, 106, 107, 108, 109, 110, 111, 112
};
-static const int hsv_blue_y[] = {
+static const s16 hsv_blue_y[] = {
-11, -13, -15, -17, -19, -21, -23, -25,
-27, -29, -31, -33, -35, -37, -39, -41,
-43, -45, -46, -48, -50, -52, -54, -55,
@@ -795,21 +805,21 @@ static u8 hv7131r_gain[] = {
0x78 /* 8x */
};
-static u8 soi968_init[][2] = {
+static struct i2c_reg_u8 soi968_init[] = {
{0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
{0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
{0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
{0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
{0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
{0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
- {0x13, 0x8a}, {0x12, 0x40}, {0x17, 0x13},
+ {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
{0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
{0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
{0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
{0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
};
-static u8 ov7660_init[][2] = {
+static struct i2c_reg_u8 ov7660_init[] = {
{0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
{0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
{0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
@@ -818,7 +828,7 @@ static u8 ov7660_init[][2] = {
{0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
};
-static u8 ov7670_init[][2] = {
+static struct i2c_reg_u8 ov7670_init[] = {
{0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
{0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
{0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
@@ -875,7 +885,7 @@ static u8 ov7670_init[][2] = {
{0x93, 0x00},
};
-static u8 ov9650_init[][2] = {
+static struct i2c_reg_u8 ov9650_init[] = {
{0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
{0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
{0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
@@ -905,7 +915,7 @@ static u8 ov9650_init[][2] = {
{0xaa, 0x92}, {0xab, 0x0a},
};
-static u8 ov9655_init[][2] = {
+static struct i2c_reg_u8 ov9655_init[] = {
{0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61},
{0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24},
{0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08},
@@ -942,7 +952,7 @@ static u8 ov9655_init[][2] = {
{0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13},
};
-static u16 mt9v112_init[][2] = {
+static struct i2c_reg_u16 mt9v112_init[] = {
{0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
{0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
{0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
@@ -961,7 +971,7 @@ static u16 mt9v112_init[][2] = {
{0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
};
-static u16 mt9v111_init[][2] = {
+static struct i2c_reg_u16 mt9v111_init[] = {
{0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
{0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1},
{0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002},
@@ -988,7 +998,7 @@ static u16 mt9v111_init[][2] = {
{0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004},
};
-static u16 mt9v011_init[][2] = {
+static struct i2c_reg_u16 mt9v011_init[] = {
{0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
{0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
{0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
@@ -1015,7 +1025,7 @@ static u16 mt9v011_init[][2] = {
{0x06, 0x0029}, {0x05, 0x0009},
};
-static u16 mt9m001_init[][2] = {
+static struct i2c_reg_u16 mt9m001_init[] = {
{0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e},
{0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
{0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002},
@@ -1028,14 +1038,14 @@ static u16 mt9m001_init[][2] = {
{0x2e, 0x0029}, {0x07, 0x0002},
};
-static u16 mt9m111_init[][2] = {
- {0xf0, 0x0000}, {0x0d, 0x0008}, {0x0d, 0x0009},
- {0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300},
- {0x9b, 0x4300}, {0xa1, 0x0280}, {0xa4, 0x0200},
- {0x06, 0x308e}, {0xf0, 0x0000},
+static struct i2c_reg_u16 mt9m111_init[] = {
+ {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
+ {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
+ {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
+ {0xf0, 0x0000},
};
-static u8 hv7131r_init[][2] = {
+static struct i2c_reg_u8 hv7131r_init[] = {
{0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
{0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
{0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
@@ -1046,7 +1056,7 @@ static u8 hv7131r_init[][2] = {
{0x23, 0x09}, {0x01, 0x08},
};
-int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
+static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
{
struct usb_device *dev = gspca_dev->dev;
int result;
@@ -1065,7 +1075,8 @@ int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
return 0;
}
-int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length)
+static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
+ const u8 *buffer, int length)
{
struct usb_device *dev = gspca_dev->dev;
int result;
@@ -1085,13 +1096,13 @@ int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length)
return 0;
}
-int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
+static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
{
u8 data[1] = {value};
return reg_w(gspca_dev, reg, data, 1);
}
-int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
+static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
{
int i;
reg_w(gspca_dev, 0x10c0, buffer, 8);
@@ -1107,7 +1118,7 @@ int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
return -EIO;
}
-int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
+static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -1129,7 +1140,7 @@ int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
return i2c_w(gspca_dev, row);
}
-int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
+static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
{
struct sd *sd = (struct sd *) gspca_dev;
u8 row[8];
@@ -1206,8 +1217,8 @@ static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
- if (i2c_w1(gspca_dev, ov9650_init[i][0],
- ov9650_init[i][1]) < 0) {
+ if (i2c_w1(gspca_dev, ov9650_init[i].reg,
+ ov9650_init[i].val) < 0) {
err("OV9650 sensor initialization failed");
return -ENODEV;
}
@@ -1223,8 +1234,8 @@ static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
- if (i2c_w1(gspca_dev, ov9655_init[i][0],
- ov9655_init[i][1]) < 0) {
+ if (i2c_w1(gspca_dev, ov9655_init[i].reg,
+ ov9655_init[i].val) < 0) {
err("OV9655 sensor initialization failed");
return -ENODEV;
}
@@ -1242,14 +1253,14 @@ static int soi968_init_sensor(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
- if (i2c_w1(gspca_dev, soi968_init[i][0],
- soi968_init[i][1]) < 0) {
+ if (i2c_w1(gspca_dev, soi968_init[i].reg,
+ soi968_init[i].val) < 0) {
err("SOI968 sensor initialization failed");
return -ENODEV;
}
}
/* disable hflip and vflip */
- gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+ gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << EXPOSURE_IDX);
sd->hstart = 60;
sd->vstart = 11;
return 0;
@@ -1261,8 +1272,8 @@ static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
- if (i2c_w1(gspca_dev, ov7660_init[i][0],
- ov7660_init[i][1]) < 0) {
+ if (i2c_w1(gspca_dev, ov7660_init[i].reg,
+ ov7660_init[i].val) < 0) {
err("OV7660 sensor initialization failed");
return -ENODEV;
}
@@ -1280,8 +1291,8 @@ static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
- if (i2c_w1(gspca_dev, ov7670_init[i][0],
- ov7670_init[i][1]) < 0) {
+ if (i2c_w1(gspca_dev, ov7670_init[i].reg,
+ ov7670_init[i].val) < 0) {
err("OV7670 sensor initialization failed");
return -ENODEV;
}
@@ -1304,8 +1315,8 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
ret = i2c_r2(gspca_dev, 0xff, &value);
if ((ret == 0) && (value == 0x8243)) {
for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
- if (i2c_w2(gspca_dev, mt9v011_init[i][0],
- mt9v011_init[i][1]) < 0) {
+ if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
+ mt9v011_init[i].val) < 0) {
err("MT9V011 sensor initialization failed");
return -ENODEV;
}
@@ -1322,8 +1333,8 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
ret = i2c_r2(gspca_dev, 0xff, &value);
if ((ret == 0) && (value == 0x823a)) {
for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
- if (i2c_w2(gspca_dev, mt9v111_init[i][0],
- mt9v111_init[i][1]) < 0) {
+ if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
+ mt9v111_init[i].val) < 0) {
err("MT9V111 sensor initialization failed");
return -ENODEV;
}
@@ -1344,8 +1355,8 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
ret = i2c_r2(gspca_dev, 0x00, &value);
if ((ret == 0) && (value == 0x1229)) {
for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
- if (i2c_w2(gspca_dev, mt9v112_init[i][0],
- mt9v112_init[i][1]) < 0) {
+ if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
+ mt9v112_init[i].val) < 0) {
err("MT9V112 sensor initialization failed");
return -ENODEV;
}
@@ -1365,12 +1376,13 @@ static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
int i;
for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
- if (i2c_w2(gspca_dev, mt9m111_init[i][0],
- mt9m111_init[i][1]) < 0) {
+ if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
+ mt9m111_init[i].val) < 0) {
err("MT9M111 sensor initialization failed");
return -ENODEV;
}
}
+ gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << GAIN_IDX);
sd->hstart = 0;
sd->vstart = 2;
return 0;
@@ -1381,8 +1393,8 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
int i;
for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
- if (i2c_w2(gspca_dev, mt9m001_init[i][0],
- mt9m001_init[i][1]) < 0) {
+ if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
+ mt9m001_init[i].val) < 0) {
err("MT9M001 sensor initialization failed");
return -ENODEV;
}
@@ -1400,8 +1412,8 @@ static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
- if (i2c_w1(gspca_dev, hv7131r_init[i][0],
- hv7131r_init[i][1]) < 0) {
+ if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
+ hv7131r_init[i].val) < 0) {
err("HV7131R Sensor initialization failed");
return -ENODEV;
}
@@ -1625,7 +1637,6 @@ static int set_exposure(struct gspca_dev *gspca_dev)
switch (sd->sensor) {
case SENSOR_OV7660:
case SENSOR_OV7670:
- case SENSOR_SOI968:
case SENSOR_OV9655:
case SENSOR_OV9650:
exp[0] |= (3 << 4);
@@ -1634,7 +1645,6 @@ static int set_exposure(struct gspca_dev *gspca_dev)
exp[4] = sd->exposure >> 8;
break;
case SENSOR_MT9M001:
- case SENSOR_MT9M111:
case SENSOR_MT9V112:
case SENSOR_MT9V111:
case SENSOR_MT9V011:
@@ -1650,6 +1660,8 @@ static int set_exposure(struct gspca_dev *gspca_dev)
exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8;
exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff;
break;
+ default:
+ return 0;
}
i2c_w(gspca_dev, exp);
return 0;
@@ -1676,7 +1688,6 @@ static int set_gain(struct gspca_dev *gspca_dev)
gain[4] = micron1_gain[sd->gain] & 0xff;
break;
case SENSOR_MT9V112:
- case SENSOR_MT9M111:
gain[0] |= (3 << 4);
gain[2] = 0x2f;
gain[3] = micron1_gain[sd->gain] >> 8;
@@ -1693,6 +1704,8 @@ static int set_gain(struct gspca_dev *gspca_dev)
gain[2] = 0x30;
gain[3] = hv7131r_gain[sd->gain];
break;
+ default:
+ return 0;
}
i2c_w(gspca_dev, gain);
return 0;
@@ -1995,7 +2008,9 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->i2c_addr = id->driver_info & 0xff;
switch (sd->sensor) {
+ case SENSOR_MT9M111:
case SENSOR_OV9650:
+ case SENSOR_SOI968:
cam->cam_mode = sxga_mode;
cam->nmodes = ARRAY_SIZE(sxga_mode);
break;
@@ -2111,6 +2126,25 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
struct sd *sd = (struct sd *) gspca_dev;
u8 value;
switch (sd->sensor) {
+ case SENSOR_SOI968:
+ if (mode & MODE_SXGA) {
+ i2c_w1(gspca_dev, 0x17, 0x1d);
+ i2c_w1(gspca_dev, 0x18, 0xbd);
+ i2c_w1(gspca_dev, 0x19, 0x01);
+ i2c_w1(gspca_dev, 0x1a, 0x81);
+ i2c_w1(gspca_dev, 0x12, 0x00);
+ sd->hstart = 140;
+ sd->vstart = 19;
+ } else {
+ i2c_w1(gspca_dev, 0x17, 0x13);
+ i2c_w1(gspca_dev, 0x18, 0x63);
+ i2c_w1(gspca_dev, 0x19, 0x01);
+ i2c_w1(gspca_dev, 0x1a, 0x79);
+ i2c_w1(gspca_dev, 0x12, 0x40);
+ sd->hstart = 60;
+ sd->vstart = 11;
+ }
+ break;
case SENSOR_OV9650:
if (mode & MODE_SXGA) {
i2c_w1(gspca_dev, 0x17, 0x1b);
@@ -2128,6 +2162,17 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
}
break;
+ case SENSOR_MT9M111:
+ if (mode & MODE_SXGA) {
+ i2c_w2(gspca_dev, 0xf0, 0x0002);
+ i2c_w2(gspca_dev, 0xc8, 0x970b);
+ i2c_w2(gspca_dev, 0xf0, 0x0000);
+ } else {
+ i2c_w2(gspca_dev, 0xf0, 0x0002);
+ i2c_w2(gspca_dev, 0xc8, 0x8000);
+ i2c_w2(gspca_dev, 0xf0, 0x0000);
+ }
+ break;
}
}
@@ -2216,15 +2261,10 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
kfree(sd->jpeg_hdr);
}
-static void do_autoexposure(struct gspca_dev *gspca_dev)
+static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
{
struct sd *sd = (struct sd *) gspca_dev;
- int avg_lum, new_exp;
-
- if (!sd->auto_exposure)
- return;
-
- avg_lum = atomic_read(&sd->avg_lum);
+ s16 new_exp;
/*
* some hardcoded values are present
@@ -2271,6 +2311,39 @@ static void do_autoexposure(struct gspca_dev *gspca_dev)
}
}
+static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (avg_lum < MIN_AVG_LUM) {
+ if (sd->gain + 1 <= 28) {
+ sd->gain++;
+ set_gain(gspca_dev);
+ }
+ }
+ if (avg_lum > MAX_AVG_LUM) {
+ if (sd->gain - 1 >= 0) {
+ sd->gain--;
+ set_gain(gspca_dev);
+ }
+ }
+}
+
+static void sd_dqcallback(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int avg_lum;
+
+ if (!sd->auto_exposure)
+ return;
+
+ avg_lum = atomic_read(&sd->avg_lum);
+ if (sd->sensor == SENSOR_SOI968)
+ do_autogain(gspca_dev, avg_lum);
+ else
+ do_autoexposure(gspca_dev, avg_lum);
+}
+
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
u8 *data, /* isoc packet */
@@ -2338,7 +2411,7 @@ static const struct sd_desc sd_desc = {
.stopN = sd_stopN,
.stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan,
- .dq_callback = do_autoexposure,
+ .dq_callback = sd_dqcallback,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.set_register = sd_dbg_s_register,
.get_register = sd_dbg_g_register,
diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c
index 98fb39c99..3746ddbbe 100644
--- a/linux/drivers/media/video/gspca/sonixj.c
+++ b/linux/drivers/media/video/gspca/sonixj.c
@@ -741,7 +741,7 @@ static const u8 ov7660_sensor_init[][8] = {
/* COM 1 BAVE GEAVE AECHH */
{0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
{0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
-#if 1
+#if 0
{0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
#else
{0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
@@ -795,7 +795,7 @@ static const u8 ov7660_sensor_init[][8] = {
{0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
{0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
{0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
- {0xb1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
+ {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
/****** (some exchanges in the win trace) ******/
{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
/* bits[3..0]reserved */
@@ -1165,17 +1165,19 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
reg_w1(gspca_dev, 0x01, 0x42);
break;
case SENSOR_OV7660:
+#if 0
reg_w1(gspca_dev, 0x01, 0x61);
reg_w1(gspca_dev, 0x17, 0x20);
reg_w1(gspca_dev, 0x01, 0x60);
reg_w1(gspca_dev, 0x01, 0x40);
break;
+#endif
case SENSOR_SP80708:
reg_w1(gspca_dev, 0x01, 0x63);
reg_w1(gspca_dev, 0x17, 0x20);
reg_w1(gspca_dev, 0x01, 0x62);
reg_w1(gspca_dev, 0x01, 0x42);
- mdelay(100);
+ msleep(100);
reg_w1(gspca_dev, 0x02, 0x62);
break;
/* case SENSOR_HV7131R: */
@@ -1654,6 +1656,8 @@ static void setvflip(struct sd *sd)
static void setinfrared(struct sd *sd)
{
+ if (sd->gspca_dev.ctrl_dis & (1 << INFRARED_IDX))
+ return;
/*fixme: different sequence for StarCam Clip and StarCam 370i */
#if 1
/* Clip */
@@ -1675,14 +1679,14 @@ static void setfreq(struct gspca_dev *gspca_dev)
if (sd->sensor == SENSOR_OV7660) {
u8 com8;
-#if 1
- com8 = 0xf8; /* no auto gain/wb/expo */
+#if 0
+ com8 = 0xd8; /* no auto gain/wb/expo */
#else
- com8 = 0xff;
+ com8 = 0xdf; /* auto gain/wb/expo */
#endif
switch (sd->freq) {
case 0: /* Banding filter disabled */
- i2c_w1(gspca_dev, 0x13, com8 & 0xdf);
+ i2c_w1(gspca_dev, 0x13, com8 | 0x20);
break;
case 1: /* 50 hz */
i2c_w1(gspca_dev, 0x13, com8);
@@ -1839,12 +1843,14 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x99, 0x60);
break;
case SENSOR_OV7660:
+#if 0
reg_w1(gspca_dev, 0x9a, 0x05);
if (sd->bridge == BRIDGE_SN9C105)
reg_w1(gspca_dev, 0x99, 0xff);
else
reg_w1(gspca_dev, 0x99, 0x5b);
break;
+#endif
case SENSOR_SP80708:
reg_w1(gspca_dev, 0x9a, 0x05);
reg_w1(gspca_dev, 0x99, 0x59);
@@ -2373,14 +2379,14 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
{USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
-/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
+/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x??)}, */
/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
{USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
{USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
- {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+ {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
{USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
#endif
{USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/
diff --git a/linux/drivers/media/video/gspca/spca501.c b/linux/drivers/media/video/gspca/spca501.c
index 61dfc714f..9c4a2e6db 100644
--- a/linux/drivers/media/video/gspca/spca501.c
+++ b/linux/drivers/media/video/gspca/spca501.c
@@ -1948,7 +1948,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam = &gspca_dev->cam;
cam->cam_mode = vga_mode;
- cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ cam->nmodes = ARRAY_SIZE(vga_mode);
sd->subtype = id->driver_info;
sd->brightness = sd_ctrls[MY_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value;
diff --git a/linux/drivers/media/video/gspca/spca506.c b/linux/drivers/media/video/gspca/spca506.c
index 3a0c893f9..a199298a6 100644
--- a/linux/drivers/media/video/gspca/spca506.c
+++ b/linux/drivers/media/video/gspca/spca506.c
@@ -286,7 +286,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam = &gspca_dev->cam;
cam->cam_mode = vga_mode;
- cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ cam->nmodes = ARRAY_SIZE(vga_mode);
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c
index 0da8e0de0..7af511b5e 100644
--- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -130,8 +130,8 @@ int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
STV06XX_URB_MSG_TIMEOUT);
if (err < 0)
return err;
- }
- return stv06xx_write_sensor_finish(sd);
+ }
+ return stv06xx_write_sensor_finish(sd);
}
int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c
index 270b86f24..32ff7cd32 100644
--- a/linux/drivers/media/video/gspca/sunplus.c
+++ b/linux/drivers/media/video/gspca/sunplus.c
@@ -32,22 +32,22 @@ MODULE_LICENSE("GPL");
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
- unsigned char brightness;
- unsigned char contrast;
- unsigned char colors;
- unsigned char autogain;
+ s8 brightness;
+ u8 contrast;
+ u8 colors;
+ u8 autogain;
u8 quality;
#define QUALITY_MIN 70
#define QUALITY_MAX 95
#define QUALITY_DEF 85
- char bridge;
+ u8 bridge;
#define BRIDGE_SPCA504 0
#define BRIDGE_SPCA504B 1
#define BRIDGE_SPCA504C 2
#define BRIDGE_SPCA533 3
#define BRIDGE_SPCA536 4
- char subtype;
+ u8 subtype;
#define AiptekMiniPenCam13 1
#define LogitechClickSmart420 2
#define LogitechClickSmart820 3
@@ -68,21 +68,20 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
-#define SD_BRIGHTNESS 0
{
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
- .minimum = 0,
- .maximum = 0xff,
+ .minimum = -128,
+ .maximum = 127,
.step = 1,
- .default_value = 0,
+#define BRIGHTNESS_DEF 0
+ .default_value = BRIGHTNESS_DEF,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
},
-#define SD_CONTRAST 1
{
{
.id = V4L2_CID_CONTRAST,
@@ -91,12 +90,12 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 0xff,
.step = 1,
- .default_value = 0x20,
+#define CONTRAST_DEF 0x20
+ .default_value = CONTRAST_DEF,
},
.set = sd_setcontrast,
.get = sd_getcontrast,
},
-#define SD_COLOR 2
{
{
.id = V4L2_CID_SATURATION,
@@ -105,12 +104,12 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 0xff,
.step = 1,
- .default_value = 0x1a,
+#define COLOR_DEF 0x1a
+ .default_value = COLOR_DEF,
},
.set = sd_setcolors,
.get = sd_getcolors,
},
-#define SD_AUTOGAIN 3
{
{
.id = V4L2_CID_AUTOGAIN,
@@ -119,7 +118,8 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 1,
.step = 1,
- .default_value = 1,
+#define AUTOGAIN_DEF 1
+ .default_value = AUTOGAIN_DEF,
},
.set = sd_setautogain,
.get = sd_getautogain,
@@ -181,14 +181,20 @@ static const struct v4l2_pix_format vga_mode2[] = {
#define SPCA504_PCCAM600_OFFSET_MODE 5
#define SPCA504_PCCAM600_OFFSET_DATA 14
/* Frame packet header offsets for the spca533 */
-#define SPCA533_OFFSET_DATA 16
+#define SPCA533_OFFSET_DATA 16
#define SPCA533_OFFSET_FRAMSEQ 15
/* Frame packet header offsets for the spca536 */
-#define SPCA536_OFFSET_DATA 4
-#define SPCA536_OFFSET_FRAMSEQ 1
+#define SPCA536_OFFSET_DATA 4
+#define SPCA536_OFFSET_FRAMSEQ 1
+
+struct cmd {
+ u8 req;
+ u16 val;
+ u16 idx;
+};
/* Initialisation data for the Creative PC-CAM 600 */
-static const __u16 spca504_pccam600_init_data[][3] = {
+static const struct cmd spca504_pccam600_init_data[] = {
/* {0xa0, 0x0000, 0x0503}, * capture mode */
{0x00, 0x0000, 0x2000},
{0x00, 0x0013, 0x2301},
@@ -219,22 +225,20 @@ static const __u16 spca504_pccam600_init_data[][3] = {
{0x00, 0x0003, 0x2000},
{0x00, 0x0013, 0x2301},
{0x00, 0x0003, 0x2000},
- {}
};
/* Creative PC-CAM 600 specific open data, sent before using the
* generic initialisation data from spca504_open_data.
*/
-static const __u16 spca504_pccam600_open_data[][3] = {
+static const struct cmd spca504_pccam600_open_data[] = {
{0x00, 0x0001, 0x2501},
{0x20, 0x0500, 0x0001}, /* snapshot mode */
{0x00, 0x0003, 0x2880},
{0x00, 0x0001, 0x2881},
- {}
};
/* Initialisation data for the logitech clicksmart 420 */
-static const __u16 spca504A_clicksmart420_init_data[][3] = {
+static const struct cmd spca504A_clicksmart420_init_data[] = {
/* {0xa0, 0x0000, 0x0503}, * capture mode */
{0x00, 0x0000, 0x2000},
{0x00, 0x0013, 0x2301},
@@ -261,7 +265,7 @@ static const __u16 spca504A_clicksmart420_init_data[][3] = {
#endif
#if 1
- {0x0a1, 0x0080, 0x0001},
+ {0xa1, 0x0080, 0x0001},
{0x30, 0x0049, 0x0000},
{0x30, 0x0060, 0x0005},
{0x0c, 0x0004, 0x0000},
@@ -285,11 +289,10 @@ static const __u16 spca504A_clicksmart420_init_data[][3] = {
{0x00, 0x0013, 0x2301},
{0x00, 0x0003, 0x2000},
#endif
- {}
};
/* clicksmart 420 open data ? */
-static const __u16 spca504A_clicksmart420_open_data[][3] = {
+static const struct cmd spca504A_clicksmart420_open_data[] = {
{0x00, 0x0001, 0x2501},
{0x20, 0x0502, 0x0000},
{0x06, 0x0000, 0x0000},
@@ -433,10 +436,9 @@ static const __u16 spca504A_clicksmart420_open_data[][3] = {
{0x00, 0x0028, 0x287f},
{0xa0, 0x0000, 0x0503},
- {}
};
-static const __u8 qtable_creative_pccam[2][64] = {
+static const u8 qtable_creative_pccam[2][64] = {
{ /* Q-table Y-components */
0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
@@ -461,7 +463,7 @@ static const __u8 qtable_creative_pccam[2][64] = {
* except for one byte. Possibly a typo?
* NWG: 18/05/2003.
*/
-static const __u8 qtable_spca504_default[2][64] = {
+static const u8 qtable_spca504_default[2][64] = {
{ /* Q-table Y-components */
0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
@@ -485,9 +487,9 @@ static const __u8 qtable_spca504_default[2][64] = {
/* read <len> bytes to gspca_dev->usb_buf */
static void reg_r(struct gspca_dev *gspca_dev,
- __u16 req,
- __u16 index,
- __u16 len)
+ u8 req,
+ u16 index,
+ u16 len)
{
#ifdef GSPCA_DEBUG
if (len > USB_BUF_SZ) {
@@ -505,31 +507,26 @@ static void reg_r(struct gspca_dev *gspca_dev,
500);
}
-/* write <len> bytes from gspca_dev->usb_buf */
-static void reg_w(struct gspca_dev *gspca_dev,
- __u16 req,
- __u16 value,
- __u16 index,
- __u16 len)
+/* write one byte */
+static void reg_w_1(struct gspca_dev *gspca_dev,
+ u8 req,
+ u16 value,
+ u16 index,
+ u16 byte)
{
-#ifdef GSPCA_DEBUG
- if (len > USB_BUF_SZ) {
- err("reg_w: buffer overflow");
- return;
- }
-#endif
+ gspca_dev->usb_buf[0] = byte;
usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0),
req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, index,
- len ? gspca_dev->usb_buf : NULL, len,
+ gspca_dev->usb_buf, 1,
500);
}
/* write req / index / value */
static int reg_w_riv(struct usb_device *dev,
- __u16 req, __u16 index, __u16 value)
+ u8 req, u16 index, u16 value)
{
int ret;
@@ -547,7 +544,7 @@ static int reg_w_riv(struct usb_device *dev,
/* read 1 byte */
static int reg_r_1(struct gspca_dev *gspca_dev,
- __u16 value) /* wValue */
+ u16 value) /* wValue */
{
int ret;
@@ -568,9 +565,9 @@ static int reg_r_1(struct gspca_dev *gspca_dev,
/* read 1 or 2 bytes - returns < 0 if error */
static int reg_r_12(struct gspca_dev *gspca_dev,
- __u16 req, /* bRequest */
- __u16 index, /* wIndex */
- __u16 length) /* wLength (1 or 2 only) */
+ u8 req, /* bRequest */
+ u16 index, /* wIndex */
+ u16 length) /* wLength (1 or 2 only) */
{
int ret;
@@ -591,43 +588,40 @@ static int reg_r_12(struct gspca_dev *gspca_dev,
}
static int write_vector(struct gspca_dev *gspca_dev,
- const __u16 data[][3])
+ const struct cmd *data, int ncmds)
{
struct usb_device *dev = gspca_dev->dev;
- int ret, i = 0;
+ int ret;
- while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
- ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
+ while (--ncmds >= 0) {
+ ret = reg_w_riv(dev, data->req, data->idx, data->val);
if (ret < 0) {
PDEBUG(D_ERR,
- "Register write failed for 0x%x,0x%x,0x%x",
- data[i][0], data[i][1], data[i][2]);
+ "Register write failed for 0x%02x, 0x%04x, 0x%04x",
+ data->req, data->val, data->idx);
return ret;
}
- i++;
+ data++;
}
return 0;
}
static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
- unsigned int request,
- unsigned int ybase,
- unsigned int cbase,
- const __u8 qtable[2][64])
+ const u8 qtable[2][64])
{
struct usb_device *dev = gspca_dev->dev;
int i, err;
/* loop over y components */
for (i = 0; i < 64; i++) {
- err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
+ err = reg_w_riv(dev, 0x00, 0x2800 + i, qtable[0][i]);
if (err < 0)
return err;
}
/* loop over c components */
for (i = 0; i < 64; i++) {
- err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
+ err = reg_w_riv(dev, 0x00, 0x2840 + i, qtable[1][i]);
if (err < 0)
return err;
}
@@ -635,34 +629,34 @@ static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
}
static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
- __u16 req, __u16 idx, __u16 val)
+ u8 req, u16 idx, u16 val)
{
struct usb_device *dev = gspca_dev->dev;
- __u8 notdone;
+ int notdone;
reg_w_riv(dev, req, idx, val);
notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
reg_w_riv(dev, req, idx, val);
- PDEBUG(D_FRAM, "before wait 0x%x", notdone);
+ PDEBUG(D_FRAM, "before wait 0x%04x", notdone);
msleep(200);
notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
- PDEBUG(D_FRAM, "after wait 0x%x", notdone);
+ PDEBUG(D_FRAM, "after wait 0x%04x", notdone);
}
static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
- __u16 req,
- __u16 idx, __u16 val, __u8 stat, __u8 count)
+ u8 req,
+ u16 idx, u16 val, u8 stat, u8 count)
{
struct usb_device *dev = gspca_dev->dev;
- __u8 status;
- __u8 endcode;
+ int status;
+ u8 endcode;
reg_w_riv(dev, req, idx, val);
status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
endcode = stat;
- PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
+ PDEBUG(D_FRAM, "Status 0x%x Need 0x%04x", status, stat);
if (!count)
return;
count = 200;
@@ -672,7 +666,7 @@ static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
/* reg_w_riv(dev, req, idx, val); */
status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
if (status == endcode) {
- PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
+ PDEBUG(D_FRAM, "status 0x%04x after wait %d",
status, 200 - count);
break;
}
@@ -699,8 +693,7 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
while (--count > 0) {
reg_r(gspca_dev, 0x21, 1, 1);
if (gspca_dev->usb_buf[0] != 0) {
- gspca_dev->usb_buf[0] = 0;
- reg_w(gspca_dev, 0x21, 0, 1, 1);
+ reg_w_1(gspca_dev, 0x21, 0, 1, 0);
reg_r(gspca_dev, 0x21, 1, 1);
spca504B_PollingDataReady(gspca_dev);
break;
@@ -711,7 +704,7 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
{
- __u8 *data;
+ u8 *data;
data = gspca_dev->usb_buf;
reg_r(gspca_dev, 0x20, 0, 5);
@@ -725,41 +718,34 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
- __u8 Size;
- __u8 Type;
+ u8 Size;
int rc;
- Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
- Type = 0;
+ Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
switch (sd->bridge) {
case BRIDGE_SPCA533:
- reg_w(gspca_dev, 0x31, 0, 0, 0);
+ reg_w_riv(dev, 0x31, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
rc = spca504B_PollingDataReady(gspca_dev);
spca50x_GetFirmware(gspca_dev);
- gspca_dev->usb_buf[0] = 2; /* type */
- reg_w(gspca_dev, 0x24, 0, 8, 1);
+ reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
reg_r(gspca_dev, 0x24, 8, 1);
- gspca_dev->usb_buf[0] = Size;
- reg_w(gspca_dev, 0x25, 0, 4, 1);
+ reg_w_1(gspca_dev, 0x25, 0, 4, Size);
reg_r(gspca_dev, 0x25, 4, 1); /* size */
rc = spca504B_PollingDataReady(gspca_dev);
/* Init the cam width height with some values get on init ? */
- reg_w(gspca_dev, 0x31, 0, 4, 0);
+ reg_w_riv(dev, 0x31, 0, 0x04);
spca504B_WaitCmdStatus(gspca_dev);
rc = spca504B_PollingDataReady(gspca_dev);
break;
default:
/* case BRIDGE_SPCA504B: */
/* case BRIDGE_SPCA536: */
- gspca_dev->usb_buf[0] = Size;
- reg_w(gspca_dev, 0x25, 0, 4, 1);
+ reg_w_1(gspca_dev, 0x25, 0, 4, Size);
reg_r(gspca_dev, 0x25, 4, 1); /* size */
- Type = 6;
- gspca_dev->usb_buf[0] = Type;
- reg_w(gspca_dev, 0x27, 0, 0, 1);
+ reg_w_1(gspca_dev, 0x27, 0, 0, 6);
reg_r(gspca_dev, 0x27, 0, 1); /* type */
rc = spca504B_PollingDataReady(gspca_dev);
break;
@@ -799,17 +785,51 @@ static void spca504_wait_status(struct gspca_dev *gspca_dev)
static void spca504B_setQtable(struct gspca_dev *gspca_dev)
{
- gspca_dev->usb_buf[0] = 3;
- reg_w(gspca_dev, 0x26, 0, 0, 1);
+ reg_w_1(gspca_dev, 0x26, 0, 0, 3);
reg_r(gspca_dev, 0x26, 0, 1);
spca504B_PollingDataReady(gspca_dev);
}
-static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ u16 reg;
+
+ reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
+ reg_w_riv(dev, 0x00, reg, sd->brightness);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ u16 reg;
+
+ reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
+ reg_w_riv(dev, 0x00, reg, sd->contrast);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ u16 reg;
+
+ reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
+ reg_w_riv(dev, 0x00, reg, sd->colors);
+}
+
+static void init_ctl_reg(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
int pollreg = 1;
+ setbrightness(gspca_dev);
+ setcontrast(gspca_dev);
+ setcolors(gspca_dev);
+
switch (sd->bridge) {
case BRIDGE_SPCA504:
case BRIDGE_SPCA504C:
@@ -818,20 +838,14 @@ static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
default:
/* case BRIDGE_SPCA533: */
/* case BRIDGE_SPCA504B: */
- reg_w(gspca_dev, 0, 0, 0x21a7, 0); /* brightness */
- reg_w(gspca_dev, 0, 0x20, 0x21a8, 0); /* contrast */
- reg_w(gspca_dev, 0, 0, 0x21ad, 0); /* hue */
- reg_w(gspca_dev, 0, 1, 0x21ac, 0); /* sat/hue */
- reg_w(gspca_dev, 0, 0x20, 0x21ae, 0); /* saturation */
- reg_w(gspca_dev, 0, 0, 0x21a3, 0); /* gamma */
+ reg_w_riv(dev, 0, 0x00, 0x21ad); /* hue */
+ reg_w_riv(dev, 0, 0x01, 0x21ac); /* sat/hue */
+ reg_w_riv(dev, 0, 0x00, 0x21a3); /* gamma */
break;
case BRIDGE_SPCA536:
- reg_w(gspca_dev, 0, 0, 0x20f0, 0);
- reg_w(gspca_dev, 0, 0x21, 0x20f1, 0);
- reg_w(gspca_dev, 0, 0x40, 0x20f5, 0);
- reg_w(gspca_dev, 0, 1, 0x20f4, 0);
- reg_w(gspca_dev, 0, 0x40, 0x20f6, 0);
- reg_w(gspca_dev, 0, 0, 0x2089, 0);
+ reg_w_riv(dev, 0, 0x40, 0x20f5);
+ reg_w_riv(dev, 0, 0x01, 0x20f4);
+ reg_w_riv(dev, 0, 0x00, 0x2089);
break;
}
if (pollreg)
@@ -872,7 +886,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
/* case BRIDGE_SPCA504: */
/* case BRIDGE_SPCA536: */
cam->cam_mode = vga_mode;
- cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ cam->nmodes =ARRAY_SIZE(vga_mode);
break;
case BRIDGE_SPCA533:
cam->cam_mode = custom_mode;
@@ -883,12 +897,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
break;
case BRIDGE_SPCA504C:
cam->cam_mode = vga_mode2;
- cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
+ cam->nmodes = ARRAY_SIZE(vga_mode2);
break;
}
- sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
- sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
- sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
+ sd->brightness = BRIGHTNESS_DEF;
+ sd->contrast = CONTRAST_DEF;
+ sd->colors = COLOR_DEF;
+ sd->autogain = AUTOGAIN_DEF;
sd->quality = QUALITY_DEF;
return 0;
}
@@ -898,32 +913,29 @@ static int sd_init(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
- int rc;
- __u8 i;
- __u8 info[6];
- int err_code;
+ int i, err_code;
+ u8 info[6];
switch (sd->bridge) {
case BRIDGE_SPCA504B:
- reg_w(gspca_dev, 0x1d, 0, 0, 0);
- reg_w(gspca_dev, 0, 1, 0x2306, 0);
- reg_w(gspca_dev, 0, 0, 0x0d04, 0);
- reg_w(gspca_dev, 0, 0, 0x2000, 0);
- reg_w(gspca_dev, 0, 0x13, 0x2301, 0);
- reg_w(gspca_dev, 0, 0, 0x2306, 0);
+ reg_w_riv(dev, 0x1d, 0x00, 0);
+ reg_w_riv(dev, 0, 0x01, 0x2306);
+ reg_w_riv(dev, 0, 0x00, 0x0d04);
+ reg_w_riv(dev, 0, 0x00, 0x2000);
+ reg_w_riv(dev, 0, 0x13, 0x2301);
+ reg_w_riv(dev, 0, 0x00, 0x2306);
/* fall thru */
case BRIDGE_SPCA533:
- rc = spca504B_PollingDataReady(gspca_dev);
+ spca504B_PollingDataReady(gspca_dev);
spca50x_GetFirmware(gspca_dev);
break;
case BRIDGE_SPCA536:
spca50x_GetFirmware(gspca_dev);
reg_r(gspca_dev, 0x00, 0x5002, 1);
- gspca_dev->usb_buf[0] = 0;
- reg_w(gspca_dev, 0x24, 0, 0, 1);
+ reg_w_1(gspca_dev, 0x24, 0, 0, 0);
reg_r(gspca_dev, 0x24, 0, 1);
- rc = spca504B_PollingDataReady(gspca_dev);
- reg_w(gspca_dev, 0x34, 0, 0, 0);
+ spca504B_PollingDataReady(gspca_dev);
+ reg_w_riv(dev, 0x34, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
break;
case BRIDGE_SPCA504C: /* pccam600 */
@@ -933,12 +945,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
spca504_wait_status(gspca_dev);
if (sd->subtype == LogitechClickSmart420)
write_vector(gspca_dev,
- spca504A_clicksmart420_open_data);
+ spca504A_clicksmart420_open_data,
+ ARRAY_SIZE(spca504A_clicksmart420_open_data));
else
- write_vector(gspca_dev, spca504_pccam600_open_data);
+ write_vector(gspca_dev, spca504_pccam600_open_data,
+ ARRAY_SIZE(spca504_pccam600_open_data));
err_code = spca50x_setup_qtable(gspca_dev,
- 0x00, 0x2800,
- 0x2840, qtable_creative_pccam);
+ qtable_creative_pccam);
if (err_code < 0) {
PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
return err_code;
@@ -976,8 +989,8 @@ static int sd_init(struct gspca_dev *gspca_dev)
6, 0, 0x86, 1); */
/* spca504A_acknowledged_command (gspca_dev, 0x24,
0, 0, 0x9D, 1); */
- reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
- reg_w_riv(dev, 0x0, 0x2310, 0x05);
+ reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */
+ reg_w_riv(dev, 0x00, 0x2310, 0x05);
spca504A_acknowledged_command(gspca_dev, 0x01,
0x0f, 0, 0xff, 0);
}
@@ -985,8 +998,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
reg_w_riv(dev, 0, 0x2000, 0);
reg_w_riv(dev, 0, 0x2883, 1);
err_code = spca50x_setup_qtable(gspca_dev,
- 0x00, 0x2800,
- 0x2840,
qtable_spca504_default);
if (err_code < 0) {
PDEBUG(D_ERR, "spca50x_setup_qtable failed");
@@ -1001,10 +1012,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
- int rc;
int enable;
- __u8 i;
- __u8 info[6];
+ int i;
+ u8 info[6];
/* create the JPEG header */
sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
@@ -1022,17 +1032,20 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* case BRIDGE_SPCA504B: */
/* case BRIDGE_SPCA533: */
/* case BRIDGE_SPCA536: */
- if (sd->subtype == MegapixV4 ||
- sd->subtype == LogitechClickSmart820 ||
- sd->subtype == MegaImageVI) {
- reg_w(gspca_dev, 0xf0, 0, 0, 0);
+ switch (sd->subtype) {
+ case MegapixV4:
+ case LogitechClickSmart820:
+ case MegaImageVI:
+ reg_w_riv(dev, 0xf0, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
reg_r(gspca_dev, 0xf0, 4, 0);
spca504B_WaitCmdStatus(gspca_dev);
- } else {
- reg_w(gspca_dev, 0x31, 0, 4, 0);
+ break;
+ default:
+ reg_w_riv(dev, 0x31, 0, 0x04);
spca504B_WaitCmdStatus(gspca_dev);
- rc = spca504B_PollingDataReady(gspca_dev);
+ spca504B_PollingDataReady(gspca_dev);
+ break;
}
break;
case BRIDGE_SPCA504:
@@ -1066,15 +1079,17 @@ static int sd_start(struct gspca_dev *gspca_dev)
spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
}
spca504B_SetSizeType(gspca_dev);
- reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
- reg_w_riv(dev, 0x0, 0x2310, 0x05);
+ reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */
+ reg_w_riv(dev, 0x00, 0x2310, 0x05);
break;
case BRIDGE_SPCA504C:
if (sd->subtype == LogitechClickSmart420) {
write_vector(gspca_dev,
- spca504A_clicksmart420_init_data);
+ spca504A_clicksmart420_init_data,
+ ARRAY_SIZE(spca504A_clicksmart420_init_data));
} else {
- write_vector(gspca_dev, spca504_pccam600_init_data);
+ write_vector(gspca_dev, spca504_pccam600_init_data,
+ ARRAY_SIZE(spca504_pccam600_init_data));
}
enable = (sd->autogain ? 0x04 : 0x01);
reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
@@ -1086,7 +1101,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
spca504B_SetSizeType(gspca_dev);
break;
}
- sp5xx_initContBrigHueRegisters(gspca_dev);
+ init_ctl_reg(gspca_dev);
return 0;
}
@@ -1100,7 +1115,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
/* case BRIDGE_SPCA533: */
/* case BRIDGE_SPCA536: */
/* case BRIDGE_SPCA504B: */
- reg_w(gspca_dev, 0x31, 0, 0, 0);
+ reg_w_riv(dev, 0x31, 0, 0);
spca504B_WaitCmdStatus(gspca_dev);
spca504B_PollingDataReady(gspca_dev);
break;
@@ -1118,7 +1133,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
0x0f, 0x00, 0xff, 1);
} else {
spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
- reg_w_riv(dev, 0x01, 0x000f, 0x00);
+ reg_w_riv(dev, 0x01, 0x000f, 0x0000);
}
break;
}
@@ -1133,12 +1148,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
- __u8 *data, /* isoc packet */
+ u8 *data, /* isoc packet */
int len) /* iso packet length */
{
struct sd *sd = (struct sd *) gspca_dev;
int i, sof = 0;
- static unsigned char ffd9[] = {0xff, 0xd9};
+ static u8 ffd9[] = {0xff, 0xd9};
/* frames are jpeg 4.1.1 without 0xff escape */
switch (sd->bridge) {
@@ -1226,63 +1241,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
-static void setbrightness(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- struct usb_device *dev = gspca_dev->dev;
-
- switch (sd->bridge) {
- default:
-/* case BRIDGE_SPCA533: */
-/* case BRIDGE_SPCA504B: */
-/* case BRIDGE_SPCA504: */
-/* case BRIDGE_SPCA504C: */
- reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
- break;
- case BRIDGE_SPCA536:
- reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
- break;
- }
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- struct usb_device *dev = gspca_dev->dev;
-
- switch (sd->bridge) {
- default:
-/* case BRIDGE_SPCA533: */
-/* case BRIDGE_SPCA504B: */
-/* case BRIDGE_SPCA504: */
-/* case BRIDGE_SPCA504C: */
- reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
- break;
- case BRIDGE_SPCA536:
- reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
- break;
- }
-}
-
-static void setcolors(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- struct usb_device *dev = gspca_dev->dev;
-
- switch (sd->bridge) {
- default:
-/* case BRIDGE_SPCA533: */
-/* case BRIDGE_SPCA504B: */
-/* case BRIDGE_SPCA504: */
-/* case BRIDGE_SPCA504C: */
- reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
- break;
- case BRIDGE_SPCA536:
- reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
- break;
- }
-}
-
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c
index 44dea7949..9464454f1 100644
--- a/linux/drivers/media/video/gspca/vc032x.c
+++ b/linux/drivers/media/video/gspca/vc032x.c
@@ -1940,109 +1940,200 @@ static const u8 po3130_initQVGA_data[][4] = {
};
static const u8 hv7131r_gamma[17] = {
-/* 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
- * 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff */
+#if 1
+ 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
+ 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
+#else
0x04, 0x1a, 0x36, 0x55, 0x6f, 0x87, 0x9d, 0xb0, 0xc1,
0xcf, 0xda, 0xe4, 0xec, 0xf3, 0xf8, 0xfd, 0xff
+#endif
};
static const u8 hv7131r_matrix[9] = {
0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
};
static const u8 hv7131r_initVGA_data[][4] = {
- {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
- {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
+ {0xb3, 0x01, 0x01, 0xcc},
+ {0xb0, 0x03, 0x19, 0xcc},
+ {0xb0, 0x04, 0x02, 0xcc},
+ {0x00, 0x00, 0x20, 0xdd},
{0xb3, 0x00, 0x24, 0xcc},
- {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
- {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
- {0xb3, 0x06, 0x01, 0xcc},
- {0xb3, 0x01, 0x45, 0xcc}, {0xb3, 0x03, 0x0b, 0xcc},
- {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
+ {0xb3, 0x00, 0x25, 0xcc},
+ {0xb3, 0x08, 0x01, 0xcc},
+ {0xb3, 0x09, 0x0c, 0xcc},
+ {0xb3, 0x05, 0x01, 0xcc},
+ {0xb3, 0x06, 0x03, 0xcc},
+ {0xb3, 0x01, 0x45, 0xcc},
+ {0xb3, 0x03, 0x0b, 0xcc},
+ {0xb3, 0x04, 0x05, 0xcc},
+ {0xb3, 0x20, 0x00, 0xcc},
{0xb3, 0x21, 0x00, 0xcc},
- {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc},
- {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
+ {0xb3, 0x22, 0x01, 0xcc},
+ {0xb3, 0x23, 0xe0, 0xcc},
+ {0xb3, 0x14, 0x00, 0xcc},
+ {0xb3, 0x15, 0x02, 0xcc},
{0xb3, 0x16, 0x02, 0xcc},
- {0xb3, 0x17, 0x7f, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
- {0xb3, 0x35, 0x91, 0xcc}, {0xb3, 0x00, 0x27, 0xcc},
+ {0xb3, 0x17, 0x7f, 0xcc},
+ {0xb3, 0x34, 0x01, 0xcc},
+ {0xb3, 0x35, 0x91, 0xcc},
+ {0xb3, 0x00, 0x27, 0xcc},
{0xbc, 0x00, 0x73, 0xcc},
- {0xb8, 0x00, 0x23, 0xcc}, {0x00, 0x01, 0x0c, 0xaa},
- {0x00, 0x14, 0x01, 0xaa}, {0x00, 0x15, 0xe6, 0xaa},
- {0x00, 0x16, 0x02, 0xaa},
- {0x00, 0x17, 0x86, 0xaa}, {0x00, 0x23, 0x00, 0xaa},
- {0x00, 0x25, 0x09, 0xaa}, {0x00, 0x26, 0x27, 0xaa},
- {0x00, 0x27, 0xc0, 0xaa},
- {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
- {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
+ {0xb8, 0x00, 0x23, 0xcc},
+ {0xb8, 0x2c, 0x50, 0xcc},
+ {0xb8, 0x2d, 0xf8, 0xcc},
+ {0xb8, 0x2e, 0xf8, 0xcc},
+ {0xb8, 0x2f, 0xf8, 0xcc},
{0xb8, 0x30, 0x50, 0xcc},
- {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc},
- {0xb8, 0x33, 0xf8, 0xcc}, {0xb8, 0x34, 0x65, 0xcc},
+ {0xb8, 0x31, 0xf8, 0xcc},
+ {0xb8, 0x32, 0xf8, 0xcc},
+ {0xb8, 0x33, 0xf8, 0xcc},
+ {0xb8, 0x34, 0x58, 0xcc},
{0xb8, 0x35, 0x00, 0xcc},
- {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
- {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x01, 0x7d, 0xcc},
+ {0xb8, 0x36, 0x00, 0xcc},
+ {0xb8, 0x37, 0x00, 0xcc},
+ {0xb8, 0x27, 0x20, 0xcc},
+ {0xb8, 0x01, 0x7d, 0xcc},
{0xb8, 0x81, 0x09, 0xcc},
- {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc},
- {0xb8, 0xff, 0x28, 0xcc}, {0xb9, 0x00, 0x28, 0xcc},
- {0xb9, 0x01, 0x28, 0xcc},
- {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
- {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
- {0xb9, 0x06, 0x3c, 0xcc},
- {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc},
- {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
+ {0xb3, 0x01, 0x41, 0xcc},
+ {0xb8, 0x8e, 0x00, 0xcc},
+ {0xb8, 0x8f, 0xff, 0xcc},
+ {0x00, 0x01, 0x0c, 0xaa},
+ {0x00, 0x14, 0x01, 0xaa},
+ {0x00, 0x15, 0xe6, 0xaa},
+ {0x00, 0x16, 0x02, 0xaa},
+ {0x00, 0x17, 0x86, 0xaa},
+ {0x00, 0x23, 0x00, 0xaa},
+ {0x00, 0x25, 0x03, 0xaa},
+ {0x00, 0x26, 0xa9, 0xaa},
+ {0x00, 0x27, 0x80, 0xaa},
{0x00, 0x30, 0x18, 0xaa},
+ {0xb6, 0x00, 0x00, 0xcc},
+ {0xb6, 0x03, 0x02, 0xcc},
+ {0xb6, 0x02, 0x80, 0xcc},
+ {0xb6, 0x05, 0x01, 0xcc},
+ {0xb6, 0x04, 0xe0, 0xcc},
+ {0xb6, 0x12, 0x78, 0xcc},
+ {0xb6, 0x18, 0x02, 0xcc},
+ {0xb6, 0x17, 0x58, 0xcc},
+ {0xb6, 0x16, 0x00, 0xcc},
+ {0xb6, 0x22, 0x12, 0xcc},
+ {0xb6, 0x23, 0x0b, 0xcc},
+ {0xb3, 0x02, 0x02, 0xcc},
+ {0xbf, 0xc0, 0x39, 0xcc},
+ {0xbf, 0xc1, 0x04, 0xcc},
+ {0xbf, 0xcc, 0x10, 0xcc},
+ {0xb6, 0x12, 0xf8, 0xcc},
+ {0xb6, 0x13, 0x13, 0xcc},
+ {0xb9, 0x12, 0x00, 0xcc},
+ {0xb9, 0x13, 0x0a, 0xcc},
+ {0xb9, 0x14, 0x0a, 0xcc},
+ {0xb9, 0x15, 0x0a, 0xcc},
+ {0xb9, 0x16, 0x0a, 0xcc},
+ {0xb8, 0x0c, 0x20, 0xcc},
+ {0xb8, 0x0d, 0x70, 0xcc},
+ {0xb9, 0x18, 0x00, 0xcc},
+ {0xb9, 0x19, 0x0f, 0xcc},
+ {0xb9, 0x1a, 0x0f, 0xcc},
+ {0xb9, 0x1b, 0x0f, 0xcc},
+ {0xb9, 0x1c, 0x0f, 0xcc},
+ {0xb3, 0x5c, 0x01, 0xcc},
{}
};
static const u8 hv7131r_initQVGA_data[][4] = {
- {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
- {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
+ {0xb3, 0x01, 0x01, 0xcc},
+ {0xb0, 0x03, 0x19, 0xcc},
+ {0xb0, 0x04, 0x02, 0xcc},
+ {0x00, 0x00, 0x20, 0xdd},
{0xb3, 0x00, 0x24, 0xcc},
- {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
- {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
- {0xb3, 0x06, 0x01, 0xcc},
- {0xb3, 0x03, 0x0b, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
- {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
+ {0xb3, 0x00, 0x25, 0xcc},
+ {0xb3, 0x08, 0x01, 0xcc},
+ {0xb3, 0x09, 0x0c, 0xcc},
+ {0xb3, 0x05, 0x01, 0xcc},
+ {0xb3, 0x06, 0x03, 0xcc},
+ {0xb3, 0x01, 0x45, 0xcc},
+ {0xb3, 0x03, 0x0b, 0xcc},
+ {0xb3, 0x04, 0x05, 0xcc},
+ {0xb3, 0x20, 0x00, 0xcc},
+ {0xb3, 0x21, 0x00, 0xcc},
{0xb3, 0x22, 0x01, 0xcc},
- {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc},
- {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x02, 0xcc},
+ {0xb3, 0x23, 0xe0, 0xcc},
+ {0xb3, 0x14, 0x00, 0xcc},
+ {0xb3, 0x15, 0x02, 0xcc},
+ {0xb3, 0x16, 0x02, 0xcc},
{0xb3, 0x17, 0x7f, 0xcc},
- {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0x91, 0xcc},
- {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc},
- {0xb8, 0x00, 0x21, 0xcc},
- {0x00, 0x01, 0x0c, 0xaa}, {0x00, 0x14, 0x01, 0xaa},
- {0x00, 0x15, 0xe6, 0xaa}, {0x00, 0x16, 0x02, 0xaa},
- {0x00, 0x17, 0x86, 0xaa},
- {0x00, 0x23, 0x00, 0xaa}, {0x00, 0x25, 0x01, 0xaa},
- {0x00, 0x26, 0xd4, 0xaa}, {0x00, 0x27, 0xc0, 0xaa},
- {0xbc, 0x02, 0x08, 0xcc},
- {0xbc, 0x03, 0x70, 0xcc}, {0xbc, 0x04, 0x08, 0xcc},
- {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc},
- {0xbc, 0x08, 0x3c, 0xcc},
- {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x04, 0xcc},
- {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
- {0xb8, 0xfe, 0x02, 0xcc},
- {0xb8, 0xff, 0x07, 0xcc}, {0xb9, 0x00, 0x14, 0xcc},
- {0xb9, 0x01, 0x14, 0xcc}, {0xb9, 0x02, 0x14, 0xcc},
- {0xb9, 0x03, 0x00, 0xcc},
- {0xb9, 0x04, 0x02, 0xcc}, {0xb9, 0x05, 0x05, 0xcc},
- {0xb9, 0x06, 0x0f, 0xcc}, {0xb9, 0x07, 0x0f, 0xcc},
- {0xb9, 0x08, 0x0f, 0xcc},
- {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
- {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
+ {0xb3, 0x34, 0x01, 0xcc},
+ {0xb3, 0x35, 0x91, 0xcc},
+ {0xb3, 0x00, 0x27, 0xcc},
+ {0xbc, 0x00, 0xd3, 0xcc},
+ {0xb8, 0x00, 0x23, 0xcc},
+ {0xb8, 0x2c, 0x50, 0xcc},
+ {0xb8, 0x2d, 0xf8, 0xcc},
+ {0xb8, 0x2e, 0xf8, 0xcc},
+ {0xb8, 0x2f, 0xf8, 0xcc},
{0xb8, 0x30, 0x50, 0xcc},
- {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc},
+ {0xb8, 0x31, 0xf8, 0xcc},
+ {0xb8, 0x32, 0xf8, 0xcc},
{0xb8, 0x33, 0xf8, 0xcc},
- {0xb8, 0x34, 0x65, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
- {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
+ {0xb8, 0x34, 0x58, 0xcc},
+ {0xb8, 0x35, 0x00, 0xcc},
+ {0xb8, 0x36, 0x00, 0xcc},
+ {0xb8, 0x37, 0x00, 0xcc},
{0xb8, 0x27, 0x20, 0xcc},
- {0xb8, 0x01, 0x7d, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
- {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc},
- {0xb8, 0xff, 0x28, 0xcc},
- {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
- {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
- {0xb9, 0x04, 0x00, 0xcc},
- {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc},
- {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc},
+ {0xb8, 0x01, 0x7d, 0xcc},
+ {0xb8, 0x81, 0x09, 0xcc},
+ {0xb3, 0x01, 0x41, 0xcc},
{0xb8, 0x8e, 0x00, 0xcc},
- {0xb8, 0x8f, 0xff, 0xcc}, {0x00, 0x30, 0x18, 0xaa},
+ {0xb8, 0x8f, 0xff, 0xcc},
+ {0x00, 0x01, 0x0c, 0xaa},
+ {0x00, 0x14, 0x01, 0xaa},
+ {0x00, 0x15, 0xe6, 0xaa},
+ {0x00, 0x16, 0x02, 0xaa},
+ {0x00, 0x17, 0x86, 0xaa},
+ {0x00, 0x23, 0x00, 0xaa},
+ {0x00, 0x25, 0x03, 0xaa},
+ {0x00, 0x26, 0xa9, 0xaa},
+ {0x00, 0x27, 0x80, 0xaa},
+ {0x00, 0x30, 0x18, 0xaa},
+ {0xb6, 0x00, 0x00, 0xcc},
+ {0xb6, 0x03, 0x01, 0xcc},
+ {0xb6, 0x02, 0x40, 0xcc},
+ {0xb6, 0x05, 0x00, 0xcc},
+ {0xb6, 0x04, 0xf0, 0xcc},
+ {0xb6, 0x12, 0x78, 0xcc},
+ {0xb6, 0x18, 0x00, 0xcc},
+ {0xb6, 0x17, 0x96, 0xcc},
+ {0xb6, 0x16, 0x00, 0xcc},
+ {0xb6, 0x22, 0x12, 0xcc},
+ {0xb6, 0x23, 0x0b, 0xcc},
+ {0xb3, 0x02, 0x02, 0xcc},
+ {0xbf, 0xc0, 0x39, 0xcc},
+ {0xbf, 0xc1, 0x04, 0xcc},
+ {0xbf, 0xcc, 0x10, 0xcc},
+ {0xbc, 0x02, 0x18, 0xcc},
+ {0xbc, 0x03, 0x50, 0xcc},
+ {0xbc, 0x04, 0x18, 0xcc},
+ {0xbc, 0x05, 0x00, 0xcc},
+ {0xbc, 0x06, 0x00, 0xcc},
+ {0xbc, 0x08, 0x30, 0xcc},
+ {0xbc, 0x09, 0x40, 0xcc},
+ {0xbc, 0x0a, 0x10, 0xcc},
+ {0xbc, 0x0b, 0x00, 0xcc},
+ {0xbc, 0x0c, 0x00, 0xcc},
+ {0xb9, 0x12, 0x00, 0xcc},
+ {0xb9, 0x13, 0x0a, 0xcc},
+ {0xb9, 0x14, 0x0a, 0xcc},
+ {0xb9, 0x15, 0x0a, 0xcc},
+ {0xb9, 0x16, 0x0a, 0xcc},
+ {0xb9, 0x18, 0x00, 0xcc},
+ {0xb9, 0x19, 0x0f, 0xcc},
+ {0xb8, 0x0c, 0x20, 0xcc},
+ {0xb8, 0x0d, 0x70, 0xcc},
+ {0xb9, 0x1a, 0x0f, 0xcc},
+ {0xb9, 0x1b, 0x0f, 0xcc},
+ {0xb9, 0x1c, 0x0f, 0xcc},
+ {0xb6, 0x12, 0xf8, 0xcc},
+ {0xb6, 0x13, 0x13, 0xcc},
+ {0xb3, 0x5c, 0x01, 0xcc},
{}
};
@@ -3135,10 +3226,10 @@ static void sethvflip(struct gspca_dev *gspca_dev)
hflip = sd->hflip;
if (sd->flags & FL_HFLIP)
- hflip != hflip;
+ hflip = !hflip;
vflip = sd->vflip;
if (sd->flags & FL_VFLIP)
- vflip != vflip;
+ vflip = !vflip;
switch (sd->sensor) {
case SENSOR_MI1310_SOC:
case SENSOR_MI1320_SOC:
@@ -3319,21 +3410,22 @@ static int sd_start(struct gspca_dev *gspca_dev)
put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c);
/* set the led on 0x0892 0x0896 */
- if (sd->sensor == SENSOR_PO1200) {
- setsharpness(gspca_dev);
- sethvflip(gspca_dev);
+ switch (sd->sensor) {
+ case SENSOR_PO1200:
+ case SENSOR_HV7131R:
reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415);
- } else if (sd->sensor == SENSOR_MI1310_SOC) {
+ break;
+ case SENSOR_MI1310_SOC:
reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000);
- msleep(100);
- sethvflip(gspca_dev);
- setlightfreq(gspca_dev);
- } else {
+ break;
+ default:
reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff);
- msleep(100);
- sethvflip(gspca_dev);
- setlightfreq(gspca_dev);
+ break;
}
+ msleep(100);
+ setsharpness(gspca_dev);
+ sethvflip(gspca_dev);
+ setlightfreq(gspca_dev);
}
return 0;
}
diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c
index 2a9480138..02b6e185f 100644
--- a/linux/drivers/media/video/gspca/zc3xx.c
+++ b/linux/drivers/media/video/gspca/zc3xx.c
@@ -7607,7 +7607,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
- .nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0],
+ .nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.init = sd_init,
.start = sd_start,